blob: c63f3b232d4d7bdc6a5a7f22849a748cf8914878 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalomc1a21442022-02-04 13:43:00 -08003 * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
Sunil8cd6f4d2022-06-28 18:40:46 +000020#include "crypto/crypto.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080022#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070023#include "eapol_supp/eapol_supp_sm.h"
24#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070025#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "eap_server/eap_methods.h"
27#include "rsn_supp/wpa.h"
28#include "eloop.h"
29#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070030#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070031#include "l2_packet/l2_packet.h"
32#include "wpa_supplicant_i.h"
33#include "driver_i.h"
34#include "ctrl_iface.h"
35#include "pcsc_funcs.h"
36#include "common/version.h"
37#include "rsn_supp/preauth.h"
38#include "rsn_supp/pmksa_cache.h"
39#include "common/wpa_ctrl.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070040#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080042#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070043#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070044#include "common/dpp.h"
Hai Shalom60840252021-02-19 19:02:11 -080045#include "common/ptksa_cache.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080047#include "fst/fst.h"
Hai Shalom60840252021-02-19 19:02:11 -080048#include "bssid_ignore.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "wpas_glue.h"
50#include "wps_supplicant.h"
51#include "ibss_rsn.h"
52#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080053#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070054#include "ap.h"
55#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070056#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070057#include "notify.h"
58#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070059#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070060#include "bss.h"
61#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080062#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070063#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070064#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070065#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080066#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070067#include "dpp_supplicant.h"
68#ifdef CONFIG_MESH
69#include "ap/ap_config.h"
70#include "ap/hostapd.h"
71#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070073const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074"wpa_supplicant v" VERSION_STR "\n"
Hai Shalomc1a21442022-02-04 13:43:00 -080075"Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070077const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080078"This software may be distributed under the terms of the BSD license.\n"
79"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070080#ifdef EAP_TLS_OPENSSL
81"\nThis product includes software developed by the OpenSSL Project\n"
82"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
83#endif /* EAP_TLS_OPENSSL */
84;
85
86#ifndef CONFIG_NO_STDOUT_DEBUG
87/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070088const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080089"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070090const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080091"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070092"\n"
93"Redistribution and use in source and binary forms, with or without\n"
94"modification, are permitted provided that the following conditions are\n"
95"met:\n"
96"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070097const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098"1. Redistributions of source code must retain the above copyright\n"
99" notice, this list of conditions and the following disclaimer.\n"
100"\n"
101"2. Redistributions in binary form must reproduce the above copyright\n"
102" notice, this list of conditions and the following disclaimer in the\n"
103" documentation and/or other materials provided with the distribution.\n"
104"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700105const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700106"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
107" names of its contributors may be used to endorse or promote products\n"
108" derived from this software without specific prior written permission.\n"
109"\n"
110"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
111"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
112"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
113"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700114const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700115"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
116"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
117"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
118"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
119"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
120"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
121"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
122"\n";
123#endif /* CONFIG_NO_STDOUT_DEBUG */
124
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700125
126static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
127#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
128static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
129#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700130#ifdef CONFIG_OWE
131static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
132#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700133
134
Hai Shalomfdcde762020-04-02 11:19:20 -0700135#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136/* Configure default/group WEP keys for static WEP */
137int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
138{
139 int i, set = 0;
140
141 for (i = 0; i < NUM_WEP_KEYS; i++) {
142 if (ssid->wep_key_len[i] == 0)
143 continue;
144
145 set = 1;
146 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
147 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700148 ssid->wep_key[i], ssid->wep_key_len[i],
149 i == ssid->wep_tx_keyidx ?
150 KEY_FLAG_GROUP_RX_TX_DEFAULT :
151 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700152 }
153
154 return set;
155}
Hai Shalomfdcde762020-04-02 11:19:20 -0700156#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700157
158
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700159int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
160 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700161{
162 u8 key[32];
163 size_t keylen;
164 enum wpa_alg alg;
165 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800166 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700167
168 /* IBSS/WPA-None uses only one key (Group) for both receiving and
169 * sending unicast and multicast packets. */
170
171 if (ssid->mode != WPAS_MODE_IBSS) {
172 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
173 "IBSS/ad-hoc) for WPA-None", ssid->mode);
174 return -1;
175 }
176
177 if (!ssid->psk_set) {
178 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
179 "WPA-None");
180 return -1;
181 }
182
183 switch (wpa_s->group_cipher) {
184 case WPA_CIPHER_CCMP:
185 os_memcpy(key, ssid->psk, 16);
186 keylen = 16;
187 alg = WPA_ALG_CCMP;
188 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700189 case WPA_CIPHER_GCMP:
190 os_memcpy(key, ssid->psk, 16);
191 keylen = 16;
192 alg = WPA_ALG_GCMP;
193 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700194 case WPA_CIPHER_TKIP:
195 /* WPA-None uses the same Michael MIC key for both TX and RX */
196 os_memcpy(key, ssid->psk, 16 + 8);
197 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
198 keylen = 32;
199 alg = WPA_ALG_TKIP;
200 break;
201 default:
202 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
203 "WPA-None", wpa_s->group_cipher);
204 return -1;
205 }
206
207 /* TODO: should actually remember the previously used seq#, both for TX
208 * and RX from each STA.. */
209
Hai Shalomfdcde762020-04-02 11:19:20 -0700210 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen,
211 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800212 os_memset(key, 0, sizeof(key));
213 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700214}
215
216
217static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
218{
219 struct wpa_supplicant *wpa_s = eloop_ctx;
220 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700221 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
222 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
223 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700224 bssid = wpa_s->pending_bssid;
225 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
226 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800227 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700228 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700229 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800230 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231 wpa_s->reassociate = 1;
232
233 /*
234 * If we timed out, the AP or the local radio may be busy.
235 * So, wait a second until scanning again.
236 */
237 wpa_supplicant_req_scan(wpa_s, 1, 0);
238}
239
240
241/**
242 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
243 * @wpa_s: Pointer to wpa_supplicant data
244 * @sec: Number of seconds after which to time out authentication
245 * @usec: Number of microseconds after which to time out authentication
246 *
247 * This function is used to schedule a timeout for the current authentication
248 * attempt.
249 */
250void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
251 int sec, int usec)
252{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700253 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
255 return;
256
257 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
258 "%d usec", sec, usec);
259 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700260 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700261 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
262}
263
264
Roshan Pius3a1667e2018-07-03 15:17:14 -0700265/*
266 * wpas_auth_timeout_restart - Restart and change timeout for authentication
267 * @wpa_s: Pointer to wpa_supplicant data
268 * @sec_diff: difference in seconds applied to original timeout value
269 */
270void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
271{
272 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
273
274 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
275 wpa_dbg(wpa_s, MSG_DEBUG,
276 "Authentication timeout restart: %d sec", new_sec);
277 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
278 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
279 wpa_s, NULL);
280 }
281}
282
283
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700284/**
285 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
286 * @wpa_s: Pointer to wpa_supplicant data
287 *
288 * This function is used to cancel authentication timeout scheduled with
289 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
290 * been completed.
291 */
292void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
293{
294 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
295 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800296 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700297 os_free(wpa_s->last_con_fail_realm);
298 wpa_s->last_con_fail_realm = NULL;
299 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700300}
301
302
303/**
304 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
305 * @wpa_s: Pointer to wpa_supplicant data
306 *
307 * This function is used to configure EAPOL state machine based on the selected
308 * authentication mode.
309 */
310void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
311{
312#ifdef IEEE8021X_EAPOL
313 struct eapol_config eapol_conf;
314 struct wpa_ssid *ssid = wpa_s->current_ssid;
315
316#ifdef CONFIG_IBSS_RSN
317 if (ssid->mode == WPAS_MODE_IBSS &&
318 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
319 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
320 /*
321 * RSN IBSS authentication is per-STA and we can disable the
322 * per-BSSID EAPOL authentication.
323 */
324 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700325 eapol_sm_notify_eap_success(wpa_s->eapol, true);
326 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700327 return;
328 }
329#endif /* CONFIG_IBSS_RSN */
330
Hai Shalome21d4e82020-04-29 16:34:06 -0700331 eapol_sm_notify_eap_success(wpa_s->eapol, false);
332 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700333
334 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
335 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
336 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
337 else
338 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
339
340 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
341 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
342 eapol_conf.accept_802_1x_keys = 1;
343 eapol_conf.required_keys = 0;
344 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
345 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
346 }
347 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
348 eapol_conf.required_keys |=
349 EAPOL_REQUIRE_KEY_BROADCAST;
350 }
351
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700352 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700353 eapol_conf.required_keys = 0;
354 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700355 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700356 eapol_conf.workaround = ssid->eap_workaround;
357 eapol_conf.eap_disabled =
358 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
359 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
360 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700361 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800362
363#ifdef CONFIG_WPS
364 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
365 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
366 if (wpa_s->current_bss) {
367 struct wpabuf *ie;
368 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
369 WPS_IE_VENDOR_TYPE);
370 if (ie) {
371 if (wps_is_20(ie))
372 eapol_conf.wps |=
373 EAPOL_PEER_IS_WPS20_AP;
374 wpabuf_free(ie);
375 }
376 }
377 }
378#endif /* CONFIG_WPS */
379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700380 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700381
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800382#ifdef CONFIG_MACSEC
383 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
384 ieee802_1x_create_preshared_mka(wpa_s, ssid);
385 else
386 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
387#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800388#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700389}
390
391
392/**
393 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
394 * @wpa_s: Pointer to wpa_supplicant data
395 * @ssid: Configuration data for the network
396 *
397 * This function is used to configure WPA state machine and related parameters
398 * to a mode where WPA is not enabled. This is called as part of the
399 * authentication configuration when the selected network does not use WPA.
400 */
401void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
402 struct wpa_ssid *ssid)
403{
Hai Shalomfdcde762020-04-02 11:19:20 -0700404#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700405 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700406#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700407
408 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
409 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
410 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
411 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
412 else
413 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
414 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
415 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700416 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700417 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700418 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
419 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700420 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
421 wpa_s->group_cipher = WPA_CIPHER_NONE;
422 wpa_s->mgmt_group_cipher = 0;
423
Hai Shalomfdcde762020-04-02 11:19:20 -0700424#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700425 for (i = 0; i < NUM_WEP_KEYS; i++) {
426 if (ssid->wep_key_len[i] > 5) {
427 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
428 wpa_s->group_cipher = WPA_CIPHER_WEP104;
429 break;
430 } else if (ssid->wep_key_len[i] > 0) {
431 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
432 wpa_s->group_cipher = WPA_CIPHER_WEP40;
433 break;
434 }
435 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700436#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700437
438 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
439 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
440 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
441 wpa_s->pairwise_cipher);
442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
444 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700445
446 pmksa_cache_clear_current(wpa_s->wpa);
447}
448
449
Dmitry Shmidt04949592012-07-19 12:16:46 -0700450void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800451{
452 int i;
453 if (wpa_s->hw.modes == NULL)
454 return;
455
456 for (i = 0; i < wpa_s->hw.num_modes; i++) {
457 os_free(wpa_s->hw.modes[i].channels);
458 os_free(wpa_s->hw.modes[i].rates);
459 }
460
461 os_free(wpa_s->hw.modes);
462 wpa_s->hw.modes = NULL;
463}
464
465
Hai Shalomc1a21442022-02-04 13:43:00 -0800466static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
467 struct wpa_bss_tmp_disallowed *bss)
468{
469 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
470 dl_list_del(&bss->list);
471 os_free(bss);
472}
473
474
Hai Shalom74f70d42019-02-11 14:42:39 -0800475void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800476{
477 struct wpa_bss_tmp_disallowed *bss, *prev;
478
479 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800480 struct wpa_bss_tmp_disallowed, list)
481 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800482}
483
484
Paul Stewart092955c2017-02-06 09:13:09 -0800485void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
486{
487 struct fils_hlp_req *req;
488
489 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
490 list)) != NULL) {
491 dl_list_del(&req->list);
492 wpabuf_free(req->pkt);
493 os_free(req);
494 }
495}
496
497
Hai Shalomfdcde762020-04-02 11:19:20 -0700498void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
499{
500 struct wpa_supplicant *wpa_s = eloop_ctx;
501
502 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
503 return;
504 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
505 wpa_bss_flush(wpa_s);
506}
507
508
509#ifdef CONFIG_TESTING_OPTIONS
510void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
511{
512 struct driver_signal_override *dso;
513
514 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
515 struct driver_signal_override, list))) {
516 dl_list_del(&dso->list);
517 os_free(dso);
518 }
519}
520#endif /* CONFIG_TESTING_OPTIONS */
521
522
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700523static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
524{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700525 int i;
526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700527 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700528 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700529 scard_deinit(wpa_s->scard);
530 wpa_s->scard = NULL;
531 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
532 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
533 l2_packet_deinit(wpa_s->l2);
534 wpa_s->l2 = NULL;
535 if (wpa_s->l2_br) {
536 l2_packet_deinit(wpa_s->l2_br);
537 wpa_s->l2_br = NULL;
538 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800539#ifdef CONFIG_TESTING_OPTIONS
540 l2_packet_deinit(wpa_s->l2_test);
541 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800542 os_free(wpa_s->get_pref_freq_list_override);
543 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700544 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
545 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800546 os_free(wpa_s->extra_sae_rejected_groups);
547 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700548 wpabuf_free(wpa_s->rsne_override_eapol);
549 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800550 wpabuf_free(wpa_s->rsnxe_override_assoc);
551 wpa_s->rsnxe_override_assoc = NULL;
552 wpabuf_free(wpa_s->rsnxe_override_eapol);
553 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700554 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800555#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557 if (wpa_s->conf != NULL) {
558 struct wpa_ssid *ssid;
559 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
560 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561 }
562
563 os_free(wpa_s->confname);
564 wpa_s->confname = NULL;
565
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700566 os_free(wpa_s->confanother);
567 wpa_s->confanother = NULL;
568
Hai Shalomce48b4a2018-09-05 11:41:35 -0700569 os_free(wpa_s->last_con_fail_realm);
570 wpa_s->last_con_fail_realm = NULL;
571 wpa_s->last_con_fail_realm_len = 0;
572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573 wpa_sm_set_eapol(wpa_s->wpa, NULL);
574 eapol_sm_deinit(wpa_s->eapol);
575 wpa_s->eapol = NULL;
576
577 rsn_preauth_deinit(wpa_s->wpa);
578
579#ifdef CONFIG_TDLS
580 wpa_tdls_deinit(wpa_s->wpa);
581#endif /* CONFIG_TDLS */
582
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800583 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700584 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800585 ptksa_cache_deinit(wpa_s->ptksa);
586 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587 wpa_sm_deinit(wpa_s->wpa);
588 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800589 wpa_bssid_ignore_clear(wpa_s);
590
591#ifdef CONFIG_PASN
592 wpas_pasn_auth_stop(wpa_s);
593#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700594
595 wpa_bss_deinit(wpa_s);
596
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700597 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598 wpa_supplicant_cancel_scan(wpa_s);
599 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800600 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
601#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
602 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
603 wpa_s, NULL);
604#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700605
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700606 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700607 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700608
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700609 wpas_wps_deinit(wpa_s);
610
611 wpabuf_free(wpa_s->pending_eapol_rx);
612 wpa_s->pending_eapol_rx = NULL;
613
614#ifdef CONFIG_IBSS_RSN
615 ibss_rsn_deinit(wpa_s->ibss_rsn);
616 wpa_s->ibss_rsn = NULL;
617#endif /* CONFIG_IBSS_RSN */
618
619 sme_deinit(wpa_s);
620
621#ifdef CONFIG_AP
622 wpa_supplicant_ap_deinit(wpa_s);
623#endif /* CONFIG_AP */
624
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700625 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700626
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800627#ifdef CONFIG_OFFCHANNEL
628 offchannel_deinit(wpa_s);
629#endif /* CONFIG_OFFCHANNEL */
630
631 wpa_supplicant_cancel_sched_scan(wpa_s);
632
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700633 os_free(wpa_s->next_scan_freqs);
634 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800635
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800636 os_free(wpa_s->manual_scan_freqs);
637 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700638 os_free(wpa_s->select_network_scan_freqs);
639 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800640
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700641 os_free(wpa_s->manual_sched_scan_freqs);
642 wpa_s->manual_sched_scan_freqs = NULL;
643
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800644 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
645
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700646 /*
647 * Need to remove any pending gas-query radio work before the
648 * gas_query_deinit() call because gas_query::work has not yet been set
649 * for works that have not been started. gas_query_free() will be unable
650 * to cancel such pending radio works and once the pending gas-query
651 * radio work eventually gets removed, the deinit notification call to
652 * gas_query_start_cb() would result in dereferencing freed memory.
653 */
654 if (wpa_s->radio)
655 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800656 gas_query_deinit(wpa_s->gas);
657 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700658 gas_server_deinit(wpa_s->gas_server);
659 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800660
661 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700662
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700663 ieee802_1x_dealloc_kay_sm(wpa_s);
664
Dmitry Shmidt04949592012-07-19 12:16:46 -0700665 os_free(wpa_s->bssid_filter);
666 wpa_s->bssid_filter = NULL;
667
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800668 os_free(wpa_s->disallow_aps_bssid);
669 wpa_s->disallow_aps_bssid = NULL;
670 os_free(wpa_s->disallow_aps_ssid);
671 wpa_s->disallow_aps_ssid = NULL;
672
Dmitry Shmidt04949592012-07-19 12:16:46 -0700673 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700674#ifdef CONFIG_WNM
675 wnm_deallocate_memory(wpa_s);
676#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700677
678 ext_password_deinit(wpa_s->ext_pw);
679 wpa_s->ext_pw = NULL;
680
681 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800682 wpa_s->last_gas_resp = NULL;
683 wpabuf_free(wpa_s->prev_gas_resp);
684 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700685
686 os_free(wpa_s->last_scan_res);
687 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800688
689#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700690 if (wpa_s->drv_priv)
691 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700692 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800693#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700694
695 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
696 wpabuf_free(wpa_s->vendor_elem[i]);
697 wpa_s->vendor_elem[i] = NULL;
698 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800699
700 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800701
702 wpa_s->sched_scan_plans_num = 0;
703 os_free(wpa_s->sched_scan_plans);
704 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800705
706#ifdef CONFIG_MBO
707 wpa_s->non_pref_chan_num = 0;
708 os_free(wpa_s->non_pref_chan);
709 wpa_s->non_pref_chan = NULL;
710#endif /* CONFIG_MBO */
711
712 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700713
714 wpabuf_free(wpa_s->lci);
715 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800716 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800717
718#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
719#ifdef CONFIG_MESH
720 {
721 struct external_pmksa_cache *entry;
722
723 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
724 struct external_pmksa_cache,
725 list)) != NULL) {
726 dl_list_del(&entry->list);
727 os_free(entry->pmksa_cache);
728 os_free(entry);
729 }
730 }
731#endif /* CONFIG_MESH */
732#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
733
734 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800735
736 wpabuf_free(wpa_s->ric_ies);
737 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700738
739#ifdef CONFIG_DPP
740 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700741 dpp_global_deinit(wpa_s->dpp);
742 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700743#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800744
745#ifdef CONFIG_PASN
746 wpas_pasn_auth_stop(wpa_s);
747#endif /* CONFIG_PASN */
Hai Shalomc1a21442022-02-04 13:43:00 -0800748 wpas_scs_deinit(wpa_s);
749 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700750}
751
752
753/**
754 * wpa_clear_keys - Clear keys configured for the driver
755 * @wpa_s: Pointer to wpa_supplicant data
756 * @addr: Previously used BSSID or %NULL if not available
757 *
758 * This function clears the encryption keys that has been previously configured
759 * for the driver.
760 */
761void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
762{
Hai Shalomc3565922019-10-28 11:58:20 -0700763 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700764
765 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800766 for (i = 0; i < max; i++) {
767 if (wpa_s->keys_cleared & BIT(i))
768 continue;
769 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700770 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800771 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700772 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
773 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800774 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700775 if (!(wpa_s->keys_cleared & BIT(0)))
776 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
777 0, NULL, 0, KEY_FLAG_PAIRWISE);
778 if (!(wpa_s->keys_cleared & BIT(15)))
779 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
780 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781 /* MLME-SETPROTECTION.request(None) */
782 wpa_drv_mlme_setprotection(
783 wpa_s, addr,
784 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
785 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
786 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800787 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700788}
789
790
791/**
792 * wpa_supplicant_state_txt - Get the connection state name as a text string
793 * @state: State (wpa_state; WPA_*)
794 * Returns: The state name as a printable text string
795 */
796const char * wpa_supplicant_state_txt(enum wpa_states state)
797{
798 switch (state) {
799 case WPA_DISCONNECTED:
800 return "DISCONNECTED";
801 case WPA_INACTIVE:
802 return "INACTIVE";
803 case WPA_INTERFACE_DISABLED:
804 return "INTERFACE_DISABLED";
805 case WPA_SCANNING:
806 return "SCANNING";
807 case WPA_AUTHENTICATING:
808 return "AUTHENTICATING";
809 case WPA_ASSOCIATING:
810 return "ASSOCIATING";
811 case WPA_ASSOCIATED:
812 return "ASSOCIATED";
813 case WPA_4WAY_HANDSHAKE:
814 return "4WAY_HANDSHAKE";
815 case WPA_GROUP_HANDSHAKE:
816 return "GROUP_HANDSHAKE";
817 case WPA_COMPLETED:
818 return "COMPLETED";
819 default:
820 return "UNKNOWN";
821 }
822}
823
824
825#ifdef CONFIG_BGSCAN
826
Hai Shalom899fcc72020-10-19 14:38:18 -0700827static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
828{
829 if (wpa_s->bgscan_ssid) {
830 bgscan_deinit(wpa_s);
831 wpa_s->bgscan_ssid = NULL;
832 }
833}
834
835
836/**
837 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
838 * @wpa_s: Pointer to the wpa_supplicant data
839 *
840 * Stop, start, or reconfigure the scan parameters depending on the method.
841 */
842void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700843{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800844 const char *name;
845
846 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
847 name = wpa_s->current_ssid->bgscan;
848 else
849 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700850 if (!name || name[0] == '\0') {
851 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800852 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700853 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800854 if (wpas_driver_bss_selection(wpa_s))
855 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800856#ifdef CONFIG_P2P
857 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
858 return;
859#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700860
861 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800862 if (wpa_s->current_ssid) {
863 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700864 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
865 "bgscan");
866 /*
867 * Live without bgscan; it is only used as a roaming
868 * optimization, so the initial connection is not
869 * affected.
870 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700871 } else {
872 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700873 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700874 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
875 0);
876 if (scan_res) {
877 bgscan_notify_scan(wpa_s, scan_res);
878 wpa_scan_results_free(scan_res);
879 }
880 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700881 } else
882 wpa_s->bgscan_ssid = NULL;
883}
884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885#endif /* CONFIG_BGSCAN */
886
887
Dmitry Shmidt04949592012-07-19 12:16:46 -0700888static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
889{
890 if (autoscan_init(wpa_s, 0))
891 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
892}
893
894
895static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
896{
897 autoscan_deinit(wpa_s);
898}
899
900
901void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
902{
903 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
904 wpa_s->wpa_state == WPA_SCANNING) {
905 autoscan_deinit(wpa_s);
906 wpa_supplicant_start_autoscan(wpa_s);
907 }
908}
909
910
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700911/**
912 * wpa_supplicant_set_state - Set current connection state
913 * @wpa_s: Pointer to wpa_supplicant data
914 * @state: The new connection state
915 *
916 * This function is called whenever the connection state changes, e.g.,
917 * association is completed for WPA/WPA2 4-Way Handshake is started.
918 */
919void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
920 enum wpa_states state)
921{
922 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700923#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700924 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700925#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700926
927 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
928 wpa_supplicant_state_txt(wpa_s->wpa_state),
929 wpa_supplicant_state_txt(state));
930
Hai Shalom74f70d42019-02-11 14:42:39 -0800931 if (state == WPA_COMPLETED &&
932 os_reltime_initialized(&wpa_s->roam_start)) {
933 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
934 wpa_s->roam_start.sec = 0;
935 wpa_s->roam_start.usec = 0;
936 wpas_notify_auth_changed(wpa_s);
937 wpas_notify_roam_time(wpa_s);
938 wpas_notify_roam_complete(wpa_s);
939 } else if (state == WPA_DISCONNECTED &&
940 os_reltime_initialized(&wpa_s->roam_start)) {
941 wpa_s->roam_start.sec = 0;
942 wpa_s->roam_start.usec = 0;
943 wpa_s->roam_time.sec = 0;
944 wpa_s->roam_time.usec = 0;
945 wpas_notify_roam_complete(wpa_s);
946 }
947
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800948 if (state == WPA_INTERFACE_DISABLED) {
949 /* Assure normal scan when interface is restored */
950 wpa_s->normal_scans = 0;
951 }
952
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700953 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800954 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700955 /* Reinitialize normal_scan counter */
956 wpa_s->normal_scans = 0;
957 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800958
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700959#ifdef CONFIG_P2P
960 /*
961 * P2PS client has to reply to Probe Request frames received on the
962 * group operating channel. Enable Probe Request frame reporting for
963 * P2P connected client in case p2p_cli_probe configuration property is
964 * set to 1.
965 */
966 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
967 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
968 wpa_s->current_ssid->p2p_group) {
969 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
970 wpa_dbg(wpa_s, MSG_DEBUG,
971 "P2P: Enable CLI Probe Request RX reporting");
972 wpa_s->p2p_cli_probe =
973 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
974 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
975 wpa_dbg(wpa_s, MSG_DEBUG,
976 "P2P: Disable CLI Probe Request RX reporting");
977 wpa_s->p2p_cli_probe = 0;
978 wpa_drv_probe_req_report(wpa_s, 0);
979 }
980 }
981#endif /* CONFIG_P2P */
982
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700983 if (state != WPA_SCANNING)
984 wpa_supplicant_notify_scanning(wpa_s, 0);
985
986 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700988 int fils_hlp_sent = 0;
989
990#ifdef CONFIG_SME
991 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
992 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
993 fils_hlp_sent = 1;
994#endif /* CONFIG_SME */
995 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
996 wpa_auth_alg_fils(wpa_s->auth_alg))
997 fils_hlp_sent = 1;
998
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700999#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001001 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001002 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001004 ssid && ssid->id_str ? ssid->id_str : "",
1005 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001007 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001008 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010 wpa_drv_set_operstate(wpa_s, 1);
1011#ifndef IEEE8021X_EAPOL
1012 wpa_drv_set_supp_port(wpa_s, 1);
1013#endif /* IEEE8021X_EAPOL */
1014 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001015 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001017
1018 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001019
1020#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1021 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001022 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001023#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001024#ifdef CONFIG_OWE
1025 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1026 wpas_update_owe_connect_params(wpa_s);
1027#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001028#ifdef CONFIG_HS20
1029 hs20_configure_frame_filters(wpa_s);
1030#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001031 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1032 state == WPA_ASSOCIATED) {
1033 wpa_s->new_connection = 1;
1034 wpa_drv_set_operstate(wpa_s, 0);
1035#ifndef IEEE8021X_EAPOL
1036 wpa_drv_set_supp_port(wpa_s, 0);
1037#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001038 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 }
1040 wpa_s->wpa_state = state;
1041
1042#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001043 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1044 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001045 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 wpa_supplicant_stop_bgscan(wpa_s);
1047#endif /* CONFIG_BGSCAN */
1048
Hai Shalom5f92bc92019-04-18 11:54:11 -07001049 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001050 wpa_supplicant_stop_autoscan(wpa_s);
1051
1052 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1053 wpa_supplicant_start_autoscan(wpa_s);
1054
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001055 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1056 wmm_ac_notify_disassoc(wpa_s);
1057
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 if (wpa_s->wpa_state != old_state) {
1059 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1060
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001061 /*
1062 * Notify the P2P Device interface about a state change in one
1063 * of the interfaces.
1064 */
1065 wpas_p2p_indicate_state_change(wpa_s);
1066
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001067 if (wpa_s->wpa_state == WPA_COMPLETED ||
1068 old_state == WPA_COMPLETED)
1069 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001070#ifdef CONFIG_DPP2
1071 if (wpa_s->wpa_state == WPA_COMPLETED)
1072 wpas_dpp_connected(wpa_s);
1073#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074 }
Hai Shalomc3565922019-10-28 11:58:20 -07001075#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1076 if (update_fils_connect_params)
1077 wpas_update_fils_connect_params(wpa_s);
1078#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001079}
1080
1081
1082void wpa_supplicant_terminate_proc(struct wpa_global *global)
1083{
1084 int pending = 0;
1085#ifdef CONFIG_WPS
1086 struct wpa_supplicant *wpa_s = global->ifaces;
1087 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001088 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001089 if (wpas_wps_terminate_pending(wpa_s) == 1)
1090 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001091#ifdef CONFIG_P2P
1092 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1093 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1094 wpas_p2p_disconnect(wpa_s);
1095#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001096 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001097 }
1098#endif /* CONFIG_WPS */
1099 if (pending)
1100 return;
1101 eloop_terminate();
1102}
1103
1104
1105static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1106{
1107 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108 wpa_supplicant_terminate_proc(global);
1109}
1110
1111
1112void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1113{
1114 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001115 enum wpa_states new_state;
1116
1117 if (old_state == WPA_SCANNING)
1118 new_state = WPA_SCANNING;
1119 else
1120 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121
1122 wpa_s->pairwise_cipher = 0;
1123 wpa_s->group_cipher = 0;
1124 wpa_s->mgmt_group_cipher = 0;
1125 wpa_s->key_mgmt = 0;
1126 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001127 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128
1129 if (wpa_s->wpa_state != old_state)
1130 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1131}
1132
1133
1134/**
1135 * wpa_supplicant_reload_configuration - Reload configuration data
1136 * @wpa_s: Pointer to wpa_supplicant data
1137 * Returns: 0 on success or -1 if configuration parsing failed
1138 *
1139 * This function can be used to request that the configuration data is reloaded
1140 * (e.g., after configuration file change). This function is reloading
1141 * configuration only for one interface, so this may need to be called multiple
1142 * times if %wpa_supplicant is controlling multiple interfaces and all
1143 * interfaces need reconfiguration.
1144 */
1145int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1146{
1147 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001148 int reconf_ctrl;
1149 int old_ap_scan;
1150
1151 if (wpa_s->confname == NULL)
1152 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001153 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001154 if (conf == NULL) {
1155 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1156 "file '%s' - exiting", wpa_s->confname);
1157 return -1;
1158 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001159 if (wpa_s->confanother &&
1160 !wpa_config_read(wpa_s->confanother, conf)) {
1161 wpa_msg(wpa_s, MSG_ERROR,
1162 "Failed to parse the configuration file '%s' - exiting",
1163 wpa_s->confanother);
1164 return -1;
1165 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001166
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001167 conf->changed_parameters = (unsigned int) -1;
1168
1169 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1170 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1171 os_strcmp(conf->ctrl_interface,
1172 wpa_s->conf->ctrl_interface) != 0);
1173
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001174 if (reconf_ctrl) {
1175 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001176 wpa_s->ctrl_iface = NULL;
1177 }
1178
1179 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001180 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001181 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1182 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001183 wpa_supplicant_deauthenticate(wpa_s,
1184 WLAN_REASON_DEAUTH_LEAVING);
1185 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001186
1187 /*
1188 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001189 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001191 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1192 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1193 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194 /*
1195 * Clear forced success to clear EAP state for next
1196 * authentication.
1197 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001198 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001199 }
1200 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1201 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001202 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001203 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1204 rsn_preauth_deinit(wpa_s->wpa);
1205
1206 old_ap_scan = wpa_s->conf->ap_scan;
1207 wpa_config_free(wpa_s->conf);
1208 wpa_s->conf = conf;
1209 if (old_ap_scan != wpa_s->conf->ap_scan)
1210 wpas_notify_ap_scan_changed(wpa_s);
1211
1212 if (reconf_ctrl)
1213 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1214
1215 wpa_supplicant_update_config(wpa_s);
1216
1217 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001218 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001219 wpa_s->reassociate = 1;
1220 wpa_supplicant_req_scan(wpa_s, 0, 0);
1221 }
Hai Shalom60840252021-02-19 19:02:11 -08001222 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001223 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1224 return 0;
1225}
1226
1227
1228static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1229{
1230 struct wpa_global *global = signal_ctx;
1231 struct wpa_supplicant *wpa_s;
1232 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1233 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1234 sig);
1235 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1236 wpa_supplicant_terminate_proc(global);
1237 }
1238 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001239
1240 if (wpa_debug_reopen_file() < 0) {
1241 /* Ignore errors since we cannot really do much to fix this */
1242 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1243 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001244}
1245
1246
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001247static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1248 struct wpa_ssid *ssid,
1249 struct wpa_ie_data *ie)
1250{
1251 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1252 if (ret) {
1253 if (ret == -2) {
1254 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1255 "from association info");
1256 }
1257 return -1;
1258 }
1259
1260 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1261 "cipher suites");
1262 if (!(ie->group_cipher & ssid->group_cipher)) {
1263 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1264 "cipher 0x%x (mask 0x%x) - reject",
1265 ie->group_cipher, ssid->group_cipher);
1266 return -1;
1267 }
1268 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1269 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1270 "cipher 0x%x (mask 0x%x) - reject",
1271 ie->pairwise_cipher, ssid->pairwise_cipher);
1272 return -1;
1273 }
1274 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1275 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1276 "management 0x%x (mask 0x%x) - reject",
1277 ie->key_mgmt, ssid->key_mgmt);
1278 return -1;
1279 }
1280
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001281 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001282 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001283 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1284 "that does not support management frame protection - "
1285 "reject");
1286 return -1;
1287 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288
1289 return 0;
1290}
1291
1292
Hai Shalom021b0b52019-04-10 11:17:58 -07001293static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1294 int freq)
1295{
1296 if (!ie->has_group)
1297 ie->group_cipher = wpa_default_rsn_cipher(freq);
1298 if (!ie->has_pairwise)
1299 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1300 return (ie->group_cipher & ssid->group_cipher) &&
1301 (ie->pairwise_cipher & ssid->pairwise_cipher);
1302}
1303
1304
Hai Shalomc1a21442022-02-04 13:43:00 -08001305void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1306 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1307{
1308 int sel;
1309
1310 sel = ie->mgmt_group_cipher;
1311 if (ssid->group_mgmt_cipher)
1312 sel &= ssid->group_mgmt_cipher;
1313 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1314 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1315 sel = 0;
1316 wpa_dbg(wpa_s, MSG_DEBUG,
1317 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1318 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1319 if (sel & WPA_CIPHER_AES_128_CMAC) {
1320 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1321 wpa_dbg(wpa_s, MSG_DEBUG,
1322 "WPA: using MGMT group cipher AES-128-CMAC");
1323 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1324 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1325 wpa_dbg(wpa_s, MSG_DEBUG,
1326 "WPA: using MGMT group cipher BIP-GMAC-128");
1327 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1328 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1329 wpa_dbg(wpa_s, MSG_DEBUG,
1330 "WPA: using MGMT group cipher BIP-GMAC-256");
1331 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1332 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1333 wpa_dbg(wpa_s, MSG_DEBUG,
1334 "WPA: using MGMT group cipher BIP-CMAC-256");
1335 } else {
1336 wpa_s->mgmt_group_cipher = 0;
1337 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1338 }
1339 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1340 wpa_s->mgmt_group_cipher);
1341 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1342 wpas_get_ssid_pmf(wpa_s, ssid));
1343}
1344
1345
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346/**
1347 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1348 * @wpa_s: Pointer to wpa_supplicant data
1349 * @bss: Scan results for the selected BSS, or %NULL if not available
1350 * @ssid: Configuration data for the selected network
1351 * @wpa_ie: Buffer for the WPA/RSN IE
1352 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1353 * used buffer length in case the functions returns success.
1354 * Returns: 0 on success or -1 on failure
1355 *
1356 * This function is used to configure authentication and encryption parameters
1357 * based on the network configuration and scan result for the selected BSS (if
1358 * available).
1359 */
1360int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1361 struct wpa_bss *bss, struct wpa_ssid *ssid,
1362 u8 *wpa_ie, size_t *wpa_ie_len)
1363{
1364 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001365 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001366 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001367
1368 if (bss) {
1369 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1370 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001371 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001372 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001373 } else {
1374 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1375 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001376
1377 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1378 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001379 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001380 (ie.key_mgmt & ssid->key_mgmt)) {
1381 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1382 proto = WPA_PROTO_RSN;
1383 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001384 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001385 (ie.group_cipher & ssid->group_cipher) &&
1386 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1387 (ie.key_mgmt & ssid->key_mgmt)) {
1388 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1389 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001390#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001391 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1392 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1393 (ie.group_cipher & ssid->group_cipher) &&
1394 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1395 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001396 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001397 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001398 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1399 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1400 (ie.group_cipher & ssid->group_cipher) &&
1401 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1402 (ie.key_mgmt & ssid->key_mgmt)) {
1403 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1404 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001405#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001406 } else if (bss) {
1407 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001408 wpa_dbg(wpa_s, MSG_DEBUG,
1409 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1410 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1411 ssid->key_mgmt);
1412 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1413 MAC2STR(bss->bssid),
1414 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1415 bss_wpa ? " WPA" : "",
1416 bss_rsn ? " RSN" : "",
1417 bss_osen ? " OSEN" : "");
1418 if (bss_rsn) {
1419 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1420 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1421 wpa_dbg(wpa_s, MSG_DEBUG,
1422 "Could not parse RSN element");
1423 } else {
1424 wpa_dbg(wpa_s, MSG_DEBUG,
1425 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1426 ie.pairwise_cipher, ie.group_cipher,
1427 ie.key_mgmt);
1428 }
1429 }
1430 if (bss_wpa) {
1431 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1432 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1433 wpa_dbg(wpa_s, MSG_DEBUG,
1434 "Could not parse WPA element");
1435 } else {
1436 wpa_dbg(wpa_s, MSG_DEBUG,
1437 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1438 ie.pairwise_cipher, ie.group_cipher,
1439 ie.key_mgmt);
1440 }
1441 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442 return -1;
1443 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001444 if (ssid->proto & WPA_PROTO_OSEN)
1445 proto = WPA_PROTO_OSEN;
1446 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001447 proto = WPA_PROTO_RSN;
1448 else
1449 proto = WPA_PROTO_WPA;
1450 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1451 os_memset(&ie, 0, sizeof(ie));
1452 ie.group_cipher = ssid->group_cipher;
1453 ie.pairwise_cipher = ssid->pairwise_cipher;
1454 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001455 ie.mgmt_group_cipher = 0;
1456 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1457 if (ssid->group_mgmt_cipher &
1458 WPA_CIPHER_BIP_GMAC_256)
1459 ie.mgmt_group_cipher =
1460 WPA_CIPHER_BIP_GMAC_256;
1461 else if (ssid->group_mgmt_cipher &
1462 WPA_CIPHER_BIP_CMAC_256)
1463 ie.mgmt_group_cipher =
1464 WPA_CIPHER_BIP_CMAC_256;
1465 else if (ssid->group_mgmt_cipher &
1466 WPA_CIPHER_BIP_GMAC_128)
1467 ie.mgmt_group_cipher =
1468 WPA_CIPHER_BIP_GMAC_128;
1469 else
1470 ie.mgmt_group_cipher =
1471 WPA_CIPHER_AES_128_CMAC;
1472 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001473#ifdef CONFIG_OWE
1474 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1475 !ssid->owe_only &&
1476 !bss_wpa && !bss_rsn && !bss_osen) {
1477 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1478 wpa_s->wpa_proto = 0;
1479 *wpa_ie_len = 0;
1480 return 0;
1481 }
1482#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001483 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1484 "based on configuration");
1485 } else
1486 proto = ie.proto;
1487 }
1488
1489 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1490 "pairwise %d key_mgmt %d proto %d",
1491 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001492 if (ssid->ieee80211w) {
1493 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1494 ie.mgmt_group_cipher);
1495 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001496
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001497 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001498 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1499 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001500 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001501
1502 if (bss || !wpa_s->ap_ies_from_associnfo) {
1503 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1504 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1505 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001506 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1507 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1508 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001509 return -1;
1510 }
1511
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001512#ifdef CONFIG_NO_WPA
1513 wpa_s->group_cipher = WPA_CIPHER_NONE;
1514 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1515#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001516 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001517 wpa_dbg(wpa_s, MSG_DEBUG,
1518 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1519 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001520 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1521 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001522 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1523 "cipher");
1524 return -1;
1525 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001526 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1527 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001528
1529 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001530 wpa_dbg(wpa_s, MSG_DEBUG,
1531 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1532 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001533 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1534 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001535 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1536 "cipher");
1537 return -1;
1538 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001539 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1540 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001541#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001542
1543 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001544#ifdef CONFIG_SAE
1545 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1546 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1547#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001548#ifdef CONFIG_IEEE80211R
1549 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1550 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1551 sel &= ~WPA_KEY_MGMT_FT;
1552#endif /* CONFIG_IEEE80211R */
1553 wpa_dbg(wpa_s, MSG_DEBUG,
1554 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1555 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001556 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001557#ifdef CONFIG_IEEE80211R
1558#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001559 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1560 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001561 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1562 wpa_dbg(wpa_s, MSG_DEBUG,
1563 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001564 if (!ssid->ft_eap_pmksa_caching &&
1565 pmksa_cache_get_current(wpa_s->wpa)) {
1566 /* PMKSA caching with FT may have interoperability
1567 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001568 wpa_dbg(wpa_s, MSG_DEBUG,
1569 "WPA: Disable PMKSA caching for FT/802.1X connection");
1570 pmksa_cache_clear_current(wpa_s->wpa);
1571 }
1572#endif /* CONFIG_SHA384 */
1573#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001574#ifdef CONFIG_SUITEB192
1575 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1576 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1577 wpa_dbg(wpa_s, MSG_DEBUG,
1578 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1579#endif /* CONFIG_SUITEB192 */
1580#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001581 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1582 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1583 wpa_dbg(wpa_s, MSG_DEBUG,
1584 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001585#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001586#ifdef CONFIG_FILS
1587#ifdef CONFIG_IEEE80211R
1588 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1589 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1590 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1591 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1592 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1593 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1594#endif /* CONFIG_IEEE80211R */
1595 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1596 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1597 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1598 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1599 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1600 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1601#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001602#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001603 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1604 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1606 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001607 if (!ssid->ft_eap_pmksa_caching &&
1608 pmksa_cache_get_current(wpa_s->wpa)) {
1609 /* PMKSA caching with FT may have interoperability
1610 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001611 wpa_dbg(wpa_s, MSG_DEBUG,
1612 "WPA: Disable PMKSA caching for FT/802.1X connection");
1613 pmksa_cache_clear_current(wpa_s->wpa);
1614 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001615#endif /* CONFIG_IEEE80211R */
1616#ifdef CONFIG_DPP
1617 } else if (sel & WPA_KEY_MGMT_DPP) {
1618 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1619 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1620#endif /* CONFIG_DPP */
1621#ifdef CONFIG_SAE
1622 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1623 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1624 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1625 } else if (sel & WPA_KEY_MGMT_SAE) {
1626 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1627 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1628#endif /* CONFIG_SAE */
1629#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001630 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1631 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1632 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1633#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001634 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1635 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1636 wpa_dbg(wpa_s, MSG_DEBUG,
1637 "WPA: using KEY_MGMT 802.1X with SHA256");
1638 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1639 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1640 wpa_dbg(wpa_s, MSG_DEBUG,
1641 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001642 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1643 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1644 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1645 } else if (sel & WPA_KEY_MGMT_PSK) {
1646 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1647 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1648 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1649 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1650 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001651#ifdef CONFIG_HS20
1652 } else if (sel & WPA_KEY_MGMT_OSEN) {
1653 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1654 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1655#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001656#ifdef CONFIG_OWE
1657 } else if (sel & WPA_KEY_MGMT_OWE) {
1658 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1659 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1660#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661 } else {
1662 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1663 "authenticated key management type");
1664 return -1;
1665 }
1666
1667 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1668 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1669 wpa_s->pairwise_cipher);
1670 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1671
Hai Shalomc3565922019-10-28 11:58:20 -07001672 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1673 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1674 wpa_msg(wpa_s, MSG_INFO,
1675 "RSN: Management frame protection required but the selected AP does not enable it");
1676 return -1;
1677 }
1678
Hai Shalomc1a21442022-02-04 13:43:00 -08001679 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001680#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001681 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1682 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1683 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001684#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001685 sae_pwe = wpa_s->conf->sae_pwe;
1686 if (ssid->sae_password_id && sae_pwe != 3)
1687 sae_pwe = 1;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001688 if (bss && is_6ghz_freq(bss->freq)) {
1689 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hash-to-element mode for 6GHz BSS.");
1690 sae_pwe = 1;
1691 }
1692#ifdef CONFIG_TESTING_OPTIONS
1693 if (wpa_s->force_hunting_and_pecking_pwe) {
1694 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hunting and pecking mode.");
1695 sae_pwe = 0;
1696 }
1697#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001698 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001699#ifdef CONFIG_SAE_PK
1700 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1701 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1702 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1703 ((ssid->sae_password &&
1704 sae_pk_valid_password(ssid->sae_password)) ||
1705 (!ssid->sae_password && ssid->passphrase &&
1706 sae_pk_valid_password(ssid->passphrase))));
1707#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001708#ifdef CONFIG_TESTING_OPTIONS
1709 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1710 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001711 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1712 wpa_s->oci_freq_override_eapol);
1713 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1714 wpa_s->oci_freq_override_eapol_g2);
1715 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1716 wpa_s->oci_freq_override_ft_assoc);
1717 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1718 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001719 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1720 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001721#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001722
1723 /* Extended Key ID is only supported in infrastructure BSS so far */
1724 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1725 (ssid->proto & WPA_PROTO_RSN) &&
1726 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1727 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1728 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1729 int use_ext_key_id = 0;
1730
1731 wpa_msg(wpa_s, MSG_DEBUG,
1732 "WPA: Enable Extended Key ID support");
1733 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1734 wpa_s->conf->extended_key_id);
1735 if (bss_rsn &&
1736 wpa_s->conf->extended_key_id &&
1737 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1738 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1739 use_ext_key_id = 1;
1740 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1741 use_ext_key_id);
1742 } else {
1743 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1744 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1745 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746
1747 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1748 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1749 return -1;
1750 }
1751
Hai Shalomc3565922019-10-28 11:58:20 -07001752 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1753 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1754 &wpa_s->rsnxe_len)) {
1755 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1756 return -1;
1757 }
1758
Hai Shalom021b0b52019-04-10 11:17:58 -07001759 if (0) {
1760#ifdef CONFIG_DPP
1761 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1762 /* Use PMK from DPP network introduction (PMKSA entry) */
1763 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001764#ifdef CONFIG_DPP2
1765 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1766#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001767#endif /* CONFIG_DPP */
1768 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001769 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001770 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001771
Roshan Pius3a1667e2018-07-03 15:17:14 -07001772 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1773 WPA_KEY_MGMT_FT_PSK |
1774 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1775
1776 if (ssid->psk_set && !sae_only) {
1777 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1778 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001779 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1780 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001781 psk_set = 1;
1782 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001783
Roshan Pius3a1667e2018-07-03 15:17:14 -07001784 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1785 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001786 psk_set = 1;
1787
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001788#ifndef CONFIG_NO_PBKDF2
1789 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001790 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001791 u8 psk[PMK_LEN];
Sunil Ravia04bd252022-05-02 22:54:18 -07001792
1793 if (pbkdf2_sha1(ssid->passphrase, bss->ssid,
1794 bss->ssid_len,
1795 4096, psk, PMK_LEN) != 0) {
1796 wpa_msg(wpa_s, MSG_WARNING,
1797 "Error in pbkdf2_sha1()");
1798 return -1;
1799 }
1800 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001801 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001802 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001803 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001804 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001805 }
1806#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001807#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001808 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001809 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1810 ssid->ext_psk);
1811 char pw_str[64 + 1];
1812 u8 psk[PMK_LEN];
1813
1814 if (pw == NULL) {
1815 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1816 "found from external storage");
1817 return -1;
1818 }
1819
1820 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1821 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1822 "PSK length %d in external storage",
1823 (int) wpabuf_len(pw));
1824 ext_password_free(pw);
1825 return -1;
1826 }
1827
1828 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1829 pw_str[wpabuf_len(pw)] = '\0';
1830
1831#ifndef CONFIG_NO_PBKDF2
1832 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1833 {
Sunil Ravia04bd252022-05-02 22:54:18 -07001834 if (pbkdf2_sha1(pw_str, bss->ssid,
1835 bss->ssid_len,
1836 4096, psk, PMK_LEN) != 0) {
1837 wpa_msg(wpa_s, MSG_WARNING,
1838 "Error in pbkdf2_sha1()");
1839 ext_password_free(pw);
1840 return -1;
1841 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001842 os_memset(pw_str, 0, sizeof(pw_str));
1843 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1844 "external passphrase)",
1845 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001846 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1847 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001848 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001849 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001850 } else
1851#endif /* CONFIG_NO_PBKDF2 */
1852 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1853 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1854 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1855 "Invalid PSK hex string");
1856 os_memset(pw_str, 0, sizeof(pw_str));
1857 ext_password_free(pw);
1858 return -1;
1859 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001860 wpa_hexdump_key(MSG_MSGDUMP,
1861 "PSK (from external PSK)",
1862 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001863 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1864 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001865 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001866 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001867 } else {
1868 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1869 "PSK available");
1870 os_memset(pw_str, 0, sizeof(pw_str));
1871 ext_password_free(pw);
1872 return -1;
1873 }
1874
1875 os_memset(pw_str, 0, sizeof(pw_str));
1876 ext_password_free(pw);
1877 }
1878#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001879
1880 if (!psk_set) {
1881 wpa_msg(wpa_s, MSG_INFO,
1882 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001883 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001884 return -1;
1885 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001886#ifdef CONFIG_OWE
1887 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1888 /* OWE Diffie-Hellman exchange in (Re)Association
1889 * Request/Response frames set the PMK, so do not override it
1890 * here. */
1891#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001892 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1894
Hai Shalomfdcde762020-04-02 11:19:20 -07001895 if (ssid->mode != WPAS_MODE_IBSS &&
1896 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1897 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1898 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1899 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1900 wpa_msg(wpa_s, MSG_INFO,
1901 "Disable PTK0 rekey support - replaced with reconnect");
1902 wpa_s->deny_ptk0_rekey = 1;
1903 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1904 } else {
1905 wpa_s->deny_ptk0_rekey = 0;
1906 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1907 }
1908
Vinayak Yadawad14709082022-03-17 14:25:11 +05301909#ifdef CONFIG_DRIVER_NL80211_BRCM
1910 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09001911 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
1912 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
1913 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05301914 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
1915 wpa_dbg(wpa_s, MSG_INFO,
1916 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
1917 }
1918#endif /* CONFIG_DRIVER_NL80211_BRCM */
1919
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001920 return 0;
1921}
1922
1923
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001924static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1925{
Hai Shalomc1a21442022-02-04 13:43:00 -08001926 bool scs = true, mscs = true;
1927
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001928 *pos = 0x00;
1929
1930 switch (idx) {
1931 case 0: /* Bits 0-7 */
1932 break;
1933 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001934 if (wpa_s->conf->coloc_intf_reporting) {
1935 /* Bit 13 - Collocated Interference Reporting */
1936 *pos |= 0x20;
1937 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001938 break;
1939 case 2: /* Bits 16-23 */
1940#ifdef CONFIG_WNM
1941 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001942 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001943 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001944#endif /* CONFIG_WNM */
1945 break;
1946 case 3: /* Bits 24-31 */
1947#ifdef CONFIG_WNM
1948 *pos |= 0x02; /* Bit 25 - SSID List */
1949#endif /* CONFIG_WNM */
1950#ifdef CONFIG_INTERWORKING
1951 if (wpa_s->conf->interworking)
1952 *pos |= 0x80; /* Bit 31 - Interworking */
1953#endif /* CONFIG_INTERWORKING */
1954 break;
1955 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001956#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001957 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001958 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001959#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001960 break;
1961 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001962#ifdef CONFIG_HS20
1963 if (wpa_s->conf->hs20)
1964 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1965#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001966#ifdef CONFIG_MBO
1967 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1968#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001969 break;
1970 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001971#ifdef CONFIG_TESTING_OPTIONS
1972 if (wpa_s->disable_scs_support)
1973 scs = false;
1974#endif /* CONFIG_TESTING_OPTIONS */
1975 if (scs)
1976 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001977 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001978 case 7: /* Bits 56-63 */
1979 break;
1980 case 8: /* Bits 64-71 */
1981 if (wpa_s->conf->ftm_responder)
1982 *pos |= 0x40; /* Bit 70 - FTM responder */
1983 if (wpa_s->conf->ftm_initiator)
1984 *pos |= 0x80; /* Bit 71 - FTM initiator */
1985 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001986 case 9: /* Bits 72-79 */
1987#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001988 if (!wpa_s->disable_fils)
1989 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001990#endif /* CONFIG_FILS */
1991 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001992 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001993#ifdef CONFIG_TESTING_OPTIONS
1994 if (wpa_s->disable_mscs_support)
1995 mscs = false;
1996#endif /* CONFIG_TESTING_OPTIONS */
1997 if (mscs)
1998 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07001999 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002000 }
2001}
2002
2003
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002004int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002005{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002006 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002007 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002008
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002009 if (len < wpa_s->extended_capa_len)
2010 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002011 if (buflen < (size_t) len + 2) {
2012 wpa_printf(MSG_INFO,
2013 "Not enough room for building extended capabilities element");
2014 return -1;
2015 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002016
2017 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002018 *pos++ = len;
2019 for (i = 0; i < len; i++, pos++) {
2020 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002021
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002022 if (i < wpa_s->extended_capa_len) {
2023 *pos &= ~wpa_s->extended_capa_mask[i];
2024 *pos |= wpa_s->extended_capa[i];
2025 }
2026 }
2027
2028 while (len > 0 && buf[1 + len] == 0) {
2029 len--;
2030 buf[1] = len;
2031 }
2032 if (len == 0)
2033 return 0;
2034
2035 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002036}
2037
2038
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002039static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2040 struct wpa_bss *test_bss)
2041{
2042 struct wpa_bss *bss;
2043
2044 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2045 if (bss == test_bss)
2046 return 1;
2047 }
2048
2049 return 0;
2050}
2051
2052
2053static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2054 struct wpa_ssid *test_ssid)
2055{
2056 struct wpa_ssid *ssid;
2057
2058 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2059 if (ssid == test_ssid)
2060 return 1;
2061 }
2062
2063 return 0;
2064}
2065
2066
2067int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2068 struct wpa_ssid *test_ssid)
2069{
2070 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2071 return 0;
2072
2073 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2074}
2075
2076
2077void wpas_connect_work_free(struct wpa_connect_work *cwork)
2078{
2079 if (cwork == NULL)
2080 return;
2081 os_free(cwork);
2082}
2083
2084
2085void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2086{
2087 struct wpa_connect_work *cwork;
2088 struct wpa_radio_work *work = wpa_s->connect_work;
2089
2090 if (!work)
2091 return;
2092
2093 wpa_s->connect_work = NULL;
2094 cwork = work->ctx;
2095 work->ctx = NULL;
2096 wpas_connect_work_free(cwork);
2097 radio_work_done(work);
2098}
2099
2100
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002101int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2102{
2103 struct os_reltime now;
2104 u8 addr[ETH_ALEN];
2105
2106 os_get_reltime(&now);
2107 if (wpa_s->last_mac_addr_style == style &&
2108 wpa_s->last_mac_addr_change.sec != 0 &&
2109 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2110 wpa_s->conf->rand_addr_lifetime)) {
2111 wpa_msg(wpa_s, MSG_DEBUG,
2112 "Previously selected random MAC address has not yet expired");
2113 return 0;
2114 }
2115
2116 switch (style) {
2117 case 1:
2118 if (random_mac_addr(addr) < 0)
2119 return -1;
2120 break;
2121 case 2:
2122 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2123 if (random_mac_addr_keep_oui(addr) < 0)
2124 return -1;
2125 break;
2126 default:
2127 return -1;
2128 }
2129
2130 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2131 wpa_msg(wpa_s, MSG_INFO,
2132 "Failed to set random MAC address");
2133 return -1;
2134 }
2135
2136 os_get_reltime(&wpa_s->last_mac_addr_change);
2137 wpa_s->mac_addr_changed = 1;
2138 wpa_s->last_mac_addr_style = style;
2139
2140 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2141 wpa_msg(wpa_s, MSG_INFO,
2142 "Could not update MAC address information");
2143 return -1;
2144 }
2145
2146 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2147 MAC2STR(addr));
2148
2149 return 0;
2150}
2151
2152
2153int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2154{
2155 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2156 !wpa_s->conf->preassoc_mac_addr)
2157 return 0;
2158
2159 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2160}
2161
2162
Hai Shalomc3565922019-10-28 11:58:20 -07002163static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2164{
2165#ifdef CONFIG_SAE
2166 int *groups = conf->sae_groups;
2167 int default_groups[] = { 19, 20, 21, 0 };
2168 const char *password;
2169
2170 if (!groups || groups[0] <= 0)
2171 groups = default_groups;
2172
2173 password = ssid->sae_password;
2174 if (!password)
2175 password = ssid->passphrase;
2176
Hai Shalom899fcc72020-10-19 14:38:18 -07002177 if (!password ||
2178 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2179 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002180 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002181 /* PT derivation not needed */
2182 sae_deinit_pt(ssid->pt);
2183 ssid->pt = NULL;
2184 return;
2185 }
2186
2187 if (ssid->pt)
2188 return; /* PT already derived */
2189 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2190 (const u8 *) password, os_strlen(password),
2191 ssid->sae_password_id);
2192#endif /* CONFIG_SAE */
2193}
2194
2195
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002196static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2197{
2198#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2199 os_free(wpa_s->sme.sae_rejected_groups);
2200 wpa_s->sme.sae_rejected_groups = NULL;
2201#ifdef CONFIG_TESTING_OPTIONS
2202 if (wpa_s->extra_sae_rejected_groups) {
2203 int i, *groups = wpa_s->extra_sae_rejected_groups;
2204
2205 for (i = 0; groups[i]; i++) {
2206 wpa_printf(MSG_DEBUG,
2207 "TESTING: Indicate rejection of an extra SAE group %d",
2208 groups[i]);
2209 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2210 groups[i]);
2211 }
2212 }
2213#endif /* CONFIG_TESTING_OPTIONS */
2214#endif /* CONFIG_SAE && CONFIG_SME */
2215}
2216
2217
Hai Shalom60840252021-02-19 19:02:11 -08002218int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2219{
2220 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2221 wpa_msg(wpa_s, MSG_INFO,
2222 "Could not restore permanent MAC address");
2223 return -1;
2224 }
2225 wpa_s->mac_addr_changed = 0;
2226 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2227 wpa_msg(wpa_s, MSG_INFO,
2228 "Could not update MAC address information");
2229 return -1;
2230 }
2231 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2232 return 0;
2233}
2234
2235
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002236static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2237
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002238/**
2239 * wpa_supplicant_associate - Request association
2240 * @wpa_s: Pointer to wpa_supplicant data
2241 * @bss: Scan results for the selected BSS, or %NULL if not available
2242 * @ssid: Configuration data for the selected network
2243 *
2244 * This function is used to request %wpa_supplicant to associate with a BSS.
2245 */
2246void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2247 struct wpa_bss *bss, struct wpa_ssid *ssid)
2248{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002249 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002250 int rand_style;
2251
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002252 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002253 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002254
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002255 /*
2256 * If we are starting a new connection, any previously pending EAPOL
2257 * RX cannot be valid anymore.
2258 */
2259 wpabuf_free(wpa_s->pending_eapol_rx);
2260 wpa_s->pending_eapol_rx = NULL;
2261
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002262 if (ssid->mac_addr == -1)
2263 rand_style = wpa_s->conf->mac_addr;
2264 else
2265 rand_style = ssid->mac_addr;
2266
Sunil Ravia04bd252022-05-02 22:54:18 -07002267 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002268 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002269 wmm_ac_clear_saved_tspecs(wpa_s);
2270 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002271 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002272#ifdef CONFIG_TESTING_OPTIONS
2273 wpa_s->testing_resend_assoc = 0;
2274#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002275
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002276 if (wpa_s->last_ssid == ssid) {
2277 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002278 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002279 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2280 wmm_ac_save_tspecs(wpa_s);
2281 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002282 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2283 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002284 }
Hai Shalomc3565922019-10-28 11:58:20 -07002285 } else {
2286#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002287 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002288#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002289 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002290#ifdef CONFIG_SAE
2291 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2292#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002293
2294 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002295 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2296 return;
2297 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002298 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002299 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002300 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002301 }
2302 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002303
2304#ifdef CONFIG_IBSS_RSN
2305 ibss_rsn_deinit(wpa_s->ibss_rsn);
2306 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002307#else /* CONFIG_IBSS_RSN */
2308 if (ssid->mode == WPAS_MODE_IBSS &&
2309 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2310 wpa_msg(wpa_s, MSG_INFO,
2311 "IBSS RSN not supported in the build");
2312 return;
2313 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314#endif /* CONFIG_IBSS_RSN */
2315
2316 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2317 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2318#ifdef CONFIG_AP
2319 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2320 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2321 "mode");
2322 return;
2323 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002324 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2325 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002326 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2327 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002328 return;
2329 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002330 wpa_s->current_bss = bss;
2331#else /* CONFIG_AP */
2332 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2333 "the build");
2334#endif /* CONFIG_AP */
2335 return;
2336 }
2337
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002338 if (ssid->mode == WPAS_MODE_MESH) {
2339#ifdef CONFIG_MESH
2340 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2341 wpa_msg(wpa_s, MSG_INFO,
2342 "Driver does not support mesh mode");
2343 return;
2344 }
2345 if (bss)
2346 ssid->frequency = bss->freq;
2347 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2348 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2349 return;
2350 }
2351 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002352#else /* CONFIG_MESH */
2353 wpa_msg(wpa_s, MSG_ERROR,
2354 "mesh mode support not included in the build");
2355#endif /* CONFIG_MESH */
2356 return;
2357 }
2358
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002359 /*
2360 * Set WPA state machine configuration to match the selected network now
2361 * so that the information is available before wpas_start_assoc_cb()
2362 * gets called. This is needed at least for RSN pre-authentication where
2363 * candidate APs are added to a list based on scan result processing
2364 * before completion of the first association.
2365 */
2366 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2367
2368#ifdef CONFIG_DPP
2369 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2370 return;
2371#endif /* CONFIG_DPP */
2372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373#ifdef CONFIG_TDLS
2374 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002375 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376#endif /* CONFIG_TDLS */
2377
Hai Shalomc3565922019-10-28 11:58:20 -07002378#ifdef CONFIG_MBO
2379 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2380#endif /* CONFIG_MBO */
2381
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002382 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002383 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384 sme_authenticate(wpa_s, bss, ssid);
2385 return;
2386 }
2387
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002388 if (wpa_s->connect_work) {
2389 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2390 return;
2391 }
2392
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002393 if (radio_work_pending(wpa_s, "connect")) {
2394 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2395 return;
2396 }
2397
Dmitry Shmidt29333592017-01-09 12:27:11 -08002398#ifdef CONFIG_SME
2399 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2400 /* Clear possibly set auth_alg, if any, from last attempt. */
2401 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2402 }
2403#endif /* CONFIG_SME */
2404
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002405 wpas_abort_ongoing_scan(wpa_s);
2406
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002407 cwork = os_zalloc(sizeof(*cwork));
2408 if (cwork == NULL)
2409 return;
2410
2411 cwork->bss = bss;
2412 cwork->ssid = ssid;
2413
2414 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2415 wpas_start_assoc_cb, cwork) < 0) {
2416 os_free(cwork);
2417 }
2418}
2419
2420
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002421static int bss_is_ibss(struct wpa_bss *bss)
2422{
2423 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2424 IEEE80211_CAP_IBSS;
2425}
2426
2427
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002428static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2429 const struct wpa_ssid *ssid)
2430{
2431 enum hostapd_hw_mode hw_mode;
2432 struct hostapd_hw_modes *mode = NULL;
2433 u8 channel;
2434 int i;
2435
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002436 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2437 if (hw_mode == NUM_HOSTAPD_MODES)
2438 return 0;
2439 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2440 if (wpa_s->hw.modes[i].mode == hw_mode) {
2441 mode = &wpa_s->hw.modes[i];
2442 break;
2443 }
2444 }
2445
2446 if (!mode)
2447 return 0;
2448
2449 return mode->vht_capab != 0;
2450}
2451
2452
Hai Shalomc1a21442022-02-04 13:43:00 -08002453static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2454{
2455 int i;
2456
2457 for (i = channel; i < channel + 16; i += 4) {
2458 struct hostapd_channel_data *chan;
2459
2460 chan = hw_get_channel_chan(mode, i, NULL);
2461 if (!chan ||
2462 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2463 return false;
2464 }
2465
2466 return true;
2467}
2468
2469
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002470void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2471 const struct wpa_ssid *ssid,
2472 struct hostapd_freq_params *freq)
2473{
Hai Shalom81f62d82019-07-22 12:10:00 -07002474 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002475 enum hostapd_hw_mode hw_mode;
2476 struct hostapd_hw_modes *mode = NULL;
2477 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2478 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002479 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2480 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2481 6595, 6675, 6755, 6835, 6915, 6995 };
2482 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002483 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2484 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002485 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002486 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002487 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002488 int chwidth, seg0, seg1;
2489 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002490 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002491
2492 freq->freq = ssid->frequency;
2493
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002494 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2495 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2496
2497 if (ssid->mode != WPAS_MODE_IBSS)
2498 break;
2499
2500 /* Don't adjust control freq in case of fixed_freq */
2501 if (ssid->fixed_freq)
2502 break;
2503
2504 if (!bss_is_ibss(bss))
2505 continue;
2506
2507 if (ssid->ssid_len == bss->ssid_len &&
2508 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2509 wpa_printf(MSG_DEBUG,
2510 "IBSS already found in scan results, adjust control freq: %d",
2511 bss->freq);
2512 freq->freq = bss->freq;
2513 obss_scan = 0;
2514 break;
2515 }
2516 }
2517
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002518 /* For IBSS check HT_IBSS flag */
2519 if (ssid->mode == WPAS_MODE_IBSS &&
2520 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2521 return;
2522
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002523 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2524 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2525 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2526 wpa_printf(MSG_DEBUG,
2527 "IBSS: WEP/TKIP detected, do not try to enable HT");
2528 return;
2529 }
2530
2531 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002532 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2533 if (wpa_s->hw.modes[i].mode == hw_mode) {
2534 mode = &wpa_s->hw.modes[i];
2535 break;
2536 }
2537 }
2538
2539 if (!mode)
2540 return;
2541
Hai Shalom60840252021-02-19 19:02:11 -08002542 freq->channel = channel;
2543
Hai Shalomc3565922019-10-28 11:58:20 -07002544 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2545 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002546
Hai Shalomc1a21442022-02-04 13:43:00 -08002547 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2548 * However, HE is mandatory for 6 GHz.
2549 */
2550 is_6ghz = is_6ghz_freq(freq->freq);
2551 if (is_6ghz)
2552 goto skip_to_6ghz;
2553
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002554#ifdef CONFIG_HT_OVERRIDES
2555 if (ssid->disable_ht) {
2556 freq->ht_enabled = 0;
2557 return;
2558 }
2559#endif /* CONFIG_HT_OVERRIDES */
2560
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002561 freq->ht_enabled = ht_supported(mode);
2562 if (!freq->ht_enabled)
2563 return;
2564
Hai Shalomc3565922019-10-28 11:58:20 -07002565 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2566 if (is_24ghz)
2567 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002568#ifdef CONFIG_HE_OVERRIDES
2569 if (is_24ghz && ssid->disable_he)
2570 freq->he_enabled = 0;
2571#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002572
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002573 /* Setup higher BW only for 5 GHz */
2574 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2575 return;
2576
2577 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2578 pri_chan = &mode->channels[chan_idx];
2579 if (pri_chan->chan == channel)
2580 break;
2581 pri_chan = NULL;
2582 }
2583 if (!pri_chan)
2584 return;
2585
2586 /* Check primary channel flags */
2587 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2588 return;
2589
Hai Shalom74f70d42019-02-11 14:42:39 -08002590 freq->channel = pri_chan->chan;
2591
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002592#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002593 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002594#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002595 if (ssid->disable_vht)
2596 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002597#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002598 goto skip_ht40;
2599 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002600#endif /* CONFIG_HT_OVERRIDES */
2601
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002602 /* Check/setup HT40+/HT40- */
2603 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2604 if (ht40plus[j] == channel) {
2605 ht40 = 1;
2606 break;
2607 }
2608 }
2609
2610 /* Find secondary channel */
2611 for (i = 0; i < mode->num_channels; i++) {
2612 sec_chan = &mode->channels[i];
2613 if (sec_chan->chan == channel + ht40 * 4)
2614 break;
2615 sec_chan = NULL;
2616 }
2617 if (!sec_chan)
2618 return;
2619
2620 /* Check secondary channel flags */
2621 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2622 return;
2623
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002624 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002625 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2626 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002627 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002628 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2629 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002630 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002631 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002632
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002633 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002634 struct wpa_scan_results *scan_res;
2635
2636 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2637 if (scan_res == NULL) {
2638 /* Back to HT20 */
2639 freq->sec_channel_offset = 0;
2640 return;
2641 }
2642
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002643 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002644 switch (res) {
2645 case 0:
2646 /* Back to HT20 */
2647 freq->sec_channel_offset = 0;
2648 break;
2649 case 1:
2650 /* Configuration allowed */
2651 break;
2652 case 2:
2653 /* Switch pri/sec channels */
2654 freq->freq = hw_get_freq(mode, sec_chan->chan);
2655 freq->sec_channel_offset = -freq->sec_channel_offset;
2656 freq->channel = sec_chan->chan;
2657 break;
2658 default:
2659 freq->sec_channel_offset = 0;
2660 break;
2661 }
2662
2663 wpa_scan_results_free(scan_res);
2664 }
2665
Hai Shalom74f70d42019-02-11 14:42:39 -08002666#ifdef CONFIG_HT_OVERRIDES
2667skip_ht40:
2668#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002669 wpa_printf(MSG_DEBUG,
2670 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2671 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002672
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002673 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002674 return;
2675
2676 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002677 if (ssid->mode == WPAS_MODE_IBSS &&
2678 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002679 return;
2680
Paul Stewart092955c2017-02-06 09:13:09 -08002681#ifdef CONFIG_VHT_OVERRIDES
2682 if (ssid->disable_vht) {
2683 freq->vht_enabled = 0;
2684 return;
2685 }
2686#endif /* CONFIG_VHT_OVERRIDES */
2687
Hai Shalomc1a21442022-02-04 13:43:00 -08002688skip_to_6ghz:
2689 vht_freq = *freq;
2690
2691 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002692 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002693 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002694 return;
2695
Hai Shalomfdcde762020-04-02 11:19:20 -07002696 /* Enable HE with VHT for 5 GHz */
2697 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002698
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002699 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002700 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2701 if (freq->freq >= bw80[j] &&
2702 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002703 break;
2704 }
2705
Hai Shalomc1a21442022-02-04 13:43:00 -08002706 if (j == ARRAY_SIZE(bw80) ||
2707 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002708 return;
2709
Hai Shalomc1a21442022-02-04 13:43:00 -08002710 /* Back to HT configuration if channel not usable */
2711 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2712 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002713
Sunil8cd6f4d2022-06-28 18:40:46 +00002714 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002715 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002716 seg1 = 0;
2717
Hai Shalomc1a21442022-02-04 13:43:00 -08002718 if ((mode->he_capab[ieee80211_mode].phy_cap[
2719 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2720 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2721 /* In 160 MHz, the initial four 20 MHz channels were validated
2722 * above; check the remaining four 20 MHz channels for the total
2723 * of 160 MHz bandwidth.
2724 */
2725 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2726 return;
2727
2728 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2729 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002730 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002731 seg0 = channel + 14;
2732 break;
2733 }
2734 }
2735 }
2736
Sunil8cd6f4d2022-06-28 18:40:46 +00002737 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002738 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002739 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002740 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002741 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002742 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002743
2744 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2745 NUM_HOSTAPD_MODES)
2746 return;
2747
2748 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002749 struct hostapd_channel_data *chan;
2750
2751 chan = hw_get_channel_chan(mode, i, NULL);
2752 if (!chan)
2753 continue;
2754
2755 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2756 HOSTAPD_CHAN_NO_IR |
2757 HOSTAPD_CHAN_RADAR))
2758 continue;
2759
2760 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00002761 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002762 if (!is_6ghz)
2763 vht_caps |=
2764 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2765 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002766 }
2767
Sunil8cd6f4d2022-06-28 18:40:46 +00002768 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002769 break;
2770 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002771 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002772 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002773 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002774 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2775 seg0 = 50;
2776 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002777 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002778 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2779 seg0 = 114;
2780 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002781 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT) {
2782 chwidth = CONF_OPER_CHWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002783 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002784#ifdef CONFIG_HT_OVERRIDES
2785 if (ssid->disable_ht40)
2786 seg0 = 0;
2787#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002788 }
2789
Hai Shalomfdcde762020-04-02 11:19:20 -07002790#ifdef CONFIG_HE_OVERRIDES
2791 if (ssid->disable_he) {
2792 vht_freq.he_enabled = 0;
2793 freq->he_enabled = 0;
2794 }
2795#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002796 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002797 freq->channel, ssid->enable_edmg,
2798 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002799 vht_freq.vht_enabled, freq->he_enabled,
Sunil Ravia04bd252022-05-02 22:54:18 -07002800 false,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002801 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002802 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07002803 &mode->he_capab[ieee80211_mode],
2804 NULL) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002805 return;
2806
2807 *freq = vht_freq;
2808
2809 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2810 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002811}
2812
2813
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002814#ifdef CONFIG_FILS
2815static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2816 size_t ie_buf_len)
2817{
2818 struct fils_hlp_req *req;
2819 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2820 const u8 *pos;
2821 u8 *buf = ie_buf;
2822
2823 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2824 list) {
2825 rem_len = ie_buf_len - ie_len;
2826 pos = wpabuf_head(req->pkt);
2827 hdr_len = 1 + 2 * ETH_ALEN + 6;
2828 hlp_len = wpabuf_len(req->pkt);
2829
2830 if (rem_len < 2 + hdr_len + hlp_len) {
2831 wpa_printf(MSG_ERROR,
2832 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2833 (unsigned long) rem_len,
2834 (unsigned long) (2 + hdr_len + hlp_len));
2835 break;
2836 }
2837
2838 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2839 /* Element ID */
2840 *buf++ = WLAN_EID_EXTENSION;
2841 /* Length */
2842 *buf++ = len;
2843 /* Element ID Extension */
2844 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2845 /* Destination MAC address */
2846 os_memcpy(buf, req->dst, ETH_ALEN);
2847 buf += ETH_ALEN;
2848 /* Source MAC address */
2849 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2850 buf += ETH_ALEN;
2851 /* LLC/SNAP Header */
2852 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2853 buf += 6;
2854 /* HLP Packet */
2855 os_memcpy(buf, pos, len - hdr_len);
2856 buf += len - hdr_len;
2857 pos += len - hdr_len;
2858
2859 hlp_len -= len - hdr_len;
2860 ie_len += 2 + len;
2861 rem_len -= 2 + len;
2862
2863 while (hlp_len) {
2864 len = (hlp_len > 255) ? 255 : hlp_len;
2865 if (rem_len < 2 + len)
2866 break;
2867 *buf++ = WLAN_EID_FRAGMENT;
2868 *buf++ = len;
2869 os_memcpy(buf, pos, len);
2870 buf += len;
2871 pos += len;
2872
2873 hlp_len -= len;
2874 ie_len += 2 + len;
2875 rem_len -= 2 + len;
2876 }
2877 }
2878
2879 return ie_len;
2880}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002881
2882
2883int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2884{
2885 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2886 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2887 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2888 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2889}
2890
2891
2892int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2893{
2894#ifdef CONFIG_FILS_SK_PFS
2895 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2896 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2897#else /* CONFIG_FILS_SK_PFS */
2898 return 0;
2899#endif /* CONFIG_FILS_SK_PFS */
2900}
2901
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002902#endif /* CONFIG_FILS */
2903
2904
Hai Shalomc1a21442022-02-04 13:43:00 -08002905static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
2906 struct wpa_bss *bss,
2907 u8 *wpa_ie, size_t wpa_ie_len,
2908 size_t max_wpa_ie_len)
2909{
2910 struct wpabuf *wfa_ie = NULL;
2911 u8 wfa_capa[1];
2912 size_t wfa_ie_len, buf_len;
2913
2914 os_memset(wfa_capa, 0, sizeof(wfa_capa));
2915 if (wpa_s->enable_dscp_policy_capa)
2916 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
2917
2918 if (!wfa_capa[0])
2919 return wpa_ie_len;
2920
2921 /* Wi-Fi Alliance element */
2922 buf_len = 1 + /* Element ID */
2923 1 + /* Length */
2924 3 + /* OUI */
2925 1 + /* OUI Type */
2926 1 + /* Capabilities Length */
2927 sizeof(wfa_capa); /* Capabilities */
2928 wfa_ie = wpabuf_alloc(buf_len);
2929 if (!wfa_ie)
2930 return wpa_ie_len;
2931
2932 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
2933 wpabuf_put_u8(wfa_ie, buf_len - 2);
2934 wpabuf_put_be24(wfa_ie, OUI_WFA);
2935 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
2936 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
2937 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
2938
2939 wfa_ie_len = wpabuf_len(wfa_ie);
2940 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
2941 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
2942 wfa_ie);
2943 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
2944 wfa_ie_len);
2945 wpa_ie_len += wfa_ie_len;
2946 }
2947
2948 wpabuf_free(wfa_ie);
2949 return wpa_ie_len;
2950}
2951
2952
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002953static u8 * wpas_populate_assoc_ies(
2954 struct wpa_supplicant *wpa_s,
2955 struct wpa_bss *bss, struct wpa_ssid *ssid,
2956 struct wpa_driver_associate_params *params,
2957 enum wpa_drv_update_connect_params_mask *mask)
2958{
2959 u8 *wpa_ie;
2960 size_t max_wpa_ie_len = 500;
2961 size_t wpa_ie_len;
2962 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002963#ifdef CONFIG_MBO
2964 const u8 *mbo_ie;
2965#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302966#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2967 int pmksa_cached = 0;
2968#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002969#ifdef CONFIG_FILS
2970 const u8 *realm, *username, *rrk;
2971 size_t realm_len, username_len, rrk_len;
2972 u16 next_seq_num;
2973 struct fils_hlp_req *req;
2974
2975 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2976 list) {
2977 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2978 2 + 2 * wpabuf_len(req->pkt) / 255;
2979 }
2980#endif /* CONFIG_FILS */
2981
2982 wpa_ie = os_malloc(max_wpa_ie_len);
2983 if (!wpa_ie) {
2984 wpa_printf(MSG_ERROR,
2985 "Failed to allocate connect IE buffer for %lu bytes",
2986 (unsigned long) max_wpa_ie_len);
2987 return NULL;
2988 }
2989
2990 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2991 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2992 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2993 int try_opportunistic;
2994 const u8 *cache_id = NULL;
2995
2996 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2997 wpa_s->conf->okc :
2998 ssid->proactive_key_caching) &&
2999 (ssid->proto & WPA_PROTO_RSN);
3000#ifdef CONFIG_FILS
3001 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3002 cache_id = wpa_bss_get_fils_cache_id(bss);
3003#endif /* CONFIG_FILS */
3004 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
3005 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003006 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003007 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303008#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3009 pmksa_cached = 1;
3010#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003011 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003012 wpa_ie_len = max_wpa_ie_len;
3013 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3014 wpa_ie, &wpa_ie_len)) {
3015 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3016 "key management and encryption suites");
3017 os_free(wpa_ie);
3018 return NULL;
3019 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003020#ifdef CONFIG_HS20
3021 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3022 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3023 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3024 wpa_ie_len = max_wpa_ie_len;
3025 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3026 wpa_ie, &wpa_ie_len)) {
3027 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3028 "key management and encryption suites");
3029 os_free(wpa_ie);
3030 return NULL;
3031 }
3032#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003033 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3034 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3035 /*
3036 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3037 * use non-WPA since the scan results did not indicate that the
3038 * AP is using WPA or WPA2.
3039 */
3040 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3041 wpa_ie_len = 0;
3042 wpa_s->wpa_proto = 0;
3043 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3044 wpa_ie_len = max_wpa_ie_len;
3045 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
3046 wpa_ie, &wpa_ie_len)) {
3047 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3048 "key management and encryption suites (no "
3049 "scan results)");
3050 os_free(wpa_ie);
3051 return NULL;
3052 }
3053#ifdef CONFIG_WPS
3054 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3055 struct wpabuf *wps_ie;
3056 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3057 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3058 wpa_ie_len = wpabuf_len(wps_ie);
3059 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3060 } else
3061 wpa_ie_len = 0;
3062 wpabuf_free(wps_ie);
3063 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3064 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3065 params->wps = WPS_MODE_PRIVACY;
3066 else
3067 params->wps = WPS_MODE_OPEN;
3068 wpa_s->wpa_proto = 0;
3069#endif /* CONFIG_WPS */
3070 } else {
3071 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3072 wpa_ie_len = 0;
3073 wpa_s->wpa_proto = 0;
3074 }
3075
3076#ifdef IEEE8021X_EAPOL
3077 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3078 if (ssid->leap) {
3079 if (ssid->non_leap == 0)
3080 algs = WPA_AUTH_ALG_LEAP;
3081 else
3082 algs |= WPA_AUTH_ALG_LEAP;
3083 }
3084 }
3085
3086#ifdef CONFIG_FILS
3087 /* Clear FILS association */
3088 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3089
3090 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3091 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3092 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3093 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003094 &next_seq_num, &rrk, &rrk_len) == 0 &&
3095 (!wpa_s->last_con_fail_realm ||
3096 wpa_s->last_con_fail_realm_len != realm_len ||
3097 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003098 algs = WPA_AUTH_ALG_FILS;
3099 params->fils_erp_username = username;
3100 params->fils_erp_username_len = username_len;
3101 params->fils_erp_realm = realm;
3102 params->fils_erp_realm_len = realm_len;
3103 params->fils_erp_next_seq_num = next_seq_num;
3104 params->fils_erp_rrk = rrk;
3105 params->fils_erp_rrk_len = rrk_len;
3106
3107 if (mask)
3108 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303109 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3110 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3111 pmksa_cached) {
3112 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003113 }
3114#endif /* CONFIG_FILS */
3115#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003116#ifdef CONFIG_SAE
3117 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
3118 algs = WPA_AUTH_ALG_SAE;
3119#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003120
3121 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3122 if (ssid->auth_alg) {
3123 algs = ssid->auth_alg;
3124 wpa_dbg(wpa_s, MSG_DEBUG,
3125 "Overriding auth_alg selection: 0x%x", algs);
3126 }
3127
Hai Shalom5f92bc92019-04-18 11:54:11 -07003128#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303129 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003130 wpa_dbg(wpa_s, MSG_DEBUG,
3131 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3132 algs = WPA_AUTH_ALG_OPEN;
3133 }
3134#endif /* CONFIG_SAE */
3135
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003136#ifdef CONFIG_P2P
3137 if (wpa_s->global->p2p) {
3138 u8 *pos;
3139 size_t len;
3140 int res;
3141 pos = wpa_ie + wpa_ie_len;
3142 len = max_wpa_ie_len - wpa_ie_len;
3143 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3144 ssid->p2p_group);
3145 if (res >= 0)
3146 wpa_ie_len += res;
3147 }
3148
3149 wpa_s->cross_connect_disallowed = 0;
3150 if (bss) {
3151 struct wpabuf *p2p;
3152 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3153 if (p2p) {
3154 wpa_s->cross_connect_disallowed =
3155 p2p_get_cross_connect_disallowed(p2p);
3156 wpabuf_free(p2p);
3157 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3158 "connection",
3159 wpa_s->cross_connect_disallowed ?
3160 "disallows" : "allows");
3161 }
3162 }
3163
3164 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3165#endif /* CONFIG_P2P */
3166
3167 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003168 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003169 wpa_ie + wpa_ie_len,
3170 max_wpa_ie_len -
3171 wpa_ie_len);
3172 }
3173
3174 /*
3175 * Workaround: Add Extended Capabilities element only if the AP
3176 * included this element in Beacon/Probe Response frames. Some older
3177 * APs seem to have interoperability issues if this element is
3178 * included, so while the standard may require us to include the
3179 * element in all cases, it is justifiable to skip it to avoid
3180 * interoperability issues.
3181 */
3182 if (ssid->p2p_group)
3183 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3184 else
3185 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3186
3187 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3188 u8 ext_capab[18];
3189 int ext_capab_len;
3190 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3191 sizeof(ext_capab));
3192 if (ext_capab_len > 0 &&
3193 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3194 u8 *pos = wpa_ie;
3195 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3196 pos += 2 + pos[1];
3197 os_memmove(pos + ext_capab_len, pos,
3198 wpa_ie_len - (pos - wpa_ie));
3199 wpa_ie_len += ext_capab_len;
3200 os_memcpy(pos, ext_capab, ext_capab_len);
3201 }
3202 }
3203
3204#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003205 if (is_hs20_network(wpa_s, ssid, bss)
3206#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3207 && is_hs20_config(wpa_s)
3208#endif /* ANDROID */
3209 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003210 struct wpabuf *hs20;
3211
Roshan Pius3a1667e2018-07-03 15:17:14 -07003212 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003213 if (hs20) {
3214 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3215 size_t len;
3216
Hai Shalom74f70d42019-02-11 14:42:39 -08003217 wpas_hs20_add_indication(hs20, pps_mo_id,
3218 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003219 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003220 len = max_wpa_ie_len - wpa_ie_len;
3221 if (wpabuf_len(hs20) <= len) {
3222 os_memcpy(wpa_ie + wpa_ie_len,
3223 wpabuf_head(hs20), wpabuf_len(hs20));
3224 wpa_ie_len += wpabuf_len(hs20);
3225 }
3226 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003227 }
3228 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003229 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003230#endif /* CONFIG_HS20 */
3231
3232 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3233 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3234 size_t len;
3235
3236 len = max_wpa_ie_len - wpa_ie_len;
3237 if (wpabuf_len(buf) <= len) {
3238 os_memcpy(wpa_ie + wpa_ie_len,
3239 wpabuf_head(buf), wpabuf_len(buf));
3240 wpa_ie_len += wpabuf_len(buf);
3241 }
3242 }
3243
3244#ifdef CONFIG_FST
3245 if (wpa_s->fst_ies) {
3246 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3247
3248 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3249 os_memcpy(wpa_ie + wpa_ie_len,
3250 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3251 wpa_ie_len += fst_ies_len;
3252 }
3253 }
3254#endif /* CONFIG_FST */
3255
3256#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003257 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003258 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003259 int len;
3260
3261 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003262 max_wpa_ie_len - wpa_ie_len,
3263 !!mbo_attr_from_mbo_ie(mbo_ie,
3264 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003265 if (len >= 0)
3266 wpa_ie_len += len;
3267 }
3268#endif /* CONFIG_MBO */
3269
3270#ifdef CONFIG_FILS
3271 if (algs == WPA_AUTH_ALG_FILS) {
3272 size_t len;
3273
3274 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3275 max_wpa_ie_len - wpa_ie_len);
3276 wpa_ie_len += len;
3277 }
3278#endif /* CONFIG_FILS */
3279
3280#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003281#ifdef CONFIG_TESTING_OPTIONS
3282 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3283 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3284 } else
3285#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003286 if (algs == WPA_AUTH_ALG_OPEN &&
3287 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3288 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003289 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003290
Roshan Pius3a1667e2018-07-03 15:17:14 -07003291 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003292 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003293 } else if (wpa_s->assoc_status_code ==
3294 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003295 if (wpa_s->last_owe_group == 19)
3296 group = 20;
3297 else if (wpa_s->last_owe_group == 20)
3298 group = 21;
3299 else
3300 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003301 } else {
3302 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003303 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003304
Roshan Pius3a1667e2018-07-03 15:17:14 -07003305 wpa_s->last_owe_group = group;
3306 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003307 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3308 if (owe_ie &&
3309 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3310 os_memcpy(wpa_ie + wpa_ie_len,
3311 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3312 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003313 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003314 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003315 }
3316#endif /* CONFIG_OWE */
3317
Hai Shalom021b0b52019-04-10 11:17:58 -07003318#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003319 if (DPP_VERSION > 1 &&
3320 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003321 ssid->dpp_netaccesskey &&
3322 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003323 struct rsn_pmksa_cache_entry *pmksa;
3324
3325 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3326 if (!pmksa || !pmksa->dpp_pfs)
3327 goto pfs_fail;
3328
Hai Shalom021b0b52019-04-10 11:17:58 -07003329 dpp_pfs_free(wpa_s->dpp_pfs);
3330 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3331 ssid->dpp_netaccesskey_len);
3332 if (!wpa_s->dpp_pfs) {
3333 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3334 /* Try to continue without PFS */
3335 goto pfs_fail;
3336 }
3337 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3338 max_wpa_ie_len - wpa_ie_len) {
3339 os_memcpy(wpa_ie + wpa_ie_len,
3340 wpabuf_head(wpa_s->dpp_pfs->ie),
3341 wpabuf_len(wpa_s->dpp_pfs->ie));
3342 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3343 }
3344 }
3345pfs_fail:
3346#endif /* CONFIG_DPP2 */
3347
Roshan Pius3a1667e2018-07-03 15:17:14 -07003348#ifdef CONFIG_IEEE80211R
3349 /*
3350 * Add MDIE under these conditions: the network profile allows FT,
3351 * the AP supports FT, and the mobility domain ID matches.
3352 */
3353 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3354 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3355
3356 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3357 size_t len = 0;
3358 const u8 *md = mdie + 2;
3359 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3360
3361 if (os_memcmp(md, wpa_md,
3362 MOBILITY_DOMAIN_ID_LEN) == 0) {
3363 /* Add mobility domain IE */
3364 len = wpa_ft_add_mdie(
3365 wpa_s->wpa, wpa_ie + wpa_ie_len,
3366 max_wpa_ie_len - wpa_ie_len, mdie);
3367 wpa_ie_len += len;
3368 }
3369#ifdef CONFIG_SME
3370 if (len > 0 && wpa_s->sme.ft_used &&
3371 wpa_sm_has_ptk(wpa_s->wpa)) {
3372 wpa_dbg(wpa_s, MSG_DEBUG,
3373 "SME: Trying to use FT over-the-air");
3374 algs |= WPA_AUTH_ALG_FT;
3375 }
3376#endif /* CONFIG_SME */
3377 }
3378 }
3379#endif /* CONFIG_IEEE80211R */
3380
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003381#ifdef CONFIG_TESTING_OPTIONS
3382 if (wpa_s->rsnxe_override_assoc &&
3383 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3384 max_wpa_ie_len - wpa_ie_len) {
3385 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3386 os_memcpy(wpa_ie + wpa_ie_len,
3387 wpabuf_head(wpa_s->rsnxe_override_assoc),
3388 wpabuf_len(wpa_s->rsnxe_override_assoc));
3389 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3390 } else
3391#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003392 if (wpa_s->rsnxe_len > 0 &&
3393 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3394 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3395 wpa_ie_len += wpa_s->rsnxe_len;
3396 }
3397
Hai Shalomc1a21442022-02-04 13:43:00 -08003398#ifdef CONFIG_TESTING_OPTIONS
3399 if (wpa_s->disable_mscs_support)
3400 goto mscs_end;
3401#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003402 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3403 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003404 struct wpabuf *mscs_ie;
3405 size_t mscs_ie_len, buf_len;
3406
Hai Shalom899fcc72020-10-19 14:38:18 -07003407 buf_len = 3 + /* MSCS descriptor IE header */
3408 1 + /* Request type */
3409 2 + /* User priority control */
3410 4 + /* Stream timeout */
3411 3 + /* TCLAS Mask IE header */
3412 wpa_s->robust_av.frame_classifier_len;
3413 mscs_ie = wpabuf_alloc(buf_len);
3414 if (!mscs_ie) {
3415 wpa_printf(MSG_INFO,
3416 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003417 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003418 }
3419
3420 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3421 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3422 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3423 mscs_ie_len = wpabuf_len(mscs_ie);
3424 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3425 mscs_ie_len);
3426 wpa_ie_len += mscs_ie_len;
3427 }
3428
3429 wpabuf_free(mscs_ie);
3430 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003431mscs_end:
3432
3433 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3434 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003435
Hai Shalom74f70d42019-02-11 14:42:39 -08003436 if (ssid->multi_ap_backhaul_sta) {
3437 size_t multi_ap_ie_len;
3438
3439 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3440 max_wpa_ie_len - wpa_ie_len,
3441 MULTI_AP_BACKHAUL_STA);
3442 if (multi_ap_ie_len == 0) {
3443 wpa_printf(MSG_ERROR,
3444 "Multi-AP: Failed to build Multi-AP IE");
3445 os_free(wpa_ie);
3446 return NULL;
3447 }
3448 wpa_ie_len += multi_ap_ie_len;
3449 }
3450
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003451 params->wpa_ie = wpa_ie;
3452 params->wpa_ie_len = wpa_ie_len;
3453 params->auth_alg = algs;
3454 if (mask)
3455 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3456
3457 return wpa_ie;
3458}
3459
3460
Hai Shalomc3565922019-10-28 11:58:20 -07003461#ifdef CONFIG_OWE
3462static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3463{
3464 struct wpa_driver_associate_params params;
3465 u8 *wpa_ie;
3466
3467 os_memset(&params, 0, sizeof(params));
3468 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3469 wpa_s->current_ssid, &params, NULL);
3470 if (!wpa_ie)
3471 return;
3472
3473 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3474 os_free(wpa_ie);
3475}
3476#endif /* CONFIG_OWE */
3477
3478
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003479#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3480static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3481{
3482 struct wpa_driver_associate_params params;
3483 enum wpa_drv_update_connect_params_mask mask = 0;
3484 u8 *wpa_ie;
3485
3486 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3487 return; /* nothing to do */
3488
3489 os_memset(&params, 0, sizeof(params));
3490 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3491 wpa_s->current_ssid, &params, &mask);
3492 if (!wpa_ie)
3493 return;
3494
Hai Shalomc1a21442022-02-04 13:43:00 -08003495 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3496 wpa_s->auth_alg = params.auth_alg;
3497 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003498 }
3499
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003500 os_free(wpa_ie);
3501}
3502#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3503
3504
Hai Shalomc3565922019-10-28 11:58:20 -07003505static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3506{
3507 if (!edmg_ie || edmg_ie[1] < 6)
3508 return 0;
3509 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3510}
3511
3512
3513static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3514{
3515 if (!edmg_ie || edmg_ie[1] < 6)
3516 return 0;
3517 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3518}
3519
3520
3521/* Returns the intersection of two EDMG configurations.
3522 * Note: The current implementation is limited to CB2 only (CB1 included),
3523 * i.e., the implementation supports up to 2 contiguous channels.
3524 * For supporting non-contiguous (aggregated) channels and for supporting
3525 * CB3 and above, this function will need to be extended.
3526 */
3527static struct ieee80211_edmg_config
3528get_edmg_intersection(struct ieee80211_edmg_config a,
3529 struct ieee80211_edmg_config b,
3530 u8 primary_channel)
3531{
3532 struct ieee80211_edmg_config result;
3533 int i, contiguous = 0;
3534 int max_contiguous = 0;
3535
3536 result.channels = b.channels & a.channels;
3537 if (!result.channels) {
3538 wpa_printf(MSG_DEBUG,
3539 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3540 a.channels, b.channels);
3541 goto fail;
3542 }
3543
3544 if (!(result.channels & BIT(primary_channel - 1))) {
3545 wpa_printf(MSG_DEBUG,
3546 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3547 primary_channel, result.channels);
3548 goto fail;
3549 }
3550
3551 /* Find max contiguous channels */
3552 for (i = 0; i < 6; i++) {
3553 if (result.channels & BIT(i))
3554 contiguous++;
3555 else
3556 contiguous = 0;
3557
3558 if (contiguous > max_contiguous)
3559 max_contiguous = contiguous;
3560 }
3561
3562 /* Assuming AP and STA supports ONLY contiguous channels,
3563 * bw configuration can have value between 4-7.
3564 */
3565 if ((b.bw_config < a.bw_config))
3566 result.bw_config = b.bw_config;
3567 else
3568 result.bw_config = a.bw_config;
3569
3570 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3571 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3572 wpa_printf(MSG_DEBUG,
3573 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3574 max_contiguous);
3575 goto fail;
3576 }
3577
3578 return result;
3579
3580fail:
3581 result.channels = 0;
3582 result.bw_config = 0;
3583 return result;
3584}
3585
3586
3587static struct ieee80211_edmg_config
3588get_supported_edmg(struct wpa_supplicant *wpa_s,
3589 struct hostapd_freq_params *freq,
3590 struct ieee80211_edmg_config request_edmg)
3591{
3592 enum hostapd_hw_mode hw_mode;
3593 struct hostapd_hw_modes *mode = NULL;
3594 u8 primary_channel;
3595
3596 if (!wpa_s->hw.modes)
3597 goto fail;
3598
3599 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3600 if (hw_mode == NUM_HOSTAPD_MODES)
3601 goto fail;
3602
Hai Shalom60840252021-02-19 19:02:11 -08003603 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003604 if (!mode)
3605 goto fail;
3606
3607 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3608
3609fail:
3610 request_edmg.channels = 0;
3611 request_edmg.bw_config = 0;
3612 return request_edmg;
3613}
3614
3615
Hai Shalom021b0b52019-04-10 11:17:58 -07003616#ifdef CONFIG_MBO
3617void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3618{
3619 struct wpa_driver_associate_params params;
3620 u8 *wpa_ie;
3621
3622 /*
3623 * Update MBO connect params only in case of change of MBO attributes
3624 * when connected, if the AP support MBO.
3625 */
3626
3627 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3628 !wpa_s->current_bss ||
3629 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3630 return;
3631
3632 os_memset(&params, 0, sizeof(params));
3633 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3634 wpa_s->current_ssid, &params, NULL);
3635 if (!wpa_ie)
3636 return;
3637
3638 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3639 os_free(wpa_ie);
3640}
3641#endif /* CONFIG_MBO */
3642
3643
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003644static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3645{
3646 struct wpa_connect_work *cwork = work->ctx;
3647 struct wpa_bss *bss = cwork->bss;
3648 struct wpa_ssid *ssid = cwork->ssid;
3649 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003650 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003651 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003652 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003653 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003654 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003655#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003656 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003657#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003658 int assoc_failed = 0;
3659 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003660 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003661#ifdef CONFIG_HT_OVERRIDES
3662 struct ieee80211_ht_capabilities htcaps;
3663 struct ieee80211_ht_capabilities htcaps_mask;
3664#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003665#ifdef CONFIG_VHT_OVERRIDES
3666 struct ieee80211_vht_capabilities vhtcaps;
3667 struct ieee80211_vht_capabilities vhtcaps_mask;
3668#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003669
Hai Shalomc1a21442022-02-04 13:43:00 -08003670 wpa_s->roam_in_progress = false;
3671#ifdef CONFIG_WNM
3672 wpa_s->bss_trans_mgmt_in_progress = false;
3673#endif /* CONFIG_WNM */
3674
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003675 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003676 if (work->started) {
3677 wpa_s->connect_work = NULL;
3678
3679 /* cancel possible auth. timeout */
3680 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3681 NULL);
3682 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003683 wpas_connect_work_free(cwork);
3684 return;
3685 }
3686
3687 wpa_s->connect_work = work;
3688
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003689 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3690 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003691 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3692 wpas_connect_work_done(wpa_s);
3693 return;
3694 }
3695
Dmitry Shmidte4663042016-04-04 10:07:49 -07003696 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003697 os_memset(&params, 0, sizeof(params));
3698 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003699 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003700
3701 /* Starting new association, so clear the possibly used WPA IE from the
3702 * previous association. */
3703 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3704 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3705 wpa_s->rsnxe_len = 0;
3706 wpa_s->mscs_setup_done = false;
3707
3708 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3709 if (!wpa_ie) {
3710 wpas_connect_work_done(wpa_s);
3711 return;
3712 }
3713
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003714 if (bss &&
3715 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003716#ifdef CONFIG_IEEE80211R
3717 const u8 *ie, *md = NULL;
3718#endif /* CONFIG_IEEE80211R */
3719 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3720 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3721 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3722 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3723 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3724 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3725 if (bssid_changed)
3726 wpas_notify_bssid_changed(wpa_s);
3727#ifdef CONFIG_IEEE80211R
3728 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3729 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3730 md = ie + 2;
3731 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3732 if (md) {
3733 /* Prepare for the next transition */
3734 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3735 }
3736#endif /* CONFIG_IEEE80211R */
3737#ifdef CONFIG_WPS
3738 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3739 wpa_s->conf->ap_scan == 2 &&
3740 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3741 /* Use ap_scan==1 style network selection to find the network
3742 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003743 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003744 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003745 wpa_s->reassociate = 1;
3746 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003747 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003748 return;
3749#endif /* CONFIG_WPS */
3750 } else {
3751 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3752 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003753 if (bss)
3754 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3755 else
3756 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003757 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003758 if (!wpa_s->pno)
3759 wpa_supplicant_cancel_sched_scan(wpa_s);
3760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003761 wpa_supplicant_cancel_scan(wpa_s);
3762
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003763 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3764 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003765 cipher_pairwise = wpa_s->pairwise_cipher;
3766 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003767 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003768 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3769 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3770 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3771 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003772#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003773 if (wpa_set_wep_keys(wpa_s, ssid)) {
3774 use_crypt = 1;
3775 wep_keys_set = 1;
3776 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003777#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003778 }
3779 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3780 use_crypt = 0;
3781
3782#ifdef IEEE8021X_EAPOL
3783 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3784 if ((ssid->eapol_flags &
3785 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3786 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3787 !wep_keys_set) {
3788 use_crypt = 0;
3789 } else {
3790 /* Assume that dynamic WEP-104 keys will be used and
3791 * set cipher suites in order for drivers to expect
3792 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003793 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003794 }
3795 }
3796#endif /* IEEE8021X_EAPOL */
3797
3798 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3799 /* Set the key before (and later after) association */
3800 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3801 }
3802
Sunil8cd6f4d2022-06-28 18:40:46 +00003803 /* Set current_ssid before changing state to ASSOCIATING, so that the
3804 * selected SSID is available to wpas_notify_state_changed(). */
3805 old_ssid = wpa_s->current_ssid;
3806 wpa_s->current_ssid = ssid;
3807
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003808 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3809 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003810 params.ssid = bss->ssid;
3811 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003812 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3813 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003814 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3815 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003816 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003817 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003818 ssid->bssid_set,
3819 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003820 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003821 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003822 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003823 params.bssid_hint = bss->bssid;
3824 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003825 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003826 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003827 if (ssid->bssid_hint_set)
3828 params.bssid_hint = ssid->bssid_hint;
3829
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003830 params.ssid = ssid->ssid;
3831 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003832 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003833 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003834
3835 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3836 wpa_s->conf->ap_scan == 2) {
3837 params.bssid = ssid->bssid;
3838 params.fixed_bssid = 1;
3839 }
3840
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003841 /* Initial frequency for IBSS/mesh */
3842 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003843 ssid->frequency > 0 && params.freq.freq == 0)
3844 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003845
3846 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003847 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003848 if (ssid->beacon_int)
3849 params.beacon_int = ssid->beacon_int;
3850 else
3851 params.beacon_int = wpa_s->conf->beacon_int;
3852 }
3853
Hai Shalomc3565922019-10-28 11:58:20 -07003854 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003855 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3856 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003857 else
3858 edmg_ie_oper = NULL;
3859
3860 if (edmg_ie_oper) {
3861 params.freq.edmg.channels =
3862 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3863 params.freq.edmg.bw_config =
3864 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3865 wpa_printf(MSG_DEBUG,
3866 "AP supports EDMG channels 0x%x, bw_config %d",
3867 params.freq.edmg.channels,
3868 params.freq.edmg.bw_config);
3869
3870 /* User may ask for specific EDMG channel for EDMG connection
3871 * (must be supported by AP)
3872 */
3873 if (ssid->edmg_channel) {
3874 struct ieee80211_edmg_config configured_edmg;
3875 enum hostapd_hw_mode hw_mode;
3876 u8 primary_channel;
3877
3878 hw_mode = ieee80211_freq_to_chan(bss->freq,
3879 &primary_channel);
3880 if (hw_mode == NUM_HOSTAPD_MODES)
3881 goto edmg_fail;
3882
3883 hostapd_encode_edmg_chan(ssid->enable_edmg,
3884 ssid->edmg_channel,
3885 primary_channel,
3886 &configured_edmg);
3887
3888 if (ieee802_edmg_is_allowed(params.freq.edmg,
3889 configured_edmg)) {
3890 params.freq.edmg = configured_edmg;
3891 wpa_printf(MSG_DEBUG,
3892 "Use EDMG channel %d for connection",
3893 ssid->edmg_channel);
3894 } else {
3895 edmg_fail:
3896 params.freq.edmg.channels = 0;
3897 params.freq.edmg.bw_config = 0;
3898 wpa_printf(MSG_WARNING,
3899 "EDMG channel %d not supported by AP, fallback to DMG",
3900 ssid->edmg_channel);
3901 }
3902 }
3903
3904 if (params.freq.edmg.channels) {
3905 wpa_printf(MSG_DEBUG,
3906 "EDMG before: channels 0x%x, bw_config %d",
3907 params.freq.edmg.channels,
3908 params.freq.edmg.bw_config);
3909 params.freq.edmg = get_supported_edmg(wpa_s,
3910 &params.freq,
3911 params.freq.edmg);
3912 wpa_printf(MSG_DEBUG,
3913 "EDMG after: channels 0x%x, bw_config %d",
3914 params.freq.edmg.channels,
3915 params.freq.edmg.bw_config);
3916 }
3917 }
3918
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003919 params.pairwise_suite = cipher_pairwise;
3920 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003921 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003922 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003923 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003924 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003925 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003926 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003927#ifdef CONFIG_WEP
3928 {
3929 int i;
3930
3931 for (i = 0; i < NUM_WEP_KEYS; i++) {
3932 if (ssid->wep_key_len[i])
3933 params.wep_key[i] = ssid->wep_key[i];
3934 params.wep_key_len[i] = ssid->wep_key_len[i];
3935 }
3936 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003937 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003938#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003939
Hai Shalom74f70d42019-02-11 14:42:39 -08003940 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Vinayak Yadawad14709082022-03-17 14:25:11 +05303941 (
3942#ifdef CONFIG_DRIVER_NL80211_BRCM
3943 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3944#else
3945 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3946#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003947 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003948 params.passphrase = ssid->passphrase;
3949 if (ssid->psk_set)
3950 params.psk = ssid->psk;
3951 }
3952
Hai Shalom74f70d42019-02-11 14:42:39 -08003953 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3954 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3955 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3956 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3957 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003958 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003959
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003960 if (wpa_s->conf->key_mgmt_offload) {
3961 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3962 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003963 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3964 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003965 params.req_key_mgmt_offload =
3966 ssid->proactive_key_caching < 0 ?
3967 wpa_s->conf->okc : ssid->proactive_key_caching;
3968 else
3969 params.req_key_mgmt_offload = 1;
3970
Vinayak Yadawad14709082022-03-17 14:25:11 +05303971 if ((
3972#ifdef CONFIG_DRIVER_NL80211_BRCM
3973 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3974#else
3975 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3976#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003977 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3978 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3979 ssid->psk_set)
3980 params.psk = ssid->psk;
3981 }
3982
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003983 params.drop_unencrypted = use_crypt;
3984
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003985 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003986 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003987 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3988 struct wpa_ie_data ie;
3989 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3990 ie.capabilities &
3991 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3992 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3993 "MFP: require MFP");
3994 params.mgmt_frame_protection =
3995 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003996#ifdef CONFIG_OWE
3997 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3998 !ssid->owe_only) {
3999 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4000#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004001 }
4002 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004003
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004004 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004005
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004006 if (wpa_s->p2pdev->set_sta_uapsd)
4007 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004008 else
4009 params.uapsd = -1;
4010
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004011#ifdef CONFIG_HT_OVERRIDES
4012 os_memset(&htcaps, 0, sizeof(htcaps));
4013 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4014 params.htcaps = (u8 *) &htcaps;
4015 params.htcaps_mask = (u8 *) &htcaps_mask;
4016 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4017#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004018#ifdef CONFIG_VHT_OVERRIDES
4019 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4020 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4021 params.vhtcaps = &vhtcaps;
4022 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004023 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004024#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004025#ifdef CONFIG_HE_OVERRIDES
4026 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4027#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004028
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004029#ifdef CONFIG_P2P
4030 /*
4031 * If multi-channel concurrency is not supported, check for any
4032 * frequency conflict. In case of any frequency conflict, remove the
4033 * least prioritized connection.
4034 */
4035 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004036 int freq, num;
4037 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004038 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004039 wpa_printf(MSG_DEBUG,
4040 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004041 freq, params.freq.freq);
4042 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004043 wpa_s, params.freq.freq, ssid) < 0) {
4044 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004045 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004046 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004047 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004048 }
4049 }
4050#endif /* CONFIG_P2P */
4051
Dmitry Shmidte4663042016-04-04 10:07:49 -07004052 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004053 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004054 params.prev_bssid = prev_bssid;
4055
Hai Shalom60840252021-02-19 19:02:11 -08004056#ifdef CONFIG_SAE
4057 params.sae_pwe = wpa_s->conf->sae_pwe;
4058#endif /* CONFIG_SAE */
4059
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004060 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004061 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004062 if (ret < 0) {
4063 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4064 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004065 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004066 /*
4067 * The driver is known to mean what is saying, so we
4068 * can stop right here; the association will not
4069 * succeed.
4070 */
4071 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004072 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004073 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004074 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4076 return;
4077 }
4078 /* try to continue anyway; new association will be tried again
4079 * after timeout */
4080 assoc_failed = 1;
4081 }
4082
4083 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4084 /* Set the key after the association just in case association
4085 * cleared the previously configured key. */
4086 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4087 /* No need to timeout authentication since there is no key
4088 * management. */
4089 wpa_supplicant_cancel_auth_timeout(wpa_s);
4090 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4091#ifdef CONFIG_IBSS_RSN
4092 } else if (ssid->mode == WPAS_MODE_IBSS &&
4093 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4094 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4095 /*
4096 * RSN IBSS authentication is per-STA and we can disable the
4097 * per-BSSID authentication.
4098 */
4099 wpa_supplicant_cancel_auth_timeout(wpa_s);
4100#endif /* CONFIG_IBSS_RSN */
4101 } else {
4102 /* Timeout for IEEE 802.11 authentication and association */
4103 int timeout = 60;
4104
4105 if (assoc_failed) {
4106 /* give IBSS a bit more time */
4107 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4108 } else if (wpa_s->conf->ap_scan == 1) {
4109 /* give IBSS a bit more time */
4110 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4111 }
4112 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4113 }
4114
Hai Shalomfdcde762020-04-02 11:19:20 -07004115#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004116 if (wep_keys_set &&
4117 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004118 /* Set static WEP keys again */
4119 wpa_set_wep_keys(wpa_s, ssid);
4120 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004121#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004122
Sunil8cd6f4d2022-06-28 18:40:46 +00004123 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004124 /*
4125 * Do not allow EAP session resumption between different
4126 * network configurations.
4127 */
4128 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4129 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004130
4131 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004132 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004133#ifdef CONFIG_HS20
4134 hs20_configure_frame_filters(wpa_s);
4135#endif /* CONFIG_HS20 */
4136 }
4137
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004138 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4139 wpa_supplicant_initiate_eapol(wpa_s);
4140 if (old_ssid != wpa_s->current_ssid)
4141 wpas_notify_network_changed(wpa_s);
4142}
4143
4144
4145static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4146 const u8 *addr)
4147{
4148 struct wpa_ssid *old_ssid;
4149
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004150 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004151 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004152 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004153 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004154 wpa_sm_set_config(wpa_s->wpa, NULL);
4155 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4156 if (old_ssid != wpa_s->current_ssid)
4157 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004158
4159 wpas_scs_deinit(wpa_s);
4160 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004161 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4162}
4163
4164
4165/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004166 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4167 * @wpa_s: Pointer to wpa_supplicant data
4168 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4169 *
4170 * This function is used to request %wpa_supplicant to deauthenticate from the
4171 * current AP.
4172 */
4173void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004174 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004175{
4176 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004177 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004178 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004179
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004180 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004181 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004182 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004183 reason_code, reason2str(reason_code),
4184 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004185
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004186 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4187 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4188 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004189 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004190 else if (!is_zero_ether_addr(wpa_s->bssid))
4191 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004192 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4193 /*
4194 * When using driver-based BSS selection, we may not know the
4195 * BSSID with which we are currently trying to associate. We
4196 * need to notify the driver of this disconnection even in such
4197 * a case, so use the all zeros address here.
4198 */
4199 addr = wpa_s->bssid;
4200 zero_addr = 1;
4201 }
4202
Hai Shalom74f70d42019-02-11 14:42:39 -08004203 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4204 wpa_s->enabled_4addr_mode = 0;
4205
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004206#ifdef CONFIG_TDLS
4207 wpa_tdls_teardown_peers(wpa_s->wpa);
4208#endif /* CONFIG_TDLS */
4209
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004210#ifdef CONFIG_MESH
4211 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004212 struct mesh_conf *mconf;
4213
4214 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004215 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4216 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004217 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4218 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004219 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004220 }
4221#endif /* CONFIG_MESH */
4222
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004223 if (addr) {
4224 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004225 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004226 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004227 event.deauth_info.locally_generated = 1;
4228 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004229 if (zero_addr)
4230 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004231 }
4232
4233 wpa_supplicant_clear_connection(wpa_s, addr);
4234}
4235
Hai Shalomfdcde762020-04-02 11:19:20 -07004236
4237void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4238{
4239 wpa_s->own_reconnect_req = 1;
4240 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4241
4242}
4243
4244
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004245static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4246 struct wpa_ssid *ssid)
4247{
4248 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4249 return;
4250
4251 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004252 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004253 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4254 wpas_notify_network_enabled_changed(wpa_s, ssid);
4255
4256 /*
4257 * Try to reassociate since there is no current configuration and a new
4258 * network was made available.
4259 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004260 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004261 wpa_s->reassociate = 1;
4262}
4263
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004264
Roshan Pius950bec92016-07-19 09:49:24 -07004265/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004266 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004267 * @wpa_s: wpa_supplicant structure for a network interface
4268 * Returns: The new network configuration or %NULL if operation failed
4269 *
4270 * This function performs the following operations:
4271 * 1. Adds a new network.
4272 * 2. Send network addition notification.
4273 * 3. Marks the network disabled.
4274 * 4. Set network default parameters.
4275 */
4276struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4277{
4278 struct wpa_ssid *ssid;
4279
4280 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004281 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004282 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004283 wpas_notify_network_added(wpa_s, ssid);
4284 ssid->disabled = 1;
4285 wpa_config_set_network_defaults(ssid);
4286
4287 return ssid;
4288}
4289
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004290
Roshan Pius950bec92016-07-19 09:49:24 -07004291/**
4292 * wpa_supplicant_remove_network - Remove a configured network based on id
4293 * @wpa_s: wpa_supplicant structure for a network interface
4294 * @id: Unique network id to search for
4295 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4296 * could not be removed
4297 *
4298 * This function performs the following operations:
4299 * 1. Removes the network.
4300 * 2. Send network removal notification.
4301 * 3. Update internal state machines.
4302 * 4. Stop any running sched scans.
4303 */
4304int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4305{
Sunil Ravia04bd252022-05-02 22:54:18 -07004306 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004307 int was_disabled;
4308
4309 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004310 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004311 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004312 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004313
Sunil Ravia04bd252022-05-02 22:54:18 -07004314 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004315#ifdef CONFIG_SME
4316 wpa_s->sme.prev_bssid_set = 0;
4317#endif /* CONFIG_SME */
4318 /*
4319 * Invalidate the EAP session cache if the current or
4320 * previously used network is removed.
4321 */
4322 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4323 }
4324
Sunil Ravia04bd252022-05-02 22:54:18 -07004325 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004326 wpa_sm_set_config(wpa_s->wpa, NULL);
4327 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4328
4329 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4330 wpa_s->own_disconnect_req = 1;
4331 wpa_supplicant_deauthenticate(wpa_s,
4332 WLAN_REASON_DEAUTH_LEAVING);
4333 }
4334
4335 was_disabled = ssid->disabled;
4336
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004337 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004338 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004339
4340 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004341 wpa_printf(MSG_DEBUG,
4342 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004343 wpa_supplicant_cancel_sched_scan(wpa_s);
4344 wpa_supplicant_req_scan(wpa_s, 0, 0);
4345 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004346
Roshan Pius950bec92016-07-19 09:49:24 -07004347 return 0;
4348}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004350
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004351/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004352 * wpa_supplicant_remove_all_networks - Remove all configured networks
4353 * @wpa_s: wpa_supplicant structure for a network interface
4354 * Returns: 0 on success (errors are currently ignored)
4355 *
4356 * This function performs the following operations:
4357 * 1. Remove all networks.
4358 * 2. Send network removal notifications.
4359 * 3. Update internal state machines.
4360 * 4. Stop any running sched scans.
4361 */
4362int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4363{
4364 struct wpa_ssid *ssid;
4365
4366 if (wpa_s->sched_scanning)
4367 wpa_supplicant_cancel_sched_scan(wpa_s);
4368
4369 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4370 if (wpa_s->current_ssid) {
4371#ifdef CONFIG_SME
4372 wpa_s->sme.prev_bssid_set = 0;
4373#endif /* CONFIG_SME */
4374 wpa_sm_set_config(wpa_s->wpa, NULL);
4375 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4376 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4377 wpa_s->own_disconnect_req = 1;
4378 wpa_supplicant_deauthenticate(
4379 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4380 }
4381 ssid = wpa_s->conf->ssid;
4382 while (ssid) {
4383 struct wpa_ssid *remove_ssid = ssid;
4384 int id;
4385
4386 id = ssid->id;
4387 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004388 wpas_notify_network_removed(wpa_s, remove_ssid);
4389 wpa_config_remove_network(wpa_s->conf, id);
4390 }
4391 return 0;
4392}
4393
4394
4395/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004396 * wpa_supplicant_enable_network - Mark a configured network as enabled
4397 * @wpa_s: wpa_supplicant structure for a network interface
4398 * @ssid: wpa_ssid structure for a configured network or %NULL
4399 *
4400 * Enables the specified network or all networks if no network specified.
4401 */
4402void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4403 struct wpa_ssid *ssid)
4404{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004405 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004406 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4407 wpa_supplicant_enable_one_network(wpa_s, ssid);
4408 } else
4409 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004410
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004411 if (wpa_s->reassociate && !wpa_s->disconnected &&
4412 (!wpa_s->current_ssid ||
4413 wpa_s->wpa_state == WPA_DISCONNECTED ||
4414 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004415 if (wpa_s->sched_scanning) {
4416 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4417 "new network to scan filters");
4418 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004419 }
4420
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004421 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4422 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004423 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004424 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004425 }
4426}
4427
4428
4429/**
4430 * wpa_supplicant_disable_network - Mark a configured network as disabled
4431 * @wpa_s: wpa_supplicant structure for a network interface
4432 * @ssid: wpa_ssid structure for a configured network or %NULL
4433 *
4434 * Disables the specified network or all networks if no network specified.
4435 */
4436void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4437 struct wpa_ssid *ssid)
4438{
4439 struct wpa_ssid *other_ssid;
4440 int was_disabled;
4441
4442 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004443 if (wpa_s->sched_scanning)
4444 wpa_supplicant_cancel_sched_scan(wpa_s);
4445
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004446 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4447 other_ssid = other_ssid->next) {
4448 was_disabled = other_ssid->disabled;
4449 if (was_disabled == 2)
4450 continue; /* do not change persistent P2P group
4451 * data */
4452
4453 other_ssid->disabled = 1;
4454
4455 if (was_disabled != other_ssid->disabled)
4456 wpas_notify_network_enabled_changed(
4457 wpa_s, other_ssid);
4458 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004459 if (wpa_s->current_ssid) {
4460 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4461 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004462 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004463 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004464 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004465 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004466 if (ssid == wpa_s->current_ssid) {
4467 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4468 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004469 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004470 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004471 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004472
4473 was_disabled = ssid->disabled;
4474
4475 ssid->disabled = 1;
4476
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004477 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004478 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004479 if (wpa_s->sched_scanning) {
4480 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4481 "to remove network from filters");
4482 wpa_supplicant_cancel_sched_scan(wpa_s);
4483 wpa_supplicant_req_scan(wpa_s, 0, 0);
4484 }
4485 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004486 }
4487}
4488
4489
4490/**
4491 * wpa_supplicant_select_network - Attempt association with a network
4492 * @wpa_s: wpa_supplicant structure for a network interface
4493 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4494 */
4495void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4496 struct wpa_ssid *ssid)
4497{
4498
4499 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004500 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004501
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004502 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004503 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4504 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004505 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004506 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004507 disconnected = 1;
4508 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004509
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004510 if (ssid)
4511 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004513 /*
4514 * Mark all other networks disabled or mark all networks enabled if no
4515 * network specified.
4516 */
4517 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4518 other_ssid = other_ssid->next) {
4519 int was_disabled = other_ssid->disabled;
4520 if (was_disabled == 2)
4521 continue; /* do not change persistent P2P group data */
4522
4523 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004524 if (was_disabled && !other_ssid->disabled)
4525 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004526
4527 if (was_disabled != other_ssid->disabled)
4528 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4529 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004530
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004531 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4532 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004533 /* We are already associated with the selected network */
4534 wpa_printf(MSG_DEBUG, "Already associated with the "
4535 "selected network - do nothing");
4536 return;
4537 }
4538
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004539 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004540 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004541 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004542 wpa_s->connect_without_scan =
4543 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004544
4545 /*
4546 * Don't optimize next scan freqs since a new ESS has been
4547 * selected.
4548 */
4549 os_free(wpa_s->next_scan_freqs);
4550 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004551 } else {
4552 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004553 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004555 wpa_s->disconnected = 0;
4556 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004557 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004558 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004559 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004560 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004561 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4562 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004563
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004564 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004565 wpa_supplicant_fast_associate(wpa_s) != 1) {
4566 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004567 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004568 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004569 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004570
4571 if (ssid)
4572 wpas_notify_network_selected(wpa_s, ssid);
4573}
4574
4575
4576/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004577 * wpas_remove_cred - Remove the specified credential and all the network
4578 * entries created based on the removed credential
4579 * @wpa_s: wpa_supplicant structure for a network interface
4580 * @cred: The credential to remove
4581 * Returns: 0 on success, -1 on failure
4582 */
4583int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4584{
4585 struct wpa_ssid *ssid, *next;
4586 int id;
4587
4588 if (!cred) {
4589 wpa_printf(MSG_DEBUG, "Could not find cred");
4590 return -1;
4591 }
4592
4593 id = cred->id;
4594 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4595 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4596 return -1;
4597 }
4598
4599 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4600
4601 /* Remove any network entry created based on the removed credential */
4602 ssid = wpa_s->conf->ssid;
4603 while (ssid) {
4604 next = ssid->next;
4605
4606 if (ssid->parent_cred == cred) {
4607 wpa_printf(MSG_DEBUG,
4608 "Remove network id %d since it used the removed credential",
4609 ssid->id);
4610 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4611 -1) {
4612 wpa_printf(MSG_DEBUG,
4613 "Could not find network id=%d",
4614 ssid->id);
4615 }
4616 }
4617
4618 ssid = next;
4619 }
4620
4621 return 0;
4622}
4623
4624
4625/**
4626 * wpas_remove_cred - Remove all the Interworking credentials
4627 * @wpa_s: wpa_supplicant structure for a network interface
4628 * Returns: 0 on success, -1 on failure
4629 */
4630int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4631{
4632 int res, ret = 0;
4633 struct wpa_cred *cred, *prev;
4634
4635 cred = wpa_s->conf->cred;
4636 while (cred) {
4637 prev = cred;
4638 cred = cred->next;
4639 res = wpas_remove_cred(wpa_s, prev);
4640 if (res < 0) {
4641 wpa_printf(MSG_DEBUG,
4642 "Removal of all credentials failed - failed to remove credential id=%d",
4643 prev->id);
4644 ret = -1;
4645 }
4646 }
4647
4648 return ret;
4649}
4650
4651
4652/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004653 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4654 * @wpa_s: wpa_supplicant structure for a network interface
4655 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4656 * @pkcs11_module_path: PKCS #11 module path or NULL
4657 * Returns: 0 on success; -1 on failure
4658 *
4659 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4660 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4661 * module path fails the paths will be reset to the default value (NULL).
4662 */
4663int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4664 const char *pkcs11_engine_path,
4665 const char *pkcs11_module_path)
4666{
4667 char *pkcs11_engine_path_copy = NULL;
4668 char *pkcs11_module_path_copy = NULL;
4669
4670 if (pkcs11_engine_path != NULL) {
4671 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4672 if (pkcs11_engine_path_copy == NULL)
4673 return -1;
4674 }
4675 if (pkcs11_module_path != NULL) {
4676 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004677 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004678 os_free(pkcs11_engine_path_copy);
4679 return -1;
4680 }
4681 }
4682
4683 os_free(wpa_s->conf->pkcs11_engine_path);
4684 os_free(wpa_s->conf->pkcs11_module_path);
4685 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4686 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4687
4688 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4689 eapol_sm_deinit(wpa_s->eapol);
4690 wpa_s->eapol = NULL;
4691 if (wpa_supplicant_init_eapol(wpa_s)) {
4692 /* Error -> Reset paths to the default value (NULL) once. */
4693 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4694 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4695 NULL);
4696
4697 return -1;
4698 }
4699 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4700
4701 return 0;
4702}
4703
4704
4705/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004706 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4707 * @wpa_s: wpa_supplicant structure for a network interface
4708 * @ap_scan: AP scan mode
4709 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4710 *
4711 */
4712int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4713{
4714
4715 int old_ap_scan;
4716
4717 if (ap_scan < 0 || ap_scan > 2)
4718 return -1;
4719
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004720 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4721 wpa_printf(MSG_INFO,
4722 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4723 }
4724
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004725#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004726 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4727 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4728 wpa_s->wpa_state < WPA_COMPLETED) {
4729 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4730 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004731 return 0;
4732 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004733#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004735 old_ap_scan = wpa_s->conf->ap_scan;
4736 wpa_s->conf->ap_scan = ap_scan;
4737
4738 if (old_ap_scan != wpa_s->conf->ap_scan)
4739 wpas_notify_ap_scan_changed(wpa_s);
4740
4741 return 0;
4742}
4743
4744
4745/**
4746 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4747 * @wpa_s: wpa_supplicant structure for a network interface
4748 * @expire_age: Expiration age in seconds
4749 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4750 *
4751 */
4752int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4753 unsigned int bss_expire_age)
4754{
4755 if (bss_expire_age < 10) {
4756 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4757 bss_expire_age);
4758 return -1;
4759 }
4760 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4761 bss_expire_age);
4762 wpa_s->conf->bss_expiration_age = bss_expire_age;
4763
4764 return 0;
4765}
4766
4767
4768/**
4769 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4770 * @wpa_s: wpa_supplicant structure for a network interface
4771 * @expire_count: number of scans after which an unseen BSS is reclaimed
4772 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4773 *
4774 */
4775int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4776 unsigned int bss_expire_count)
4777{
4778 if (bss_expire_count < 1) {
4779 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4780 bss_expire_count);
4781 return -1;
4782 }
4783 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4784 bss_expire_count);
4785 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4786
4787 return 0;
4788}
4789
4790
4791/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004792 * wpa_supplicant_set_scan_interval - Set scan interval
4793 * @wpa_s: wpa_supplicant structure for a network interface
4794 * @scan_interval: scan interval in seconds
4795 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4796 *
4797 */
4798int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4799 int scan_interval)
4800{
4801 if (scan_interval < 0) {
4802 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4803 scan_interval);
4804 return -1;
4805 }
4806 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4807 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004808 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004809
4810 return 0;
4811}
4812
4813
4814/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004815 * wpa_supplicant_set_debug_params - Set global debug params
4816 * @global: wpa_global structure
4817 * @debug_level: debug level
4818 * @debug_timestamp: determines if show timestamp in debug data
4819 * @debug_show_keys: determines if show keys in debug data
4820 * Returns: 0 if succeed or -1 if debug_level has wrong value
4821 */
4822int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4823 int debug_timestamp, int debug_show_keys)
4824{
4825
4826 int old_level, old_timestamp, old_show_keys;
4827
4828 /* check for allowed debuglevels */
4829 if (debug_level != MSG_EXCESSIVE &&
4830 debug_level != MSG_MSGDUMP &&
4831 debug_level != MSG_DEBUG &&
4832 debug_level != MSG_INFO &&
4833 debug_level != MSG_WARNING &&
4834 debug_level != MSG_ERROR)
4835 return -1;
4836
4837 old_level = wpa_debug_level;
4838 old_timestamp = wpa_debug_timestamp;
4839 old_show_keys = wpa_debug_show_keys;
4840
4841 wpa_debug_level = debug_level;
4842 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4843 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4844
4845 if (wpa_debug_level != old_level)
4846 wpas_notify_debug_level_changed(global);
4847 if (wpa_debug_timestamp != old_timestamp)
4848 wpas_notify_debug_timestamp_changed(global);
4849 if (wpa_debug_show_keys != old_show_keys)
4850 wpas_notify_debug_show_keys_changed(global);
4851
4852 return 0;
4853}
4854
4855
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004856#ifdef CONFIG_OWE
4857static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4858 const u8 *entry_ssid, size_t entry_ssid_len)
4859{
4860 const u8 *owe, *pos, *end;
4861 u8 ssid_len;
4862 struct wpa_bss *bss;
4863
4864 /* Check network profile SSID aganst the SSID in the
4865 * OWE Transition Mode element. */
4866
4867 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4868 if (!bss)
4869 return 0;
4870
4871 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4872 if (!owe)
4873 return 0;
4874
4875 pos = owe + 6;
4876 end = owe + 2 + owe[1];
4877
4878 if (end - pos < ETH_ALEN + 1)
4879 return 0;
4880 pos += ETH_ALEN;
4881 ssid_len = *pos++;
4882 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4883 return 0;
4884
4885 return entry_ssid_len == ssid_len &&
4886 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4887}
4888#endif /* CONFIG_OWE */
4889
4890
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004891/**
4892 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4893 * @wpa_s: Pointer to wpa_supplicant data
4894 * Returns: A pointer to the current network structure or %NULL on failure
4895 */
4896struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4897{
4898 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004899 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004900 int res;
4901 size_t ssid_len;
4902 u8 bssid[ETH_ALEN];
4903 int wired;
4904
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004905 res = wpa_drv_get_ssid(wpa_s, ssid);
4906 if (res < 0) {
4907 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4908 "driver");
4909 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004910 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004911 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004912
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004913 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004914 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4915 "driver");
4916 return NULL;
4917 }
4918
4919 wired = wpa_s->conf->ap_scan == 0 &&
4920 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4921
4922 entry = wpa_s->conf->ssid;
4923 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004924 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004925 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004926 (!entry->ssid ||
4927 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4928 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004929 (!entry->bssid_set ||
4930 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4931 return entry;
4932#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004933 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004934 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4935 (entry->ssid == NULL || entry->ssid_len == 0) &&
4936 (!entry->bssid_set ||
4937 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4938 return entry;
4939#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004940
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004941#ifdef CONFIG_OWE
4942 if (!wpas_network_disabled(wpa_s, entry) &&
4943 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4944 entry->ssid_len) &&
4945 (!entry->bssid_set ||
4946 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4947 return entry;
4948#endif /* CONFIG_OWE */
4949
Dmitry Shmidt04949592012-07-19 12:16:46 -07004950 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004951 entry->ssid_len == 0 &&
4952 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4953 return entry;
4954
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004955 entry = entry->next;
4956 }
4957
4958 return NULL;
4959}
4960
4961
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004962static int select_driver(struct wpa_supplicant *wpa_s, int i)
4963{
4964 struct wpa_global *global = wpa_s->global;
4965
4966 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004967 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004968 if (global->drv_priv[i] == NULL) {
4969 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4970 "'%s'", wpa_drivers[i]->name);
4971 return -1;
4972 }
4973 }
4974
4975 wpa_s->driver = wpa_drivers[i];
4976 wpa_s->global_drv_priv = global->drv_priv[i];
4977
4978 return 0;
4979}
4980
4981
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004982static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4983 const char *name)
4984{
4985 int i;
4986 size_t len;
4987 const char *pos, *driver = name;
4988
4989 if (wpa_s == NULL)
4990 return -1;
4991
4992 if (wpa_drivers[0] == NULL) {
4993 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4994 "wpa_supplicant");
4995 return -1;
4996 }
4997
4998 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08004999 /* Default to first successful driver in the list */
5000 for (i = 0; wpa_drivers[i]; i++) {
5001 if (select_driver(wpa_s, i) == 0)
5002 return 0;
5003 }
5004 /* Drivers have each reported failure, so no wpa_msg() here. */
5005 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005006 }
5007
5008 do {
5009 pos = os_strchr(driver, ',');
5010 if (pos)
5011 len = pos - driver;
5012 else
5013 len = os_strlen(driver);
5014
5015 for (i = 0; wpa_drivers[i]; i++) {
5016 if (os_strlen(wpa_drivers[i]->name) == len &&
5017 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005018 0) {
5019 /* First driver that succeeds wins */
5020 if (select_driver(wpa_s, i) == 0)
5021 return 0;
5022 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005023 }
5024
5025 driver = pos + 1;
5026 } while (pos);
5027
5028 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5029 return -1;
5030}
5031
5032
5033/**
5034 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5035 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5036 * with struct wpa_driver_ops::init()
5037 * @src_addr: Source address of the EAPOL frame
5038 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5039 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005040 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005041 *
5042 * This function is called for each received EAPOL frame. Most driver
5043 * interfaces rely on more generic OS mechanism for receiving frames through
5044 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5045 * take care of received EAPOL frames and deliver them to the core supplicant
5046 * code by calling this function.
5047 */
5048void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005049 const u8 *buf, size_t len,
5050 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005051{
5052 struct wpa_supplicant *wpa_s = ctx;
5053
Sunil8cd6f4d2022-06-28 18:40:46 +00005054 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5055 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005056 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5057
Hai Shalomc1a21442022-02-04 13:43:00 -08005058 if (wpa_s->own_disconnect_req) {
5059 wpa_printf(MSG_DEBUG,
5060 "Drop received EAPOL frame as we are disconnecting");
5061 return;
5062 }
5063
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005064#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005065 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5066 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005067 if (wpa_s->ignore_auth_resp) {
5068 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5069 return;
5070 }
5071#endif /* CONFIG_TESTING_OPTIONS */
5072
Jouni Malinena05074c2012-12-21 21:35:35 +02005073 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5074 (wpa_s->last_eapol_matches_bssid &&
5075#ifdef CONFIG_AP
5076 !wpa_s->ap_iface &&
5077#endif /* CONFIG_AP */
5078 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005079 /*
5080 * There is possible race condition between receiving the
5081 * association event and the EAPOL frame since they are coming
5082 * through different paths from the driver. In order to avoid
5083 * issues in trying to process the EAPOL frame before receiving
5084 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005085 * the association event is received. This may also be needed in
5086 * driver-based roaming case, so also use src_addr != BSSID as a
5087 * trigger if we have previously confirmed that the
5088 * Authenticator uses BSSID as the src_addr (which is not the
5089 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005090 */
5091 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02005092 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
5093 wpa_supplicant_state_txt(wpa_s->wpa_state),
5094 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005095 wpabuf_free(wpa_s->pending_eapol_rx);
5096 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5097 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005098 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005099 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5100 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005101 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005102 }
5103 return;
5104 }
5105
Jouni Malinena05074c2012-12-21 21:35:35 +02005106 wpa_s->last_eapol_matches_bssid =
5107 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
5108
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005109#ifdef CONFIG_AP
5110 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005111 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5112 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005113 return;
5114 }
5115#endif /* CONFIG_AP */
5116
5117 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5118 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5119 "no key management is configured");
5120 return;
5121 }
5122
5123 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005124 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005125 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5126 wpa_s->wpa_state != WPA_COMPLETED) &&
5127 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005128 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005129 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005130 int timeout = 10;
5131
5132 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5133 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5134 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5135 /* Use longer timeout for IEEE 802.1X/EAP */
5136 timeout = 70;
5137 }
5138
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005139#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005140 if (wpa_s->current_ssid && wpa_s->current_bss &&
5141 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5142 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5143 /*
5144 * Use shorter timeout if going through WPS AP iteration
5145 * for PIN config method with an AP that does not
5146 * advertise Selected Registrar.
5147 */
5148 struct wpabuf *wps_ie;
5149
5150 wps_ie = wpa_bss_get_vendor_ie_multi(
5151 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5152 if (wps_ie &&
5153 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5154 timeout = 10;
5155 wpabuf_free(wps_ie);
5156 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005157#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005158
5159 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005160 }
5161 wpa_s->eapol_received++;
5162
5163 if (wpa_s->countermeasures) {
5164 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5165 "EAPOL packet");
5166 return;
5167 }
5168
5169#ifdef CONFIG_IBSS_RSN
5170 if (wpa_s->current_ssid &&
5171 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005172 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5173 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005174 return;
5175 }
5176#endif /* CONFIG_IBSS_RSN */
5177
5178 /* Source address of the incoming EAPOL frame could be compared to the
5179 * current BSSID. However, it is possible that a centralized
5180 * Authenticator could be using another MAC address than the BSSID of
5181 * an AP, so just allow any address to be used for now. The replies are
5182 * still sent to the current BSSID (if available), though. */
5183
5184 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5185 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005186 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5187 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005188 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5189 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005190 return;
5191 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005192 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005193 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005194 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5195 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005196 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005197 * handshake processing which would normally set portValid. We
5198 * need this to allow the EAPOL state machines to be completed
5199 * without going through EAPOL-Key handshake.
5200 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005201 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005202 }
5203}
5204
5205
Sunil8cd6f4d2022-06-28 18:40:46 +00005206static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5207 const u8 *buf, size_t len)
5208{
5209 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5210 FRAME_ENCRYPTION_UNKNOWN);
5211}
5212
5213
Hai Shalomb755a2a2020-04-23 21:49:02 -07005214static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5215{
5216 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5217 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5218}
5219
5220
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005221int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005222{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005223 if ((!wpa_s->p2p_mgmt ||
5224 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5225 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005226 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005227 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5228 wpa_drv_get_mac_addr(wpa_s),
5229 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005230 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005231 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005232 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005233 if (wpa_s->l2 == NULL)
5234 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005235
5236 if (l2_packet_set_packet_filter(wpa_s->l2,
5237 L2_PACKET_FILTER_PKTTYPE))
5238 wpa_dbg(wpa_s, MSG_DEBUG,
5239 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005240
5241 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5242 wpa_msg(wpa_s, MSG_ERROR,
5243 "Failed to get own L2 address");
5244 return -1;
5245 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005246 } else {
5247 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5248 if (addr)
5249 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5250 }
5251
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005252 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005253 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005254
Hai Shalomc3565922019-10-28 11:58:20 -07005255#ifdef CONFIG_FST
5256 if (wpa_s->fst)
5257 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5258#endif /* CONFIG_FST */
5259
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005260 return 0;
5261}
5262
5263
Dmitry Shmidt04949592012-07-19 12:16:46 -07005264static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5265 const u8 *buf, size_t len)
5266{
5267 struct wpa_supplicant *wpa_s = ctx;
5268 const struct l2_ethhdr *eth;
5269
5270 if (len < sizeof(*eth))
5271 return;
5272 eth = (const struct l2_ethhdr *) buf;
5273
5274 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5275 !(eth->h_dest[0] & 0x01)) {
5276 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5277 " (bridge - not for this interface - ignore)",
5278 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5279 return;
5280 }
5281
5282 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5283 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5284 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005285 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005286}
5287
5288
Hai Shalom899fcc72020-10-19 14:38:18 -07005289int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5290 const char *bridge_ifname)
5291{
5292 if (wpa_s->wpa_state > WPA_SCANNING)
5293 return -EBUSY;
5294
5295 if (bridge_ifname &&
5296 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5297 return -EINVAL;
5298
5299 if (!bridge_ifname)
5300 bridge_ifname = "";
5301
5302 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5303 return 0;
5304
5305 if (wpa_s->l2_br) {
5306 l2_packet_deinit(wpa_s->l2_br);
5307 wpa_s->l2_br = NULL;
5308 }
5309
5310 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5311 sizeof(wpa_s->bridge_ifname));
5312
5313 if (wpa_s->bridge_ifname[0]) {
5314 wpa_dbg(wpa_s, MSG_DEBUG,
5315 "Receiving packets from bridge interface '%s'",
5316 wpa_s->bridge_ifname);
5317 wpa_s->l2_br = l2_packet_init_bridge(
5318 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5319 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5320 if (!wpa_s->l2_br) {
5321 wpa_msg(wpa_s, MSG_ERROR,
5322 "Failed to open l2_packet connection for the bridge interface '%s'",
5323 wpa_s->bridge_ifname);
5324 goto fail;
5325 }
5326 }
5327
5328#ifdef CONFIG_TDLS
5329 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5330 goto fail;
5331#endif /* CONFIG_TDLS */
5332
5333 return 0;
5334fail:
5335 wpa_s->bridge_ifname[0] = 0;
5336 if (wpa_s->l2_br) {
5337 l2_packet_deinit(wpa_s->l2_br);
5338 wpa_s->l2_br = NULL;
5339 }
5340#ifdef CONFIG_TDLS
5341 if (!wpa_s->p2p_mgmt)
5342 wpa_tdls_init(wpa_s->wpa);
5343#endif /* CONFIG_TDLS */
5344 return -EIO;
5345}
5346
5347
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005348/**
5349 * wpa_supplicant_driver_init - Initialize driver interface parameters
5350 * @wpa_s: Pointer to wpa_supplicant data
5351 * Returns: 0 on success, -1 on failure
5352 *
5353 * This function is called to initialize driver interface parameters.
5354 * wpa_drv_init() must have been called before this function to initialize the
5355 * driver interface.
5356 */
5357int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5358{
5359 static int interface_count = 0;
5360
5361 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5362 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005363
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005364 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5365 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005366 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005367 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5368
Hai Shalomb755a2a2020-04-23 21:49:02 -07005369 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005370 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5371 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005372 wpa_s->l2_br = l2_packet_init_bridge(
5373 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5374 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005375 if (wpa_s->l2_br == NULL) {
5376 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5377 "connection for the bridge interface '%s'",
5378 wpa_s->bridge_ifname);
5379 return -1;
5380 }
5381 }
5382
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005383 if (wpa_s->conf->ap_scan == 2 &&
5384 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5385 wpa_printf(MSG_INFO,
5386 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5387 }
5388
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005389 wpa_clear_keys(wpa_s, NULL);
5390
5391 /* Make sure that TKIP countermeasures are not left enabled (could
5392 * happen if wpa_supplicant is killed during countermeasures. */
5393 wpa_drv_set_countermeasures(wpa_s, 0);
5394
5395 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5396 wpa_drv_flush_pmkid(wpa_s);
5397
5398 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005399 wpa_s->prev_scan_wildcard = 0;
5400
Dmitry Shmidt04949592012-07-19 12:16:46 -07005401 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005402 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5403 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5404 interface_count = 0;
5405 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005406#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005407 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005408 wpa_supplicant_delayed_sched_scan(wpa_s,
5409 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005410 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005411 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005412 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005413#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005414 interface_count++;
5415 } else
5416 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5417
5418 return 0;
5419}
5420
5421
5422static int wpa_supplicant_daemon(const char *pid_file)
5423{
5424 wpa_printf(MSG_DEBUG, "Daemonize..");
5425 return os_daemonize(pid_file);
5426}
5427
5428
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005429static struct wpa_supplicant *
5430wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005431{
5432 struct wpa_supplicant *wpa_s;
5433
5434 wpa_s = os_zalloc(sizeof(*wpa_s));
5435 if (wpa_s == NULL)
5436 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005437 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005438 wpa_s->scan_interval = 5;
5439 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005440 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005441 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005442 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005443 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005444
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005445 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005446 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005447#ifdef CONFIG_TESTING_OPTIONS
5448 dl_list_init(&wpa_s->drv_signal_override);
5449#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005450 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005451
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005452 return wpa_s;
5453}
5454
5455
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005456#ifdef CONFIG_HT_OVERRIDES
5457
5458static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5459 struct ieee80211_ht_capabilities *htcaps,
5460 struct ieee80211_ht_capabilities *htcaps_mask,
5461 const char *ht_mcs)
5462{
5463 /* parse ht_mcs into hex array */
5464 int i;
5465 const char *tmp = ht_mcs;
5466 char *end = NULL;
5467
5468 /* If ht_mcs is null, do not set anything */
5469 if (!ht_mcs)
5470 return 0;
5471
5472 /* This is what we are setting in the kernel */
5473 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5474
5475 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5476
5477 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005478 long v;
5479
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005480 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005481 v = strtol(tmp, &end, 16);
5482
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005483 if (errno == 0) {
5484 wpa_msg(wpa_s, MSG_DEBUG,
5485 "htcap value[%i]: %ld end: %p tmp: %p",
5486 i, v, end, tmp);
5487 if (end == tmp)
5488 break;
5489
5490 htcaps->supported_mcs_set[i] = v;
5491 tmp = end;
5492 } else {
5493 wpa_msg(wpa_s, MSG_ERROR,
5494 "Failed to parse ht-mcs: %s, error: %s\n",
5495 ht_mcs, strerror(errno));
5496 return -1;
5497 }
5498 }
5499
5500 /*
5501 * If we were able to parse any values, then set mask for the MCS set.
5502 */
5503 if (i) {
5504 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5505 IEEE80211_HT_MCS_MASK_LEN - 1);
5506 /* skip the 3 reserved bits */
5507 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5508 0x1f;
5509 }
5510
5511 return 0;
5512}
5513
5514
5515static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5516 struct ieee80211_ht_capabilities *htcaps,
5517 struct ieee80211_ht_capabilities *htcaps_mask,
5518 int disabled)
5519{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005520 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005521
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005522 if (disabled == -1)
5523 return 0;
5524
Hai Shalom74f70d42019-02-11 14:42:39 -08005525 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5526
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005527 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5528 htcaps_mask->ht_capabilities_info |= msk;
5529 if (disabled)
5530 htcaps->ht_capabilities_info &= msk;
5531 else
5532 htcaps->ht_capabilities_info |= msk;
5533
5534 return 0;
5535}
5536
5537
5538static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5539 struct ieee80211_ht_capabilities *htcaps,
5540 struct ieee80211_ht_capabilities *htcaps_mask,
5541 int factor)
5542{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005543 if (factor == -1)
5544 return 0;
5545
Hai Shalom74f70d42019-02-11 14:42:39 -08005546 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5547
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005548 if (factor < 0 || factor > 3) {
5549 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5550 "Must be 0-3 or -1", factor);
5551 return -EINVAL;
5552 }
5553
5554 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5555 htcaps->a_mpdu_params &= ~0x3;
5556 htcaps->a_mpdu_params |= factor & 0x3;
5557
5558 return 0;
5559}
5560
5561
5562static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5563 struct ieee80211_ht_capabilities *htcaps,
5564 struct ieee80211_ht_capabilities *htcaps_mask,
5565 int density)
5566{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005567 if (density == -1)
5568 return 0;
5569
Hai Shalom74f70d42019-02-11 14:42:39 -08005570 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5571
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005572 if (density < 0 || density > 7) {
5573 wpa_msg(wpa_s, MSG_ERROR,
5574 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5575 density);
5576 return -EINVAL;
5577 }
5578
5579 htcaps_mask->a_mpdu_params |= 0x1C;
5580 htcaps->a_mpdu_params &= ~(0x1C);
5581 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5582
5583 return 0;
5584}
5585
5586
5587static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5588 struct ieee80211_ht_capabilities *htcaps,
5589 struct ieee80211_ht_capabilities *htcaps_mask,
5590 int disabled)
5591{
Hai Shalom74f70d42019-02-11 14:42:39 -08005592 if (disabled)
5593 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005594
Paul Stewart092955c2017-02-06 09:13:09 -08005595 set_disable_ht40(htcaps, disabled);
5596 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005597
5598 return 0;
5599}
5600
5601
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005602static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5603 struct ieee80211_ht_capabilities *htcaps,
5604 struct ieee80211_ht_capabilities *htcaps_mask,
5605 int disabled)
5606{
5607 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005608 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5609 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005610
Hai Shalom74f70d42019-02-11 14:42:39 -08005611 if (disabled)
5612 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005613
5614 if (disabled)
5615 htcaps->ht_capabilities_info &= ~msk;
5616 else
5617 htcaps->ht_capabilities_info |= msk;
5618
5619 htcaps_mask->ht_capabilities_info |= msk;
5620
5621 return 0;
5622}
5623
5624
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005625static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5626 struct ieee80211_ht_capabilities *htcaps,
5627 struct ieee80211_ht_capabilities *htcaps_mask,
5628 int disabled)
5629{
5630 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005631 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005632
Hai Shalom74f70d42019-02-11 14:42:39 -08005633 if (disabled)
5634 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005635
5636 if (disabled)
5637 htcaps->ht_capabilities_info &= ~msk;
5638 else
5639 htcaps->ht_capabilities_info |= msk;
5640
5641 htcaps_mask->ht_capabilities_info |= msk;
5642
5643 return 0;
5644}
5645
5646
Hai Shalom74f70d42019-02-11 14:42:39 -08005647static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5648 struct ieee80211_ht_capabilities *htcaps,
5649 struct ieee80211_ht_capabilities *htcaps_mask,
5650 int tx_stbc)
5651{
5652 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5653
5654 if (tx_stbc == -1)
5655 return 0;
5656
5657 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5658
5659 if (tx_stbc < 0 || tx_stbc > 1) {
5660 wpa_msg(wpa_s, MSG_ERROR,
5661 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5662 return -EINVAL;
5663 }
5664
5665 htcaps_mask->ht_capabilities_info |= msk;
5666 htcaps->ht_capabilities_info &= ~msk;
5667 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5668
5669 return 0;
5670}
5671
5672
5673static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5674 struct ieee80211_ht_capabilities *htcaps,
5675 struct ieee80211_ht_capabilities *htcaps_mask,
5676 int rx_stbc)
5677{
5678 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5679
5680 if (rx_stbc == -1)
5681 return 0;
5682
5683 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5684
5685 if (rx_stbc < 0 || rx_stbc > 3) {
5686 wpa_msg(wpa_s, MSG_ERROR,
5687 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5688 return -EINVAL;
5689 }
5690
5691 htcaps_mask->ht_capabilities_info |= msk;
5692 htcaps->ht_capabilities_info &= ~msk;
5693 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5694
5695 return 0;
5696}
5697
5698
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005699void wpa_supplicant_apply_ht_overrides(
5700 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5701 struct wpa_driver_associate_params *params)
5702{
5703 struct ieee80211_ht_capabilities *htcaps;
5704 struct ieee80211_ht_capabilities *htcaps_mask;
5705
5706 if (!ssid)
5707 return;
5708
5709 params->disable_ht = ssid->disable_ht;
5710 if (!params->htcaps || !params->htcaps_mask)
5711 return;
5712
5713 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5714 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5715 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5716 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5717 ssid->disable_max_amsdu);
5718 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5719 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5720 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005721 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005722 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005723 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5724 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005725
5726 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005727 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005728 htcaps->ht_capabilities_info |= bit;
5729 htcaps_mask->ht_capabilities_info |= bit;
5730 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005731}
5732
5733#endif /* CONFIG_HT_OVERRIDES */
5734
5735
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005736#ifdef CONFIG_VHT_OVERRIDES
5737void wpa_supplicant_apply_vht_overrides(
5738 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5739 struct wpa_driver_associate_params *params)
5740{
5741 struct ieee80211_vht_capabilities *vhtcaps;
5742 struct ieee80211_vht_capabilities *vhtcaps_mask;
5743
5744 if (!ssid)
5745 return;
5746
5747 params->disable_vht = ssid->disable_vht;
5748
5749 vhtcaps = (void *) params->vhtcaps;
5750 vhtcaps_mask = (void *) params->vhtcaps_mask;
5751
5752 if (!vhtcaps || !vhtcaps_mask)
5753 return;
5754
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005755 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5756 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005757
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005758#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005759 if (ssid->disable_sgi) {
5760 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5761 VHT_CAP_SHORT_GI_160);
5762 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5763 VHT_CAP_SHORT_GI_160);
5764 wpa_msg(wpa_s, MSG_DEBUG,
5765 "disable-sgi override specified, vht-caps: 0x%x",
5766 vhtcaps->vht_capabilities_info);
5767 }
5768
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005769 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005770 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5771 int max_ampdu;
5772
5773 max_ampdu = (ssid->vht_capa &
5774 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5775 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005776
5777 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5778 wpa_set_ampdu_factor(wpa_s,
5779 (void *) params->htcaps,
5780 (void *) params->htcaps_mask,
5781 max_ampdu);
5782 }
5783#endif /* CONFIG_HT_OVERRIDES */
5784
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005785#define OVERRIDE_MCS(i) \
5786 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5787 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005788 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005789 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005790 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5791 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005792 } \
5793 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5794 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005795 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005796 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005797 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5798 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005799 }
5800
5801 OVERRIDE_MCS(1);
5802 OVERRIDE_MCS(2);
5803 OVERRIDE_MCS(3);
5804 OVERRIDE_MCS(4);
5805 OVERRIDE_MCS(5);
5806 OVERRIDE_MCS(6);
5807 OVERRIDE_MCS(7);
5808 OVERRIDE_MCS(8);
5809}
5810#endif /* CONFIG_VHT_OVERRIDES */
5811
5812
Hai Shalomfdcde762020-04-02 11:19:20 -07005813#ifdef CONFIG_HE_OVERRIDES
5814void wpa_supplicant_apply_he_overrides(
5815 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5816 struct wpa_driver_associate_params *params)
5817{
5818 if (!ssid)
5819 return;
5820
5821 params->disable_he = ssid->disable_he;
5822}
5823#endif /* CONFIG_HE_OVERRIDES */
5824
5825
Dmitry Shmidt04949592012-07-19 12:16:46 -07005826static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5827{
5828#ifdef PCSC_FUNCS
5829 size_t len;
5830
5831 if (!wpa_s->conf->pcsc_reader)
5832 return 0;
5833
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005834 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005835 if (!wpa_s->scard)
5836 return 1;
5837
5838 if (wpa_s->conf->pcsc_pin &&
5839 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5840 scard_deinit(wpa_s->scard);
5841 wpa_s->scard = NULL;
5842 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5843 return -1;
5844 }
5845
5846 len = sizeof(wpa_s->imsi) - 1;
5847 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5848 scard_deinit(wpa_s->scard);
5849 wpa_s->scard = NULL;
5850 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5851 return -1;
5852 }
5853 wpa_s->imsi[len] = '\0';
5854
5855 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5856
5857 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5858 wpa_s->imsi, wpa_s->mnc_len);
5859
5860 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5861 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5862#endif /* PCSC_FUNCS */
5863
5864 return 0;
5865}
5866
5867
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005868int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5869{
5870 char *val, *pos;
5871
5872 ext_password_deinit(wpa_s->ext_pw);
5873 wpa_s->ext_pw = NULL;
5874 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5875
5876 if (!wpa_s->conf->ext_password_backend)
5877 return 0;
5878
5879 val = os_strdup(wpa_s->conf->ext_password_backend);
5880 if (val == NULL)
5881 return -1;
5882 pos = os_strchr(val, ':');
5883 if (pos)
5884 *pos++ = '\0';
5885
5886 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5887
5888 wpa_s->ext_pw = ext_password_init(val, pos);
5889 os_free(val);
5890 if (wpa_s->ext_pw == NULL) {
5891 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5892 return -1;
5893 }
5894 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5895
5896 return 0;
5897}
5898
5899
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005900#ifdef CONFIG_FST
5901
5902static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5903{
5904 struct wpa_supplicant *wpa_s = ctx;
5905
5906 return (is_zero_ether_addr(wpa_s->bssid) ||
5907 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5908}
5909
5910
5911static void wpas_fst_get_channel_info_cb(void *ctx,
5912 enum hostapd_hw_mode *hw_mode,
5913 u8 *channel)
5914{
5915 struct wpa_supplicant *wpa_s = ctx;
5916
5917 if (wpa_s->current_bss) {
5918 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5919 channel);
5920 } else if (wpa_s->hw.num_modes) {
5921 *hw_mode = wpa_s->hw.modes[0].mode;
5922 } else {
5923 WPA_ASSERT(0);
5924 *hw_mode = 0;
5925 }
5926}
5927
5928
5929static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5930{
5931 struct wpa_supplicant *wpa_s = ctx;
5932
5933 *modes = wpa_s->hw.modes;
5934 return wpa_s->hw.num_modes;
5935}
5936
5937
5938static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5939{
5940 struct wpa_supplicant *wpa_s = ctx;
5941
5942 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5943 wpa_s->fst_ies = fst_ies;
5944}
5945
5946
5947static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5948{
5949 struct wpa_supplicant *wpa_s = ctx;
5950
Paul Stewart092955c2017-02-06 09:13:09 -08005951 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5952 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5953 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5954 return -1;
5955 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005956 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005957 wpa_s->own_addr, wpa_s->bssid,
5958 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005959 0);
5960}
5961
5962
5963static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5964{
5965 struct wpa_supplicant *wpa_s = ctx;
5966
5967 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5968 return wpa_s->received_mb_ies;
5969}
5970
5971
5972static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5973 const u8 *buf, size_t size)
5974{
5975 struct wpa_supplicant *wpa_s = ctx;
5976 struct mb_ies_info info;
5977
5978 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5979
5980 if (!mb_ies_info_by_ies(&info, buf, size)) {
5981 wpabuf_free(wpa_s->received_mb_ies);
5982 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5983 }
5984}
5985
5986
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005987static const u8 * wpas_fst_get_peer_first(void *ctx,
5988 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005989 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005990{
5991 struct wpa_supplicant *wpa_s = ctx;
5992
5993 *get_ctx = NULL;
5994 if (!is_zero_ether_addr(wpa_s->bssid))
5995 return (wpa_s->received_mb_ies || !mb_only) ?
5996 wpa_s->bssid : NULL;
5997 return NULL;
5998}
5999
6000
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006001static const u8 * wpas_fst_get_peer_next(void *ctx,
6002 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006003 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006004{
6005 return NULL;
6006}
6007
6008void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6009 struct fst_wpa_obj *iface_obj)
6010{
Sunil8cd6f4d2022-06-28 18:40:46 +00006011 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006012 iface_obj->ctx = wpa_s;
6013 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6014 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6015 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6016 iface_obj->set_ies = wpas_fst_set_ies_cb;
6017 iface_obj->send_action = wpas_fst_send_action_cb;
6018 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6019 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6020 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6021 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6022}
6023#endif /* CONFIG_FST */
6024
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006025static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006026 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006027{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006028 struct wowlan_triggers *triggers;
6029 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006030
6031 if (!wpa_s->conf->wowlan_triggers)
6032 return 0;
6033
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006034 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6035 if (triggers) {
6036 ret = wpa_drv_wowlan(wpa_s, triggers);
6037 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006038 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006039 return ret;
6040}
6041
6042
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006043enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006044{
6045 if (freq < 3000)
6046 return BAND_2_4_GHZ;
6047 if (freq > 50000)
6048 return BAND_60_GHZ;
6049 return BAND_5_GHZ;
6050}
6051
6052
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006053unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006054{
6055 int i;
6056 unsigned int band = 0;
6057
6058 if (freqs) {
6059 /* freqs are specified for the radio work */
6060 for (i = 0; freqs[i]; i++)
6061 band |= wpas_freq_to_band(freqs[i]);
6062 } else {
6063 /*
6064 * freqs are not specified, implies all
6065 * the supported freqs by HW
6066 */
6067 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6068 if (wpa_s->hw.modes[i].num_channels != 0) {
6069 if (wpa_s->hw.modes[i].mode ==
6070 HOSTAPD_MODE_IEEE80211B ||
6071 wpa_s->hw.modes[i].mode ==
6072 HOSTAPD_MODE_IEEE80211G)
6073 band |= BAND_2_4_GHZ;
6074 else if (wpa_s->hw.modes[i].mode ==
6075 HOSTAPD_MODE_IEEE80211A)
6076 band |= BAND_5_GHZ;
6077 else if (wpa_s->hw.modes[i].mode ==
6078 HOSTAPD_MODE_IEEE80211AD)
6079 band |= BAND_60_GHZ;
6080 else if (wpa_s->hw.modes[i].mode ==
6081 HOSTAPD_MODE_IEEE80211ANY)
6082 band = BAND_2_4_GHZ | BAND_5_GHZ |
6083 BAND_60_GHZ;
6084 }
6085 }
6086 }
6087
6088 return band;
6089}
6090
6091
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006092static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6093 const char *rn)
6094{
6095 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6096 struct wpa_radio *radio;
6097
6098 while (rn && iface) {
6099 radio = iface->radio;
6100 if (radio && os_strcmp(rn, radio->name) == 0) {
6101 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6102 wpa_s->ifname, rn);
6103 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6104 return radio;
6105 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006106
6107 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006108 }
6109
6110 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6111 wpa_s->ifname, rn ? rn : "N/A");
6112 radio = os_zalloc(sizeof(*radio));
6113 if (radio == NULL)
6114 return NULL;
6115
6116 if (rn)
6117 os_strlcpy(radio->name, rn, sizeof(radio->name));
6118 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006119 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006120 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6121
6122 return radio;
6123}
6124
6125
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006126static void radio_work_free(struct wpa_radio_work *work)
6127{
6128 if (work->wpa_s->scan_work == work) {
6129 /* This should not really happen. */
6130 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6131 work->type, work, work->started);
6132 work->wpa_s->scan_work = NULL;
6133 }
6134
6135#ifdef CONFIG_P2P
6136 if (work->wpa_s->p2p_scan_work == work) {
6137 /* This should not really happen. */
6138 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6139 work->type, work, work->started);
6140 work->wpa_s->p2p_scan_work = NULL;
6141 }
6142#endif /* CONFIG_P2P */
6143
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006144 if (work->started) {
6145 work->wpa_s->radio->num_active_works--;
6146 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006147 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006148 work->type, work,
6149 work->wpa_s->radio->num_active_works);
6150 }
6151
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006152 dl_list_del(&work->list);
6153 os_free(work);
6154}
6155
6156
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006157static int radio_work_is_connect(struct wpa_radio_work *work)
6158{
6159 return os_strcmp(work->type, "sme-connect") == 0 ||
6160 os_strcmp(work->type, "connect") == 0;
6161}
6162
6163
6164static int radio_work_is_scan(struct wpa_radio_work *work)
6165{
6166 return os_strcmp(work->type, "scan") == 0 ||
6167 os_strcmp(work->type, "p2p-scan") == 0;
6168}
6169
6170
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006171static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6172{
6173 struct wpa_radio_work *active_work = NULL;
6174 struct wpa_radio_work *tmp;
6175
6176 /* Get the active work to know the type and band. */
6177 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6178 if (tmp->started) {
6179 active_work = tmp;
6180 break;
6181 }
6182 }
6183
6184 if (!active_work) {
6185 /* No active work, start one */
6186 radio->num_active_works = 0;
6187 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6188 list) {
6189 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006190 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006191 (((struct wpa_driver_scan_params *)
6192 tmp->ctx)->only_new_results ||
6193 tmp->wpa_s->clear_driver_scan_cache))
6194 continue;
6195 return tmp;
6196 }
6197 return NULL;
6198 }
6199
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006200 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006201 /*
6202 * If the active work is either connect or sme-connect,
6203 * do not parallelize them with other radio works.
6204 */
6205 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6206 "Do not parallelize radio work with %s",
6207 active_work->type);
6208 return NULL;
6209 }
6210
6211 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6212 if (tmp->started)
6213 continue;
6214
6215 /*
6216 * If connect or sme-connect are enqueued, parallelize only
6217 * those operations ahead of them in the queue.
6218 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006219 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006220 break;
6221
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006222 /* Serialize parallel scan and p2p_scan operations on the same
6223 * interface since the driver_nl80211 mechanism for tracking
6224 * scan cookies does not yet have support for this. */
6225 if (active_work->wpa_s == tmp->wpa_s &&
6226 radio_work_is_scan(active_work) &&
6227 radio_work_is_scan(tmp)) {
6228 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6229 "Do not start work '%s' when another work '%s' is already scheduled",
6230 tmp->type, active_work->type);
6231 continue;
6232 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006233 /*
6234 * Check that the radio works are distinct and
6235 * on different bands.
6236 */
6237 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6238 (active_work->bands != tmp->bands)) {
6239 /*
6240 * If a scan has to be scheduled through nl80211 scan
6241 * interface and if an external scan is already running,
6242 * do not schedule the scan since it is likely to get
6243 * rejected by kernel.
6244 */
6245 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006246 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006247 (((struct wpa_driver_scan_params *)
6248 tmp->ctx)->only_new_results ||
6249 tmp->wpa_s->clear_driver_scan_cache))
6250 continue;
6251
6252 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6253 "active_work:%s new_work:%s",
6254 active_work->type, tmp->type);
6255 return tmp;
6256 }
6257 }
6258
6259 /* Did not find a radio work to schedule in parallel. */
6260 return NULL;
6261}
6262
6263
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006264static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6265{
6266 struct wpa_radio *radio = eloop_ctx;
6267 struct wpa_radio_work *work;
6268 struct os_reltime now, diff;
6269 struct wpa_supplicant *wpa_s;
6270
6271 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006272 if (work == NULL) {
6273 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006274 return;
6275 }
6276
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006277 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6278 radio_list);
6279
6280 if (!(wpa_s &&
6281 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6282 if (work->started)
6283 return; /* already started and still in progress */
6284
Hai Shalom60840252021-02-19 19:02:11 -08006285 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006286 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6287 return;
6288 }
6289 } else {
6290 work = NULL;
6291 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6292 /* get the work to schedule next */
6293 work = radio_work_get_next_work(radio);
6294 }
6295 if (!work)
6296 return;
6297 }
6298
6299 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006300 os_get_reltime(&now);
6301 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006302 wpa_dbg(wpa_s, MSG_DEBUG,
6303 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006304 work->type, work, diff.sec, diff.usec);
6305 work->started = 1;
6306 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006307 radio->num_active_works++;
6308
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006309 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006310
6311 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6312 radio->num_active_works < MAX_ACTIVE_WORKS)
6313 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006314}
6315
6316
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006317/*
6318 * This function removes both started and pending radio works running on
6319 * the provided interface's radio.
6320 * Prior to the removal of the radio work, its callback (cb) is called with
6321 * deinit set to be 1. Each work's callback is responsible for clearing its
6322 * internal data and restoring to a correct state.
6323 * @wpa_s: wpa_supplicant data
6324 * @type: type of works to be removed
6325 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6326 * this interface's works.
6327 */
6328void radio_remove_works(struct wpa_supplicant *wpa_s,
6329 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006330{
6331 struct wpa_radio_work *work, *tmp;
6332 struct wpa_radio *radio = wpa_s->radio;
6333
6334 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6335 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006336 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006337 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006338
6339 /* skip other ifaces' works */
6340 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006341 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006342
6343 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6344 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006345 work->cb(work, 1);
6346 radio_work_free(work);
6347 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006348
6349 /* in case we removed the started work */
6350 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006351}
6352
6353
Roshan Pius3a1667e2018-07-03 15:17:14 -07006354void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6355{
6356 struct wpa_radio_work *work;
6357 struct wpa_radio *radio = wpa_s->radio;
6358
6359 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6360 if (work->ctx != ctx)
6361 continue;
6362 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6363 work->type, work, work->started ? " (started)" : "");
6364 radio_work_free(work);
6365 break;
6366 }
6367}
6368
6369
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006370static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6371{
6372 struct wpa_radio *radio = wpa_s->radio;
6373
6374 if (!radio)
6375 return;
6376
6377 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6378 wpa_s->ifname, radio->name);
6379 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006380 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006381 /* If the interface that triggered the external scan was removed, the
6382 * external scan is no longer running. */
6383 if (wpa_s == radio->external_scan_req_interface)
6384 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006385 wpa_s->radio = NULL;
6386 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006387 return; /* Interfaces remain for this radio */
6388
6389 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006390 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006391 os_free(radio);
6392}
6393
6394
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006395void radio_work_check_next(struct wpa_supplicant *wpa_s)
6396{
6397 struct wpa_radio *radio = wpa_s->radio;
6398
6399 if (dl_list_empty(&radio->work))
6400 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006401 if (wpa_s->ext_work_in_progress) {
6402 wpa_printf(MSG_DEBUG,
6403 "External radio work in progress - delay start of pending item");
6404 return;
6405 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006406 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6407 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6408}
6409
6410
6411/**
6412 * radio_add_work - Add a radio work item
6413 * @wpa_s: Pointer to wpa_supplicant data
6414 * @freq: Frequency of the offchannel operation in MHz or 0
6415 * @type: Unique identifier for each type of work
6416 * @next: Force as the next work to be executed
6417 * @cb: Callback function for indicating when radio is available
6418 * @ctx: Context pointer for the work (work->ctx in cb())
6419 * Returns: 0 on success, -1 on failure
6420 *
6421 * This function is used to request time for an operation that requires
6422 * exclusive radio control. Once the radio is available, the registered callback
6423 * function will be called. radio_work_done() must be called once the exclusive
6424 * radio operation has been completed, so that the radio is freed for other
6425 * operations. The special case of deinit=1 is used to free the context data
6426 * during interface removal. That does not allow the callback function to start
6427 * the radio operation, i.e., it must free any resources allocated for the radio
6428 * work and return.
6429 *
6430 * The @freq parameter can be used to indicate a single channel on which the
6431 * offchannel operation will occur. This may allow multiple radio work
6432 * operations to be performed in parallel if they apply for the same channel.
6433 * Setting this to 0 indicates that the work item may use multiple channels or
6434 * requires exclusive control of the radio.
6435 */
6436int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6437 const char *type, int next,
6438 void (*cb)(struct wpa_radio_work *work, int deinit),
6439 void *ctx)
6440{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006441 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006442 struct wpa_radio_work *work;
6443 int was_empty;
6444
6445 work = os_zalloc(sizeof(*work));
6446 if (work == NULL)
6447 return -1;
6448 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6449 os_get_reltime(&work->time);
6450 work->freq = freq;
6451 work->type = type;
6452 work->wpa_s = wpa_s;
6453 work->cb = cb;
6454 work->ctx = ctx;
6455
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006456 if (freq)
6457 work->bands = wpas_freq_to_band(freq);
6458 else if (os_strcmp(type, "scan") == 0 ||
6459 os_strcmp(type, "p2p-scan") == 0)
6460 work->bands = wpas_get_bands(wpa_s,
6461 ((struct wpa_driver_scan_params *)
6462 ctx)->freqs);
6463 else
6464 work->bands = wpas_get_bands(wpa_s, NULL);
6465
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006466 was_empty = dl_list_empty(&wpa_s->radio->work);
6467 if (next)
6468 dl_list_add(&wpa_s->radio->work, &work->list);
6469 else
6470 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6471 if (was_empty) {
6472 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6473 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006474 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6475 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6476 wpa_dbg(wpa_s, MSG_DEBUG,
6477 "Try to schedule a radio work (num_active_works=%u)",
6478 radio->num_active_works);
6479 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006480 }
6481
6482 return 0;
6483}
6484
6485
6486/**
6487 * radio_work_done - Indicate that a radio work item has been completed
6488 * @work: Completed work
6489 *
6490 * This function is called once the callback function registered with
6491 * radio_add_work() has completed its work.
6492 */
6493void radio_work_done(struct wpa_radio_work *work)
6494{
6495 struct wpa_supplicant *wpa_s = work->wpa_s;
6496 struct os_reltime now, diff;
6497 unsigned int started = work->started;
6498
6499 os_get_reltime(&now);
6500 os_reltime_sub(&now, &work->time, &diff);
6501 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6502 work->type, work, started ? "done" : "canceled",
6503 diff.sec, diff.usec);
6504 radio_work_free(work);
6505 if (started)
6506 radio_work_check_next(wpa_s);
6507}
6508
6509
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006510struct wpa_radio_work *
6511radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006512{
6513 struct wpa_radio_work *work;
6514 struct wpa_radio *radio = wpa_s->radio;
6515
6516 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6517 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006518 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006519 }
6520
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006521 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006522}
6523
6524
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006525static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006526 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006527{
6528 const char *ifname, *driver, *rn;
6529
6530 driver = iface->driver;
6531next_driver:
6532 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6533 return -1;
6534
6535 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6536 if (wpa_s->drv_priv == NULL) {
6537 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006538 int level = MSG_ERROR;
6539
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006540 pos = driver ? os_strchr(driver, ',') : NULL;
6541 if (pos) {
6542 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6543 "driver interface - try next driver wrapper");
6544 driver = pos + 1;
6545 goto next_driver;
6546 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006547
6548#ifdef CONFIG_MATCH_IFACE
6549 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6550 level = MSG_DEBUG;
6551#endif /* CONFIG_MATCH_IFACE */
6552 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006553 return -1;
6554 }
6555 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6556 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6557 "driver_param '%s'", wpa_s->conf->driver_param);
6558 return -1;
6559 }
6560
6561 ifname = wpa_drv_get_ifname(wpa_s);
6562 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6563 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6564 "interface name with '%s'", ifname);
6565 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6566 }
6567
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006568 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006569 if (rn && rn[0] == '\0')
6570 rn = NULL;
6571
6572 wpa_s->radio = radio_add_interface(wpa_s, rn);
6573 if (wpa_s->radio == NULL)
6574 return -1;
6575
6576 return 0;
6577}
6578
6579
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006580#ifdef CONFIG_GAS_SERVER
6581
6582static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6583 unsigned int freq, const u8 *dst,
6584 const u8 *src, const u8 *bssid,
6585 const u8 *data, size_t data_len,
6586 enum offchannel_send_action_result result)
6587{
6588 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6589 " result=%s",
6590 freq, MAC2STR(dst),
6591 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6592 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6593 "FAILED"));
6594 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6595 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6596}
6597
6598
6599static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6600 struct wpabuf *buf, unsigned int wait_time)
6601{
6602 struct wpa_supplicant *wpa_s = ctx;
6603 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6604
6605 if (wait_time > wpa_s->max_remain_on_chan)
6606 wait_time = wpa_s->max_remain_on_chan;
6607
6608 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6609 wpabuf_head(buf), wpabuf_len(buf),
6610 wait_time, wpas_gas_server_tx_status, 0);
6611}
6612
6613#endif /* CONFIG_GAS_SERVER */
6614
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006615static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006616 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006617{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006618 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006619 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006620 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006621
6622 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6623 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6624 iface->confname ? iface->confname : "N/A",
6625 iface->driver ? iface->driver : "default",
6626 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6627 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6628
6629 if (iface->confname) {
6630#ifdef CONFIG_BACKEND_FILE
6631 wpa_s->confname = os_rel2abs_path(iface->confname);
6632 if (wpa_s->confname == NULL) {
6633 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6634 "for configuration file '%s'.",
6635 iface->confname);
6636 return -1;
6637 }
6638 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6639 iface->confname, wpa_s->confname);
6640#else /* CONFIG_BACKEND_FILE */
6641 wpa_s->confname = os_strdup(iface->confname);
6642#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006643 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006644 if (wpa_s->conf == NULL) {
6645 wpa_printf(MSG_ERROR, "Failed to read or parse "
6646 "configuration '%s'.", wpa_s->confname);
6647 return -1;
6648 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006649 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006650 if (wpa_s->confanother &&
6651 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6652 wpa_printf(MSG_ERROR,
6653 "Failed to read or parse configuration '%s'.",
6654 wpa_s->confanother);
6655 return -1;
6656 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006657
6658 /*
6659 * Override ctrl_interface and driver_param if set on command
6660 * line.
6661 */
6662 if (iface->ctrl_interface) {
6663 os_free(wpa_s->conf->ctrl_interface);
6664 wpa_s->conf->ctrl_interface =
6665 os_strdup(iface->ctrl_interface);
6666 }
6667
6668 if (iface->driver_param) {
6669 os_free(wpa_s->conf->driver_param);
6670 wpa_s->conf->driver_param =
6671 os_strdup(iface->driver_param);
6672 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006673
6674 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6675 os_free(wpa_s->conf->ctrl_interface);
6676 wpa_s->conf->ctrl_interface = NULL;
6677 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006678 } else
6679 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6680 iface->driver_param);
6681
6682 if (wpa_s->conf == NULL) {
6683 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6684 return -1;
6685 }
6686
6687 if (iface->ifname == NULL) {
6688 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6689 return -1;
6690 }
6691 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6692 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6693 iface->ifname);
6694 return -1;
6695 }
6696 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006697#ifdef CONFIG_MATCH_IFACE
6698 wpa_s->matched = iface->matched;
6699#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006700
6701 if (iface->bridge_ifname) {
6702 if (os_strlen(iface->bridge_ifname) >=
6703 sizeof(wpa_s->bridge_ifname)) {
6704 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6705 "name '%s'.", iface->bridge_ifname);
6706 return -1;
6707 }
6708 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6709 sizeof(wpa_s->bridge_ifname));
6710 }
6711
6712 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006713 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6714 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006715
6716 /* Initialize driver interface and register driver event handler before
6717 * L2 receive handler so that association events are processed before
6718 * EAPOL-Key packets if both become available for the same select()
6719 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006720 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006721 return -1;
6722
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006723 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6724 return -1;
6725
6726 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6727 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6728 NULL);
6729 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6730
6731 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6732 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6733 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6734 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6735 "dot11RSNAConfigPMKLifetime");
6736 return -1;
6737 }
6738
6739 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6740 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6741 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6742 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6743 "dot11RSNAConfigPMKReauthThreshold");
6744 return -1;
6745 }
6746
6747 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6748 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6749 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6750 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6751 "dot11RSNAConfigSATimeout");
6752 return -1;
6753 }
6754
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006755 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6756 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006757 &wpa_s->hw.flags,
6758 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006759 if (wpa_s->hw.modes) {
6760 u16 i;
6761
6762 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6763 if (wpa_s->hw.modes[i].vht_capab) {
6764 wpa_s->hw_capab = CAPAB_VHT;
6765 break;
6766 }
6767
6768 if (wpa_s->hw.modes[i].ht_capab &
6769 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6770 wpa_s->hw_capab = CAPAB_HT40;
6771 else if (wpa_s->hw.modes[i].ht_capab &&
6772 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6773 wpa_s->hw_capab = CAPAB_HT;
6774 }
6775 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006776
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006777 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6778 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006779 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006780 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006781 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006782 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006783 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07006784 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006785 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006786 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006787 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006788 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6789 wpa_s->max_sched_scan_plan_interval =
6790 capa.max_sched_scan_plan_interval;
6791 wpa_s->max_sched_scan_plan_iterations =
6792 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006793 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6794 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006795 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6796 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006797 wpa_s->extended_capa = capa.extended_capa;
6798 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6799 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006800 wpa_s->num_multichan_concurrent =
6801 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006802 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6803
6804 if (capa.mac_addr_rand_scan_supported)
6805 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6806 if (wpa_s->sched_scan_supported &&
6807 capa.mac_addr_rand_sched_scan_supported)
6808 wpa_s->mac_addr_rand_supported |=
6809 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006810
6811 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6812 if (wpa_s->extended_capa &&
6813 wpa_s->extended_capa_len >= 3 &&
6814 wpa_s->extended_capa[2] & 0x40)
6815 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006816 }
6817 if (wpa_s->max_remain_on_chan == 0)
6818 wpa_s->max_remain_on_chan = 1000;
6819
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006820 /*
6821 * Only take p2p_mgmt parameters when P2P Device is supported.
6822 * Doing it here as it determines whether l2_packet_init() will be done
6823 * during wpa_supplicant_driver_init().
6824 */
6825 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6826 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006827
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006828 if (wpa_s->num_multichan_concurrent == 0)
6829 wpa_s->num_multichan_concurrent = 1;
6830
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006831 if (wpa_supplicant_driver_init(wpa_s) < 0)
6832 return -1;
6833
6834#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006835 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006836 return -1;
6837#endif /* CONFIG_TDLS */
6838
6839 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6840 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6841 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6842 return -1;
6843 }
6844
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006845#ifdef CONFIG_FST
6846 if (wpa_s->conf->fst_group_id) {
6847 struct fst_iface_cfg cfg;
6848 struct fst_wpa_obj iface_obj;
6849
6850 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6851 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6852 sizeof(cfg.group_id));
6853 cfg.priority = wpa_s->conf->fst_priority;
6854 cfg.llt = wpa_s->conf->fst_llt;
6855
6856 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6857 &iface_obj, &cfg);
6858 if (!wpa_s->fst) {
6859 wpa_msg(wpa_s, MSG_ERROR,
6860 "FST: Cannot attach iface %s to group %s",
6861 wpa_s->ifname, cfg.group_id);
6862 return -1;
6863 }
6864 }
6865#endif /* CONFIG_FST */
6866
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006867 if (wpas_wps_init(wpa_s))
6868 return -1;
6869
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006870#ifdef CONFIG_GAS_SERVER
6871 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6872 if (!wpa_s->gas_server) {
6873 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6874 return -1;
6875 }
6876#endif /* CONFIG_GAS_SERVER */
6877
6878#ifdef CONFIG_DPP
6879 if (wpas_dpp_init(wpa_s) < 0)
6880 return -1;
6881#endif /* CONFIG_DPP */
6882
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006883 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6884 return -1;
6885 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6886
6887 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6888 if (wpa_s->ctrl_iface == NULL) {
6889 wpa_printf(MSG_ERROR,
6890 "Failed to initialize control interface '%s'.\n"
6891 "You may have another wpa_supplicant process "
6892 "already running or the file was\n"
6893 "left by an unclean termination of wpa_supplicant "
6894 "in which case you will need\n"
6895 "to manually remove this file before starting "
6896 "wpa_supplicant again.\n",
6897 wpa_s->conf->ctrl_interface);
6898 return -1;
6899 }
6900
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006901 wpa_s->gas = gas_query_init(wpa_s);
6902 if (wpa_s->gas == NULL) {
6903 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6904 return -1;
6905 }
6906
Roshan Pius3a1667e2018-07-03 15:17:14 -07006907 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6908 wpa_s->p2p_mgmt) &&
6909 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006910 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6911 return -1;
6912 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006913
6914 if (wpa_bss_init(wpa_s) < 0)
6915 return -1;
6916
Paul Stewart092955c2017-02-06 09:13:09 -08006917#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6918#ifdef CONFIG_MESH
6919 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6920#endif /* CONFIG_MESH */
6921#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6922
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006923 /*
6924 * Set Wake-on-WLAN triggers, if configured.
6925 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6926 * have effect anyway when the interface is down).
6927 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006928 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006929 return -1;
6930
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006931#ifdef CONFIG_EAP_PROXY
6932{
6933 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006934 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6935 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006936 if (wpa_s->mnc_len > 0) {
6937 wpa_s->imsi[len] = '\0';
6938 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6939 wpa_s->imsi, wpa_s->mnc_len);
6940 } else {
6941 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6942 }
6943}
6944#endif /* CONFIG_EAP_PROXY */
6945
Dmitry Shmidt04949592012-07-19 12:16:46 -07006946 if (pcsc_reader_init(wpa_s) < 0)
6947 return -1;
6948
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006949 if (wpas_init_ext_pw(wpa_s) < 0)
6950 return -1;
6951
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006952 wpas_rrm_reset(wpa_s);
6953
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006954 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6955
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006956#ifdef CONFIG_HS20
6957 hs20_init(wpa_s);
6958#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006959#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006960 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006961 if ((wpa_s->conf->oce & OCE_STA) &&
6962 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6963 wpa_s->enable_oce = OCE_STA;
6964 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6965 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6966 /* TODO: Need to add STA-CFON support */
6967 wpa_printf(MSG_ERROR,
6968 "OCE STA-CFON feature is not yet supported");
6969 }
6970 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006971 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6972#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006973
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006974 wpa_supplicant_set_default_scan_ies(wpa_s);
6975
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006976 return 0;
6977}
6978
6979
6980static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006981 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006982{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006983 struct wpa_global *global = wpa_s->global;
6984 struct wpa_supplicant *iface, *prev;
6985
Jimmy Chen0e73c002021-08-18 13:21:30 +08006986 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006987 wpas_p2p_group_remove(wpa_s, "*");
6988
6989 iface = global->ifaces;
6990 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006991 if (iface->p2pdev == wpa_s)
6992 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006993 if (iface == wpa_s || iface->parent != wpa_s) {
6994 iface = iface->next;
6995 continue;
6996 }
6997 wpa_printf(MSG_DEBUG,
6998 "Remove remaining child interface %s from parent %s",
6999 iface->ifname, wpa_s->ifname);
7000 prev = iface;
7001 iface = iface->next;
7002 wpa_supplicant_remove_iface(global, prev, terminate);
7003 }
7004
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007005 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007006 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007007 /*
7008 * Don't deauthenticate if WoWLAN is enable and not explicitly
7009 * been configured to disconnect.
7010 */
7011 if (!wpa_drv_get_wowlan(wpa_s) ||
7012 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007013 wpa_supplicant_deauthenticate(
7014 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007015
Hai Shalomfdcde762020-04-02 11:19:20 -07007016 wpa_drv_set_countermeasures(wpa_s, 0);
7017 wpa_clear_keys(wpa_s, NULL);
7018 } else {
7019 wpa_msg(wpa_s, MSG_INFO,
7020 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7021 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007022 }
7023
7024 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007025 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007026
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007027 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007028 radio_remove_interface(wpa_s);
7029
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007030#ifdef CONFIG_FST
7031 if (wpa_s->fst) {
7032 fst_detach(wpa_s->fst);
7033 wpa_s->fst = NULL;
7034 }
7035 if (wpa_s->received_mb_ies) {
7036 wpabuf_free(wpa_s->received_mb_ies);
7037 wpa_s->received_mb_ies = NULL;
7038 }
7039#endif /* CONFIG_FST */
7040
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007041 if (wpa_s->drv_priv)
7042 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007043
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007044 if (notify)
7045 wpas_notify_iface_removed(wpa_s);
7046
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007047 if (terminate)
7048 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007049
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007050 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7051 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007052
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007053#ifdef CONFIG_MESH
7054 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007055 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007056 wpa_s->ifmsh = NULL;
7057 }
7058#endif /* CONFIG_MESH */
7059
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007060 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007061 wpa_config_free(wpa_s->conf);
7062 wpa_s->conf = NULL;
7063 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007064
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007065 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007066 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007067
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007068 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007069}
7070
7071
Dmitry Shmidte4663042016-04-04 10:07:49 -07007072#ifdef CONFIG_MATCH_IFACE
7073
7074/**
7075 * wpa_supplicant_match_iface - Match an interface description to a name
7076 * @global: Pointer to global data from wpa_supplicant_init()
7077 * @ifname: Name of the interface to match
7078 * Returns: Pointer to the created interface description or %NULL on failure
7079 */
7080struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7081 const char *ifname)
7082{
7083 int i;
7084 struct wpa_interface *iface, *miface;
7085
7086 for (i = 0; i < global->params.match_iface_count; i++) {
7087 miface = &global->params.match_ifaces[i];
7088 if (!miface->ifname ||
7089 fnmatch(miface->ifname, ifname, 0) == 0) {
7090 iface = os_zalloc(sizeof(*iface));
7091 if (!iface)
7092 return NULL;
7093 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007094 if (!miface->ifname)
7095 iface->matched = WPA_IFACE_MATCHED_NULL;
7096 else
7097 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007098 iface->ifname = ifname;
7099 return iface;
7100 }
7101 }
7102
7103 return NULL;
7104}
7105
7106
7107/**
7108 * wpa_supplicant_match_existing - Match existing interfaces
7109 * @global: Pointer to global data from wpa_supplicant_init()
7110 * Returns: 0 on success, -1 on failure
7111 */
7112static int wpa_supplicant_match_existing(struct wpa_global *global)
7113{
7114 struct if_nameindex *ifi, *ifp;
7115 struct wpa_supplicant *wpa_s;
7116 struct wpa_interface *iface;
7117
7118 ifp = if_nameindex();
7119 if (!ifp) {
7120 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7121 return -1;
7122 }
7123
7124 for (ifi = ifp; ifi->if_name; ifi++) {
7125 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7126 if (wpa_s)
7127 continue;
7128 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7129 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007130 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007131 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007132 }
7133 }
7134
7135 if_freenameindex(ifp);
7136 return 0;
7137}
7138
7139#endif /* CONFIG_MATCH_IFACE */
7140
7141
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007142/**
7143 * wpa_supplicant_add_iface - Add a new network interface
7144 * @global: Pointer to global data from wpa_supplicant_init()
7145 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007146 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007147 * Returns: Pointer to the created interface or %NULL on failure
7148 *
7149 * This function is used to add new network interfaces for %wpa_supplicant.
7150 * This can be called before wpa_supplicant_run() to add interfaces before the
7151 * main event loop has been started. In addition, new interfaces can be added
7152 * dynamically while %wpa_supplicant is already running. This could happen,
7153 * e.g., when a hotplug network adapter is inserted.
7154 */
7155struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007156 struct wpa_interface *iface,
7157 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007158{
7159 struct wpa_supplicant *wpa_s;
7160 struct wpa_interface t_iface;
7161 struct wpa_ssid *ssid;
7162
7163 if (global == NULL || iface == NULL)
7164 return NULL;
7165
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007166 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007167 if (wpa_s == NULL)
7168 return NULL;
7169
7170 wpa_s->global = global;
7171
7172 t_iface = *iface;
7173 if (global->params.override_driver) {
7174 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7175 "('%s' -> '%s')",
7176 iface->driver, global->params.override_driver);
7177 t_iface.driver = global->params.override_driver;
7178 }
7179 if (global->params.override_ctrl_interface) {
7180 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7181 "ctrl_interface ('%s' -> '%s')",
7182 iface->ctrl_interface,
7183 global->params.override_ctrl_interface);
7184 t_iface.ctrl_interface =
7185 global->params.override_ctrl_interface;
7186 }
7187 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7188 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7189 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007190 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007191 return NULL;
7192 }
7193
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007194 /* Notify the control interfaces about new iface */
7195 if (wpas_notify_iface_added(wpa_s)) {
7196 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7197 return NULL;
7198 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007199
Jimmy Chene2206be2022-07-10 10:25:21 +08007200 /* Notify the control interfaces about new networks */
7201 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7202 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007203 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007204 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7205 && os_strncmp((const char *) ssid->ssid,
7206 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7207 wpas_notify_persistent_group_added(wpa_s, ssid);
7208 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007209 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007210
7211 wpa_s->next = global->ifaces;
7212 global->ifaces = wpa_s;
7213
7214 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007215 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007216
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007217#ifdef CONFIG_P2P
7218 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007219 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007220 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007221 wpas_p2p_add_p2pdev_interface(
7222 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007223 wpa_printf(MSG_INFO,
7224 "P2P: Failed to enable P2P Device interface");
7225 /* Try to continue without. P2P will be disabled. */
7226 }
7227#endif /* CONFIG_P2P */
7228
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007229 return wpa_s;
7230}
7231
7232
7233/**
7234 * wpa_supplicant_remove_iface - Remove a network interface
7235 * @global: Pointer to global data from wpa_supplicant_init()
7236 * @wpa_s: Pointer to the network interface to be removed
7237 * Returns: 0 if interface was removed, -1 if interface was not found
7238 *
7239 * This function can be used to dynamically remove network interfaces from
7240 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7241 * addition, this function is used to remove all remaining interfaces when
7242 * %wpa_supplicant is terminated.
7243 */
7244int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007245 struct wpa_supplicant *wpa_s,
7246 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007247{
7248 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007249#ifdef CONFIG_MESH
7250 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7251 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007252 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007253#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007254
7255 /* Remove interface from the global list of interfaces */
7256 prev = global->ifaces;
7257 if (prev == wpa_s) {
7258 global->ifaces = wpa_s->next;
7259 } else {
7260 while (prev && prev->next != wpa_s)
7261 prev = prev->next;
7262 if (prev == NULL)
7263 return -1;
7264 prev->next = wpa_s->next;
7265 }
7266
7267 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7268
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007269#ifdef CONFIG_MESH
7270 if (mesh_if_created) {
7271 ifname = os_strdup(wpa_s->ifname);
7272 if (ifname == NULL) {
7273 wpa_dbg(wpa_s, MSG_ERROR,
7274 "mesh: Failed to malloc ifname");
7275 return -1;
7276 }
7277 }
7278#endif /* CONFIG_MESH */
7279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007280 if (global->p2p_group_formation == wpa_s)
7281 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007282 if (global->p2p_invite_group == wpa_s)
7283 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007284 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007285
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007286#ifdef CONFIG_MESH
7287 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007288 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007289 os_free(ifname);
7290 }
7291#endif /* CONFIG_MESH */
7292
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007293 return 0;
7294}
7295
7296
7297/**
7298 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7299 * @wpa_s: Pointer to the network interface
7300 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7301 */
7302const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7303{
7304 const char *eapol_method;
7305
7306 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7307 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7308 return "NO-EAP";
7309 }
7310
7311 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7312 if (eapol_method == NULL)
7313 return "UNKNOWN-EAP";
7314
7315 return eapol_method;
7316}
7317
7318
7319/**
7320 * wpa_supplicant_get_iface - Get a new network interface
7321 * @global: Pointer to global data from wpa_supplicant_init()
7322 * @ifname: Interface name
7323 * Returns: Pointer to the interface or %NULL if not found
7324 */
7325struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7326 const char *ifname)
7327{
7328 struct wpa_supplicant *wpa_s;
7329
7330 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7331 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7332 return wpa_s;
7333 }
7334 return NULL;
7335}
7336
7337
7338#ifndef CONFIG_NO_WPA_MSG
7339static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7340{
7341 struct wpa_supplicant *wpa_s = ctx;
7342 if (wpa_s == NULL)
7343 return NULL;
7344 return wpa_s->ifname;
7345}
7346#endif /* CONFIG_NO_WPA_MSG */
7347
7348
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007349#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7350#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7351#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7352
7353/* Periodic cleanup tasks */
7354static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7355{
7356 struct wpa_global *global = eloop_ctx;
7357 struct wpa_supplicant *wpa_s;
7358
7359 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7360 wpas_periodic, global, NULL);
7361
7362#ifdef CONFIG_P2P
7363 if (global->p2p)
7364 p2p_expire_peers(global->p2p);
7365#endif /* CONFIG_P2P */
7366
7367 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7368 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7369#ifdef CONFIG_AP
7370 ap_periodic(wpa_s);
7371#endif /* CONFIG_AP */
7372 }
7373}
7374
7375
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007376/**
7377 * wpa_supplicant_init - Initialize %wpa_supplicant
7378 * @params: Parameters for %wpa_supplicant
7379 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7380 *
7381 * This function is used to initialize %wpa_supplicant. After successful
7382 * initialization, the returned data pointer can be used to add and remove
7383 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7384 */
7385struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7386{
7387 struct wpa_global *global;
7388 int ret, i;
7389
7390 if (params == NULL)
7391 return NULL;
7392
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007393#ifdef CONFIG_DRIVER_NDIS
7394 {
7395 void driver_ndis_init_ops(void);
7396 driver_ndis_init_ops();
7397 }
7398#endif /* CONFIG_DRIVER_NDIS */
7399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007400#ifndef CONFIG_NO_WPA_MSG
7401 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7402#endif /* CONFIG_NO_WPA_MSG */
7403
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007404 if (params->wpa_debug_file_path)
7405 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007406 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007407 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007408 if (params->wpa_debug_syslog)
7409 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007410 if (params->wpa_debug_tracing) {
7411 ret = wpa_debug_open_linux_tracing();
7412 if (ret) {
7413 wpa_printf(MSG_ERROR,
7414 "Failed to enable trace logging");
7415 return NULL;
7416 }
7417 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007418
7419 ret = eap_register_methods();
7420 if (ret) {
7421 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7422 if (ret == -2)
7423 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7424 "the same EAP type.");
7425 return NULL;
7426 }
7427
7428 global = os_zalloc(sizeof(*global));
7429 if (global == NULL)
7430 return NULL;
7431 dl_list_init(&global->p2p_srv_bonjour);
7432 dl_list_init(&global->p2p_srv_upnp);
7433 global->params.daemonize = params->daemonize;
7434 global->params.wait_for_monitor = params->wait_for_monitor;
7435 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7436 if (params->pid_file)
7437 global->params.pid_file = os_strdup(params->pid_file);
7438 if (params->ctrl_interface)
7439 global->params.ctrl_interface =
7440 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007441 if (params->ctrl_interface_group)
7442 global->params.ctrl_interface_group =
7443 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007444 if (params->override_driver)
7445 global->params.override_driver =
7446 os_strdup(params->override_driver);
7447 if (params->override_ctrl_interface)
7448 global->params.override_ctrl_interface =
7449 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007450#ifdef CONFIG_MATCH_IFACE
7451 global->params.match_iface_count = params->match_iface_count;
7452 if (params->match_iface_count) {
7453 global->params.match_ifaces =
7454 os_calloc(params->match_iface_count,
7455 sizeof(struct wpa_interface));
7456 os_memcpy(global->params.match_ifaces,
7457 params->match_ifaces,
7458 params->match_iface_count *
7459 sizeof(struct wpa_interface));
7460 }
7461#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007462#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007463 if (params->conf_p2p_dev)
7464 global->params.conf_p2p_dev =
7465 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007466#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007467 wpa_debug_level = global->params.wpa_debug_level =
7468 params->wpa_debug_level;
7469 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7470 params->wpa_debug_show_keys;
7471 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7472 params->wpa_debug_timestamp;
7473
Hai Shalomfdcde762020-04-02 11:19:20 -07007474 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007475
7476 if (eloop_init()) {
7477 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7478 wpa_supplicant_deinit(global);
7479 return NULL;
7480 }
7481
Jouni Malinen75ecf522011-06-27 15:19:46 -07007482 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007483
7484 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7485 if (global->ctrl_iface == NULL) {
7486 wpa_supplicant_deinit(global);
7487 return NULL;
7488 }
7489
7490 if (wpas_notify_supplicant_initialized(global)) {
7491 wpa_supplicant_deinit(global);
7492 return NULL;
7493 }
7494
7495 for (i = 0; wpa_drivers[i]; i++)
7496 global->drv_count++;
7497 if (global->drv_count == 0) {
7498 wpa_printf(MSG_ERROR, "No drivers enabled");
7499 wpa_supplicant_deinit(global);
7500 return NULL;
7501 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007502 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007503 if (global->drv_priv == NULL) {
7504 wpa_supplicant_deinit(global);
7505 return NULL;
7506 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007507
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007508#ifdef CONFIG_WIFI_DISPLAY
7509 if (wifi_display_init(global) < 0) {
7510 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7511 wpa_supplicant_deinit(global);
7512 return NULL;
7513 }
7514#endif /* CONFIG_WIFI_DISPLAY */
7515
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007516 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7517 wpas_periodic, global, NULL);
7518
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007519 return global;
7520}
7521
7522
7523/**
7524 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7525 * @global: Pointer to global data from wpa_supplicant_init()
7526 * Returns: 0 after successful event loop run, -1 on failure
7527 *
7528 * This function starts the main event loop and continues running as long as
7529 * there are any remaining events. In most cases, this function is running as
7530 * long as the %wpa_supplicant process in still in use.
7531 */
7532int wpa_supplicant_run(struct wpa_global *global)
7533{
7534 struct wpa_supplicant *wpa_s;
7535
7536 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007537 (wpa_supplicant_daemon(global->params.pid_file) ||
7538 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007539 return -1;
7540
Dmitry Shmidte4663042016-04-04 10:07:49 -07007541#ifdef CONFIG_MATCH_IFACE
7542 if (wpa_supplicant_match_existing(global))
7543 return -1;
7544#endif
7545
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007546 if (global->params.wait_for_monitor) {
7547 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007548 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007549 wpa_supplicant_ctrl_iface_wait(
7550 wpa_s->ctrl_iface);
7551 }
7552
7553 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7554 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7555
7556 eloop_run();
7557
7558 return 0;
7559}
7560
7561
7562/**
7563 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7564 * @global: Pointer to global data from wpa_supplicant_init()
7565 *
7566 * This function is called to deinitialize %wpa_supplicant and to free all
7567 * allocated resources. Remaining network interfaces will also be removed.
7568 */
7569void wpa_supplicant_deinit(struct wpa_global *global)
7570{
7571 int i;
7572
7573 if (global == NULL)
7574 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007575
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007576 eloop_cancel_timeout(wpas_periodic, global, NULL);
7577
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007578#ifdef CONFIG_WIFI_DISPLAY
7579 wifi_display_deinit(global);
7580#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007581
7582 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007583 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007584
7585 if (global->ctrl_iface)
7586 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7587
7588 wpas_notify_supplicant_deinitialized(global);
7589
7590 eap_peer_unregister_methods();
7591#ifdef CONFIG_AP
7592 eap_server_unregister_methods();
7593#endif /* CONFIG_AP */
7594
7595 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7596 if (!global->drv_priv[i])
7597 continue;
7598 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7599 }
7600 os_free(global->drv_priv);
7601
7602 random_deinit();
7603
7604 eloop_destroy();
7605
7606 if (global->params.pid_file) {
7607 os_daemonize_terminate(global->params.pid_file);
7608 os_free(global->params.pid_file);
7609 }
7610 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007611 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007612 os_free(global->params.override_driver);
7613 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007614#ifdef CONFIG_MATCH_IFACE
7615 os_free(global->params.match_ifaces);
7616#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007617#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007618 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007619#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007620
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007621 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007622 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007623 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007624
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007625 os_free(global);
7626 wpa_debug_close_syslog();
7627 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007628 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007629}
7630
7631
7632void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7633{
7634 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7635 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7636 char country[3];
7637 country[0] = wpa_s->conf->country[0];
7638 country[1] = wpa_s->conf->country[1];
7639 country[2] = '\0';
7640 if (wpa_drv_set_country(wpa_s, country) < 0) {
7641 wpa_printf(MSG_ERROR, "Failed to set country code "
7642 "'%s'", country);
7643 }
7644 }
7645
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007646 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7647 wpas_init_ext_pw(wpa_s);
7648
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007649 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7650 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7651
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007652 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7653 struct wpa_driver_capa capa;
7654 int res = wpa_drv_get_capa(wpa_s, &capa);
7655
7656 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7657 wpa_printf(MSG_ERROR,
7658 "Failed to update wowlan_triggers to '%s'",
7659 wpa_s->conf->wowlan_triggers);
7660 }
7661
Hai Shalom81f62d82019-07-22 12:10:00 -07007662 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7663 wpa_supplicant_set_default_scan_ies(wpa_s);
7664
Hai Shalom899fcc72020-10-19 14:38:18 -07007665#ifdef CONFIG_BGSCAN
7666 /*
7667 * We default to global bgscan parameters only when per-network bgscan
7668 * parameters aren't set. Only bother resetting bgscan parameters if
7669 * this is the case.
7670 */
7671 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7672 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7673 wpa_s->wpa_state == WPA_COMPLETED)
7674 wpa_supplicant_reset_bgscan(wpa_s);
7675#endif /* CONFIG_BGSCAN */
7676
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007677#ifdef CONFIG_WPS
7678 wpas_wps_update_config(wpa_s);
7679#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007680 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007681 wpa_s->conf->changed_parameters = 0;
7682}
7683
7684
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007685void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007686{
7687 int i;
7688
7689 for (i = 0; i < *num_freqs; i++) {
7690 if (freqs[i] == freq)
7691 return;
7692 }
7693
7694 freqs[*num_freqs] = freq;
7695 (*num_freqs)++;
7696}
7697
7698
7699static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7700{
7701 struct wpa_bss *bss, *cbss;
7702 const int max_freqs = 10;
7703 int *freqs;
7704 int num_freqs = 0;
7705
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007706 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007707 if (freqs == NULL)
7708 return NULL;
7709
7710 cbss = wpa_s->current_bss;
7711
7712 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7713 if (bss == cbss)
7714 continue;
7715 if (bss->ssid_len == cbss->ssid_len &&
7716 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007717 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007718 add_freq(freqs, &num_freqs, bss->freq);
7719 if (num_freqs == max_freqs)
7720 break;
7721 }
7722 }
7723
7724 if (num_freqs == 0) {
7725 os_free(freqs);
7726 freqs = NULL;
7727 }
7728
7729 return freqs;
7730}
7731
7732
7733void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7734{
7735 int timeout;
7736 int count;
7737 int *freqs = NULL;
7738
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007739 wpas_connect_work_done(wpa_s);
7740
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007741 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007742 * Remove possible authentication timeout since the connection failed.
7743 */
7744 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7745
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007746 /*
Hai Shalom60840252021-02-19 19:02:11 -08007747 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007748 * generated based on local request to disconnect.
7749 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007750 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007751 wpa_s->own_disconnect_req = 0;
7752 wpa_dbg(wpa_s, MSG_DEBUG,
7753 "Ignore connection failure due to local request to disconnect");
7754 return;
7755 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007756 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007757 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7758 "indication since interface has been put into "
7759 "disconnected state");
7760 return;
7761 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007762 if (wpa_s->auto_reconnect_disabled) {
7763 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7764 "indication since auto connect is disabled");
7765 return;
7766 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007767
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007768 /*
Hai Shalom60840252021-02-19 19:02:11 -08007769 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007770 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007771 */
Hai Shalom60840252021-02-19 19:02:11 -08007772 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007773 if (count == 1 && wpa_s->current_bss) {
7774 /*
Hai Shalom60840252021-02-19 19:02:11 -08007775 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007776 * another BSS available for the same ESS, we should try that
7777 * next. Otherwise, we may as well try this one once more
7778 * before allowing other, likely worse, ESSes to be considered.
7779 */
7780 freqs = get_bss_freqs_in_ess(wpa_s);
7781 if (freqs) {
7782 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7783 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007784 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007785 /*
7786 * On the next scan, go through only the known channels
7787 * used in this ESS based on previous scans to speed up
7788 * common load balancing use case.
7789 */
7790 os_free(wpa_s->next_scan_freqs);
7791 wpa_s->next_scan_freqs = freqs;
7792 }
7793 }
7794
Hai Shalom899fcc72020-10-19 14:38:18 -07007795 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007796
Hai Shalom899fcc72020-10-19 14:38:18 -07007797 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007798 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7799 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007800 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007801 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007802 /*
7803 * Multiple consecutive connection failures mean that other APs are
7804 * either not available or have already been tried, so we can start
7805 * increasing the delay here to avoid constant scanning.
7806 */
7807 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007808 case 1:
7809 timeout = 100;
7810 break;
7811 case 2:
7812 timeout = 500;
7813 break;
7814 case 3:
7815 timeout = 1000;
7816 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007817 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007818 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007819 break;
7820 default:
7821 timeout = 10000;
7822 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007823 }
7824
Hai Shalom899fcc72020-10-19 14:38:18 -07007825 wpa_dbg(wpa_s, MSG_DEBUG,
7826 "Consecutive connection failures: %d --> request scan in %d ms",
7827 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007828
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007829 /*
7830 * TODO: if more than one possible AP is available in scan results,
7831 * could try the other ones before requesting a new scan.
7832 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007833
7834 /* speed up the connection attempt with normal scan */
7835 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007836 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7837 1000 * (timeout % 1000));
7838}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007839
7840
Hai Shalomce48b4a2018-09-05 11:41:35 -07007841#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08007842
7843void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
7844{
7845 struct wpa_ssid *ssid = wpa_s->current_ssid;
7846 const u8 *realm, *username, *rrk;
7847 size_t realm_len, username_len, rrk_len;
7848 u16 next_seq_num;
7849
7850 /* Clear the PMKSA cache entry if FILS authentication was rejected.
7851 * Check for ERP keys existing to limit when this can be done since
7852 * the rejection response is not protected and such triggers should
7853 * really not allow internal state to be modified unless required to
7854 * avoid significant issues in functionality. In addition, drop
7855 * externally configure PMKSA entries even without ERP keys since it
7856 * is possible for an external component to add PMKSA entries for FILS
7857 * authentication without restoring previously generated ERP keys.
7858 *
7859 * In this case, this is needed to allow recovery from cases where the
7860 * AP or authentication server has dropped PMKSAs and ERP keys. */
7861 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
7862 return;
7863
7864 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7865 &username, &username_len,
7866 &realm, &realm_len, &next_seq_num,
7867 &rrk, &rrk_len) != 0 ||
7868 !realm) {
7869 wpa_dbg(wpa_s, MSG_DEBUG,
7870 "FILS: Drop external PMKSA cache entry");
7871 wpa_sm_aborted_external_cached(wpa_s->wpa);
7872 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
7873 return;
7874 }
7875
7876 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
7877 wpa_sm_aborted_cached(wpa_s->wpa);
7878 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
7879}
7880
7881
Hai Shalomce48b4a2018-09-05 11:41:35 -07007882void fils_connection_failure(struct wpa_supplicant *wpa_s)
7883{
7884 struct wpa_ssid *ssid = wpa_s->current_ssid;
7885 const u8 *realm, *username, *rrk;
7886 size_t realm_len, username_len, rrk_len;
7887 u16 next_seq_num;
7888
7889 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7890 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7891 &username, &username_len,
7892 &realm, &realm_len, &next_seq_num,
7893 &rrk, &rrk_len) != 0 ||
7894 !realm)
7895 return;
7896
7897 wpa_hexdump_ascii(MSG_DEBUG,
7898 "FILS: Store last connection failure realm",
7899 realm, realm_len);
7900 os_free(wpa_s->last_con_fail_realm);
7901 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7902 if (wpa_s->last_con_fail_realm) {
7903 wpa_s->last_con_fail_realm_len = realm_len;
7904 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7905 }
7906}
7907#endif /* CONFIG_FILS */
7908
7909
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007910int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7911{
7912 return wpa_s->conf->ap_scan == 2 ||
7913 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7914}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007915
Dmitry Shmidt04949592012-07-19 12:16:46 -07007916
Gabriel Biren57ededa2021-09-03 16:08:50 +00007917#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007918int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7919 struct wpa_ssid *ssid,
7920 const char *field,
7921 const char *value)
7922{
7923#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007924 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007925
7926 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7927 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7928 (const u8 *) value, os_strlen(value));
7929
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007930 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007931 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007932#else /* IEEE8021X_EAPOL */
7933 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7934 return -1;
7935#endif /* IEEE8021X_EAPOL */
7936}
7937
7938int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7939 struct wpa_ssid *ssid,
7940 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007941 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007942{
7943#ifdef IEEE8021X_EAPOL
7944 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007945 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007946
7947 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007948 case WPA_CTRL_REQ_EAP_IDENTITY:
7949 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007950 os_free(eap->imsi_identity);
7951 if (value == NULL)
7952 return -1;
7953 identity = os_strchr(value, ':');
7954 if (identity == NULL) {
7955 /* plain identity */
7956 eap->identity = (u8 *)os_strdup(value);
7957 eap->identity_len = os_strlen(value);
7958 } else {
7959 /* have both plain identity and encrypted identity */
7960 imsi_identity = value;
7961 *identity++ = '\0';
7962 /* plain identity */
7963 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7964 eap->imsi_identity_len = strlen(imsi_identity);
7965 /* encrypted identity */
7966 eap->identity = (u8 *)dup_binstr(identity,
7967 value_len - strlen(imsi_identity) - 1);
7968 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7969 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007970 eap->pending_req_identity = 0;
7971 if (ssid == wpa_s->current_ssid)
7972 wpa_s->reassociate = 1;
7973 break;
7974 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007975 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007976 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007977 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007978 eap->pending_req_password = 0;
7979 if (ssid == wpa_s->current_ssid)
7980 wpa_s->reassociate = 1;
7981 break;
7982 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007983 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007984 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007985 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007986 eap->pending_req_new_password = 0;
7987 if (ssid == wpa_s->current_ssid)
7988 wpa_s->reassociate = 1;
7989 break;
7990 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007991 str_clear_free(eap->cert.pin);
7992 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007993 eap->pending_req_pin = 0;
7994 if (ssid == wpa_s->current_ssid)
7995 wpa_s->reassociate = 1;
7996 break;
7997 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007998 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007999 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07008000 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008001 os_free(eap->pending_req_otp);
8002 eap->pending_req_otp = NULL;
8003 eap->pending_req_otp_len = 0;
8004 break;
8005 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008006 str_clear_free(eap->cert.private_key_passwd);
8007 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008008 eap->pending_req_passphrase = 0;
8009 if (ssid == wpa_s->current_ssid)
8010 wpa_s->reassociate = 1;
8011 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008012 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008013 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008014 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008015 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008016 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008017 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8018 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8019 return -1;
8020 ssid->mem_only_psk = 1;
8021 if (ssid->passphrase)
8022 wpa_config_update_psk(ssid);
8023 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8024 wpa_supplicant_req_scan(wpa_s, 0, 0);
8025 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008026 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8027 if (eap->pending_ext_cert_check != PENDING_CHECK)
8028 return -1;
8029 if (os_strcmp(value, "good") == 0)
8030 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8031 else if (os_strcmp(value, "bad") == 0)
8032 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8033 else
8034 return -1;
8035 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008036 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008037 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008038 return -1;
8039 }
8040
8041 return 0;
8042#else /* IEEE8021X_EAPOL */
8043 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8044 return -1;
8045#endif /* IEEE8021X_EAPOL */
8046}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008047#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008048
8049
8050int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8051{
Hai Shalomfdcde762020-04-02 11:19:20 -07008052#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008053 int i;
8054 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008055#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008056
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008057 if (wpa_s->p2p_mgmt)
8058 return 1; /* no normal network profiles on p2p_mgmt interface */
8059
Dmitry Shmidt04949592012-07-19 12:16:46 -07008060 if (ssid == NULL)
8061 return 1;
8062
8063 if (ssid->disabled)
8064 return 1;
8065
Hai Shalomfdcde762020-04-02 11:19:20 -07008066#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008067 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008068 drv_enc = wpa_s->drv_enc;
8069 else
8070 drv_enc = (unsigned int) -1;
8071
8072 for (i = 0; i < NUM_WEP_KEYS; i++) {
8073 size_t len = ssid->wep_key_len[i];
8074 if (len == 0)
8075 continue;
8076 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8077 continue;
8078 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8079 continue;
8080 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8081 continue;
8082 return 1; /* invalid WEP key */
8083 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008084#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008085
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008086 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008087 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008088 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008089 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008090 return 1;
8091
Sunil8cd6f4d2022-06-28 18:40:46 +00008092#ifdef CRYPTO_RSA_OAEP_SHA256
8093 if (ssid->eap.imsi_privacy_cert) {
8094 struct crypto_rsa_key *key;
8095 bool failed = false;
8096
8097 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8098 if (!key)
8099 failed = true;
8100 crypto_rsa_key_free(key);
8101 if (failed) {
8102 wpa_printf(MSG_DEBUG,
8103 "Invalid imsi_privacy_cert (%s) - disable network",
8104 ssid->eap.imsi_privacy_cert);
8105 return 1;
8106 }
8107 }
8108#endif /* CRYPTO_RSA_OAEP_SHA256 */
8109
Dmitry Shmidt04949592012-07-19 12:16:46 -07008110 return 0;
8111}
8112
8113
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008114int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8115{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008116 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8117 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8118 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8119 /*
8120 * Driver does not support BIP -- ignore pmf=1 default
8121 * since the connection with PMF would fail and the
8122 * configuration does not require PMF to be enabled.
8123 */
8124 return NO_MGMT_FRAME_PROTECTION;
8125 }
8126
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008127 if (ssid &&
8128 (ssid->key_mgmt &
8129 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8130 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8131 /*
8132 * Do not use the default PMF value for non-RSN networks
8133 * since PMF is available only with RSN and pmf=2
8134 * configuration would otherwise prevent connections to
8135 * all open networks.
8136 */
8137 return NO_MGMT_FRAME_PROTECTION;
8138 }
8139
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008140 return wpa_s->conf->pmf;
8141 }
8142
8143 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008144}
8145
8146
Hai Shalomc1a21442022-02-04 13:43:00 -08008147int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8148{
8149 if (wpa_s->current_ssid == NULL ||
8150 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8151 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8152 return 0;
8153 return wpa_sm_pmf_enabled(wpa_s->wpa);
8154}
8155
8156
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008157int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008158{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008159 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008160 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008161 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008162 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008163 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008164}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008165
8166
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008167void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008168{
8169 struct wpa_ssid *ssid = wpa_s->current_ssid;
8170 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008171 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008172
8173 if (ssid == NULL) {
8174 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8175 "SSID block");
8176 return;
8177 }
8178
8179 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8180 return;
8181
8182 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008183
8184#ifdef CONFIG_P2P
8185 if (ssid->p2p_group &&
8186 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8187 /*
8188 * Skip the wait time since there is a short timeout on the
8189 * connection to a P2P group.
8190 */
8191 return;
8192 }
8193#endif /* CONFIG_P2P */
8194
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008195 if (ssid->auth_failures > 50)
8196 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008197 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008198 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008199 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008200 dur = 90;
8201 else if (ssid->auth_failures > 3)
8202 dur = 60;
8203 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008204 dur = 30;
8205 else if (ssid->auth_failures > 1)
8206 dur = 20;
8207 else
8208 dur = 10;
8209
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008210 if (ssid->auth_failures > 1 &&
8211 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8212 dur += os_random() % (ssid->auth_failures * 10);
8213
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008214 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008215 if (now.sec + dur <= ssid->disabled_until.sec)
8216 return;
8217
8218 ssid->disabled_until.sec = now.sec + dur;
8219
8220 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008221 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008222 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008223 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008224
8225 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8226 int msg_len = snprintf(NULL, 0, format_str,
8227 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8228 ssid->auth_failures, dur, reason) + 1;
8229 char *msg = os_malloc(msg_len);
8230 snprintf(msg, msg_len, format_str,
8231 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8232 ssid->auth_failures, dur, reason);
8233 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8234 os_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008235}
8236
8237
8238void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8239 struct wpa_ssid *ssid, int clear_failures)
8240{
8241 if (ssid == NULL)
8242 return;
8243
8244 if (ssid->disabled_until.sec) {
8245 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8246 "id=%d ssid=\"%s\"",
8247 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8248 }
8249 ssid->disabled_until.sec = 0;
8250 ssid->disabled_until.usec = 0;
8251 if (clear_failures)
8252 ssid->auth_failures = 0;
8253}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008254
8255
8256int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8257{
8258 size_t i;
8259
8260 if (wpa_s->disallow_aps_bssid == NULL)
8261 return 0;
8262
8263 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8264 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8265 bssid, ETH_ALEN) == 0)
8266 return 1;
8267 }
8268
8269 return 0;
8270}
8271
8272
8273int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8274 size_t ssid_len)
8275{
8276 size_t i;
8277
8278 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8279 return 0;
8280
8281 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8282 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8283 if (ssid_len == s->ssid_len &&
8284 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8285 return 1;
8286 }
8287
8288 return 0;
8289}
8290
8291
8292/**
8293 * wpas_request_connection - Request a new connection
8294 * @wpa_s: Pointer to the network interface
8295 *
8296 * This function is used to request a new connection to be found. It will mark
8297 * the interface to allow reassociation and request a new scan to find a
8298 * suitable network to connect to.
8299 */
8300void wpas_request_connection(struct wpa_supplicant *wpa_s)
8301{
8302 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008303 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008304 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008305 wpa_s->disconnected = 0;
8306 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008307 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008308
8309 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8310 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008311 else
8312 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008313}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008314
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008315
Roshan Pius02242d72016-08-09 15:31:48 -07008316/**
8317 * wpas_request_disconnection - Request disconnection
8318 * @wpa_s: Pointer to the network interface
8319 *
8320 * This function is used to request disconnection from the currently connected
8321 * network. This will stop any ongoing scans and initiate deauthentication.
8322 */
8323void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8324{
8325#ifdef CONFIG_SME
8326 wpa_s->sme.prev_bssid_set = 0;
8327#endif /* CONFIG_SME */
8328 wpa_s->reassociate = 0;
8329 wpa_s->disconnected = 1;
8330 wpa_supplicant_cancel_sched_scan(wpa_s);
8331 wpa_supplicant_cancel_scan(wpa_s);
8332 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8333 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008334 radio_remove_works(wpa_s, "connect", 0);
8335 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008336 wpa_s->roam_in_progress = false;
8337#ifdef CONFIG_WNM
8338 wpa_s->bss_trans_mgmt_in_progress = false;
8339#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008340}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008341
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008342
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008343void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8344 struct wpa_used_freq_data *freqs_data,
8345 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008346{
8347 unsigned int i;
8348
8349 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8350 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008351 for (i = 0; i < len; i++) {
8352 struct wpa_used_freq_data *cur = &freqs_data[i];
8353 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8354 i, cur->freq, cur->flags);
8355 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008356}
8357
8358
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008359/*
8360 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008361 * are using the same radio as the current interface, and in addition, get
8362 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008363 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008364int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8365 struct wpa_used_freq_data *freqs_data,
8366 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008367{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008368 struct wpa_supplicant *ifs;
8369 u8 bssid[ETH_ALEN];
8370 int freq;
8371 unsigned int idx = 0, i;
8372
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008373 wpa_dbg(wpa_s, MSG_DEBUG,
8374 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008375 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008376
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008377 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8378 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008379 if (idx == len)
8380 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008381
8382 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8383 continue;
8384
8385 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008386 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8387 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008388 freq = ifs->current_ssid->frequency;
8389 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8390 freq = ifs->assoc_freq;
8391 else
8392 continue;
8393
8394 /* Hold only distinct freqs */
8395 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008396 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008397 break;
8398
8399 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008400 freqs_data[idx++].freq = freq;
8401
8402 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008403 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008404 WPA_FREQ_USED_BY_P2P_CLIENT :
8405 WPA_FREQ_USED_BY_INFRA_STATION;
8406 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008407 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008408
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008409 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008410 return idx;
8411}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008412
8413
8414/*
8415 * Find the operating frequencies of any of the virtual interfaces that
8416 * are using the same radio as the current interface.
8417 */
8418int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8419 int *freq_array, unsigned int len)
8420{
8421 struct wpa_used_freq_data *freqs_data;
8422 int num, i;
8423
8424 os_memset(freq_array, 0, sizeof(int) * len);
8425
8426 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8427 if (!freqs_data)
8428 return -1;
8429
8430 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8431 for (i = 0; i < num; i++)
8432 freq_array[i] = freqs_data[i].freq;
8433
8434 os_free(freqs_data);
8435
8436 return num;
8437}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008438
8439
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008440struct wpa_supplicant *
8441wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8442{
8443 switch (frame) {
8444#ifdef CONFIG_P2P
8445 case VENDOR_ELEM_PROBE_REQ_P2P:
8446 case VENDOR_ELEM_PROBE_RESP_P2P:
8447 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8448 case VENDOR_ELEM_BEACON_P2P_GO:
8449 case VENDOR_ELEM_P2P_PD_REQ:
8450 case VENDOR_ELEM_P2P_PD_RESP:
8451 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8452 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8453 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8454 case VENDOR_ELEM_P2P_INV_REQ:
8455 case VENDOR_ELEM_P2P_INV_RESP:
8456 case VENDOR_ELEM_P2P_ASSOC_REQ:
8457 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008458 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008459#endif /* CONFIG_P2P */
8460 default:
8461 return wpa_s;
8462 }
8463}
8464
8465
8466void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8467{
8468 unsigned int i;
8469 char buf[30];
8470
8471 wpa_printf(MSG_DEBUG, "Update vendor elements");
8472
8473 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8474 if (wpa_s->vendor_elem[i]) {
8475 int res;
8476
8477 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8478 if (!os_snprintf_error(sizeof(buf), res)) {
8479 wpa_hexdump_buf(MSG_DEBUG, buf,
8480 wpa_s->vendor_elem[i]);
8481 }
8482 }
8483 }
8484
8485#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008486 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008487 wpa_s->global->p2p &&
8488 !wpa_s->global->p2p_disabled)
8489 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8490#endif /* CONFIG_P2P */
8491}
8492
8493
8494int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8495 const u8 *elem, size_t len)
8496{
8497 u8 *ie, *end;
8498
8499 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8500 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8501
8502 for (; ie + 1 < end; ie += 2 + ie[1]) {
8503 if (ie + len > end)
8504 break;
8505 if (os_memcmp(ie, elem, len) != 0)
8506 continue;
8507
8508 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8509 wpabuf_free(wpa_s->vendor_elem[frame]);
8510 wpa_s->vendor_elem[frame] = NULL;
8511 } else {
8512 os_memmove(ie, ie + len, end - (ie + len));
8513 wpa_s->vendor_elem[frame]->used -= len;
8514 }
8515 wpas_vendor_elem_update(wpa_s);
8516 return 0;
8517 }
8518
8519 return -1;
8520}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008521
8522
8523struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008524 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008525 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008526{
8527 u16 i;
8528
Hai Shalomc1a21442022-02-04 13:43:00 -08008529 if (!modes)
8530 return NULL;
8531
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008532 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008533 if (modes[i].mode != mode ||
8534 !modes[i].num_channels || !modes[i].channels)
8535 continue;
8536 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8537 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008538 return &modes[i];
8539 }
8540
8541 return NULL;
8542}
8543
8544
Hai Shalomc1a21442022-02-04 13:43:00 -08008545struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8546 u16 num_modes, int freq)
8547{
8548 int i, j;
8549
8550 for (i = 0; i < num_modes; i++) {
8551 for (j = 0; j < modes[i].num_channels; j++) {
8552 if (freq == modes[i].channels[j].freq)
8553 return &modes[i];
8554 }
8555 }
8556
8557 return NULL;
8558}
8559
8560
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008561static struct
8562wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8563 const u8 *bssid)
8564{
8565 struct wpa_bss_tmp_disallowed *bss;
8566
8567 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8568 struct wpa_bss_tmp_disallowed, list) {
8569 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8570 return bss;
8571 }
8572
8573 return NULL;
8574}
8575
8576
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008577static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8578{
8579 struct wpa_bss_tmp_disallowed *tmp;
8580 unsigned int num_bssid = 0;
8581 u8 *bssids;
8582 int ret;
8583
8584 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8585 if (!bssids)
8586 return -1;
8587 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8588 struct wpa_bss_tmp_disallowed, list) {
8589 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8590 ETH_ALEN);
8591 num_bssid++;
8592 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008593 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008594 os_free(bssids);
8595 return ret;
8596}
8597
8598
8599static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8600{
8601 struct wpa_supplicant *wpa_s = eloop_ctx;
8602 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8603
8604 /* Make sure the bss is not already freed */
8605 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8606 struct wpa_bss_tmp_disallowed, list) {
8607 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008608 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008609 wpa_set_driver_tmp_disallow_list(wpa_s);
8610 break;
8611 }
8612 }
8613}
8614
8615
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008616void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008617 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008618{
8619 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008620
8621 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8622 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008623 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008624 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008625 }
8626
8627 bss = os_malloc(sizeof(*bss));
8628 if (!bss) {
8629 wpa_printf(MSG_DEBUG,
8630 "Failed to allocate memory for temp disallow BSS");
8631 return;
8632 }
8633
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008634 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8635 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008636 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008637
8638finish:
8639 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008640 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8641 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008642}
8643
8644
Hai Shalom74f70d42019-02-11 14:42:39 -08008645int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8646 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008647{
Hai Shalom74f70d42019-02-11 14:42:39 -08008648 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008649
8650 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8651 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008652 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8653 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008654 break;
8655 }
8656 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008657 if (!disallowed)
8658 return 0;
8659
8660 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008661 bss->level > disallowed->rssi_threshold) {
8662 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8663 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008664 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008665 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008666
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008667 return 1;
8668}
Hai Shalom81f62d82019-07-22 12:10:00 -07008669
8670
8671int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8672 unsigned int type, const u8 *addr,
8673 const u8 *mask)
8674{
8675 if ((addr && !mask) || (!addr && mask)) {
8676 wpa_printf(MSG_INFO,
8677 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8678 return -1;
8679 }
8680
8681 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8682 wpa_printf(MSG_INFO,
8683 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8684 return -1;
8685 }
8686
8687 if (type & MAC_ADDR_RAND_SCAN) {
8688 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8689 addr, mask))
8690 return -1;
8691 }
8692
8693 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8694 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8695 addr, mask))
8696 return -1;
8697
8698 if (wpa_s->sched_scanning && !wpa_s->pno)
8699 wpas_scan_restart_sched_scan(wpa_s);
8700 }
8701
8702 if (type & MAC_ADDR_RAND_PNO) {
8703 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8704 addr, mask))
8705 return -1;
8706
8707 if (wpa_s->pno) {
8708 wpas_stop_pno(wpa_s);
8709 wpas_start_pno(wpa_s);
8710 }
8711 }
8712
8713 return 0;
8714}
8715
8716
8717int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8718 unsigned int type)
8719{
8720 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8721 if (wpa_s->pno) {
8722 if (type & MAC_ADDR_RAND_PNO) {
8723 wpas_stop_pno(wpa_s);
8724 wpas_start_pno(wpa_s);
8725 }
8726 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8727 wpas_scan_restart_sched_scan(wpa_s);
8728 }
8729
8730 return 0;
8731}
Hai Shalomfdcde762020-04-02 11:19:20 -07008732
8733
8734int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8735 struct wpa_signal_info *si)
8736{
8737 int res;
8738
8739 if (!wpa_s->driver->signal_poll)
8740 return -1;
8741
8742 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8743
8744#ifdef CONFIG_TESTING_OPTIONS
8745 if (res == 0) {
8746 struct driver_signal_override *dso;
8747
8748 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8749 struct driver_signal_override, list) {
8750 if (os_memcmp(wpa_s->bssid, dso->bssid,
8751 ETH_ALEN) != 0)
8752 continue;
8753 wpa_printf(MSG_DEBUG,
8754 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8755 si->current_signal,
8756 dso->si_current_signal,
8757 si->avg_signal,
8758 dso->si_avg_signal,
8759 si->avg_beacon_signal,
8760 dso->si_avg_beacon_signal,
8761 si->current_noise,
8762 dso->si_current_noise);
8763 si->current_signal = dso->si_current_signal;
8764 si->avg_signal = dso->si_avg_signal;
8765 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8766 si->current_noise = dso->si_current_noise;
8767 break;
8768 }
8769 }
8770#endif /* CONFIG_TESTING_OPTIONS */
8771
8772 return res;
8773}
8774
8775
8776struct wpa_scan_results *
8777wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8778{
8779 struct wpa_scan_results *scan_res;
8780#ifdef CONFIG_TESTING_OPTIONS
8781 size_t idx;
8782#endif /* CONFIG_TESTING_OPTIONS */
8783
8784 if (!wpa_s->driver->get_scan_results2)
8785 return NULL;
8786
8787 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8788
8789#ifdef CONFIG_TESTING_OPTIONS
8790 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8791 struct driver_signal_override *dso;
8792 struct wpa_scan_res *res = scan_res->res[idx];
8793
8794 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8795 struct driver_signal_override, list) {
8796 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8797 continue;
8798 wpa_printf(MSG_DEBUG,
8799 "Override driver scan signal level %d->%d for "
8800 MACSTR,
8801 res->level, dso->scan_level,
8802 MAC2STR(res->bssid));
8803 res->flags |= WPA_SCAN_QUAL_INVALID;
8804 if (dso->scan_level < 0)
8805 res->flags |= WPA_SCAN_LEVEL_DBM;
8806 else
8807 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8808 res->level = dso->scan_level;
8809 break;
8810 }
8811 }
8812#endif /* CONFIG_TESTING_OPTIONS */
8813
8814 return scan_res;
8815}