blob: 7d896f4d40df5302a4a46bc9bbfc631a9ef71e67 [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;
Sunil Ravi89eba102022-09-13 21:04:37 -0700989 char mld_addr[50];
990
991 mld_addr[0] = '\0';
992 if (wpa_s->valid_links)
993 os_snprintf(mld_addr, sizeof(mld_addr),
994 " ap_mld_addr=" MACSTR,
995 MAC2STR(wpa_s->ap_mld_addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700996
997#ifdef CONFIG_SME
998 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
999 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
1000 fils_hlp_sent = 1;
1001#endif /* CONFIG_SME */
1002 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1003 wpa_auth_alg_fils(wpa_s->auth_alg))
1004 fils_hlp_sent = 1;
1005
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001006#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Sunil Ravi89eba102022-09-13 21:04:37 -07001008 MACSTR " completed [id=%d id_str=%s%s]%s",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001009 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001011 ssid && ssid->id_str ? ssid->id_str : "",
Sunil Ravi89eba102022-09-13 21:04:37 -07001012 fils_hlp_sent ? " FILS_HLP_SENT" : "", mld_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001014 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001015 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001017 wpa_drv_set_operstate(wpa_s, 1);
1018#ifndef IEEE8021X_EAPOL
1019 wpa_drv_set_supp_port(wpa_s, 1);
1020#endif /* IEEE8021X_EAPOL */
1021 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001022 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001023 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001024
1025 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001026
1027#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1028 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001029 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001030#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001031#ifdef CONFIG_OWE
1032 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1033 wpas_update_owe_connect_params(wpa_s);
1034#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001035#ifdef CONFIG_HS20
1036 hs20_configure_frame_filters(wpa_s);
1037#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001038 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1039 state == WPA_ASSOCIATED) {
1040 wpa_s->new_connection = 1;
1041 wpa_drv_set_operstate(wpa_s, 0);
1042#ifndef IEEE8021X_EAPOL
1043 wpa_drv_set_supp_port(wpa_s, 0);
1044#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001045 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 }
1047 wpa_s->wpa_state = state;
1048
1049#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001050 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1051 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001052 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053 wpa_supplicant_stop_bgscan(wpa_s);
1054#endif /* CONFIG_BGSCAN */
1055
Hai Shalom5f92bc92019-04-18 11:54:11 -07001056 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001057 wpa_supplicant_stop_autoscan(wpa_s);
1058
1059 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1060 wpa_supplicant_start_autoscan(wpa_s);
1061
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001062 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1063 wmm_ac_notify_disassoc(wpa_s);
1064
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001065 if (wpa_s->wpa_state != old_state) {
1066 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1067
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001068 /*
1069 * Notify the P2P Device interface about a state change in one
1070 * of the interfaces.
1071 */
1072 wpas_p2p_indicate_state_change(wpa_s);
1073
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074 if (wpa_s->wpa_state == WPA_COMPLETED ||
1075 old_state == WPA_COMPLETED)
1076 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001077#ifdef CONFIG_DPP2
1078 if (wpa_s->wpa_state == WPA_COMPLETED)
1079 wpas_dpp_connected(wpa_s);
1080#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001081 }
Hai Shalomc3565922019-10-28 11:58:20 -07001082#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1083 if (update_fils_connect_params)
1084 wpas_update_fils_connect_params(wpa_s);
1085#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001086}
1087
1088
1089void wpa_supplicant_terminate_proc(struct wpa_global *global)
1090{
1091 int pending = 0;
1092#ifdef CONFIG_WPS
1093 struct wpa_supplicant *wpa_s = global->ifaces;
1094 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001095 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001096 if (wpas_wps_terminate_pending(wpa_s) == 1)
1097 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001098#ifdef CONFIG_P2P
1099 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1100 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1101 wpas_p2p_disconnect(wpa_s);
1102#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001103 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104 }
1105#endif /* CONFIG_WPS */
1106 if (pending)
1107 return;
1108 eloop_terminate();
1109}
1110
1111
1112static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1113{
1114 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001115 wpa_supplicant_terminate_proc(global);
1116}
1117
1118
1119void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1120{
1121 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001122 enum wpa_states new_state;
1123
1124 if (old_state == WPA_SCANNING)
1125 new_state = WPA_SCANNING;
1126 else
1127 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128
1129 wpa_s->pairwise_cipher = 0;
1130 wpa_s->group_cipher = 0;
1131 wpa_s->mgmt_group_cipher = 0;
1132 wpa_s->key_mgmt = 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07001133 wpa_s->allowed_key_mgmts = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001134 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001135 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001136
1137 if (wpa_s->wpa_state != old_state)
1138 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1139}
1140
1141
1142/**
1143 * wpa_supplicant_reload_configuration - Reload configuration data
1144 * @wpa_s: Pointer to wpa_supplicant data
1145 * Returns: 0 on success or -1 if configuration parsing failed
1146 *
1147 * This function can be used to request that the configuration data is reloaded
1148 * (e.g., after configuration file change). This function is reloading
1149 * configuration only for one interface, so this may need to be called multiple
1150 * times if %wpa_supplicant is controlling multiple interfaces and all
1151 * interfaces need reconfiguration.
1152 */
1153int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1154{
1155 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001156 int reconf_ctrl;
1157 int old_ap_scan;
1158
1159 if (wpa_s->confname == NULL)
1160 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001161 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001162 if (conf == NULL) {
1163 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1164 "file '%s' - exiting", wpa_s->confname);
1165 return -1;
1166 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001167 if (wpa_s->confanother &&
1168 !wpa_config_read(wpa_s->confanother, conf)) {
1169 wpa_msg(wpa_s, MSG_ERROR,
1170 "Failed to parse the configuration file '%s' - exiting",
1171 wpa_s->confanother);
1172 return -1;
1173 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001174
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001175 conf->changed_parameters = (unsigned int) -1;
1176
1177 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1178 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1179 os_strcmp(conf->ctrl_interface,
1180 wpa_s->conf->ctrl_interface) != 0);
1181
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001182 if (reconf_ctrl) {
1183 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 wpa_s->ctrl_iface = NULL;
1185 }
1186
1187 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001188 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001189 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1190 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001191 wpa_supplicant_deauthenticate(wpa_s,
1192 WLAN_REASON_DEAUTH_LEAVING);
1193 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194
1195 /*
1196 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001197 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001198 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001199 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1200 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1201 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001202 /*
1203 * Clear forced success to clear EAP state for next
1204 * authentication.
1205 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001206 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001207 }
1208 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1209 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001210 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001211 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1212 rsn_preauth_deinit(wpa_s->wpa);
1213
1214 old_ap_scan = wpa_s->conf->ap_scan;
1215 wpa_config_free(wpa_s->conf);
1216 wpa_s->conf = conf;
1217 if (old_ap_scan != wpa_s->conf->ap_scan)
1218 wpas_notify_ap_scan_changed(wpa_s);
1219
1220 if (reconf_ctrl)
1221 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1222
1223 wpa_supplicant_update_config(wpa_s);
1224
1225 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001226 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001227 wpa_s->reassociate = 1;
1228 wpa_supplicant_req_scan(wpa_s, 0, 0);
1229 }
Hai Shalom60840252021-02-19 19:02:11 -08001230 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001231 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1232 return 0;
1233}
1234
1235
1236static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1237{
1238 struct wpa_global *global = signal_ctx;
1239 struct wpa_supplicant *wpa_s;
1240 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1241 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1242 sig);
1243 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1244 wpa_supplicant_terminate_proc(global);
1245 }
1246 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001247
1248 if (wpa_debug_reopen_file() < 0) {
1249 /* Ignore errors since we cannot really do much to fix this */
1250 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1251 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001252}
1253
1254
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001255static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1256 struct wpa_ssid *ssid,
1257 struct wpa_ie_data *ie)
1258{
1259 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1260 if (ret) {
1261 if (ret == -2) {
1262 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1263 "from association info");
1264 }
1265 return -1;
1266 }
1267
1268 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1269 "cipher suites");
1270 if (!(ie->group_cipher & ssid->group_cipher)) {
1271 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1272 "cipher 0x%x (mask 0x%x) - reject",
1273 ie->group_cipher, ssid->group_cipher);
1274 return -1;
1275 }
1276 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1277 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1278 "cipher 0x%x (mask 0x%x) - reject",
1279 ie->pairwise_cipher, ssid->pairwise_cipher);
1280 return -1;
1281 }
1282 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1283 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1284 "management 0x%x (mask 0x%x) - reject",
1285 ie->key_mgmt, ssid->key_mgmt);
1286 return -1;
1287 }
1288
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001289 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001290 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001291 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1292 "that does not support management frame protection - "
1293 "reject");
1294 return -1;
1295 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296
1297 return 0;
1298}
1299
1300
Hai Shalom021b0b52019-04-10 11:17:58 -07001301static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1302 int freq)
1303{
1304 if (!ie->has_group)
1305 ie->group_cipher = wpa_default_rsn_cipher(freq);
1306 if (!ie->has_pairwise)
1307 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1308 return (ie->group_cipher & ssid->group_cipher) &&
1309 (ie->pairwise_cipher & ssid->pairwise_cipher);
1310}
1311
1312
Hai Shalomc1a21442022-02-04 13:43:00 -08001313void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1314 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1315{
1316 int sel;
1317
1318 sel = ie->mgmt_group_cipher;
1319 if (ssid->group_mgmt_cipher)
1320 sel &= ssid->group_mgmt_cipher;
1321 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1322 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1323 sel = 0;
1324 wpa_dbg(wpa_s, MSG_DEBUG,
1325 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1326 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1327 if (sel & WPA_CIPHER_AES_128_CMAC) {
1328 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1329 wpa_dbg(wpa_s, MSG_DEBUG,
1330 "WPA: using MGMT group cipher AES-128-CMAC");
1331 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1332 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1333 wpa_dbg(wpa_s, MSG_DEBUG,
1334 "WPA: using MGMT group cipher BIP-GMAC-128");
1335 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1336 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1337 wpa_dbg(wpa_s, MSG_DEBUG,
1338 "WPA: using MGMT group cipher BIP-GMAC-256");
1339 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1340 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1341 wpa_dbg(wpa_s, MSG_DEBUG,
1342 "WPA: using MGMT group cipher BIP-CMAC-256");
1343 } else {
1344 wpa_s->mgmt_group_cipher = 0;
1345 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1346 }
1347 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1348 wpa_s->mgmt_group_cipher);
1349 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1350 wpas_get_ssid_pmf(wpa_s, ssid));
1351}
1352
1353
Sunil Ravi89eba102022-09-13 21:04:37 -07001354static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
1355 struct wpa_ssid *ssid)
1356{
1357 int akm_count = wpa_s->max_num_akms;
1358 u8 capab = 0;
1359
1360 if (akm_count < 2)
1361 return;
1362
1363 akm_count--;
1364 wpa_s->allowed_key_mgmts = 0;
1365 switch (wpa_s->key_mgmt) {
1366 case WPA_KEY_MGMT_PSK:
1367 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1368 akm_count--;
1369 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1370 }
1371 if (!akm_count)
1372 break;
1373 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1374 akm_count--;
1375 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1376 }
1377 if (!akm_count)
1378 break;
1379 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1380 wpa_s->allowed_key_mgmts |=
1381 WPA_KEY_MGMT_PSK_SHA256;
1382 break;
1383 case WPA_KEY_MGMT_PSK_SHA256:
1384 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1385 akm_count--;
1386 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1387 }
1388 if (!akm_count)
1389 break;
1390 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1391 akm_count--;
1392 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1393 }
1394 if (!akm_count)
1395 break;
1396 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
1397 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1398 break;
1399 case WPA_KEY_MGMT_SAE:
1400 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1401 akm_count--;
1402 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1403 }
1404 if (!akm_count)
1405 break;
1406 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
1407 akm_count--;
1408 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
1409 }
1410 if (!akm_count)
1411 break;
1412 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1413 wpa_s->allowed_key_mgmts |=
1414 WPA_KEY_MGMT_PSK_SHA256;
1415 break;
1416 case WPA_KEY_MGMT_SAE_EXT_KEY:
1417 if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
1418 akm_count--;
1419 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
1420 }
1421 if (!akm_count)
1422 break;
1423 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1424 akm_count--;
1425 wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
1426 }
1427 if (!akm_count)
1428 break;
1429 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
1430 wpa_s->allowed_key_mgmts |=
1431 WPA_KEY_MGMT_PSK_SHA256;
1432 break;
1433 default:
1434 return;
1435 }
1436
1437 if (wpa_s->conf->sae_pwe)
1438 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1439#ifdef CONFIG_SAE_PK
1440 if (ssid->sae_pk)
1441 capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
1442#endif /* CONFIG_SAE_PK */
1443
1444 if (!((wpa_s->allowed_key_mgmts &
1445 (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
1446 return;
1447
1448 if (!wpa_s->rsnxe_len) {
1449 wpa_s->rsnxe_len = 3;
1450 wpa_s->rsnxe[0] = WLAN_EID_RSNX;
1451 wpa_s->rsnxe[1] = 1;
1452 wpa_s->rsnxe[2] = 0;
1453 }
1454
1455 wpa_s->rsnxe[2] |= capab;
1456}
1457
1458
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459/**
1460 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1461 * @wpa_s: Pointer to wpa_supplicant data
1462 * @bss: Scan results for the selected BSS, or %NULL if not available
1463 * @ssid: Configuration data for the selected network
1464 * @wpa_ie: Buffer for the WPA/RSN IE
1465 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1466 * used buffer length in case the functions returns success.
1467 * Returns: 0 on success or -1 on failure
1468 *
1469 * This function is used to configure authentication and encryption parameters
1470 * based on the network configuration and scan result for the selected BSS (if
1471 * available).
1472 */
1473int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1474 struct wpa_bss *bss, struct wpa_ssid *ssid,
1475 u8 *wpa_ie, size_t *wpa_ie_len)
1476{
1477 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001478 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001479 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001480
1481 if (bss) {
1482 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1483 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001484 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001485 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001486 } else {
1487 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1488 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001489
1490 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1491 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001492 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001493 (ie.key_mgmt & ssid->key_mgmt)) {
1494 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1495 proto = WPA_PROTO_RSN;
1496 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001497 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001498 (ie.group_cipher & ssid->group_cipher) &&
1499 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1500 (ie.key_mgmt & ssid->key_mgmt)) {
1501 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1502 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001503#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001504 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1505 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1506 (ie.group_cipher & ssid->group_cipher) &&
1507 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1508 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001509 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001510 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001511 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1512 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1513 (ie.group_cipher & ssid->group_cipher) &&
1514 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1515 (ie.key_mgmt & ssid->key_mgmt)) {
1516 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1517 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001518#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001519 } else if (bss) {
1520 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001521 wpa_dbg(wpa_s, MSG_DEBUG,
1522 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1523 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1524 ssid->key_mgmt);
1525 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1526 MAC2STR(bss->bssid),
1527 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1528 bss_wpa ? " WPA" : "",
1529 bss_rsn ? " RSN" : "",
1530 bss_osen ? " OSEN" : "");
1531 if (bss_rsn) {
1532 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1533 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1534 wpa_dbg(wpa_s, MSG_DEBUG,
1535 "Could not parse RSN element");
1536 } else {
1537 wpa_dbg(wpa_s, MSG_DEBUG,
1538 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1539 ie.pairwise_cipher, ie.group_cipher,
1540 ie.key_mgmt);
1541 }
1542 }
1543 if (bss_wpa) {
1544 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1545 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1546 wpa_dbg(wpa_s, MSG_DEBUG,
1547 "Could not parse WPA element");
1548 } else {
1549 wpa_dbg(wpa_s, MSG_DEBUG,
1550 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1551 ie.pairwise_cipher, ie.group_cipher,
1552 ie.key_mgmt);
1553 }
1554 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555 return -1;
1556 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001557 if (ssid->proto & WPA_PROTO_OSEN)
1558 proto = WPA_PROTO_OSEN;
1559 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001560 proto = WPA_PROTO_RSN;
1561 else
1562 proto = WPA_PROTO_WPA;
1563 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1564 os_memset(&ie, 0, sizeof(ie));
1565 ie.group_cipher = ssid->group_cipher;
1566 ie.pairwise_cipher = ssid->pairwise_cipher;
1567 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001568 ie.mgmt_group_cipher = 0;
1569 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1570 if (ssid->group_mgmt_cipher &
1571 WPA_CIPHER_BIP_GMAC_256)
1572 ie.mgmt_group_cipher =
1573 WPA_CIPHER_BIP_GMAC_256;
1574 else if (ssid->group_mgmt_cipher &
1575 WPA_CIPHER_BIP_CMAC_256)
1576 ie.mgmt_group_cipher =
1577 WPA_CIPHER_BIP_CMAC_256;
1578 else if (ssid->group_mgmt_cipher &
1579 WPA_CIPHER_BIP_GMAC_128)
1580 ie.mgmt_group_cipher =
1581 WPA_CIPHER_BIP_GMAC_128;
1582 else
1583 ie.mgmt_group_cipher =
1584 WPA_CIPHER_AES_128_CMAC;
1585 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001586#ifdef CONFIG_OWE
1587 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1588 !ssid->owe_only &&
1589 !bss_wpa && !bss_rsn && !bss_osen) {
1590 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1591 wpa_s->wpa_proto = 0;
1592 *wpa_ie_len = 0;
1593 return 0;
1594 }
1595#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001596 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1597 "based on configuration");
1598 } else
1599 proto = ie.proto;
1600 }
1601
1602 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1603 "pairwise %d key_mgmt %d proto %d",
1604 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605 if (ssid->ieee80211w) {
1606 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1607 ie.mgmt_group_cipher);
1608 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001609
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001610 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001611 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1612 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001613 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001614
1615 if (bss || !wpa_s->ap_ies_from_associnfo) {
1616 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1617 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1618 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001619 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1620 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1621 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622 return -1;
1623 }
1624
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001625#ifdef CONFIG_NO_WPA
1626 wpa_s->group_cipher = WPA_CIPHER_NONE;
1627 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1628#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001630 wpa_dbg(wpa_s, MSG_DEBUG,
1631 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1632 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001633 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1634 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001635 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1636 "cipher");
1637 return -1;
1638 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001639 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1640 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641
1642 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001643 wpa_dbg(wpa_s, MSG_DEBUG,
1644 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1645 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001646 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1647 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001648 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1649 "cipher");
1650 return -1;
1651 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001652 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1653 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001654#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001655
1656 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001657#ifdef CONFIG_SAE
1658 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
Sunil Ravi89eba102022-09-13 21:04:37 -07001659 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
1660 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001661#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001662#ifdef CONFIG_IEEE80211R
1663 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1664 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1665 sel &= ~WPA_KEY_MGMT_FT;
1666#endif /* CONFIG_IEEE80211R */
1667 wpa_dbg(wpa_s, MSG_DEBUG,
1668 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1669 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001670 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001671#ifdef CONFIG_IEEE80211R
1672#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001673 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1674 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001675 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1676 wpa_dbg(wpa_s, MSG_DEBUG,
1677 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001678 if (!ssid->ft_eap_pmksa_caching &&
1679 pmksa_cache_get_current(wpa_s->wpa)) {
1680 /* PMKSA caching with FT may have interoperability
1681 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001682 wpa_dbg(wpa_s, MSG_DEBUG,
1683 "WPA: Disable PMKSA caching for FT/802.1X connection");
1684 pmksa_cache_clear_current(wpa_s->wpa);
1685 }
1686#endif /* CONFIG_SHA384 */
1687#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001688#ifdef CONFIG_SUITEB192
1689 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1690 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1691 wpa_dbg(wpa_s, MSG_DEBUG,
1692 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1693#endif /* CONFIG_SUITEB192 */
1694#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001695 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1696 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1697 wpa_dbg(wpa_s, MSG_DEBUG,
1698 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001699#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001700#ifdef CONFIG_FILS
1701#ifdef CONFIG_IEEE80211R
1702 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1703 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1704 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001705#endif /* CONFIG_IEEE80211R */
1706 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1707 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1708 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
Sunil Ravi89eba102022-09-13 21:04:37 -07001709#ifdef CONFIG_IEEE80211R
1710 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1711 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1712 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1713#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001714 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1715 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1716 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1717#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001719 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1720 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1722 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001723 if (!ssid->ft_eap_pmksa_caching &&
1724 pmksa_cache_get_current(wpa_s->wpa)) {
1725 /* PMKSA caching with FT may have interoperability
1726 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001727 wpa_dbg(wpa_s, MSG_DEBUG,
1728 "WPA: Disable PMKSA caching for FT/802.1X connection");
1729 pmksa_cache_clear_current(wpa_s->wpa);
1730 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001731#endif /* CONFIG_IEEE80211R */
1732#ifdef CONFIG_DPP
1733 } else if (sel & WPA_KEY_MGMT_DPP) {
1734 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1735 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1736#endif /* CONFIG_DPP */
1737#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07001738 } else if (sel & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
1739 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1740 wpa_dbg(wpa_s, MSG_DEBUG,
1741 "RSN: using KEY_MGMT FT/SAE (ext key)");
1742 } else if (sel & WPA_KEY_MGMT_SAE_EXT_KEY) {
1743 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1744 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE (ext key)");
Hai Shalom021b0b52019-04-10 11:17:58 -07001745 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1746 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1747 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1748 } else if (sel & WPA_KEY_MGMT_SAE) {
1749 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1750 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1751#endif /* CONFIG_SAE */
1752#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1754 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1755 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1756#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001757 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1758 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1759 wpa_dbg(wpa_s, MSG_DEBUG,
1760 "WPA: using KEY_MGMT 802.1X with SHA256");
1761 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1762 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1763 wpa_dbg(wpa_s, MSG_DEBUG,
1764 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001765 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1766 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1767 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1768 } else if (sel & WPA_KEY_MGMT_PSK) {
1769 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1770 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1771 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1772 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1773 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001774#ifdef CONFIG_HS20
1775 } else if (sel & WPA_KEY_MGMT_OSEN) {
1776 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1777 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1778#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001779#ifdef CONFIG_OWE
1780 } else if (sel & WPA_KEY_MGMT_OWE) {
1781 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1782 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1783#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001784 } else {
1785 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1786 "authenticated key management type");
1787 return -1;
1788 }
1789
1790 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1791 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1792 wpa_s->pairwise_cipher);
1793 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1794
Hai Shalomc3565922019-10-28 11:58:20 -07001795 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1796 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1797 wpa_msg(wpa_s, MSG_INFO,
1798 "RSN: Management frame protection required but the selected AP does not enable it");
1799 return -1;
1800 }
1801
Hai Shalomc1a21442022-02-04 13:43:00 -08001802 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001803#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001804 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1805 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1806 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001807#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001808 sae_pwe = wpa_s->conf->sae_pwe;
Sunil Ravi89eba102022-09-13 21:04:37 -07001809 if ((ssid->sae_password_id ||
1810 wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
1811 sae_pwe != 3)
Hai Shalomfdcde762020-04-02 11:19:20 -07001812 sae_pwe = 1;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001813 if (bss && is_6ghz_freq(bss->freq)) {
1814 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hash-to-element mode for 6GHz BSS.");
1815 sae_pwe = 1;
1816 }
1817#ifdef CONFIG_TESTING_OPTIONS
1818 if (wpa_s->force_hunting_and_pecking_pwe) {
1819 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hunting and pecking mode.");
1820 sae_pwe = 0;
1821 }
1822#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001823 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001824#ifdef CONFIG_SAE_PK
1825 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1826 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1827 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1828 ((ssid->sae_password &&
1829 sae_pk_valid_password(ssid->sae_password)) ||
1830 (!ssid->sae_password && ssid->passphrase &&
1831 sae_pk_valid_password(ssid->passphrase))));
1832#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001833#ifdef CONFIG_TESTING_OPTIONS
1834 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1835 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001836 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1837 wpa_s->oci_freq_override_eapol);
1838 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1839 wpa_s->oci_freq_override_eapol_g2);
1840 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1841 wpa_s->oci_freq_override_ft_assoc);
1842 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1843 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001844 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1845 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001846#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001847
1848 /* Extended Key ID is only supported in infrastructure BSS so far */
1849 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1850 (ssid->proto & WPA_PROTO_RSN) &&
1851 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1852 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1853 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1854 int use_ext_key_id = 0;
1855
1856 wpa_msg(wpa_s, MSG_DEBUG,
1857 "WPA: Enable Extended Key ID support");
1858 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1859 wpa_s->conf->extended_key_id);
1860 if (bss_rsn &&
1861 wpa_s->conf->extended_key_id &&
1862 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1863 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1864 use_ext_key_id = 1;
1865 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1866 use_ext_key_id);
1867 } else {
1868 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1869 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1870 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001871
1872 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1873 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1874 return -1;
1875 }
1876
Hai Shalomc3565922019-10-28 11:58:20 -07001877 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1878 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1879 &wpa_s->rsnxe_len)) {
1880 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1881 return -1;
1882 }
1883
Hai Shalom021b0b52019-04-10 11:17:58 -07001884 if (0) {
1885#ifdef CONFIG_DPP
1886 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1887 /* Use PMK from DPP network introduction (PMKSA entry) */
1888 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001889#ifdef CONFIG_DPP2
1890 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1891#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001892#endif /* CONFIG_DPP */
1893 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001894 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001895 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001896
Roshan Pius3a1667e2018-07-03 15:17:14 -07001897 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1898 WPA_KEY_MGMT_FT_PSK |
1899 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1900
1901 if (ssid->psk_set && !sae_only) {
1902 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1903 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001904 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1905 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001906 psk_set = 1;
1907 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001908
Roshan Pius3a1667e2018-07-03 15:17:14 -07001909 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1910 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001911 psk_set = 1;
1912
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001913#ifndef CONFIG_NO_PBKDF2
1914 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001915 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001916 u8 psk[PMK_LEN];
Sunil Ravia04bd252022-05-02 22:54:18 -07001917
1918 if (pbkdf2_sha1(ssid->passphrase, bss->ssid,
1919 bss->ssid_len,
1920 4096, psk, PMK_LEN) != 0) {
1921 wpa_msg(wpa_s, MSG_WARNING,
1922 "Error in pbkdf2_sha1()");
1923 return -1;
1924 }
1925 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001926 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001927 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001928 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001929 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001930 }
1931#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001932#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001933 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001934 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1935 ssid->ext_psk);
1936 char pw_str[64 + 1];
1937 u8 psk[PMK_LEN];
1938
1939 if (pw == NULL) {
1940 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1941 "found from external storage");
1942 return -1;
1943 }
1944
1945 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1946 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1947 "PSK length %d in external storage",
1948 (int) wpabuf_len(pw));
1949 ext_password_free(pw);
1950 return -1;
1951 }
1952
1953 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1954 pw_str[wpabuf_len(pw)] = '\0';
1955
1956#ifndef CONFIG_NO_PBKDF2
1957 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1958 {
Sunil Ravia04bd252022-05-02 22:54:18 -07001959 if (pbkdf2_sha1(pw_str, bss->ssid,
1960 bss->ssid_len,
1961 4096, psk, PMK_LEN) != 0) {
1962 wpa_msg(wpa_s, MSG_WARNING,
1963 "Error in pbkdf2_sha1()");
1964 ext_password_free(pw);
1965 return -1;
1966 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001967 os_memset(pw_str, 0, sizeof(pw_str));
1968 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1969 "external passphrase)",
1970 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001971 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1972 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001973 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001974 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001975 } else
1976#endif /* CONFIG_NO_PBKDF2 */
1977 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1978 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1979 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1980 "Invalid PSK hex string");
1981 os_memset(pw_str, 0, sizeof(pw_str));
1982 ext_password_free(pw);
1983 return -1;
1984 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001985 wpa_hexdump_key(MSG_MSGDUMP,
1986 "PSK (from external PSK)",
1987 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001988 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1989 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001990 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001991 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001992 } else {
1993 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1994 "PSK available");
1995 os_memset(pw_str, 0, sizeof(pw_str));
1996 ext_password_free(pw);
1997 return -1;
1998 }
1999
2000 os_memset(pw_str, 0, sizeof(pw_str));
2001 ext_password_free(pw);
2002 }
2003#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002004
2005 if (!psk_set) {
2006 wpa_msg(wpa_s, MSG_INFO,
2007 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002008 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07002009 return -1;
2010 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002011#ifdef CONFIG_OWE
2012 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2013 /* OWE Diffie-Hellman exchange in (Re)Association
2014 * Request/Response frames set the PMK, so do not override it
2015 * here. */
2016#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002017 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002018 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
2019
Hai Shalomfdcde762020-04-02 11:19:20 -07002020 if (ssid->mode != WPAS_MODE_IBSS &&
2021 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
2022 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
2023 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
2024 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
2025 wpa_msg(wpa_s, MSG_INFO,
2026 "Disable PTK0 rekey support - replaced with reconnect");
2027 wpa_s->deny_ptk0_rekey = 1;
2028 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
2029 } else {
2030 wpa_s->deny_ptk0_rekey = 0;
2031 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
2032 }
2033
Winnie Chen4138eec2022-11-10 16:32:53 +08002034#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Vinayak Yadawad14709082022-03-17 14:25:11 +05302035 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
Dennis Jeon2a960552022-07-05 13:56:50 +09002036 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt) &&
2037 (wpa_s->group_cipher == WPA_CIPHER_CCMP) &&
Dennis Jeona3930812022-10-24 15:31:04 +09002038 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) &&
2039 (wpa_s->wpa_proto == WPA_PROTO_RSN)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302040 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2041 wpa_dbg(wpa_s, MSG_INFO,
2042 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2043 }
Sunil Ravif42be322022-11-04 03:31:21 +00002044#else
2045 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2046 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2047 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Winnie Chen4138eec2022-11-10 16:32:53 +08002048#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Vinayak Yadawad14709082022-03-17 14:25:11 +05302049
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050 return 0;
2051}
2052
2053
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002054static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
2055{
Hai Shalomc1a21442022-02-04 13:43:00 -08002056 bool scs = true, mscs = true;
2057
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002058 *pos = 0x00;
2059
2060 switch (idx) {
2061 case 0: /* Bits 0-7 */
2062 break;
2063 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002064 if (wpa_s->conf->coloc_intf_reporting) {
2065 /* Bit 13 - Collocated Interference Reporting */
2066 *pos |= 0x20;
2067 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002068 break;
2069 case 2: /* Bits 16-23 */
2070#ifdef CONFIG_WNM
2071 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07002072 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002073 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002074#endif /* CONFIG_WNM */
2075 break;
2076 case 3: /* Bits 24-31 */
2077#ifdef CONFIG_WNM
2078 *pos |= 0x02; /* Bit 25 - SSID List */
2079#endif /* CONFIG_WNM */
2080#ifdef CONFIG_INTERWORKING
2081 if (wpa_s->conf->interworking)
2082 *pos |= 0x80; /* Bit 31 - Interworking */
2083#endif /* CONFIG_INTERWORKING */
2084 break;
2085 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002086#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002087 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002088 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002089#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002090 break;
2091 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002092#ifdef CONFIG_HS20
2093 if (wpa_s->conf->hs20)
2094 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2095#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002096#ifdef CONFIG_MBO
2097 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2098#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002099 break;
2100 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002101#ifdef CONFIG_TESTING_OPTIONS
2102 if (wpa_s->disable_scs_support)
2103 scs = false;
2104#endif /* CONFIG_TESTING_OPTIONS */
2105 if (scs)
2106 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002107 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002108 case 7: /* Bits 56-63 */
2109 break;
2110 case 8: /* Bits 64-71 */
2111 if (wpa_s->conf->ftm_responder)
2112 *pos |= 0x40; /* Bit 70 - FTM responder */
2113 if (wpa_s->conf->ftm_initiator)
2114 *pos |= 0x80; /* Bit 71 - FTM initiator */
2115 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002116 case 9: /* Bits 72-79 */
2117#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002118 if (!wpa_s->disable_fils)
2119 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002120#endif /* CONFIG_FILS */
2121 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002122 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002123#ifdef CONFIG_TESTING_OPTIONS
2124 if (wpa_s->disable_mscs_support)
2125 mscs = false;
2126#endif /* CONFIG_TESTING_OPTIONS */
2127 if (mscs)
2128 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07002129 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002130 }
2131}
2132
2133
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002134int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002135{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002136 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002137 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002138
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002139 if (len < wpa_s->extended_capa_len)
2140 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002141 if (buflen < (size_t) len + 2) {
2142 wpa_printf(MSG_INFO,
2143 "Not enough room for building extended capabilities element");
2144 return -1;
2145 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002146
2147 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002148 *pos++ = len;
2149 for (i = 0; i < len; i++, pos++) {
2150 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002151
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002152 if (i < wpa_s->extended_capa_len) {
2153 *pos &= ~wpa_s->extended_capa_mask[i];
2154 *pos |= wpa_s->extended_capa[i];
2155 }
2156 }
2157
2158 while (len > 0 && buf[1 + len] == 0) {
2159 len--;
2160 buf[1] = len;
2161 }
2162 if (len == 0)
2163 return 0;
2164
2165 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002166}
2167
2168
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002169static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2170 struct wpa_bss *test_bss)
2171{
2172 struct wpa_bss *bss;
2173
2174 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2175 if (bss == test_bss)
2176 return 1;
2177 }
2178
2179 return 0;
2180}
2181
2182
2183static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2184 struct wpa_ssid *test_ssid)
2185{
2186 struct wpa_ssid *ssid;
2187
2188 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2189 if (ssid == test_ssid)
2190 return 1;
2191 }
2192
2193 return 0;
2194}
2195
2196
2197int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2198 struct wpa_ssid *test_ssid)
2199{
2200 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2201 return 0;
2202
2203 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2204}
2205
2206
2207void wpas_connect_work_free(struct wpa_connect_work *cwork)
2208{
2209 if (cwork == NULL)
2210 return;
2211 os_free(cwork);
2212}
2213
2214
2215void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2216{
2217 struct wpa_connect_work *cwork;
2218 struct wpa_radio_work *work = wpa_s->connect_work;
2219
2220 if (!work)
2221 return;
2222
2223 wpa_s->connect_work = NULL;
2224 cwork = work->ctx;
2225 work->ctx = NULL;
2226 wpas_connect_work_free(cwork);
2227 radio_work_done(work);
2228}
2229
2230
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002231int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2232{
2233 struct os_reltime now;
2234 u8 addr[ETH_ALEN];
2235
2236 os_get_reltime(&now);
2237 if (wpa_s->last_mac_addr_style == style &&
2238 wpa_s->last_mac_addr_change.sec != 0 &&
2239 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2240 wpa_s->conf->rand_addr_lifetime)) {
2241 wpa_msg(wpa_s, MSG_DEBUG,
2242 "Previously selected random MAC address has not yet expired");
2243 return 0;
2244 }
2245
2246 switch (style) {
2247 case 1:
2248 if (random_mac_addr(addr) < 0)
2249 return -1;
2250 break;
2251 case 2:
2252 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2253 if (random_mac_addr_keep_oui(addr) < 0)
2254 return -1;
2255 break;
2256 default:
2257 return -1;
2258 }
2259
2260 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2261 wpa_msg(wpa_s, MSG_INFO,
2262 "Failed to set random MAC address");
2263 return -1;
2264 }
2265
2266 os_get_reltime(&wpa_s->last_mac_addr_change);
2267 wpa_s->mac_addr_changed = 1;
2268 wpa_s->last_mac_addr_style = style;
2269
2270 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2271 wpa_msg(wpa_s, MSG_INFO,
2272 "Could not update MAC address information");
2273 return -1;
2274 }
2275
2276 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2277 MAC2STR(addr));
2278
2279 return 0;
2280}
2281
2282
2283int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2284{
2285 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2286 !wpa_s->conf->preassoc_mac_addr)
2287 return 0;
2288
2289 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2290}
2291
2292
Sunil Ravi89eba102022-09-13 21:04:37 -07002293void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
Hai Shalomc3565922019-10-28 11:58:20 -07002294{
2295#ifdef CONFIG_SAE
2296 int *groups = conf->sae_groups;
2297 int default_groups[] = { 19, 20, 21, 0 };
2298 const char *password;
2299
2300 if (!groups || groups[0] <= 0)
2301 groups = default_groups;
2302
2303 password = ssid->sae_password;
2304 if (!password)
2305 password = ssid->passphrase;
2306
Hai Shalom899fcc72020-10-19 14:38:18 -07002307 if (!password ||
2308 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002309 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002310 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002311 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002312 /* PT derivation not needed */
2313 sae_deinit_pt(ssid->pt);
2314 ssid->pt = NULL;
2315 return;
2316 }
2317
2318 if (ssid->pt)
2319 return; /* PT already derived */
2320 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2321 (const u8 *) password, os_strlen(password),
2322 ssid->sae_password_id);
2323#endif /* CONFIG_SAE */
2324}
2325
2326
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002327static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2328{
2329#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2330 os_free(wpa_s->sme.sae_rejected_groups);
2331 wpa_s->sme.sae_rejected_groups = NULL;
2332#ifdef CONFIG_TESTING_OPTIONS
2333 if (wpa_s->extra_sae_rejected_groups) {
2334 int i, *groups = wpa_s->extra_sae_rejected_groups;
2335
2336 for (i = 0; groups[i]; i++) {
2337 wpa_printf(MSG_DEBUG,
2338 "TESTING: Indicate rejection of an extra SAE group %d",
2339 groups[i]);
2340 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2341 groups[i]);
2342 }
2343 }
2344#endif /* CONFIG_TESTING_OPTIONS */
2345#endif /* CONFIG_SAE && CONFIG_SME */
2346}
2347
2348
Hai Shalom60840252021-02-19 19:02:11 -08002349int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2350{
2351 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2352 wpa_msg(wpa_s, MSG_INFO,
2353 "Could not restore permanent MAC address");
2354 return -1;
2355 }
2356 wpa_s->mac_addr_changed = 0;
2357 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2358 wpa_msg(wpa_s, MSG_INFO,
2359 "Could not update MAC address information");
2360 return -1;
2361 }
2362 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2363 return 0;
2364}
2365
2366
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002367static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2368
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002369/**
2370 * wpa_supplicant_associate - Request association
2371 * @wpa_s: Pointer to wpa_supplicant data
2372 * @bss: Scan results for the selected BSS, or %NULL if not available
2373 * @ssid: Configuration data for the selected network
2374 *
2375 * This function is used to request %wpa_supplicant to associate with a BSS.
2376 */
2377void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2378 struct wpa_bss *bss, struct wpa_ssid *ssid)
2379{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002380 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002381 int rand_style;
2382
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002383 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002384 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002385
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002386 /*
2387 * If we are starting a new connection, any previously pending EAPOL
2388 * RX cannot be valid anymore.
2389 */
2390 wpabuf_free(wpa_s->pending_eapol_rx);
2391 wpa_s->pending_eapol_rx = NULL;
2392
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002393 if (ssid->mac_addr == -1)
2394 rand_style = wpa_s->conf->mac_addr;
2395 else
2396 rand_style = ssid->mac_addr;
2397
Sunil Ravia04bd252022-05-02 22:54:18 -07002398 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002399 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002400 wmm_ac_clear_saved_tspecs(wpa_s);
2401 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002402 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002403#ifdef CONFIG_TESTING_OPTIONS
2404 wpa_s->testing_resend_assoc = 0;
2405#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002406
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002407 if (wpa_s->last_ssid == ssid) {
2408 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002409 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002410 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2411 wmm_ac_save_tspecs(wpa_s);
2412 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002413 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2414 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002415 }
Hai Shalomc3565922019-10-28 11:58:20 -07002416 } else {
2417#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002418 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002419#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002420 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002421#ifdef CONFIG_SAE
2422 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2423#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002424
2425 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002426 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2427 return;
2428 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002429 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002430 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002431 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002432 }
2433 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002434
2435#ifdef CONFIG_IBSS_RSN
2436 ibss_rsn_deinit(wpa_s->ibss_rsn);
2437 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002438#else /* CONFIG_IBSS_RSN */
2439 if (ssid->mode == WPAS_MODE_IBSS &&
2440 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2441 wpa_msg(wpa_s, MSG_INFO,
2442 "IBSS RSN not supported in the build");
2443 return;
2444 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445#endif /* CONFIG_IBSS_RSN */
2446
2447 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2448 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2449#ifdef CONFIG_AP
2450 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2451 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2452 "mode");
2453 return;
2454 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002455 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2456 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002457 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2458 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002459 return;
2460 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461 wpa_s->current_bss = bss;
2462#else /* CONFIG_AP */
2463 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2464 "the build");
2465#endif /* CONFIG_AP */
2466 return;
2467 }
2468
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002469 if (ssid->mode == WPAS_MODE_MESH) {
2470#ifdef CONFIG_MESH
2471 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2472 wpa_msg(wpa_s, MSG_INFO,
2473 "Driver does not support mesh mode");
2474 return;
2475 }
2476 if (bss)
2477 ssid->frequency = bss->freq;
2478 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2479 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2480 return;
2481 }
2482 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002483#else /* CONFIG_MESH */
2484 wpa_msg(wpa_s, MSG_ERROR,
2485 "mesh mode support not included in the build");
2486#endif /* CONFIG_MESH */
2487 return;
2488 }
2489
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002490 /*
2491 * Set WPA state machine configuration to match the selected network now
2492 * so that the information is available before wpas_start_assoc_cb()
2493 * gets called. This is needed at least for RSN pre-authentication where
2494 * candidate APs are added to a list based on scan result processing
2495 * before completion of the first association.
2496 */
2497 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2498
2499#ifdef CONFIG_DPP
2500 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2501 return;
2502#endif /* CONFIG_DPP */
2503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504#ifdef CONFIG_TDLS
2505 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002506 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507#endif /* CONFIG_TDLS */
2508
Hai Shalomc3565922019-10-28 11:58:20 -07002509#ifdef CONFIG_MBO
2510 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2511#endif /* CONFIG_MBO */
2512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002514 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 sme_authenticate(wpa_s, bss, ssid);
2516 return;
2517 }
2518
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002519 if (wpa_s->connect_work) {
2520 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2521 return;
2522 }
2523
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002524 if (radio_work_pending(wpa_s, "connect")) {
2525 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2526 return;
2527 }
2528
Dmitry Shmidt29333592017-01-09 12:27:11 -08002529#ifdef CONFIG_SME
2530 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2531 /* Clear possibly set auth_alg, if any, from last attempt. */
2532 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2533 }
2534#endif /* CONFIG_SME */
2535
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002536 wpas_abort_ongoing_scan(wpa_s);
2537
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002538 cwork = os_zalloc(sizeof(*cwork));
2539 if (cwork == NULL)
2540 return;
2541
2542 cwork->bss = bss;
2543 cwork->ssid = ssid;
2544
2545 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2546 wpas_start_assoc_cb, cwork) < 0) {
2547 os_free(cwork);
2548 }
2549}
2550
2551
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002552static int bss_is_ibss(struct wpa_bss *bss)
2553{
2554 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2555 IEEE80211_CAP_IBSS;
2556}
2557
2558
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002559static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2560 const struct wpa_ssid *ssid)
2561{
2562 enum hostapd_hw_mode hw_mode;
2563 struct hostapd_hw_modes *mode = NULL;
2564 u8 channel;
2565 int i;
2566
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002567 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2568 if (hw_mode == NUM_HOSTAPD_MODES)
2569 return 0;
2570 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2571 if (wpa_s->hw.modes[i].mode == hw_mode) {
2572 mode = &wpa_s->hw.modes[i];
2573 break;
2574 }
2575 }
2576
2577 if (!mode)
2578 return 0;
2579
2580 return mode->vht_capab != 0;
2581}
2582
2583
Hai Shalomc1a21442022-02-04 13:43:00 -08002584static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2585{
2586 int i;
2587
2588 for (i = channel; i < channel + 16; i += 4) {
2589 struct hostapd_channel_data *chan;
2590
2591 chan = hw_get_channel_chan(mode, i, NULL);
2592 if (!chan ||
2593 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2594 return false;
2595 }
2596
2597 return true;
2598}
2599
2600
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002601void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2602 const struct wpa_ssid *ssid,
2603 struct hostapd_freq_params *freq)
2604{
Hai Shalom81f62d82019-07-22 12:10:00 -07002605 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002606 enum hostapd_hw_mode hw_mode;
2607 struct hostapd_hw_modes *mode = NULL;
2608 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2609 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002610 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2611 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2612 6595, 6675, 6755, 6835, 6915, 6995 };
2613 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002614 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2615 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002616 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002617 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002618 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002619 int chwidth, seg0, seg1;
2620 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002621 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002622
2623 freq->freq = ssid->frequency;
2624
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002625 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2626 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2627
2628 if (ssid->mode != WPAS_MODE_IBSS)
2629 break;
2630
2631 /* Don't adjust control freq in case of fixed_freq */
2632 if (ssid->fixed_freq)
2633 break;
2634
2635 if (!bss_is_ibss(bss))
2636 continue;
2637
2638 if (ssid->ssid_len == bss->ssid_len &&
2639 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2640 wpa_printf(MSG_DEBUG,
2641 "IBSS already found in scan results, adjust control freq: %d",
2642 bss->freq);
2643 freq->freq = bss->freq;
2644 obss_scan = 0;
2645 break;
2646 }
2647 }
2648
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002649 /* For IBSS check HT_IBSS flag */
2650 if (ssid->mode == WPAS_MODE_IBSS &&
2651 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2652 return;
2653
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002654 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2655 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2656 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2657 wpa_printf(MSG_DEBUG,
2658 "IBSS: WEP/TKIP detected, do not try to enable HT");
2659 return;
2660 }
2661
2662 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002663 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2664 if (wpa_s->hw.modes[i].mode == hw_mode) {
2665 mode = &wpa_s->hw.modes[i];
2666 break;
2667 }
2668 }
2669
2670 if (!mode)
2671 return;
2672
Hai Shalom60840252021-02-19 19:02:11 -08002673 freq->channel = channel;
2674
Hai Shalomc3565922019-10-28 11:58:20 -07002675 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2676 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002677
Hai Shalomc1a21442022-02-04 13:43:00 -08002678 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2679 * However, HE is mandatory for 6 GHz.
2680 */
2681 is_6ghz = is_6ghz_freq(freq->freq);
2682 if (is_6ghz)
2683 goto skip_to_6ghz;
2684
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002685#ifdef CONFIG_HT_OVERRIDES
2686 if (ssid->disable_ht) {
2687 freq->ht_enabled = 0;
2688 return;
2689 }
2690#endif /* CONFIG_HT_OVERRIDES */
2691
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002692 freq->ht_enabled = ht_supported(mode);
2693 if (!freq->ht_enabled)
2694 return;
2695
Hai Shalomc3565922019-10-28 11:58:20 -07002696 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2697 if (is_24ghz)
2698 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002699#ifdef CONFIG_HE_OVERRIDES
2700 if (is_24ghz && ssid->disable_he)
2701 freq->he_enabled = 0;
2702#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002703
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002704 /* Setup higher BW only for 5 GHz */
2705 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2706 return;
2707
2708 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2709 pri_chan = &mode->channels[chan_idx];
2710 if (pri_chan->chan == channel)
2711 break;
2712 pri_chan = NULL;
2713 }
2714 if (!pri_chan)
2715 return;
2716
2717 /* Check primary channel flags */
2718 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2719 return;
2720
Hai Shalom74f70d42019-02-11 14:42:39 -08002721 freq->channel = pri_chan->chan;
2722
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002723#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002724 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002725#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002726 if (ssid->disable_vht)
2727 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002728#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002729 goto skip_ht40;
2730 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002731#endif /* CONFIG_HT_OVERRIDES */
2732
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002733 /* Check/setup HT40+/HT40- */
2734 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2735 if (ht40plus[j] == channel) {
2736 ht40 = 1;
2737 break;
2738 }
2739 }
2740
2741 /* Find secondary channel */
2742 for (i = 0; i < mode->num_channels; i++) {
2743 sec_chan = &mode->channels[i];
2744 if (sec_chan->chan == channel + ht40 * 4)
2745 break;
2746 sec_chan = NULL;
2747 }
2748 if (!sec_chan)
2749 return;
2750
2751 /* Check secondary channel flags */
2752 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2753 return;
2754
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002755 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002756 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2757 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002758 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002759 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2760 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002761 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002762 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002763
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002764 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002765 struct wpa_scan_results *scan_res;
2766
2767 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2768 if (scan_res == NULL) {
2769 /* Back to HT20 */
2770 freq->sec_channel_offset = 0;
2771 return;
2772 }
2773
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002774 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002775 switch (res) {
2776 case 0:
2777 /* Back to HT20 */
2778 freq->sec_channel_offset = 0;
2779 break;
2780 case 1:
2781 /* Configuration allowed */
2782 break;
2783 case 2:
2784 /* Switch pri/sec channels */
2785 freq->freq = hw_get_freq(mode, sec_chan->chan);
2786 freq->sec_channel_offset = -freq->sec_channel_offset;
2787 freq->channel = sec_chan->chan;
2788 break;
2789 default:
2790 freq->sec_channel_offset = 0;
2791 break;
2792 }
2793
2794 wpa_scan_results_free(scan_res);
2795 }
2796
Hai Shalom74f70d42019-02-11 14:42:39 -08002797#ifdef CONFIG_HT_OVERRIDES
2798skip_ht40:
2799#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002800 wpa_printf(MSG_DEBUG,
2801 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2802 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002803
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002804 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002805 return;
2806
2807 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002808 if (ssid->mode == WPAS_MODE_IBSS &&
2809 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002810 return;
2811
Paul Stewart092955c2017-02-06 09:13:09 -08002812#ifdef CONFIG_VHT_OVERRIDES
2813 if (ssid->disable_vht) {
2814 freq->vht_enabled = 0;
2815 return;
2816 }
2817#endif /* CONFIG_VHT_OVERRIDES */
2818
Hai Shalomc1a21442022-02-04 13:43:00 -08002819skip_to_6ghz:
2820 vht_freq = *freq;
2821
2822 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002823 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002824 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002825 return;
2826
Hai Shalomfdcde762020-04-02 11:19:20 -07002827 /* Enable HE with VHT for 5 GHz */
2828 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002829
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002830 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002831 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2832 if (freq->freq >= bw80[j] &&
2833 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002834 break;
2835 }
2836
Hai Shalomc1a21442022-02-04 13:43:00 -08002837 if (j == ARRAY_SIZE(bw80) ||
2838 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002839 return;
2840
Hai Shalomc1a21442022-02-04 13:43:00 -08002841 /* Back to HT configuration if channel not usable */
2842 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2843 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002844
Sunil8cd6f4d2022-06-28 18:40:46 +00002845 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002846 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002847 seg1 = 0;
2848
Hai Shalomc1a21442022-02-04 13:43:00 -08002849 if ((mode->he_capab[ieee80211_mode].phy_cap[
2850 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2851 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2852 /* In 160 MHz, the initial four 20 MHz channels were validated
2853 * above; check the remaining four 20 MHz channels for the total
2854 * of 160 MHz bandwidth.
2855 */
2856 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2857 return;
2858
2859 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2860 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002861 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002862 seg0 = channel + 14;
2863 break;
2864 }
2865 }
2866 }
2867
Sunil8cd6f4d2022-06-28 18:40:46 +00002868 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002869 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002870 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002871 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002872 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002873 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002874
2875 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2876 NUM_HOSTAPD_MODES)
2877 return;
2878
2879 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002880 struct hostapd_channel_data *chan;
2881
2882 chan = hw_get_channel_chan(mode, i, NULL);
2883 if (!chan)
2884 continue;
2885
2886 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2887 HOSTAPD_CHAN_NO_IR |
2888 HOSTAPD_CHAN_RADAR))
2889 continue;
2890
2891 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00002892 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002893 if (!is_6ghz)
2894 vht_caps |=
2895 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2896 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002897 }
2898
Sunil8cd6f4d2022-06-28 18:40:46 +00002899 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002900 break;
2901 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002902 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002903 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002904 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002905 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2906 seg0 = 50;
2907 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002908 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002909 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2910 seg0 = 114;
2911 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002912 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT) {
2913 chwidth = CONF_OPER_CHWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002914 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002915#ifdef CONFIG_HT_OVERRIDES
2916 if (ssid->disable_ht40)
2917 seg0 = 0;
2918#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002919 }
2920
Hai Shalomfdcde762020-04-02 11:19:20 -07002921#ifdef CONFIG_HE_OVERRIDES
2922 if (ssid->disable_he) {
2923 vht_freq.he_enabled = 0;
2924 freq->he_enabled = 0;
2925 }
2926#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002927 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002928 freq->channel, ssid->enable_edmg,
2929 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002930 vht_freq.vht_enabled, freq->he_enabled,
Sunil Ravia04bd252022-05-02 22:54:18 -07002931 false,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002932 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002933 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07002934 &mode->he_capab[ieee80211_mode],
2935 NULL) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002936 return;
2937
2938 *freq = vht_freq;
2939
2940 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2941 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002942}
2943
2944
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002945#ifdef CONFIG_FILS
2946static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2947 size_t ie_buf_len)
2948{
2949 struct fils_hlp_req *req;
2950 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2951 const u8 *pos;
2952 u8 *buf = ie_buf;
2953
2954 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2955 list) {
2956 rem_len = ie_buf_len - ie_len;
2957 pos = wpabuf_head(req->pkt);
2958 hdr_len = 1 + 2 * ETH_ALEN + 6;
2959 hlp_len = wpabuf_len(req->pkt);
2960
2961 if (rem_len < 2 + hdr_len + hlp_len) {
2962 wpa_printf(MSG_ERROR,
2963 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2964 (unsigned long) rem_len,
2965 (unsigned long) (2 + hdr_len + hlp_len));
2966 break;
2967 }
2968
2969 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2970 /* Element ID */
2971 *buf++ = WLAN_EID_EXTENSION;
2972 /* Length */
2973 *buf++ = len;
2974 /* Element ID Extension */
2975 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2976 /* Destination MAC address */
2977 os_memcpy(buf, req->dst, ETH_ALEN);
2978 buf += ETH_ALEN;
2979 /* Source MAC address */
2980 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2981 buf += ETH_ALEN;
2982 /* LLC/SNAP Header */
2983 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2984 buf += 6;
2985 /* HLP Packet */
2986 os_memcpy(buf, pos, len - hdr_len);
2987 buf += len - hdr_len;
2988 pos += len - hdr_len;
2989
2990 hlp_len -= len - hdr_len;
2991 ie_len += 2 + len;
2992 rem_len -= 2 + len;
2993
2994 while (hlp_len) {
2995 len = (hlp_len > 255) ? 255 : hlp_len;
2996 if (rem_len < 2 + len)
2997 break;
2998 *buf++ = WLAN_EID_FRAGMENT;
2999 *buf++ = len;
3000 os_memcpy(buf, pos, len);
3001 buf += len;
3002 pos += len;
3003
3004 hlp_len -= len;
3005 ie_len += 2 + len;
3006 rem_len -= 2 + len;
3007 }
3008 }
3009
3010 return ie_len;
3011}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003012
3013
3014int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3015{
3016 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3017 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3018 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3019 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3020}
3021
3022
3023int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3024{
3025#ifdef CONFIG_FILS_SK_PFS
3026 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3027 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3028#else /* CONFIG_FILS_SK_PFS */
3029 return 0;
3030#endif /* CONFIG_FILS_SK_PFS */
3031}
3032
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003033#endif /* CONFIG_FILS */
3034
3035
Hai Shalomc1a21442022-02-04 13:43:00 -08003036static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3037 struct wpa_bss *bss,
3038 u8 *wpa_ie, size_t wpa_ie_len,
3039 size_t max_wpa_ie_len)
3040{
3041 struct wpabuf *wfa_ie = NULL;
3042 u8 wfa_capa[1];
3043 size_t wfa_ie_len, buf_len;
3044
3045 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3046 if (wpa_s->enable_dscp_policy_capa)
3047 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3048
3049 if (!wfa_capa[0])
3050 return wpa_ie_len;
3051
3052 /* Wi-Fi Alliance element */
3053 buf_len = 1 + /* Element ID */
3054 1 + /* Length */
3055 3 + /* OUI */
3056 1 + /* OUI Type */
3057 1 + /* Capabilities Length */
3058 sizeof(wfa_capa); /* Capabilities */
3059 wfa_ie = wpabuf_alloc(buf_len);
3060 if (!wfa_ie)
3061 return wpa_ie_len;
3062
3063 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3064 wpabuf_put_u8(wfa_ie, buf_len - 2);
3065 wpabuf_put_be24(wfa_ie, OUI_WFA);
3066 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3067 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3068 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3069
3070 wfa_ie_len = wpabuf_len(wfa_ie);
3071 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3072 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3073 wfa_ie);
3074 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3075 wfa_ie_len);
3076 wpa_ie_len += wfa_ie_len;
3077 }
3078
3079 wpabuf_free(wfa_ie);
3080 return wpa_ie_len;
3081}
3082
3083
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003084static u8 * wpas_populate_assoc_ies(
3085 struct wpa_supplicant *wpa_s,
3086 struct wpa_bss *bss, struct wpa_ssid *ssid,
3087 struct wpa_driver_associate_params *params,
3088 enum wpa_drv_update_connect_params_mask *mask)
3089{
3090 u8 *wpa_ie;
3091 size_t max_wpa_ie_len = 500;
3092 size_t wpa_ie_len;
3093 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003094#ifdef CONFIG_MBO
3095 const u8 *mbo_ie;
3096#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303097#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3098 int pmksa_cached = 0;
3099#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003100#ifdef CONFIG_FILS
3101 const u8 *realm, *username, *rrk;
3102 size_t realm_len, username_len, rrk_len;
3103 u16 next_seq_num;
3104 struct fils_hlp_req *req;
3105
3106 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3107 list) {
3108 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3109 2 + 2 * wpabuf_len(req->pkt) / 255;
3110 }
3111#endif /* CONFIG_FILS */
3112
3113 wpa_ie = os_malloc(max_wpa_ie_len);
3114 if (!wpa_ie) {
3115 wpa_printf(MSG_ERROR,
3116 "Failed to allocate connect IE buffer for %lu bytes",
3117 (unsigned long) max_wpa_ie_len);
3118 return NULL;
3119 }
3120
3121 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3122 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3123 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3124 int try_opportunistic;
3125 const u8 *cache_id = NULL;
3126
3127 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3128 wpa_s->conf->okc :
3129 ssid->proactive_key_caching) &&
3130 (ssid->proto & WPA_PROTO_RSN);
3131#ifdef CONFIG_FILS
3132 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3133 cache_id = wpa_bss_get_fils_cache_id(bss);
3134#endif /* CONFIG_FILS */
3135 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
3136 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003137 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003138 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303139#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3140 pmksa_cached = 1;
3141#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003142 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003143 wpa_ie_len = max_wpa_ie_len;
3144 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3145 wpa_ie, &wpa_ie_len)) {
3146 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3147 "key management and encryption suites");
3148 os_free(wpa_ie);
3149 return NULL;
3150 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003151#ifdef CONFIG_HS20
3152 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3153 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3154 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3155 wpa_ie_len = max_wpa_ie_len;
3156 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3157 wpa_ie, &wpa_ie_len)) {
3158 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3159 "key management and encryption suites");
3160 os_free(wpa_ie);
3161 return NULL;
3162 }
3163#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003164 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3165 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3166 /*
3167 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3168 * use non-WPA since the scan results did not indicate that the
3169 * AP is using WPA or WPA2.
3170 */
3171 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3172 wpa_ie_len = 0;
3173 wpa_s->wpa_proto = 0;
3174 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3175 wpa_ie_len = max_wpa_ie_len;
3176 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
3177 wpa_ie, &wpa_ie_len)) {
3178 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3179 "key management and encryption suites (no "
3180 "scan results)");
3181 os_free(wpa_ie);
3182 return NULL;
3183 }
3184#ifdef CONFIG_WPS
3185 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3186 struct wpabuf *wps_ie;
3187 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3188 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3189 wpa_ie_len = wpabuf_len(wps_ie);
3190 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3191 } else
3192 wpa_ie_len = 0;
3193 wpabuf_free(wps_ie);
3194 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3195 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3196 params->wps = WPS_MODE_PRIVACY;
3197 else
3198 params->wps = WPS_MODE_OPEN;
3199 wpa_s->wpa_proto = 0;
3200#endif /* CONFIG_WPS */
3201 } else {
3202 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3203 wpa_ie_len = 0;
3204 wpa_s->wpa_proto = 0;
3205 }
3206
3207#ifdef IEEE8021X_EAPOL
3208 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3209 if (ssid->leap) {
3210 if (ssid->non_leap == 0)
3211 algs = WPA_AUTH_ALG_LEAP;
3212 else
3213 algs |= WPA_AUTH_ALG_LEAP;
3214 }
3215 }
3216
3217#ifdef CONFIG_FILS
3218 /* Clear FILS association */
3219 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3220
3221 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3222 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3223 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3224 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003225 &next_seq_num, &rrk, &rrk_len) == 0 &&
3226 (!wpa_s->last_con_fail_realm ||
3227 wpa_s->last_con_fail_realm_len != realm_len ||
3228 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003229 algs = WPA_AUTH_ALG_FILS;
3230 params->fils_erp_username = username;
3231 params->fils_erp_username_len = username_len;
3232 params->fils_erp_realm = realm;
3233 params->fils_erp_realm_len = realm_len;
3234 params->fils_erp_next_seq_num = next_seq_num;
3235 params->fils_erp_rrk = rrk;
3236 params->fils_erp_rrk_len = rrk_len;
3237
3238 if (mask)
3239 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303240 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3241 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3242 pmksa_cached) {
3243 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003244 }
3245#endif /* CONFIG_FILS */
3246#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003247#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003248 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003249 algs = WPA_AUTH_ALG_SAE;
3250#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003251
3252 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3253 if (ssid->auth_alg) {
3254 algs = ssid->auth_alg;
3255 wpa_dbg(wpa_s, MSG_DEBUG,
3256 "Overriding auth_alg selection: 0x%x", algs);
3257 }
3258
Hai Shalom5f92bc92019-04-18 11:54:11 -07003259#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303260 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003261 wpa_dbg(wpa_s, MSG_DEBUG,
3262 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3263 algs = WPA_AUTH_ALG_OPEN;
3264 }
3265#endif /* CONFIG_SAE */
3266
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003267#ifdef CONFIG_P2P
3268 if (wpa_s->global->p2p) {
3269 u8 *pos;
3270 size_t len;
3271 int res;
3272 pos = wpa_ie + wpa_ie_len;
3273 len = max_wpa_ie_len - wpa_ie_len;
3274 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3275 ssid->p2p_group);
3276 if (res >= 0)
3277 wpa_ie_len += res;
3278 }
3279
3280 wpa_s->cross_connect_disallowed = 0;
3281 if (bss) {
3282 struct wpabuf *p2p;
3283 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3284 if (p2p) {
3285 wpa_s->cross_connect_disallowed =
3286 p2p_get_cross_connect_disallowed(p2p);
3287 wpabuf_free(p2p);
3288 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3289 "connection",
3290 wpa_s->cross_connect_disallowed ?
3291 "disallows" : "allows");
3292 }
3293 }
3294
3295 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3296#endif /* CONFIG_P2P */
3297
3298 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003299 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003300 wpa_ie + wpa_ie_len,
3301 max_wpa_ie_len -
3302 wpa_ie_len);
3303 }
3304
3305 /*
3306 * Workaround: Add Extended Capabilities element only if the AP
3307 * included this element in Beacon/Probe Response frames. Some older
3308 * APs seem to have interoperability issues if this element is
3309 * included, so while the standard may require us to include the
3310 * element in all cases, it is justifiable to skip it to avoid
3311 * interoperability issues.
3312 */
3313 if (ssid->p2p_group)
3314 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3315 else
3316 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3317
3318 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3319 u8 ext_capab[18];
3320 int ext_capab_len;
3321 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3322 sizeof(ext_capab));
3323 if (ext_capab_len > 0 &&
3324 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3325 u8 *pos = wpa_ie;
3326 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3327 pos += 2 + pos[1];
3328 os_memmove(pos + ext_capab_len, pos,
3329 wpa_ie_len - (pos - wpa_ie));
3330 wpa_ie_len += ext_capab_len;
3331 os_memcpy(pos, ext_capab, ext_capab_len);
3332 }
3333 }
3334
3335#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003336 if (is_hs20_network(wpa_s, ssid, bss)
3337#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3338 && is_hs20_config(wpa_s)
3339#endif /* ANDROID */
3340 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003341 struct wpabuf *hs20;
3342
Roshan Pius3a1667e2018-07-03 15:17:14 -07003343 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003344 if (hs20) {
3345 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3346 size_t len;
3347
Hai Shalom74f70d42019-02-11 14:42:39 -08003348 wpas_hs20_add_indication(hs20, pps_mo_id,
3349 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003350 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003351 len = max_wpa_ie_len - wpa_ie_len;
3352 if (wpabuf_len(hs20) <= len) {
3353 os_memcpy(wpa_ie + wpa_ie_len,
3354 wpabuf_head(hs20), wpabuf_len(hs20));
3355 wpa_ie_len += wpabuf_len(hs20);
3356 }
3357 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003358 }
3359 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003360 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003361#endif /* CONFIG_HS20 */
3362
3363 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3364 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3365 size_t len;
3366
3367 len = max_wpa_ie_len - wpa_ie_len;
3368 if (wpabuf_len(buf) <= len) {
3369 os_memcpy(wpa_ie + wpa_ie_len,
3370 wpabuf_head(buf), wpabuf_len(buf));
3371 wpa_ie_len += wpabuf_len(buf);
3372 }
3373 }
3374
3375#ifdef CONFIG_FST
3376 if (wpa_s->fst_ies) {
3377 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3378
3379 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3380 os_memcpy(wpa_ie + wpa_ie_len,
3381 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3382 wpa_ie_len += fst_ies_len;
3383 }
3384 }
3385#endif /* CONFIG_FST */
3386
3387#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003388 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003389 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003390 int len;
3391
3392 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003393 max_wpa_ie_len - wpa_ie_len,
3394 !!mbo_attr_from_mbo_ie(mbo_ie,
3395 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003396 if (len >= 0)
3397 wpa_ie_len += len;
3398 }
3399#endif /* CONFIG_MBO */
3400
3401#ifdef CONFIG_FILS
3402 if (algs == WPA_AUTH_ALG_FILS) {
3403 size_t len;
3404
3405 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3406 max_wpa_ie_len - wpa_ie_len);
3407 wpa_ie_len += len;
3408 }
3409#endif /* CONFIG_FILS */
3410
3411#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003412#ifdef CONFIG_TESTING_OPTIONS
3413 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3414 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3415 } else
3416#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003417 if (algs == WPA_AUTH_ALG_OPEN &&
3418 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3419 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003420 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003421
Roshan Pius3a1667e2018-07-03 15:17:14 -07003422 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003423 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003424 } else if (wpa_s->assoc_status_code ==
3425 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003426 if (wpa_s->last_owe_group == 19)
3427 group = 20;
3428 else if (wpa_s->last_owe_group == 20)
3429 group = 21;
3430 else
3431 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003432 } else {
3433 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003434 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003435
Roshan Pius3a1667e2018-07-03 15:17:14 -07003436 wpa_s->last_owe_group = group;
3437 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003438 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3439 if (owe_ie &&
3440 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3441 os_memcpy(wpa_ie + wpa_ie_len,
3442 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3443 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003444 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003445 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003446 }
3447#endif /* CONFIG_OWE */
3448
Hai Shalom021b0b52019-04-10 11:17:58 -07003449#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003450 if (DPP_VERSION > 1 &&
3451 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003452 ssid->dpp_netaccesskey &&
3453 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003454 struct rsn_pmksa_cache_entry *pmksa;
3455
3456 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3457 if (!pmksa || !pmksa->dpp_pfs)
3458 goto pfs_fail;
3459
Hai Shalom021b0b52019-04-10 11:17:58 -07003460 dpp_pfs_free(wpa_s->dpp_pfs);
3461 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3462 ssid->dpp_netaccesskey_len);
3463 if (!wpa_s->dpp_pfs) {
3464 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3465 /* Try to continue without PFS */
3466 goto pfs_fail;
3467 }
3468 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3469 max_wpa_ie_len - wpa_ie_len) {
3470 os_memcpy(wpa_ie + wpa_ie_len,
3471 wpabuf_head(wpa_s->dpp_pfs->ie),
3472 wpabuf_len(wpa_s->dpp_pfs->ie));
3473 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3474 }
3475 }
3476pfs_fail:
3477#endif /* CONFIG_DPP2 */
3478
Roshan Pius3a1667e2018-07-03 15:17:14 -07003479#ifdef CONFIG_IEEE80211R
3480 /*
3481 * Add MDIE under these conditions: the network profile allows FT,
3482 * the AP supports FT, and the mobility domain ID matches.
3483 */
3484 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3485 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3486
3487 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3488 size_t len = 0;
3489 const u8 *md = mdie + 2;
3490 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3491
3492 if (os_memcmp(md, wpa_md,
3493 MOBILITY_DOMAIN_ID_LEN) == 0) {
3494 /* Add mobility domain IE */
3495 len = wpa_ft_add_mdie(
3496 wpa_s->wpa, wpa_ie + wpa_ie_len,
3497 max_wpa_ie_len - wpa_ie_len, mdie);
3498 wpa_ie_len += len;
3499 }
3500#ifdef CONFIG_SME
3501 if (len > 0 && wpa_s->sme.ft_used &&
3502 wpa_sm_has_ptk(wpa_s->wpa)) {
3503 wpa_dbg(wpa_s, MSG_DEBUG,
3504 "SME: Trying to use FT over-the-air");
3505 algs |= WPA_AUTH_ALG_FT;
3506 }
3507#endif /* CONFIG_SME */
3508 }
3509 }
3510#endif /* CONFIG_IEEE80211R */
3511
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003512#ifdef CONFIG_TESTING_OPTIONS
3513 if (wpa_s->rsnxe_override_assoc &&
3514 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3515 max_wpa_ie_len - wpa_ie_len) {
3516 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3517 os_memcpy(wpa_ie + wpa_ie_len,
3518 wpabuf_head(wpa_s->rsnxe_override_assoc),
3519 wpabuf_len(wpa_s->rsnxe_override_assoc));
3520 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3521 } else
3522#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003523 if (wpa_s->rsnxe_len > 0 &&
3524 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3525 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3526 wpa_ie_len += wpa_s->rsnxe_len;
3527 }
3528
Hai Shalomc1a21442022-02-04 13:43:00 -08003529#ifdef CONFIG_TESTING_OPTIONS
3530 if (wpa_s->disable_mscs_support)
3531 goto mscs_end;
3532#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003533 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3534 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003535 struct wpabuf *mscs_ie;
3536 size_t mscs_ie_len, buf_len;
3537
Hai Shalom899fcc72020-10-19 14:38:18 -07003538 buf_len = 3 + /* MSCS descriptor IE header */
3539 1 + /* Request type */
3540 2 + /* User priority control */
3541 4 + /* Stream timeout */
3542 3 + /* TCLAS Mask IE header */
3543 wpa_s->robust_av.frame_classifier_len;
3544 mscs_ie = wpabuf_alloc(buf_len);
3545 if (!mscs_ie) {
3546 wpa_printf(MSG_INFO,
3547 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003548 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003549 }
3550
3551 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3552 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3553 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3554 mscs_ie_len = wpabuf_len(mscs_ie);
3555 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3556 mscs_ie_len);
3557 wpa_ie_len += mscs_ie_len;
3558 }
3559
3560 wpabuf_free(mscs_ie);
3561 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003562mscs_end:
3563
3564 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3565 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003566
Hai Shalom74f70d42019-02-11 14:42:39 -08003567 if (ssid->multi_ap_backhaul_sta) {
3568 size_t multi_ap_ie_len;
3569
3570 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3571 max_wpa_ie_len - wpa_ie_len,
3572 MULTI_AP_BACKHAUL_STA);
3573 if (multi_ap_ie_len == 0) {
3574 wpa_printf(MSG_ERROR,
3575 "Multi-AP: Failed to build Multi-AP IE");
3576 os_free(wpa_ie);
3577 return NULL;
3578 }
3579 wpa_ie_len += multi_ap_ie_len;
3580 }
3581
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003582 params->wpa_ie = wpa_ie;
3583 params->wpa_ie_len = wpa_ie_len;
3584 params->auth_alg = algs;
3585 if (mask)
3586 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3587
3588 return wpa_ie;
3589}
3590
3591
Hai Shalomc3565922019-10-28 11:58:20 -07003592#ifdef CONFIG_OWE
3593static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3594{
3595 struct wpa_driver_associate_params params;
3596 u8 *wpa_ie;
3597
3598 os_memset(&params, 0, sizeof(params));
3599 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3600 wpa_s->current_ssid, &params, NULL);
3601 if (!wpa_ie)
3602 return;
3603
3604 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3605 os_free(wpa_ie);
3606}
3607#endif /* CONFIG_OWE */
3608
3609
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003610#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3611static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3612{
3613 struct wpa_driver_associate_params params;
3614 enum wpa_drv_update_connect_params_mask mask = 0;
3615 u8 *wpa_ie;
3616
3617 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3618 return; /* nothing to do */
3619
3620 os_memset(&params, 0, sizeof(params));
3621 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3622 wpa_s->current_ssid, &params, &mask);
3623 if (!wpa_ie)
3624 return;
3625
Hai Shalomc1a21442022-02-04 13:43:00 -08003626 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3627 wpa_s->auth_alg = params.auth_alg;
3628 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003629 }
3630
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003631 os_free(wpa_ie);
3632}
3633#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3634
3635
Hai Shalomc3565922019-10-28 11:58:20 -07003636static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3637{
3638 if (!edmg_ie || edmg_ie[1] < 6)
3639 return 0;
3640 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3641}
3642
3643
3644static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3645{
3646 if (!edmg_ie || edmg_ie[1] < 6)
3647 return 0;
3648 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3649}
3650
3651
3652/* Returns the intersection of two EDMG configurations.
3653 * Note: The current implementation is limited to CB2 only (CB1 included),
3654 * i.e., the implementation supports up to 2 contiguous channels.
3655 * For supporting non-contiguous (aggregated) channels and for supporting
3656 * CB3 and above, this function will need to be extended.
3657 */
3658static struct ieee80211_edmg_config
3659get_edmg_intersection(struct ieee80211_edmg_config a,
3660 struct ieee80211_edmg_config b,
3661 u8 primary_channel)
3662{
3663 struct ieee80211_edmg_config result;
3664 int i, contiguous = 0;
3665 int max_contiguous = 0;
3666
3667 result.channels = b.channels & a.channels;
3668 if (!result.channels) {
3669 wpa_printf(MSG_DEBUG,
3670 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3671 a.channels, b.channels);
3672 goto fail;
3673 }
3674
3675 if (!(result.channels & BIT(primary_channel - 1))) {
3676 wpa_printf(MSG_DEBUG,
3677 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3678 primary_channel, result.channels);
3679 goto fail;
3680 }
3681
3682 /* Find max contiguous channels */
3683 for (i = 0; i < 6; i++) {
3684 if (result.channels & BIT(i))
3685 contiguous++;
3686 else
3687 contiguous = 0;
3688
3689 if (contiguous > max_contiguous)
3690 max_contiguous = contiguous;
3691 }
3692
3693 /* Assuming AP and STA supports ONLY contiguous channels,
3694 * bw configuration can have value between 4-7.
3695 */
3696 if ((b.bw_config < a.bw_config))
3697 result.bw_config = b.bw_config;
3698 else
3699 result.bw_config = a.bw_config;
3700
3701 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3702 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3703 wpa_printf(MSG_DEBUG,
3704 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3705 max_contiguous);
3706 goto fail;
3707 }
3708
3709 return result;
3710
3711fail:
3712 result.channels = 0;
3713 result.bw_config = 0;
3714 return result;
3715}
3716
3717
3718static struct ieee80211_edmg_config
3719get_supported_edmg(struct wpa_supplicant *wpa_s,
3720 struct hostapd_freq_params *freq,
3721 struct ieee80211_edmg_config request_edmg)
3722{
3723 enum hostapd_hw_mode hw_mode;
3724 struct hostapd_hw_modes *mode = NULL;
3725 u8 primary_channel;
3726
3727 if (!wpa_s->hw.modes)
3728 goto fail;
3729
3730 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3731 if (hw_mode == NUM_HOSTAPD_MODES)
3732 goto fail;
3733
Hai Shalom60840252021-02-19 19:02:11 -08003734 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003735 if (!mode)
3736 goto fail;
3737
3738 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3739
3740fail:
3741 request_edmg.channels = 0;
3742 request_edmg.bw_config = 0;
3743 return request_edmg;
3744}
3745
3746
Hai Shalom021b0b52019-04-10 11:17:58 -07003747#ifdef CONFIG_MBO
3748void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3749{
3750 struct wpa_driver_associate_params params;
3751 u8 *wpa_ie;
3752
3753 /*
3754 * Update MBO connect params only in case of change of MBO attributes
3755 * when connected, if the AP support MBO.
3756 */
3757
3758 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3759 !wpa_s->current_bss ||
3760 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3761 return;
3762
3763 os_memset(&params, 0, sizeof(params));
3764 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3765 wpa_s->current_ssid, &params, NULL);
3766 if (!wpa_ie)
3767 return;
3768
3769 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3770 os_free(wpa_ie);
3771}
3772#endif /* CONFIG_MBO */
3773
3774
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003775static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3776{
3777 struct wpa_connect_work *cwork = work->ctx;
3778 struct wpa_bss *bss = cwork->bss;
3779 struct wpa_ssid *ssid = cwork->ssid;
3780 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003781 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003782 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003783 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003784 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003785 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003786#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003787 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003788#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003789 int assoc_failed = 0;
3790 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003791 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003792#ifdef CONFIG_HT_OVERRIDES
3793 struct ieee80211_ht_capabilities htcaps;
3794 struct ieee80211_ht_capabilities htcaps_mask;
3795#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003796#ifdef CONFIG_VHT_OVERRIDES
3797 struct ieee80211_vht_capabilities vhtcaps;
3798 struct ieee80211_vht_capabilities vhtcaps_mask;
3799#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003800
Hai Shalomc1a21442022-02-04 13:43:00 -08003801 wpa_s->roam_in_progress = false;
3802#ifdef CONFIG_WNM
3803 wpa_s->bss_trans_mgmt_in_progress = false;
3804#endif /* CONFIG_WNM */
3805
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003806 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003807 if (work->started) {
3808 wpa_s->connect_work = NULL;
3809
3810 /* cancel possible auth. timeout */
3811 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3812 NULL);
3813 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003814 wpas_connect_work_free(cwork);
3815 return;
3816 }
3817
3818 wpa_s->connect_work = work;
3819
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003820 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3821 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003822 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3823 wpas_connect_work_done(wpa_s);
3824 return;
3825 }
3826
Dmitry Shmidte4663042016-04-04 10:07:49 -07003827 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003828 os_memset(&params, 0, sizeof(params));
3829 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003830 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003831
3832 /* Starting new association, so clear the possibly used WPA IE from the
3833 * previous association. */
3834 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3835 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3836 wpa_s->rsnxe_len = 0;
3837 wpa_s->mscs_setup_done = false;
3838
3839 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3840 if (!wpa_ie) {
3841 wpas_connect_work_done(wpa_s);
3842 return;
3843 }
3844
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003845 if (bss &&
3846 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003847#ifdef CONFIG_IEEE80211R
3848 const u8 *ie, *md = NULL;
3849#endif /* CONFIG_IEEE80211R */
3850 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3851 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3852 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3853 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3854 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3855 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3856 if (bssid_changed)
3857 wpas_notify_bssid_changed(wpa_s);
3858#ifdef CONFIG_IEEE80211R
3859 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3860 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3861 md = ie + 2;
3862 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3863 if (md) {
3864 /* Prepare for the next transition */
3865 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3866 }
3867#endif /* CONFIG_IEEE80211R */
3868#ifdef CONFIG_WPS
3869 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3870 wpa_s->conf->ap_scan == 2 &&
3871 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3872 /* Use ap_scan==1 style network selection to find the network
3873 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003874 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003875 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003876 wpa_s->reassociate = 1;
3877 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003878 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003879 return;
3880#endif /* CONFIG_WPS */
3881 } else {
3882 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3883 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003884 if (bss)
3885 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3886 else
3887 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003888 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003889 if (!wpa_s->pno)
3890 wpa_supplicant_cancel_sched_scan(wpa_s);
3891
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003892 wpa_supplicant_cancel_scan(wpa_s);
3893
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003894 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3895 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003896 cipher_pairwise = wpa_s->pairwise_cipher;
3897 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003898 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003899 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3900 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3901 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3902 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003903#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003904 if (wpa_set_wep_keys(wpa_s, ssid)) {
3905 use_crypt = 1;
3906 wep_keys_set = 1;
3907 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003908#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003909 }
3910 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3911 use_crypt = 0;
3912
3913#ifdef IEEE8021X_EAPOL
3914 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3915 if ((ssid->eapol_flags &
3916 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3917 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3918 !wep_keys_set) {
3919 use_crypt = 0;
3920 } else {
3921 /* Assume that dynamic WEP-104 keys will be used and
3922 * set cipher suites in order for drivers to expect
3923 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003924 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003925 }
3926 }
3927#endif /* IEEE8021X_EAPOL */
3928
3929 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3930 /* Set the key before (and later after) association */
3931 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3932 }
3933
Sunil8cd6f4d2022-06-28 18:40:46 +00003934 /* Set current_ssid before changing state to ASSOCIATING, so that the
3935 * selected SSID is available to wpas_notify_state_changed(). */
3936 old_ssid = wpa_s->current_ssid;
3937 wpa_s->current_ssid = ssid;
3938
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003939 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3940 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003941 params.ssid = bss->ssid;
3942 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003943 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3944 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003945 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3946 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003947 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003948 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003949 ssid->bssid_set,
3950 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003951 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003952 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003953 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003954 params.bssid_hint = bss->bssid;
3955 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003956 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003957 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003958 if (ssid->bssid_hint_set)
3959 params.bssid_hint = ssid->bssid_hint;
3960
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003961 params.ssid = ssid->ssid;
3962 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003963 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003964 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003965
3966 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3967 wpa_s->conf->ap_scan == 2) {
3968 params.bssid = ssid->bssid;
3969 params.fixed_bssid = 1;
3970 }
3971
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003972 /* Initial frequency for IBSS/mesh */
3973 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003974 ssid->frequency > 0 && params.freq.freq == 0)
3975 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003976
3977 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003978 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003979 if (ssid->beacon_int)
3980 params.beacon_int = ssid->beacon_int;
3981 else
3982 params.beacon_int = wpa_s->conf->beacon_int;
3983 }
3984
Hai Shalomc3565922019-10-28 11:58:20 -07003985 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003986 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3987 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003988 else
3989 edmg_ie_oper = NULL;
3990
3991 if (edmg_ie_oper) {
3992 params.freq.edmg.channels =
3993 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3994 params.freq.edmg.bw_config =
3995 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3996 wpa_printf(MSG_DEBUG,
3997 "AP supports EDMG channels 0x%x, bw_config %d",
3998 params.freq.edmg.channels,
3999 params.freq.edmg.bw_config);
4000
4001 /* User may ask for specific EDMG channel for EDMG connection
4002 * (must be supported by AP)
4003 */
4004 if (ssid->edmg_channel) {
4005 struct ieee80211_edmg_config configured_edmg;
4006 enum hostapd_hw_mode hw_mode;
4007 u8 primary_channel;
4008
4009 hw_mode = ieee80211_freq_to_chan(bss->freq,
4010 &primary_channel);
4011 if (hw_mode == NUM_HOSTAPD_MODES)
4012 goto edmg_fail;
4013
4014 hostapd_encode_edmg_chan(ssid->enable_edmg,
4015 ssid->edmg_channel,
4016 primary_channel,
4017 &configured_edmg);
4018
4019 if (ieee802_edmg_is_allowed(params.freq.edmg,
4020 configured_edmg)) {
4021 params.freq.edmg = configured_edmg;
4022 wpa_printf(MSG_DEBUG,
4023 "Use EDMG channel %d for connection",
4024 ssid->edmg_channel);
4025 } else {
4026 edmg_fail:
4027 params.freq.edmg.channels = 0;
4028 params.freq.edmg.bw_config = 0;
4029 wpa_printf(MSG_WARNING,
4030 "EDMG channel %d not supported by AP, fallback to DMG",
4031 ssid->edmg_channel);
4032 }
4033 }
4034
4035 if (params.freq.edmg.channels) {
4036 wpa_printf(MSG_DEBUG,
4037 "EDMG before: channels 0x%x, bw_config %d",
4038 params.freq.edmg.channels,
4039 params.freq.edmg.bw_config);
4040 params.freq.edmg = get_supported_edmg(wpa_s,
4041 &params.freq,
4042 params.freq.edmg);
4043 wpa_printf(MSG_DEBUG,
4044 "EDMG after: channels 0x%x, bw_config %d",
4045 params.freq.edmg.channels,
4046 params.freq.edmg.bw_config);
4047 }
4048 }
4049
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004050 params.pairwise_suite = cipher_pairwise;
4051 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004052 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004053 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004054 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004055 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004056 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004057 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004058 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004059#ifdef CONFIG_WEP
4060 {
4061 int i;
4062
4063 for (i = 0; i < NUM_WEP_KEYS; i++) {
4064 if (ssid->wep_key_len[i])
4065 params.wep_key[i] = ssid->wep_key[i];
4066 params.wep_key_len[i] = ssid->wep_key_len[i];
4067 }
4068 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004069 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004070#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004071
Hai Shalom74f70d42019-02-11 14:42:39 -08004072 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004073#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004074 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4075 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304076#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004077 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4078 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4079 (params.allowed_key_mgmts &
4080 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Winnie Chen4138eec2022-11-10 16:32:53 +08004081#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004082 params.passphrase = ssid->passphrase;
4083 if (ssid->psk_set)
4084 params.psk = ssid->psk;
4085 }
4086
Hai Shalom74f70d42019-02-11 14:42:39 -08004087 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4088 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4089 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4090 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4091 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07004092 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004093
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004094 if (wpa_s->conf->key_mgmt_offload) {
4095 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4096 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004097 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4098 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004099 params.req_key_mgmt_offload =
4100 ssid->proactive_key_caching < 0 ?
4101 wpa_s->conf->okc : ssid->proactive_key_caching;
4102 else
4103 params.req_key_mgmt_offload = 1;
4104
Winnie Chen4138eec2022-11-10 16:32:53 +08004105#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Sunil Ravi89eba102022-09-13 21:04:37 -07004106 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004107 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4108 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004109#else
4110 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4111 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
Winnie Chen4138eec2022-11-10 16:32:53 +08004112#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004113 ssid->psk_set)
4114 params.psk = ssid->psk;
4115 }
4116
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004117 params.drop_unencrypted = use_crypt;
4118
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004119 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004120 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004121 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4122 struct wpa_ie_data ie;
4123 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
4124 ie.capabilities &
4125 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4126 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4127 "MFP: require MFP");
4128 params.mgmt_frame_protection =
4129 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004130#ifdef CONFIG_OWE
4131 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4132 !ssid->owe_only) {
4133 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4134#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004135 }
4136 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004137
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004138 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004139
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004140 if (wpa_s->p2pdev->set_sta_uapsd)
4141 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004142 else
4143 params.uapsd = -1;
4144
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004145#ifdef CONFIG_HT_OVERRIDES
4146 os_memset(&htcaps, 0, sizeof(htcaps));
4147 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4148 params.htcaps = (u8 *) &htcaps;
4149 params.htcaps_mask = (u8 *) &htcaps_mask;
4150 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4151#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004152#ifdef CONFIG_VHT_OVERRIDES
4153 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4154 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4155 params.vhtcaps = &vhtcaps;
4156 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004157 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004158#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004159#ifdef CONFIG_HE_OVERRIDES
4160 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4161#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004162
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004163#ifdef CONFIG_P2P
4164 /*
4165 * If multi-channel concurrency is not supported, check for any
4166 * frequency conflict. In case of any frequency conflict, remove the
4167 * least prioritized connection.
4168 */
4169 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004170 int freq, num;
4171 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004172 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004173 wpa_printf(MSG_DEBUG,
4174 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004175 freq, params.freq.freq);
4176 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004177 wpa_s, params.freq.freq, ssid) < 0) {
4178 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004179 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004180 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004181 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004182 }
4183 }
4184#endif /* CONFIG_P2P */
4185
Dmitry Shmidte4663042016-04-04 10:07:49 -07004186 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004187 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004188 params.prev_bssid = prev_bssid;
4189
Hai Shalom60840252021-02-19 19:02:11 -08004190#ifdef CONFIG_SAE
4191 params.sae_pwe = wpa_s->conf->sae_pwe;
4192#endif /* CONFIG_SAE */
4193
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004194 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004195 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004196 if (ret < 0) {
4197 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4198 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004199 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004200 /*
4201 * The driver is known to mean what is saying, so we
4202 * can stop right here; the association will not
4203 * succeed.
4204 */
4205 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004206 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004207 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004208 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004209 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4210 return;
4211 }
4212 /* try to continue anyway; new association will be tried again
4213 * after timeout */
4214 assoc_failed = 1;
4215 }
4216
4217 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4218 /* Set the key after the association just in case association
4219 * cleared the previously configured key. */
4220 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4221 /* No need to timeout authentication since there is no key
4222 * management. */
4223 wpa_supplicant_cancel_auth_timeout(wpa_s);
4224 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4225#ifdef CONFIG_IBSS_RSN
4226 } else if (ssid->mode == WPAS_MODE_IBSS &&
4227 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4228 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4229 /*
4230 * RSN IBSS authentication is per-STA and we can disable the
4231 * per-BSSID authentication.
4232 */
4233 wpa_supplicant_cancel_auth_timeout(wpa_s);
4234#endif /* CONFIG_IBSS_RSN */
4235 } else {
4236 /* Timeout for IEEE 802.11 authentication and association */
4237 int timeout = 60;
4238
4239 if (assoc_failed) {
4240 /* give IBSS a bit more time */
4241 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4242 } else if (wpa_s->conf->ap_scan == 1) {
4243 /* give IBSS a bit more time */
4244 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4245 }
4246 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4247 }
4248
Hai Shalomfdcde762020-04-02 11:19:20 -07004249#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004250 if (wep_keys_set &&
4251 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004252 /* Set static WEP keys again */
4253 wpa_set_wep_keys(wpa_s, ssid);
4254 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004255#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004256
Sunil8cd6f4d2022-06-28 18:40:46 +00004257 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004258 /*
4259 * Do not allow EAP session resumption between different
4260 * network configurations.
4261 */
4262 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4263 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004264
4265 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004266 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004267#ifdef CONFIG_HS20
4268 hs20_configure_frame_filters(wpa_s);
4269#endif /* CONFIG_HS20 */
4270 }
4271
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004272 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4273 wpa_supplicant_initiate_eapol(wpa_s);
4274 if (old_ssid != wpa_s->current_ssid)
4275 wpas_notify_network_changed(wpa_s);
4276}
4277
4278
4279static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4280 const u8 *addr)
4281{
4282 struct wpa_ssid *old_ssid;
4283
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004284 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004286 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004287 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004288 wpa_sm_set_config(wpa_s->wpa, NULL);
4289 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4290 if (old_ssid != wpa_s->current_ssid)
4291 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004292
4293 wpas_scs_deinit(wpa_s);
4294 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004295 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4296}
4297
4298
4299/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004300 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4301 * @wpa_s: Pointer to wpa_supplicant data
4302 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4303 *
4304 * This function is used to request %wpa_supplicant to deauthenticate from the
4305 * current AP.
4306 */
4307void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004308 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004309{
4310 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004311 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004312 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004313
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004314 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004315 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004316 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004317 reason_code, reason2str(reason_code),
4318 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004319
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004320 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4321 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4322 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004323 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004324 else if (!is_zero_ether_addr(wpa_s->bssid))
4325 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004326 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4327 /*
4328 * When using driver-based BSS selection, we may not know the
4329 * BSSID with which we are currently trying to associate. We
4330 * need to notify the driver of this disconnection even in such
4331 * a case, so use the all zeros address here.
4332 */
4333 addr = wpa_s->bssid;
4334 zero_addr = 1;
4335 }
4336
Hai Shalom74f70d42019-02-11 14:42:39 -08004337 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4338 wpa_s->enabled_4addr_mode = 0;
4339
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004340#ifdef CONFIG_TDLS
4341 wpa_tdls_teardown_peers(wpa_s->wpa);
4342#endif /* CONFIG_TDLS */
4343
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004344#ifdef CONFIG_MESH
4345 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004346 struct mesh_conf *mconf;
4347
4348 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004349 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4350 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004351 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4352 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004353 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004354 }
4355#endif /* CONFIG_MESH */
4356
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004357 if (addr) {
4358 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004359 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004360 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004361 event.deauth_info.locally_generated = 1;
4362 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004363 if (zero_addr)
4364 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004365 }
4366
4367 wpa_supplicant_clear_connection(wpa_s, addr);
4368}
4369
Hai Shalomfdcde762020-04-02 11:19:20 -07004370
4371void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4372{
4373 wpa_s->own_reconnect_req = 1;
4374 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4375
4376}
4377
4378
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004379static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4380 struct wpa_ssid *ssid)
4381{
4382 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4383 return;
4384
4385 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004386 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004387 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4388 wpas_notify_network_enabled_changed(wpa_s, ssid);
4389
4390 /*
4391 * Try to reassociate since there is no current configuration and a new
4392 * network was made available.
4393 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004394 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004395 wpa_s->reassociate = 1;
4396}
4397
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004398
Roshan Pius950bec92016-07-19 09:49:24 -07004399/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004400 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004401 * @wpa_s: wpa_supplicant structure for a network interface
4402 * Returns: The new network configuration or %NULL if operation failed
4403 *
4404 * This function performs the following operations:
4405 * 1. Adds a new network.
4406 * 2. Send network addition notification.
4407 * 3. Marks the network disabled.
4408 * 4. Set network default parameters.
4409 */
4410struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4411{
4412 struct wpa_ssid *ssid;
4413
4414 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004415 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004416 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004417 wpas_notify_network_added(wpa_s, ssid);
4418 ssid->disabled = 1;
4419 wpa_config_set_network_defaults(ssid);
4420
4421 return ssid;
4422}
4423
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004424
Roshan Pius950bec92016-07-19 09:49:24 -07004425/**
4426 * wpa_supplicant_remove_network - Remove a configured network based on id
4427 * @wpa_s: wpa_supplicant structure for a network interface
4428 * @id: Unique network id to search for
4429 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4430 * could not be removed
4431 *
4432 * This function performs the following operations:
4433 * 1. Removes the network.
4434 * 2. Send network removal notification.
4435 * 3. Update internal state machines.
4436 * 4. Stop any running sched scans.
4437 */
4438int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4439{
Sunil Ravia04bd252022-05-02 22:54:18 -07004440 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004441 int was_disabled;
4442
4443 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004444 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004445 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004446 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004447
Sunil Ravia04bd252022-05-02 22:54:18 -07004448 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004449#ifdef CONFIG_SME
4450 wpa_s->sme.prev_bssid_set = 0;
4451#endif /* CONFIG_SME */
4452 /*
4453 * Invalidate the EAP session cache if the current or
4454 * previously used network is removed.
4455 */
4456 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4457 }
4458
Sunil Ravia04bd252022-05-02 22:54:18 -07004459 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004460 wpa_sm_set_config(wpa_s->wpa, NULL);
4461 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4462
4463 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4464 wpa_s->own_disconnect_req = 1;
4465 wpa_supplicant_deauthenticate(wpa_s,
4466 WLAN_REASON_DEAUTH_LEAVING);
4467 }
4468
4469 was_disabled = ssid->disabled;
4470
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004471 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004472 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004473
4474 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004475 wpa_printf(MSG_DEBUG,
4476 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004477 wpa_supplicant_cancel_sched_scan(wpa_s);
4478 wpa_supplicant_req_scan(wpa_s, 0, 0);
4479 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004480
Roshan Pius950bec92016-07-19 09:49:24 -07004481 return 0;
4482}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004483
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004485/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004486 * wpa_supplicant_remove_all_networks - Remove all configured networks
4487 * @wpa_s: wpa_supplicant structure for a network interface
4488 * Returns: 0 on success (errors are currently ignored)
4489 *
4490 * This function performs the following operations:
4491 * 1. Remove all networks.
4492 * 2. Send network removal notifications.
4493 * 3. Update internal state machines.
4494 * 4. Stop any running sched scans.
4495 */
4496int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4497{
4498 struct wpa_ssid *ssid;
4499
4500 if (wpa_s->sched_scanning)
4501 wpa_supplicant_cancel_sched_scan(wpa_s);
4502
4503 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4504 if (wpa_s->current_ssid) {
4505#ifdef CONFIG_SME
4506 wpa_s->sme.prev_bssid_set = 0;
4507#endif /* CONFIG_SME */
4508 wpa_sm_set_config(wpa_s->wpa, NULL);
4509 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4510 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4511 wpa_s->own_disconnect_req = 1;
4512 wpa_supplicant_deauthenticate(
4513 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4514 }
4515 ssid = wpa_s->conf->ssid;
4516 while (ssid) {
4517 struct wpa_ssid *remove_ssid = ssid;
4518 int id;
4519
4520 id = ssid->id;
4521 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004522 wpas_notify_network_removed(wpa_s, remove_ssid);
4523 wpa_config_remove_network(wpa_s->conf, id);
4524 }
4525 return 0;
4526}
4527
4528
4529/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004530 * wpa_supplicant_enable_network - Mark a configured network as enabled
4531 * @wpa_s: wpa_supplicant structure for a network interface
4532 * @ssid: wpa_ssid structure for a configured network or %NULL
4533 *
4534 * Enables the specified network or all networks if no network specified.
4535 */
4536void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4537 struct wpa_ssid *ssid)
4538{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004539 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004540 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4541 wpa_supplicant_enable_one_network(wpa_s, ssid);
4542 } else
4543 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004544
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004545 if (wpa_s->reassociate && !wpa_s->disconnected &&
4546 (!wpa_s->current_ssid ||
4547 wpa_s->wpa_state == WPA_DISCONNECTED ||
4548 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004549 if (wpa_s->sched_scanning) {
4550 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4551 "new network to scan filters");
4552 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004553 }
4554
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004555 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4556 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004557 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004558 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004559 }
4560}
4561
4562
4563/**
4564 * wpa_supplicant_disable_network - Mark a configured network as disabled
4565 * @wpa_s: wpa_supplicant structure for a network interface
4566 * @ssid: wpa_ssid structure for a configured network or %NULL
4567 *
4568 * Disables the specified network or all networks if no network specified.
4569 */
4570void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4571 struct wpa_ssid *ssid)
4572{
4573 struct wpa_ssid *other_ssid;
4574 int was_disabled;
4575
4576 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004577 if (wpa_s->sched_scanning)
4578 wpa_supplicant_cancel_sched_scan(wpa_s);
4579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004580 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4581 other_ssid = other_ssid->next) {
4582 was_disabled = other_ssid->disabled;
4583 if (was_disabled == 2)
4584 continue; /* do not change persistent P2P group
4585 * data */
4586
4587 other_ssid->disabled = 1;
4588
4589 if (was_disabled != other_ssid->disabled)
4590 wpas_notify_network_enabled_changed(
4591 wpa_s, other_ssid);
4592 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004593 if (wpa_s->current_ssid) {
4594 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4595 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004596 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004597 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004598 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004599 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004600 if (ssid == wpa_s->current_ssid) {
4601 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4602 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004603 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004604 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004605 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004606
4607 was_disabled = ssid->disabled;
4608
4609 ssid->disabled = 1;
4610
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004611 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004612 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004613 if (wpa_s->sched_scanning) {
4614 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4615 "to remove network from filters");
4616 wpa_supplicant_cancel_sched_scan(wpa_s);
4617 wpa_supplicant_req_scan(wpa_s, 0, 0);
4618 }
4619 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004620 }
4621}
4622
4623
4624/**
4625 * wpa_supplicant_select_network - Attempt association with a network
4626 * @wpa_s: wpa_supplicant structure for a network interface
4627 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4628 */
4629void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4630 struct wpa_ssid *ssid)
4631{
4632
4633 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004634 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004635
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004636 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004637 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4638 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004639 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004640 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004641 disconnected = 1;
4642 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004643
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004644 if (ssid)
4645 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4646
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004647 /*
4648 * Mark all other networks disabled or mark all networks enabled if no
4649 * network specified.
4650 */
4651 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4652 other_ssid = other_ssid->next) {
4653 int was_disabled = other_ssid->disabled;
4654 if (was_disabled == 2)
4655 continue; /* do not change persistent P2P group data */
4656
4657 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004658 if (was_disabled && !other_ssid->disabled)
4659 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004660
4661 if (was_disabled != other_ssid->disabled)
4662 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4663 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004664
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004665 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4666 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004667 /* We are already associated with the selected network */
4668 wpa_printf(MSG_DEBUG, "Already associated with the "
4669 "selected network - do nothing");
4670 return;
4671 }
4672
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004673 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004674 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004675 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004676 wpa_s->connect_without_scan =
4677 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004678
4679 /*
4680 * Don't optimize next scan freqs since a new ESS has been
4681 * selected.
4682 */
4683 os_free(wpa_s->next_scan_freqs);
4684 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004685 } else {
4686 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004687 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004688
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004689 wpa_s->disconnected = 0;
4690 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004691 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004692 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004693 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004694 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004695 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4696 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004697
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004698 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004699 wpa_supplicant_fast_associate(wpa_s) != 1) {
4700 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004701 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004702 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004703 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004704
4705 if (ssid)
4706 wpas_notify_network_selected(wpa_s, ssid);
4707}
4708
4709
4710/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004711 * wpas_remove_cred - Remove the specified credential and all the network
4712 * entries created based on the removed credential
4713 * @wpa_s: wpa_supplicant structure for a network interface
4714 * @cred: The credential to remove
4715 * Returns: 0 on success, -1 on failure
4716 */
4717int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4718{
4719 struct wpa_ssid *ssid, *next;
4720 int id;
4721
4722 if (!cred) {
4723 wpa_printf(MSG_DEBUG, "Could not find cred");
4724 return -1;
4725 }
4726
4727 id = cred->id;
4728 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4729 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4730 return -1;
4731 }
4732
4733 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4734
4735 /* Remove any network entry created based on the removed credential */
4736 ssid = wpa_s->conf->ssid;
4737 while (ssid) {
4738 next = ssid->next;
4739
4740 if (ssid->parent_cred == cred) {
4741 wpa_printf(MSG_DEBUG,
4742 "Remove network id %d since it used the removed credential",
4743 ssid->id);
4744 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4745 -1) {
4746 wpa_printf(MSG_DEBUG,
4747 "Could not find network id=%d",
4748 ssid->id);
4749 }
4750 }
4751
4752 ssid = next;
4753 }
4754
4755 return 0;
4756}
4757
4758
4759/**
4760 * wpas_remove_cred - Remove all the Interworking credentials
4761 * @wpa_s: wpa_supplicant structure for a network interface
4762 * Returns: 0 on success, -1 on failure
4763 */
4764int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4765{
4766 int res, ret = 0;
4767 struct wpa_cred *cred, *prev;
4768
4769 cred = wpa_s->conf->cred;
4770 while (cred) {
4771 prev = cred;
4772 cred = cred->next;
4773 res = wpas_remove_cred(wpa_s, prev);
4774 if (res < 0) {
4775 wpa_printf(MSG_DEBUG,
4776 "Removal of all credentials failed - failed to remove credential id=%d",
4777 prev->id);
4778 ret = -1;
4779 }
4780 }
4781
4782 return ret;
4783}
4784
4785
4786/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004787 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4788 * @wpa_s: wpa_supplicant structure for a network interface
4789 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4790 * @pkcs11_module_path: PKCS #11 module path or NULL
4791 * Returns: 0 on success; -1 on failure
4792 *
4793 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4794 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4795 * module path fails the paths will be reset to the default value (NULL).
4796 */
4797int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4798 const char *pkcs11_engine_path,
4799 const char *pkcs11_module_path)
4800{
4801 char *pkcs11_engine_path_copy = NULL;
4802 char *pkcs11_module_path_copy = NULL;
4803
4804 if (pkcs11_engine_path != NULL) {
4805 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4806 if (pkcs11_engine_path_copy == NULL)
4807 return -1;
4808 }
4809 if (pkcs11_module_path != NULL) {
4810 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004811 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004812 os_free(pkcs11_engine_path_copy);
4813 return -1;
4814 }
4815 }
4816
4817 os_free(wpa_s->conf->pkcs11_engine_path);
4818 os_free(wpa_s->conf->pkcs11_module_path);
4819 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4820 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4821
4822 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4823 eapol_sm_deinit(wpa_s->eapol);
4824 wpa_s->eapol = NULL;
4825 if (wpa_supplicant_init_eapol(wpa_s)) {
4826 /* Error -> Reset paths to the default value (NULL) once. */
4827 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4828 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4829 NULL);
4830
4831 return -1;
4832 }
4833 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4834
4835 return 0;
4836}
4837
4838
4839/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004840 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4841 * @wpa_s: wpa_supplicant structure for a network interface
4842 * @ap_scan: AP scan mode
4843 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4844 *
4845 */
4846int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4847{
4848
4849 int old_ap_scan;
4850
4851 if (ap_scan < 0 || ap_scan > 2)
4852 return -1;
4853
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004854 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4855 wpa_printf(MSG_INFO,
4856 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4857 }
4858
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004859#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004860 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4861 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4862 wpa_s->wpa_state < WPA_COMPLETED) {
4863 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4864 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004865 return 0;
4866 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004867#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004868
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004869 old_ap_scan = wpa_s->conf->ap_scan;
4870 wpa_s->conf->ap_scan = ap_scan;
4871
4872 if (old_ap_scan != wpa_s->conf->ap_scan)
4873 wpas_notify_ap_scan_changed(wpa_s);
4874
4875 return 0;
4876}
4877
4878
4879/**
4880 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4881 * @wpa_s: wpa_supplicant structure for a network interface
4882 * @expire_age: Expiration age in seconds
4883 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4884 *
4885 */
4886int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4887 unsigned int bss_expire_age)
4888{
4889 if (bss_expire_age < 10) {
4890 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4891 bss_expire_age);
4892 return -1;
4893 }
4894 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4895 bss_expire_age);
4896 wpa_s->conf->bss_expiration_age = bss_expire_age;
4897
4898 return 0;
4899}
4900
4901
4902/**
4903 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4904 * @wpa_s: wpa_supplicant structure for a network interface
4905 * @expire_count: number of scans after which an unseen BSS is reclaimed
4906 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4907 *
4908 */
4909int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4910 unsigned int bss_expire_count)
4911{
4912 if (bss_expire_count < 1) {
4913 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4914 bss_expire_count);
4915 return -1;
4916 }
4917 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4918 bss_expire_count);
4919 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4920
4921 return 0;
4922}
4923
4924
4925/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004926 * wpa_supplicant_set_scan_interval - Set scan interval
4927 * @wpa_s: wpa_supplicant structure for a network interface
4928 * @scan_interval: scan interval in seconds
4929 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4930 *
4931 */
4932int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4933 int scan_interval)
4934{
4935 if (scan_interval < 0) {
4936 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4937 scan_interval);
4938 return -1;
4939 }
4940 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4941 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004942 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004943
4944 return 0;
4945}
4946
4947
4948/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004949 * wpa_supplicant_set_debug_params - Set global debug params
4950 * @global: wpa_global structure
4951 * @debug_level: debug level
4952 * @debug_timestamp: determines if show timestamp in debug data
4953 * @debug_show_keys: determines if show keys in debug data
4954 * Returns: 0 if succeed or -1 if debug_level has wrong value
4955 */
4956int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4957 int debug_timestamp, int debug_show_keys)
4958{
4959
4960 int old_level, old_timestamp, old_show_keys;
4961
4962 /* check for allowed debuglevels */
4963 if (debug_level != MSG_EXCESSIVE &&
4964 debug_level != MSG_MSGDUMP &&
4965 debug_level != MSG_DEBUG &&
4966 debug_level != MSG_INFO &&
4967 debug_level != MSG_WARNING &&
4968 debug_level != MSG_ERROR)
4969 return -1;
4970
4971 old_level = wpa_debug_level;
4972 old_timestamp = wpa_debug_timestamp;
4973 old_show_keys = wpa_debug_show_keys;
4974
4975 wpa_debug_level = debug_level;
4976 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4977 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4978
4979 if (wpa_debug_level != old_level)
4980 wpas_notify_debug_level_changed(global);
4981 if (wpa_debug_timestamp != old_timestamp)
4982 wpas_notify_debug_timestamp_changed(global);
4983 if (wpa_debug_show_keys != old_show_keys)
4984 wpas_notify_debug_show_keys_changed(global);
4985
4986 return 0;
4987}
4988
4989
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004990#ifdef CONFIG_OWE
4991static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4992 const u8 *entry_ssid, size_t entry_ssid_len)
4993{
4994 const u8 *owe, *pos, *end;
4995 u8 ssid_len;
4996 struct wpa_bss *bss;
4997
4998 /* Check network profile SSID aganst the SSID in the
4999 * OWE Transition Mode element. */
5000
5001 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5002 if (!bss)
5003 return 0;
5004
5005 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5006 if (!owe)
5007 return 0;
5008
5009 pos = owe + 6;
5010 end = owe + 2 + owe[1];
5011
5012 if (end - pos < ETH_ALEN + 1)
5013 return 0;
5014 pos += ETH_ALEN;
5015 ssid_len = *pos++;
5016 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5017 return 0;
5018
5019 return entry_ssid_len == ssid_len &&
5020 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5021}
5022#endif /* CONFIG_OWE */
5023
5024
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005025/**
5026 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5027 * @wpa_s: Pointer to wpa_supplicant data
5028 * Returns: A pointer to the current network structure or %NULL on failure
5029 */
5030struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5031{
5032 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005033 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005034 int res;
5035 size_t ssid_len;
5036 u8 bssid[ETH_ALEN];
5037 int wired;
5038
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005039 res = wpa_drv_get_ssid(wpa_s, ssid);
5040 if (res < 0) {
5041 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5042 "driver");
5043 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005044 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005045 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005046
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005047 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005048 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5049 "driver");
5050 return NULL;
5051 }
5052
5053 wired = wpa_s->conf->ap_scan == 0 &&
5054 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5055
5056 entry = wpa_s->conf->ssid;
5057 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005058 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005059 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005060 (!entry->ssid ||
5061 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5062 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005063 (!entry->bssid_set ||
5064 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5065 return entry;
5066#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005067 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005068 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5069 (entry->ssid == NULL || entry->ssid_len == 0) &&
5070 (!entry->bssid_set ||
5071 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5072 return entry;
5073#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005074
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005075#ifdef CONFIG_OWE
5076 if (!wpas_network_disabled(wpa_s, entry) &&
5077 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5078 entry->ssid_len) &&
5079 (!entry->bssid_set ||
5080 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5081 return entry;
5082#endif /* CONFIG_OWE */
5083
Dmitry Shmidt04949592012-07-19 12:16:46 -07005084 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005085 entry->ssid_len == 0 &&
5086 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5087 return entry;
5088
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005089 entry = entry->next;
5090 }
5091
5092 return NULL;
5093}
5094
5095
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005096static int select_driver(struct wpa_supplicant *wpa_s, int i)
5097{
5098 struct wpa_global *global = wpa_s->global;
5099
5100 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005101 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005102 if (global->drv_priv[i] == NULL) {
5103 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5104 "'%s'", wpa_drivers[i]->name);
5105 return -1;
5106 }
5107 }
5108
5109 wpa_s->driver = wpa_drivers[i];
5110 wpa_s->global_drv_priv = global->drv_priv[i];
5111
5112 return 0;
5113}
5114
5115
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005116static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5117 const char *name)
5118{
5119 int i;
5120 size_t len;
5121 const char *pos, *driver = name;
5122
5123 if (wpa_s == NULL)
5124 return -1;
5125
5126 if (wpa_drivers[0] == NULL) {
5127 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5128 "wpa_supplicant");
5129 return -1;
5130 }
5131
5132 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005133 /* Default to first successful driver in the list */
5134 for (i = 0; wpa_drivers[i]; i++) {
5135 if (select_driver(wpa_s, i) == 0)
5136 return 0;
5137 }
5138 /* Drivers have each reported failure, so no wpa_msg() here. */
5139 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005140 }
5141
5142 do {
5143 pos = os_strchr(driver, ',');
5144 if (pos)
5145 len = pos - driver;
5146 else
5147 len = os_strlen(driver);
5148
5149 for (i = 0; wpa_drivers[i]; i++) {
5150 if (os_strlen(wpa_drivers[i]->name) == len &&
5151 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005152 0) {
5153 /* First driver that succeeds wins */
5154 if (select_driver(wpa_s, i) == 0)
5155 return 0;
5156 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005157 }
5158
5159 driver = pos + 1;
5160 } while (pos);
5161
5162 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5163 return -1;
5164}
5165
5166
5167/**
5168 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5169 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5170 * with struct wpa_driver_ops::init()
5171 * @src_addr: Source address of the EAPOL frame
5172 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5173 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005174 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005175 *
5176 * This function is called for each received EAPOL frame. Most driver
5177 * interfaces rely on more generic OS mechanism for receiving frames through
5178 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5179 * take care of received EAPOL frames and deliver them to the core supplicant
5180 * code by calling this function.
5181 */
5182void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005183 const u8 *buf, size_t len,
5184 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005185{
5186 struct wpa_supplicant *wpa_s = ctx;
5187
Sunil8cd6f4d2022-06-28 18:40:46 +00005188 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5189 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005190 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5191
Hai Shalomc1a21442022-02-04 13:43:00 -08005192 if (wpa_s->own_disconnect_req) {
5193 wpa_printf(MSG_DEBUG,
5194 "Drop received EAPOL frame as we are disconnecting");
5195 return;
5196 }
5197
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005198#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005199 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5200 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005201 if (wpa_s->ignore_auth_resp) {
5202 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5203 return;
5204 }
5205#endif /* CONFIG_TESTING_OPTIONS */
5206
Jouni Malinena05074c2012-12-21 21:35:35 +02005207 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5208 (wpa_s->last_eapol_matches_bssid &&
5209#ifdef CONFIG_AP
5210 !wpa_s->ap_iface &&
5211#endif /* CONFIG_AP */
5212 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005213 /*
5214 * There is possible race condition between receiving the
5215 * association event and the EAPOL frame since they are coming
5216 * through different paths from the driver. In order to avoid
5217 * issues in trying to process the EAPOL frame before receiving
5218 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005219 * the association event is received. This may also be needed in
5220 * driver-based roaming case, so also use src_addr != BSSID as a
5221 * trigger if we have previously confirmed that the
5222 * Authenticator uses BSSID as the src_addr (which is not the
5223 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005224 */
5225 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02005226 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
5227 wpa_supplicant_state_txt(wpa_s->wpa_state),
5228 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005229 wpabuf_free(wpa_s->pending_eapol_rx);
5230 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5231 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005232 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005233 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5234 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005235 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005236 }
5237 return;
5238 }
5239
Jouni Malinena05074c2012-12-21 21:35:35 +02005240 wpa_s->last_eapol_matches_bssid =
5241 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
5242
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005243#ifdef CONFIG_AP
5244 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005245 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5246 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005247 return;
5248 }
5249#endif /* CONFIG_AP */
5250
5251 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5252 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5253 "no key management is configured");
5254 return;
5255 }
5256
5257 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005258 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005259 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5260 wpa_s->wpa_state != WPA_COMPLETED) &&
5261 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005262 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005263 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005264 int timeout = 10;
5265
5266 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5267 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5268 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5269 /* Use longer timeout for IEEE 802.1X/EAP */
5270 timeout = 70;
5271 }
5272
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005273#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005274 if (wpa_s->current_ssid && wpa_s->current_bss &&
5275 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5276 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5277 /*
5278 * Use shorter timeout if going through WPS AP iteration
5279 * for PIN config method with an AP that does not
5280 * advertise Selected Registrar.
5281 */
5282 struct wpabuf *wps_ie;
5283
5284 wps_ie = wpa_bss_get_vendor_ie_multi(
5285 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5286 if (wps_ie &&
5287 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5288 timeout = 10;
5289 wpabuf_free(wps_ie);
5290 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005291#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005292
5293 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005294 }
5295 wpa_s->eapol_received++;
5296
5297 if (wpa_s->countermeasures) {
5298 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5299 "EAPOL packet");
5300 return;
5301 }
5302
5303#ifdef CONFIG_IBSS_RSN
5304 if (wpa_s->current_ssid &&
5305 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005306 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5307 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005308 return;
5309 }
5310#endif /* CONFIG_IBSS_RSN */
5311
5312 /* Source address of the incoming EAPOL frame could be compared to the
5313 * current BSSID. However, it is possible that a centralized
5314 * Authenticator could be using another MAC address than the BSSID of
5315 * an AP, so just allow any address to be used for now. The replies are
5316 * still sent to the current BSSID (if available), though. */
5317
5318 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5319 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005320 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5321 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005322 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5323 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005324 return;
5325 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005326 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005327 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005328 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5329 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005330 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005331 * handshake processing which would normally set portValid. We
5332 * need this to allow the EAPOL state machines to be completed
5333 * without going through EAPOL-Key handshake.
5334 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005335 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005336 }
5337}
5338
5339
Sunil8cd6f4d2022-06-28 18:40:46 +00005340static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5341 const u8 *buf, size_t len)
5342{
5343 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5344 FRAME_ENCRYPTION_UNKNOWN);
5345}
5346
5347
Hai Shalomb755a2a2020-04-23 21:49:02 -07005348static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5349{
5350 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5351 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5352}
5353
5354
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005355int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005356{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005357 if ((!wpa_s->p2p_mgmt ||
5358 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5359 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005360 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005361 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5362 wpa_drv_get_mac_addr(wpa_s),
5363 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005364 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005365 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005366 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005367 if (wpa_s->l2 == NULL)
5368 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005369
5370 if (l2_packet_set_packet_filter(wpa_s->l2,
5371 L2_PACKET_FILTER_PKTTYPE))
5372 wpa_dbg(wpa_s, MSG_DEBUG,
5373 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005374
5375 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5376 wpa_msg(wpa_s, MSG_ERROR,
5377 "Failed to get own L2 address");
5378 return -1;
5379 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005380 } else {
5381 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5382 if (addr)
5383 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5384 }
5385
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005386 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005387 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005388
Hai Shalomc3565922019-10-28 11:58:20 -07005389#ifdef CONFIG_FST
5390 if (wpa_s->fst)
5391 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5392#endif /* CONFIG_FST */
5393
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005394 return 0;
5395}
5396
5397
Dmitry Shmidt04949592012-07-19 12:16:46 -07005398static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5399 const u8 *buf, size_t len)
5400{
5401 struct wpa_supplicant *wpa_s = ctx;
5402 const struct l2_ethhdr *eth;
5403
5404 if (len < sizeof(*eth))
5405 return;
5406 eth = (const struct l2_ethhdr *) buf;
5407
5408 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5409 !(eth->h_dest[0] & 0x01)) {
5410 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5411 " (bridge - not for this interface - ignore)",
5412 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5413 return;
5414 }
5415
5416 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5417 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5418 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005419 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005420}
5421
5422
Hai Shalom899fcc72020-10-19 14:38:18 -07005423int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5424 const char *bridge_ifname)
5425{
5426 if (wpa_s->wpa_state > WPA_SCANNING)
5427 return -EBUSY;
5428
5429 if (bridge_ifname &&
5430 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5431 return -EINVAL;
5432
5433 if (!bridge_ifname)
5434 bridge_ifname = "";
5435
5436 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5437 return 0;
5438
5439 if (wpa_s->l2_br) {
5440 l2_packet_deinit(wpa_s->l2_br);
5441 wpa_s->l2_br = NULL;
5442 }
5443
5444 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5445 sizeof(wpa_s->bridge_ifname));
5446
5447 if (wpa_s->bridge_ifname[0]) {
5448 wpa_dbg(wpa_s, MSG_DEBUG,
5449 "Receiving packets from bridge interface '%s'",
5450 wpa_s->bridge_ifname);
5451 wpa_s->l2_br = l2_packet_init_bridge(
5452 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5453 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5454 if (!wpa_s->l2_br) {
5455 wpa_msg(wpa_s, MSG_ERROR,
5456 "Failed to open l2_packet connection for the bridge interface '%s'",
5457 wpa_s->bridge_ifname);
5458 goto fail;
5459 }
5460 }
5461
5462#ifdef CONFIG_TDLS
5463 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5464 goto fail;
5465#endif /* CONFIG_TDLS */
5466
5467 return 0;
5468fail:
5469 wpa_s->bridge_ifname[0] = 0;
5470 if (wpa_s->l2_br) {
5471 l2_packet_deinit(wpa_s->l2_br);
5472 wpa_s->l2_br = NULL;
5473 }
5474#ifdef CONFIG_TDLS
5475 if (!wpa_s->p2p_mgmt)
5476 wpa_tdls_init(wpa_s->wpa);
5477#endif /* CONFIG_TDLS */
5478 return -EIO;
5479}
5480
5481
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005482/**
5483 * wpa_supplicant_driver_init - Initialize driver interface parameters
5484 * @wpa_s: Pointer to wpa_supplicant data
5485 * Returns: 0 on success, -1 on failure
5486 *
5487 * This function is called to initialize driver interface parameters.
5488 * wpa_drv_init() must have been called before this function to initialize the
5489 * driver interface.
5490 */
5491int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5492{
5493 static int interface_count = 0;
5494
5495 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5496 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005497
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005498 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5499 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005500 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005501 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5502
Hai Shalomb755a2a2020-04-23 21:49:02 -07005503 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005504 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5505 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005506 wpa_s->l2_br = l2_packet_init_bridge(
5507 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5508 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005509 if (wpa_s->l2_br == NULL) {
5510 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5511 "connection for the bridge interface '%s'",
5512 wpa_s->bridge_ifname);
5513 return -1;
5514 }
5515 }
5516
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005517 if (wpa_s->conf->ap_scan == 2 &&
5518 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5519 wpa_printf(MSG_INFO,
5520 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5521 }
5522
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005523 wpa_clear_keys(wpa_s, NULL);
5524
5525 /* Make sure that TKIP countermeasures are not left enabled (could
5526 * happen if wpa_supplicant is killed during countermeasures. */
5527 wpa_drv_set_countermeasures(wpa_s, 0);
5528
5529 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5530 wpa_drv_flush_pmkid(wpa_s);
5531
5532 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005533 wpa_s->prev_scan_wildcard = 0;
5534
Dmitry Shmidt04949592012-07-19 12:16:46 -07005535 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005536 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5537 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5538 interface_count = 0;
5539 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005540#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005541 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005542 wpa_supplicant_delayed_sched_scan(wpa_s,
5543 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005544 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005545 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005546 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005547#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005548 interface_count++;
5549 } else
5550 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5551
5552 return 0;
5553}
5554
5555
5556static int wpa_supplicant_daemon(const char *pid_file)
5557{
5558 wpa_printf(MSG_DEBUG, "Daemonize..");
5559 return os_daemonize(pid_file);
5560}
5561
5562
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005563static struct wpa_supplicant *
5564wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005565{
5566 struct wpa_supplicant *wpa_s;
5567
5568 wpa_s = os_zalloc(sizeof(*wpa_s));
5569 if (wpa_s == NULL)
5570 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005571 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005572 wpa_s->scan_interval = 5;
5573 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005574 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005575 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005576 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005577 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005578
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005579 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005580 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005581#ifdef CONFIG_TESTING_OPTIONS
5582 dl_list_init(&wpa_s->drv_signal_override);
5583#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005584 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005585
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005586 return wpa_s;
5587}
5588
5589
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005590#ifdef CONFIG_HT_OVERRIDES
5591
5592static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5593 struct ieee80211_ht_capabilities *htcaps,
5594 struct ieee80211_ht_capabilities *htcaps_mask,
5595 const char *ht_mcs)
5596{
5597 /* parse ht_mcs into hex array */
5598 int i;
5599 const char *tmp = ht_mcs;
5600 char *end = NULL;
5601
5602 /* If ht_mcs is null, do not set anything */
5603 if (!ht_mcs)
5604 return 0;
5605
5606 /* This is what we are setting in the kernel */
5607 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5608
5609 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5610
5611 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005612 long v;
5613
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005614 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005615 v = strtol(tmp, &end, 16);
5616
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005617 if (errno == 0) {
5618 wpa_msg(wpa_s, MSG_DEBUG,
5619 "htcap value[%i]: %ld end: %p tmp: %p",
5620 i, v, end, tmp);
5621 if (end == tmp)
5622 break;
5623
5624 htcaps->supported_mcs_set[i] = v;
5625 tmp = end;
5626 } else {
5627 wpa_msg(wpa_s, MSG_ERROR,
5628 "Failed to parse ht-mcs: %s, error: %s\n",
5629 ht_mcs, strerror(errno));
5630 return -1;
5631 }
5632 }
5633
5634 /*
5635 * If we were able to parse any values, then set mask for the MCS set.
5636 */
5637 if (i) {
5638 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5639 IEEE80211_HT_MCS_MASK_LEN - 1);
5640 /* skip the 3 reserved bits */
5641 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5642 0x1f;
5643 }
5644
5645 return 0;
5646}
5647
5648
5649static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5650 struct ieee80211_ht_capabilities *htcaps,
5651 struct ieee80211_ht_capabilities *htcaps_mask,
5652 int disabled)
5653{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005654 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005655
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005656 if (disabled == -1)
5657 return 0;
5658
Hai Shalom74f70d42019-02-11 14:42:39 -08005659 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5660
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005661 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5662 htcaps_mask->ht_capabilities_info |= msk;
5663 if (disabled)
5664 htcaps->ht_capabilities_info &= msk;
5665 else
5666 htcaps->ht_capabilities_info |= msk;
5667
5668 return 0;
5669}
5670
5671
5672static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5673 struct ieee80211_ht_capabilities *htcaps,
5674 struct ieee80211_ht_capabilities *htcaps_mask,
5675 int factor)
5676{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005677 if (factor == -1)
5678 return 0;
5679
Hai Shalom74f70d42019-02-11 14:42:39 -08005680 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5681
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005682 if (factor < 0 || factor > 3) {
5683 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5684 "Must be 0-3 or -1", factor);
5685 return -EINVAL;
5686 }
5687
5688 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5689 htcaps->a_mpdu_params &= ~0x3;
5690 htcaps->a_mpdu_params |= factor & 0x3;
5691
5692 return 0;
5693}
5694
5695
5696static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5697 struct ieee80211_ht_capabilities *htcaps,
5698 struct ieee80211_ht_capabilities *htcaps_mask,
5699 int density)
5700{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005701 if (density == -1)
5702 return 0;
5703
Hai Shalom74f70d42019-02-11 14:42:39 -08005704 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5705
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005706 if (density < 0 || density > 7) {
5707 wpa_msg(wpa_s, MSG_ERROR,
5708 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5709 density);
5710 return -EINVAL;
5711 }
5712
5713 htcaps_mask->a_mpdu_params |= 0x1C;
5714 htcaps->a_mpdu_params &= ~(0x1C);
5715 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5716
5717 return 0;
5718}
5719
5720
5721static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5722 struct ieee80211_ht_capabilities *htcaps,
5723 struct ieee80211_ht_capabilities *htcaps_mask,
5724 int disabled)
5725{
Hai Shalom74f70d42019-02-11 14:42:39 -08005726 if (disabled)
5727 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005728
Paul Stewart092955c2017-02-06 09:13:09 -08005729 set_disable_ht40(htcaps, disabled);
5730 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005731
5732 return 0;
5733}
5734
5735
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005736static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5737 struct ieee80211_ht_capabilities *htcaps,
5738 struct ieee80211_ht_capabilities *htcaps_mask,
5739 int disabled)
5740{
5741 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005742 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5743 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005744
Hai Shalom74f70d42019-02-11 14:42:39 -08005745 if (disabled)
5746 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005747
5748 if (disabled)
5749 htcaps->ht_capabilities_info &= ~msk;
5750 else
5751 htcaps->ht_capabilities_info |= msk;
5752
5753 htcaps_mask->ht_capabilities_info |= msk;
5754
5755 return 0;
5756}
5757
5758
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005759static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5760 struct ieee80211_ht_capabilities *htcaps,
5761 struct ieee80211_ht_capabilities *htcaps_mask,
5762 int disabled)
5763{
5764 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005765 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005766
Hai Shalom74f70d42019-02-11 14:42:39 -08005767 if (disabled)
5768 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005769
5770 if (disabled)
5771 htcaps->ht_capabilities_info &= ~msk;
5772 else
5773 htcaps->ht_capabilities_info |= msk;
5774
5775 htcaps_mask->ht_capabilities_info |= msk;
5776
5777 return 0;
5778}
5779
5780
Hai Shalom74f70d42019-02-11 14:42:39 -08005781static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5782 struct ieee80211_ht_capabilities *htcaps,
5783 struct ieee80211_ht_capabilities *htcaps_mask,
5784 int tx_stbc)
5785{
5786 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5787
5788 if (tx_stbc == -1)
5789 return 0;
5790
5791 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5792
5793 if (tx_stbc < 0 || tx_stbc > 1) {
5794 wpa_msg(wpa_s, MSG_ERROR,
5795 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5796 return -EINVAL;
5797 }
5798
5799 htcaps_mask->ht_capabilities_info |= msk;
5800 htcaps->ht_capabilities_info &= ~msk;
5801 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5802
5803 return 0;
5804}
5805
5806
5807static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5808 struct ieee80211_ht_capabilities *htcaps,
5809 struct ieee80211_ht_capabilities *htcaps_mask,
5810 int rx_stbc)
5811{
5812 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5813
5814 if (rx_stbc == -1)
5815 return 0;
5816
5817 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5818
5819 if (rx_stbc < 0 || rx_stbc > 3) {
5820 wpa_msg(wpa_s, MSG_ERROR,
5821 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5822 return -EINVAL;
5823 }
5824
5825 htcaps_mask->ht_capabilities_info |= msk;
5826 htcaps->ht_capabilities_info &= ~msk;
5827 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5828
5829 return 0;
5830}
5831
5832
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005833void wpa_supplicant_apply_ht_overrides(
5834 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5835 struct wpa_driver_associate_params *params)
5836{
5837 struct ieee80211_ht_capabilities *htcaps;
5838 struct ieee80211_ht_capabilities *htcaps_mask;
5839
5840 if (!ssid)
5841 return;
5842
5843 params->disable_ht = ssid->disable_ht;
5844 if (!params->htcaps || !params->htcaps_mask)
5845 return;
5846
5847 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5848 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5849 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5850 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5851 ssid->disable_max_amsdu);
5852 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5853 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5854 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005855 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005856 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005857 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5858 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005859
5860 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005861 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005862 htcaps->ht_capabilities_info |= bit;
5863 htcaps_mask->ht_capabilities_info |= bit;
5864 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005865}
5866
5867#endif /* CONFIG_HT_OVERRIDES */
5868
5869
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005870#ifdef CONFIG_VHT_OVERRIDES
5871void wpa_supplicant_apply_vht_overrides(
5872 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5873 struct wpa_driver_associate_params *params)
5874{
5875 struct ieee80211_vht_capabilities *vhtcaps;
5876 struct ieee80211_vht_capabilities *vhtcaps_mask;
5877
5878 if (!ssid)
5879 return;
5880
5881 params->disable_vht = ssid->disable_vht;
5882
5883 vhtcaps = (void *) params->vhtcaps;
5884 vhtcaps_mask = (void *) params->vhtcaps_mask;
5885
5886 if (!vhtcaps || !vhtcaps_mask)
5887 return;
5888
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005889 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5890 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005891
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005892#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005893 if (ssid->disable_sgi) {
5894 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5895 VHT_CAP_SHORT_GI_160);
5896 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5897 VHT_CAP_SHORT_GI_160);
5898 wpa_msg(wpa_s, MSG_DEBUG,
5899 "disable-sgi override specified, vht-caps: 0x%x",
5900 vhtcaps->vht_capabilities_info);
5901 }
5902
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005903 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005904 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5905 int max_ampdu;
5906
5907 max_ampdu = (ssid->vht_capa &
5908 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5909 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005910
5911 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5912 wpa_set_ampdu_factor(wpa_s,
5913 (void *) params->htcaps,
5914 (void *) params->htcaps_mask,
5915 max_ampdu);
5916 }
5917#endif /* CONFIG_HT_OVERRIDES */
5918
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005919#define OVERRIDE_MCS(i) \
5920 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5921 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005922 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005923 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005924 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5925 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005926 } \
5927 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5928 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005929 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005930 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005931 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5932 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005933 }
5934
5935 OVERRIDE_MCS(1);
5936 OVERRIDE_MCS(2);
5937 OVERRIDE_MCS(3);
5938 OVERRIDE_MCS(4);
5939 OVERRIDE_MCS(5);
5940 OVERRIDE_MCS(6);
5941 OVERRIDE_MCS(7);
5942 OVERRIDE_MCS(8);
5943}
5944#endif /* CONFIG_VHT_OVERRIDES */
5945
5946
Hai Shalomfdcde762020-04-02 11:19:20 -07005947#ifdef CONFIG_HE_OVERRIDES
5948void wpa_supplicant_apply_he_overrides(
5949 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5950 struct wpa_driver_associate_params *params)
5951{
5952 if (!ssid)
5953 return;
5954
5955 params->disable_he = ssid->disable_he;
5956}
5957#endif /* CONFIG_HE_OVERRIDES */
5958
5959
Dmitry Shmidt04949592012-07-19 12:16:46 -07005960static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5961{
5962#ifdef PCSC_FUNCS
5963 size_t len;
5964
5965 if (!wpa_s->conf->pcsc_reader)
5966 return 0;
5967
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005968 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005969 if (!wpa_s->scard)
5970 return 1;
5971
5972 if (wpa_s->conf->pcsc_pin &&
5973 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5974 scard_deinit(wpa_s->scard);
5975 wpa_s->scard = NULL;
5976 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5977 return -1;
5978 }
5979
5980 len = sizeof(wpa_s->imsi) - 1;
5981 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5982 scard_deinit(wpa_s->scard);
5983 wpa_s->scard = NULL;
5984 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5985 return -1;
5986 }
5987 wpa_s->imsi[len] = '\0';
5988
5989 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5990
5991 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5992 wpa_s->imsi, wpa_s->mnc_len);
5993
5994 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5995 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5996#endif /* PCSC_FUNCS */
5997
5998 return 0;
5999}
6000
6001
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006002int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6003{
6004 char *val, *pos;
6005
6006 ext_password_deinit(wpa_s->ext_pw);
6007 wpa_s->ext_pw = NULL;
6008 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6009
6010 if (!wpa_s->conf->ext_password_backend)
6011 return 0;
6012
6013 val = os_strdup(wpa_s->conf->ext_password_backend);
6014 if (val == NULL)
6015 return -1;
6016 pos = os_strchr(val, ':');
6017 if (pos)
6018 *pos++ = '\0';
6019
6020 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6021
6022 wpa_s->ext_pw = ext_password_init(val, pos);
6023 os_free(val);
6024 if (wpa_s->ext_pw == NULL) {
6025 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6026 return -1;
6027 }
6028 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6029
6030 return 0;
6031}
6032
6033
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006034#ifdef CONFIG_FST
6035
6036static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6037{
6038 struct wpa_supplicant *wpa_s = ctx;
6039
6040 return (is_zero_ether_addr(wpa_s->bssid) ||
6041 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6042}
6043
6044
6045static void wpas_fst_get_channel_info_cb(void *ctx,
6046 enum hostapd_hw_mode *hw_mode,
6047 u8 *channel)
6048{
6049 struct wpa_supplicant *wpa_s = ctx;
6050
6051 if (wpa_s->current_bss) {
6052 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6053 channel);
6054 } else if (wpa_s->hw.num_modes) {
6055 *hw_mode = wpa_s->hw.modes[0].mode;
6056 } else {
6057 WPA_ASSERT(0);
6058 *hw_mode = 0;
6059 }
6060}
6061
6062
6063static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6064{
6065 struct wpa_supplicant *wpa_s = ctx;
6066
6067 *modes = wpa_s->hw.modes;
6068 return wpa_s->hw.num_modes;
6069}
6070
6071
6072static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6073{
6074 struct wpa_supplicant *wpa_s = ctx;
6075
6076 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6077 wpa_s->fst_ies = fst_ies;
6078}
6079
6080
6081static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6082{
6083 struct wpa_supplicant *wpa_s = ctx;
6084
Paul Stewart092955c2017-02-06 09:13:09 -08006085 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6086 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6087 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6088 return -1;
6089 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006090 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006091 wpa_s->own_addr, wpa_s->bssid,
6092 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006093 0);
6094}
6095
6096
6097static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6098{
6099 struct wpa_supplicant *wpa_s = ctx;
6100
6101 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6102 return wpa_s->received_mb_ies;
6103}
6104
6105
6106static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6107 const u8 *buf, size_t size)
6108{
6109 struct wpa_supplicant *wpa_s = ctx;
6110 struct mb_ies_info info;
6111
6112 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6113
6114 if (!mb_ies_info_by_ies(&info, buf, size)) {
6115 wpabuf_free(wpa_s->received_mb_ies);
6116 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6117 }
6118}
6119
6120
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006121static const u8 * wpas_fst_get_peer_first(void *ctx,
6122 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006123 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006124{
6125 struct wpa_supplicant *wpa_s = ctx;
6126
6127 *get_ctx = NULL;
6128 if (!is_zero_ether_addr(wpa_s->bssid))
6129 return (wpa_s->received_mb_ies || !mb_only) ?
6130 wpa_s->bssid : NULL;
6131 return NULL;
6132}
6133
6134
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006135static const u8 * wpas_fst_get_peer_next(void *ctx,
6136 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006137 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006138{
6139 return NULL;
6140}
6141
6142void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6143 struct fst_wpa_obj *iface_obj)
6144{
Sunil8cd6f4d2022-06-28 18:40:46 +00006145 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006146 iface_obj->ctx = wpa_s;
6147 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6148 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6149 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6150 iface_obj->set_ies = wpas_fst_set_ies_cb;
6151 iface_obj->send_action = wpas_fst_send_action_cb;
6152 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6153 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6154 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6155 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6156}
6157#endif /* CONFIG_FST */
6158
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006159static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006160 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006161{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006162 struct wowlan_triggers *triggers;
6163 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006164
6165 if (!wpa_s->conf->wowlan_triggers)
6166 return 0;
6167
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006168 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6169 if (triggers) {
6170 ret = wpa_drv_wowlan(wpa_s, triggers);
6171 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006172 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006173 return ret;
6174}
6175
6176
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006177enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006178{
6179 if (freq < 3000)
6180 return BAND_2_4_GHZ;
6181 if (freq > 50000)
6182 return BAND_60_GHZ;
6183 return BAND_5_GHZ;
6184}
6185
6186
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006187unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006188{
6189 int i;
6190 unsigned int band = 0;
6191
6192 if (freqs) {
6193 /* freqs are specified for the radio work */
6194 for (i = 0; freqs[i]; i++)
6195 band |= wpas_freq_to_band(freqs[i]);
6196 } else {
6197 /*
6198 * freqs are not specified, implies all
6199 * the supported freqs by HW
6200 */
6201 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6202 if (wpa_s->hw.modes[i].num_channels != 0) {
6203 if (wpa_s->hw.modes[i].mode ==
6204 HOSTAPD_MODE_IEEE80211B ||
6205 wpa_s->hw.modes[i].mode ==
6206 HOSTAPD_MODE_IEEE80211G)
6207 band |= BAND_2_4_GHZ;
6208 else if (wpa_s->hw.modes[i].mode ==
6209 HOSTAPD_MODE_IEEE80211A)
6210 band |= BAND_5_GHZ;
6211 else if (wpa_s->hw.modes[i].mode ==
6212 HOSTAPD_MODE_IEEE80211AD)
6213 band |= BAND_60_GHZ;
6214 else if (wpa_s->hw.modes[i].mode ==
6215 HOSTAPD_MODE_IEEE80211ANY)
6216 band = BAND_2_4_GHZ | BAND_5_GHZ |
6217 BAND_60_GHZ;
6218 }
6219 }
6220 }
6221
6222 return band;
6223}
6224
6225
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006226static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6227 const char *rn)
6228{
6229 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6230 struct wpa_radio *radio;
6231
6232 while (rn && iface) {
6233 radio = iface->radio;
6234 if (radio && os_strcmp(rn, radio->name) == 0) {
6235 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6236 wpa_s->ifname, rn);
6237 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6238 return radio;
6239 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006240
6241 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006242 }
6243
6244 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6245 wpa_s->ifname, rn ? rn : "N/A");
6246 radio = os_zalloc(sizeof(*radio));
6247 if (radio == NULL)
6248 return NULL;
6249
6250 if (rn)
6251 os_strlcpy(radio->name, rn, sizeof(radio->name));
6252 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006253 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006254 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6255
6256 return radio;
6257}
6258
6259
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006260static void radio_work_free(struct wpa_radio_work *work)
6261{
6262 if (work->wpa_s->scan_work == work) {
6263 /* This should not really happen. */
6264 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6265 work->type, work, work->started);
6266 work->wpa_s->scan_work = NULL;
6267 }
6268
6269#ifdef CONFIG_P2P
6270 if (work->wpa_s->p2p_scan_work == work) {
6271 /* This should not really happen. */
6272 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6273 work->type, work, work->started);
6274 work->wpa_s->p2p_scan_work = NULL;
6275 }
6276#endif /* CONFIG_P2P */
6277
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006278 if (work->started) {
6279 work->wpa_s->radio->num_active_works--;
6280 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006281 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006282 work->type, work,
6283 work->wpa_s->radio->num_active_works);
6284 }
6285
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006286 dl_list_del(&work->list);
6287 os_free(work);
6288}
6289
6290
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006291static int radio_work_is_connect(struct wpa_radio_work *work)
6292{
6293 return os_strcmp(work->type, "sme-connect") == 0 ||
6294 os_strcmp(work->type, "connect") == 0;
6295}
6296
6297
6298static int radio_work_is_scan(struct wpa_radio_work *work)
6299{
6300 return os_strcmp(work->type, "scan") == 0 ||
6301 os_strcmp(work->type, "p2p-scan") == 0;
6302}
6303
6304
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006305static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6306{
6307 struct wpa_radio_work *active_work = NULL;
6308 struct wpa_radio_work *tmp;
6309
6310 /* Get the active work to know the type and band. */
6311 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6312 if (tmp->started) {
6313 active_work = tmp;
6314 break;
6315 }
6316 }
6317
6318 if (!active_work) {
6319 /* No active work, start one */
6320 radio->num_active_works = 0;
6321 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6322 list) {
6323 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006324 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006325 (((struct wpa_driver_scan_params *)
6326 tmp->ctx)->only_new_results ||
6327 tmp->wpa_s->clear_driver_scan_cache))
6328 continue;
6329 return tmp;
6330 }
6331 return NULL;
6332 }
6333
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006334 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006335 /*
6336 * If the active work is either connect or sme-connect,
6337 * do not parallelize them with other radio works.
6338 */
6339 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6340 "Do not parallelize radio work with %s",
6341 active_work->type);
6342 return NULL;
6343 }
6344
6345 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6346 if (tmp->started)
6347 continue;
6348
6349 /*
6350 * If connect or sme-connect are enqueued, parallelize only
6351 * those operations ahead of them in the queue.
6352 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006353 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006354 break;
6355
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006356 /* Serialize parallel scan and p2p_scan operations on the same
6357 * interface since the driver_nl80211 mechanism for tracking
6358 * scan cookies does not yet have support for this. */
6359 if (active_work->wpa_s == tmp->wpa_s &&
6360 radio_work_is_scan(active_work) &&
6361 radio_work_is_scan(tmp)) {
6362 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6363 "Do not start work '%s' when another work '%s' is already scheduled",
6364 tmp->type, active_work->type);
6365 continue;
6366 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006367 /*
6368 * Check that the radio works are distinct and
6369 * on different bands.
6370 */
6371 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6372 (active_work->bands != tmp->bands)) {
6373 /*
6374 * If a scan has to be scheduled through nl80211 scan
6375 * interface and if an external scan is already running,
6376 * do not schedule the scan since it is likely to get
6377 * rejected by kernel.
6378 */
6379 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006380 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006381 (((struct wpa_driver_scan_params *)
6382 tmp->ctx)->only_new_results ||
6383 tmp->wpa_s->clear_driver_scan_cache))
6384 continue;
6385
6386 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6387 "active_work:%s new_work:%s",
6388 active_work->type, tmp->type);
6389 return tmp;
6390 }
6391 }
6392
6393 /* Did not find a radio work to schedule in parallel. */
6394 return NULL;
6395}
6396
6397
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006398static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6399{
6400 struct wpa_radio *radio = eloop_ctx;
6401 struct wpa_radio_work *work;
6402 struct os_reltime now, diff;
6403 struct wpa_supplicant *wpa_s;
6404
6405 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006406 if (work == NULL) {
6407 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006408 return;
6409 }
6410
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006411 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6412 radio_list);
6413
6414 if (!(wpa_s &&
6415 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6416 if (work->started)
6417 return; /* already started and still in progress */
6418
Hai Shalom60840252021-02-19 19:02:11 -08006419 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006420 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6421 return;
6422 }
6423 } else {
6424 work = NULL;
6425 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6426 /* get the work to schedule next */
6427 work = radio_work_get_next_work(radio);
6428 }
6429 if (!work)
6430 return;
6431 }
6432
6433 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006434 os_get_reltime(&now);
6435 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006436 wpa_dbg(wpa_s, MSG_DEBUG,
6437 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006438 work->type, work, diff.sec, diff.usec);
6439 work->started = 1;
6440 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006441 radio->num_active_works++;
6442
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006443 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006444
6445 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6446 radio->num_active_works < MAX_ACTIVE_WORKS)
6447 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006448}
6449
6450
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006451/*
6452 * This function removes both started and pending radio works running on
6453 * the provided interface's radio.
6454 * Prior to the removal of the radio work, its callback (cb) is called with
6455 * deinit set to be 1. Each work's callback is responsible for clearing its
6456 * internal data and restoring to a correct state.
6457 * @wpa_s: wpa_supplicant data
6458 * @type: type of works to be removed
6459 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6460 * this interface's works.
6461 */
6462void radio_remove_works(struct wpa_supplicant *wpa_s,
6463 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006464{
6465 struct wpa_radio_work *work, *tmp;
6466 struct wpa_radio *radio = wpa_s->radio;
6467
6468 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6469 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006470 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006471 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006472
6473 /* skip other ifaces' works */
6474 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006475 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006476
6477 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6478 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006479 work->cb(work, 1);
6480 radio_work_free(work);
6481 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006482
6483 /* in case we removed the started work */
6484 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006485}
6486
6487
Roshan Pius3a1667e2018-07-03 15:17:14 -07006488void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6489{
6490 struct wpa_radio_work *work;
6491 struct wpa_radio *radio = wpa_s->radio;
6492
6493 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6494 if (work->ctx != ctx)
6495 continue;
6496 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6497 work->type, work, work->started ? " (started)" : "");
6498 radio_work_free(work);
6499 break;
6500 }
6501}
6502
6503
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006504static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6505{
6506 struct wpa_radio *radio = wpa_s->radio;
6507
6508 if (!radio)
6509 return;
6510
6511 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6512 wpa_s->ifname, radio->name);
6513 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006514 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006515 /* If the interface that triggered the external scan was removed, the
6516 * external scan is no longer running. */
6517 if (wpa_s == radio->external_scan_req_interface)
6518 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006519 wpa_s->radio = NULL;
6520 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006521 return; /* Interfaces remain for this radio */
6522
6523 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006524 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006525 os_free(radio);
6526}
6527
6528
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006529void radio_work_check_next(struct wpa_supplicant *wpa_s)
6530{
6531 struct wpa_radio *radio = wpa_s->radio;
6532
6533 if (dl_list_empty(&radio->work))
6534 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006535 if (wpa_s->ext_work_in_progress) {
6536 wpa_printf(MSG_DEBUG,
6537 "External radio work in progress - delay start of pending item");
6538 return;
6539 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006540 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6541 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6542}
6543
6544
6545/**
6546 * radio_add_work - Add a radio work item
6547 * @wpa_s: Pointer to wpa_supplicant data
6548 * @freq: Frequency of the offchannel operation in MHz or 0
6549 * @type: Unique identifier for each type of work
6550 * @next: Force as the next work to be executed
6551 * @cb: Callback function for indicating when radio is available
6552 * @ctx: Context pointer for the work (work->ctx in cb())
6553 * Returns: 0 on success, -1 on failure
6554 *
6555 * This function is used to request time for an operation that requires
6556 * exclusive radio control. Once the radio is available, the registered callback
6557 * function will be called. radio_work_done() must be called once the exclusive
6558 * radio operation has been completed, so that the radio is freed for other
6559 * operations. The special case of deinit=1 is used to free the context data
6560 * during interface removal. That does not allow the callback function to start
6561 * the radio operation, i.e., it must free any resources allocated for the radio
6562 * work and return.
6563 *
6564 * The @freq parameter can be used to indicate a single channel on which the
6565 * offchannel operation will occur. This may allow multiple radio work
6566 * operations to be performed in parallel if they apply for the same channel.
6567 * Setting this to 0 indicates that the work item may use multiple channels or
6568 * requires exclusive control of the radio.
6569 */
6570int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6571 const char *type, int next,
6572 void (*cb)(struct wpa_radio_work *work, int deinit),
6573 void *ctx)
6574{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006575 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006576 struct wpa_radio_work *work;
6577 int was_empty;
6578
6579 work = os_zalloc(sizeof(*work));
6580 if (work == NULL)
6581 return -1;
6582 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6583 os_get_reltime(&work->time);
6584 work->freq = freq;
6585 work->type = type;
6586 work->wpa_s = wpa_s;
6587 work->cb = cb;
6588 work->ctx = ctx;
6589
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006590 if (freq)
6591 work->bands = wpas_freq_to_band(freq);
6592 else if (os_strcmp(type, "scan") == 0 ||
6593 os_strcmp(type, "p2p-scan") == 0)
6594 work->bands = wpas_get_bands(wpa_s,
6595 ((struct wpa_driver_scan_params *)
6596 ctx)->freqs);
6597 else
6598 work->bands = wpas_get_bands(wpa_s, NULL);
6599
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006600 was_empty = dl_list_empty(&wpa_s->radio->work);
6601 if (next)
6602 dl_list_add(&wpa_s->radio->work, &work->list);
6603 else
6604 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6605 if (was_empty) {
6606 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6607 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006608 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6609 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6610 wpa_dbg(wpa_s, MSG_DEBUG,
6611 "Try to schedule a radio work (num_active_works=%u)",
6612 radio->num_active_works);
6613 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006614 }
6615
6616 return 0;
6617}
6618
6619
6620/**
6621 * radio_work_done - Indicate that a radio work item has been completed
6622 * @work: Completed work
6623 *
6624 * This function is called once the callback function registered with
6625 * radio_add_work() has completed its work.
6626 */
6627void radio_work_done(struct wpa_radio_work *work)
6628{
6629 struct wpa_supplicant *wpa_s = work->wpa_s;
6630 struct os_reltime now, diff;
6631 unsigned int started = work->started;
6632
6633 os_get_reltime(&now);
6634 os_reltime_sub(&now, &work->time, &diff);
6635 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6636 work->type, work, started ? "done" : "canceled",
6637 diff.sec, diff.usec);
6638 radio_work_free(work);
6639 if (started)
6640 radio_work_check_next(wpa_s);
6641}
6642
6643
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006644struct wpa_radio_work *
6645radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006646{
6647 struct wpa_radio_work *work;
6648 struct wpa_radio *radio = wpa_s->radio;
6649
6650 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6651 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006652 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006653 }
6654
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006655 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006656}
6657
6658
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006659static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006660 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006661{
6662 const char *ifname, *driver, *rn;
6663
6664 driver = iface->driver;
6665next_driver:
6666 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6667 return -1;
6668
6669 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6670 if (wpa_s->drv_priv == NULL) {
6671 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006672 int level = MSG_ERROR;
6673
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006674 pos = driver ? os_strchr(driver, ',') : NULL;
6675 if (pos) {
6676 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6677 "driver interface - try next driver wrapper");
6678 driver = pos + 1;
6679 goto next_driver;
6680 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006681
6682#ifdef CONFIG_MATCH_IFACE
6683 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6684 level = MSG_DEBUG;
6685#endif /* CONFIG_MATCH_IFACE */
6686 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006687 return -1;
6688 }
6689 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6690 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6691 "driver_param '%s'", wpa_s->conf->driver_param);
6692 return -1;
6693 }
6694
6695 ifname = wpa_drv_get_ifname(wpa_s);
6696 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6697 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6698 "interface name with '%s'", ifname);
6699 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6700 }
6701
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006702 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006703 if (rn && rn[0] == '\0')
6704 rn = NULL;
6705
6706 wpa_s->radio = radio_add_interface(wpa_s, rn);
6707 if (wpa_s->radio == NULL)
6708 return -1;
6709
6710 return 0;
6711}
6712
6713
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006714#ifdef CONFIG_GAS_SERVER
6715
6716static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6717 unsigned int freq, const u8 *dst,
6718 const u8 *src, const u8 *bssid,
6719 const u8 *data, size_t data_len,
6720 enum offchannel_send_action_result result)
6721{
6722 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6723 " result=%s",
6724 freq, MAC2STR(dst),
6725 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6726 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6727 "FAILED"));
6728 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6729 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6730}
6731
6732
6733static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6734 struct wpabuf *buf, unsigned int wait_time)
6735{
6736 struct wpa_supplicant *wpa_s = ctx;
6737 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6738
6739 if (wait_time > wpa_s->max_remain_on_chan)
6740 wait_time = wpa_s->max_remain_on_chan;
6741
6742 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6743 wpabuf_head(buf), wpabuf_len(buf),
6744 wait_time, wpas_gas_server_tx_status, 0);
6745}
6746
6747#endif /* CONFIG_GAS_SERVER */
6748
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006749static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006750 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006751{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006752 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006753 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006754 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006755
6756 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6757 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6758 iface->confname ? iface->confname : "N/A",
6759 iface->driver ? iface->driver : "default",
6760 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6761 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6762
6763 if (iface->confname) {
6764#ifdef CONFIG_BACKEND_FILE
6765 wpa_s->confname = os_rel2abs_path(iface->confname);
6766 if (wpa_s->confname == NULL) {
6767 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6768 "for configuration file '%s'.",
6769 iface->confname);
6770 return -1;
6771 }
6772 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6773 iface->confname, wpa_s->confname);
6774#else /* CONFIG_BACKEND_FILE */
6775 wpa_s->confname = os_strdup(iface->confname);
6776#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006777 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006778 if (wpa_s->conf == NULL) {
6779 wpa_printf(MSG_ERROR, "Failed to read or parse "
6780 "configuration '%s'.", wpa_s->confname);
6781 return -1;
6782 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006783 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006784 if (wpa_s->confanother &&
6785 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6786 wpa_printf(MSG_ERROR,
6787 "Failed to read or parse configuration '%s'.",
6788 wpa_s->confanother);
6789 return -1;
6790 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006791
6792 /*
6793 * Override ctrl_interface and driver_param if set on command
6794 * line.
6795 */
6796 if (iface->ctrl_interface) {
6797 os_free(wpa_s->conf->ctrl_interface);
6798 wpa_s->conf->ctrl_interface =
6799 os_strdup(iface->ctrl_interface);
6800 }
6801
6802 if (iface->driver_param) {
6803 os_free(wpa_s->conf->driver_param);
6804 wpa_s->conf->driver_param =
6805 os_strdup(iface->driver_param);
6806 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006807
6808 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6809 os_free(wpa_s->conf->ctrl_interface);
6810 wpa_s->conf->ctrl_interface = NULL;
6811 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006812 } else
6813 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6814 iface->driver_param);
6815
6816 if (wpa_s->conf == NULL) {
6817 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6818 return -1;
6819 }
6820
6821 if (iface->ifname == NULL) {
6822 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6823 return -1;
6824 }
6825 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6826 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6827 iface->ifname);
6828 return -1;
6829 }
6830 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006831#ifdef CONFIG_MATCH_IFACE
6832 wpa_s->matched = iface->matched;
6833#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006834
6835 if (iface->bridge_ifname) {
6836 if (os_strlen(iface->bridge_ifname) >=
6837 sizeof(wpa_s->bridge_ifname)) {
6838 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6839 "name '%s'.", iface->bridge_ifname);
6840 return -1;
6841 }
6842 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6843 sizeof(wpa_s->bridge_ifname));
6844 }
6845
6846 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006847 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6848 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006849
6850 /* Initialize driver interface and register driver event handler before
6851 * L2 receive handler so that association events are processed before
6852 * EAPOL-Key packets if both become available for the same select()
6853 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006854 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006855 return -1;
6856
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006857 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6858 return -1;
6859
6860 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6861 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6862 NULL);
6863 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6864
6865 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6866 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6867 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6868 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6869 "dot11RSNAConfigPMKLifetime");
6870 return -1;
6871 }
6872
6873 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6874 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6875 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6876 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6877 "dot11RSNAConfigPMKReauthThreshold");
6878 return -1;
6879 }
6880
6881 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6882 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6883 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6884 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6885 "dot11RSNAConfigSATimeout");
6886 return -1;
6887 }
6888
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006889 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6890 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006891 &wpa_s->hw.flags,
6892 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006893 if (wpa_s->hw.modes) {
6894 u16 i;
6895
6896 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6897 if (wpa_s->hw.modes[i].vht_capab) {
6898 wpa_s->hw_capab = CAPAB_VHT;
6899 break;
6900 }
6901
6902 if (wpa_s->hw.modes[i].ht_capab &
6903 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6904 wpa_s->hw_capab = CAPAB_HT40;
6905 else if (wpa_s->hw.modes[i].ht_capab &&
6906 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6907 wpa_s->hw_capab = CAPAB_HT;
6908 }
6909 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006910
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006911 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6912 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006913 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006914 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006915 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006916 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006917 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07006918 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006919 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006920 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006921 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006922 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6923 wpa_s->max_sched_scan_plan_interval =
6924 capa.max_sched_scan_plan_interval;
6925 wpa_s->max_sched_scan_plan_iterations =
6926 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006927 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6928 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006929 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6930 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006931 wpa_s->extended_capa = capa.extended_capa;
6932 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6933 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006934 wpa_s->num_multichan_concurrent =
6935 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006936 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07006937 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006938
6939 if (capa.mac_addr_rand_scan_supported)
6940 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6941 if (wpa_s->sched_scan_supported &&
6942 capa.mac_addr_rand_sched_scan_supported)
6943 wpa_s->mac_addr_rand_supported |=
6944 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006945
6946 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6947 if (wpa_s->extended_capa &&
6948 wpa_s->extended_capa_len >= 3 &&
6949 wpa_s->extended_capa[2] & 0x40)
6950 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006951 }
Sunil Ravi89eba102022-09-13 21:04:37 -07006952#ifdef CONFIG_PASN
6953 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
6954#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006955 if (wpa_s->max_remain_on_chan == 0)
6956 wpa_s->max_remain_on_chan = 1000;
6957
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006958 /*
6959 * Only take p2p_mgmt parameters when P2P Device is supported.
6960 * Doing it here as it determines whether l2_packet_init() will be done
6961 * during wpa_supplicant_driver_init().
6962 */
6963 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6964 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006965
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006966 if (wpa_s->num_multichan_concurrent == 0)
6967 wpa_s->num_multichan_concurrent = 1;
6968
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006969 if (wpa_supplicant_driver_init(wpa_s) < 0)
6970 return -1;
6971
6972#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006973 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006974 return -1;
6975#endif /* CONFIG_TDLS */
6976
6977 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6978 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6979 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6980 return -1;
6981 }
6982
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006983#ifdef CONFIG_FST
6984 if (wpa_s->conf->fst_group_id) {
6985 struct fst_iface_cfg cfg;
6986 struct fst_wpa_obj iface_obj;
6987
6988 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6989 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6990 sizeof(cfg.group_id));
6991 cfg.priority = wpa_s->conf->fst_priority;
6992 cfg.llt = wpa_s->conf->fst_llt;
6993
6994 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6995 &iface_obj, &cfg);
6996 if (!wpa_s->fst) {
6997 wpa_msg(wpa_s, MSG_ERROR,
6998 "FST: Cannot attach iface %s to group %s",
6999 wpa_s->ifname, cfg.group_id);
7000 return -1;
7001 }
7002 }
7003#endif /* CONFIG_FST */
7004
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007005 if (wpas_wps_init(wpa_s))
7006 return -1;
7007
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007008#ifdef CONFIG_GAS_SERVER
7009 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7010 if (!wpa_s->gas_server) {
7011 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7012 return -1;
7013 }
7014#endif /* CONFIG_GAS_SERVER */
7015
7016#ifdef CONFIG_DPP
7017 if (wpas_dpp_init(wpa_s) < 0)
7018 return -1;
7019#endif /* CONFIG_DPP */
7020
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007021 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7022 return -1;
7023 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7024
7025 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7026 if (wpa_s->ctrl_iface == NULL) {
7027 wpa_printf(MSG_ERROR,
7028 "Failed to initialize control interface '%s'.\n"
7029 "You may have another wpa_supplicant process "
7030 "already running or the file was\n"
7031 "left by an unclean termination of wpa_supplicant "
7032 "in which case you will need\n"
7033 "to manually remove this file before starting "
7034 "wpa_supplicant again.\n",
7035 wpa_s->conf->ctrl_interface);
7036 return -1;
7037 }
7038
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007039 wpa_s->gas = gas_query_init(wpa_s);
7040 if (wpa_s->gas == NULL) {
7041 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7042 return -1;
7043 }
7044
Roshan Pius3a1667e2018-07-03 15:17:14 -07007045 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7046 wpa_s->p2p_mgmt) &&
7047 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007048 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7049 return -1;
7050 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007051
7052 if (wpa_bss_init(wpa_s) < 0)
7053 return -1;
7054
Paul Stewart092955c2017-02-06 09:13:09 -08007055#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7056#ifdef CONFIG_MESH
7057 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7058#endif /* CONFIG_MESH */
7059#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7060
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007061 /*
7062 * Set Wake-on-WLAN triggers, if configured.
7063 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7064 * have effect anyway when the interface is down).
7065 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007066 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007067 return -1;
7068
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007069#ifdef CONFIG_EAP_PROXY
7070{
7071 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007072 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7073 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007074 if (wpa_s->mnc_len > 0) {
7075 wpa_s->imsi[len] = '\0';
7076 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7077 wpa_s->imsi, wpa_s->mnc_len);
7078 } else {
7079 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7080 }
7081}
7082#endif /* CONFIG_EAP_PROXY */
7083
Dmitry Shmidt04949592012-07-19 12:16:46 -07007084 if (pcsc_reader_init(wpa_s) < 0)
7085 return -1;
7086
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007087 if (wpas_init_ext_pw(wpa_s) < 0)
7088 return -1;
7089
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007090 wpas_rrm_reset(wpa_s);
7091
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007092 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7093
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007094#ifdef CONFIG_HS20
7095 hs20_init(wpa_s);
7096#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007097#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007098 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007099 if ((wpa_s->conf->oce & OCE_STA) &&
7100 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7101 wpa_s->enable_oce = OCE_STA;
7102 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7103 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7104 /* TODO: Need to add STA-CFON support */
7105 wpa_printf(MSG_ERROR,
7106 "OCE STA-CFON feature is not yet supported");
7107 }
7108 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007109 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7110#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007111
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007112 wpa_supplicant_set_default_scan_ies(wpa_s);
7113
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007114 return 0;
7115}
7116
7117
7118static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007119 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007120{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007121 struct wpa_global *global = wpa_s->global;
7122 struct wpa_supplicant *iface, *prev;
7123
Jimmy Chen0e73c002021-08-18 13:21:30 +08007124 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007125 wpas_p2p_group_remove(wpa_s, "*");
7126
7127 iface = global->ifaces;
7128 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007129 if (iface->p2pdev == wpa_s)
7130 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007131 if (iface == wpa_s || iface->parent != wpa_s) {
7132 iface = iface->next;
7133 continue;
7134 }
7135 wpa_printf(MSG_DEBUG,
7136 "Remove remaining child interface %s from parent %s",
7137 iface->ifname, wpa_s->ifname);
7138 prev = iface;
7139 iface = iface->next;
7140 wpa_supplicant_remove_iface(global, prev, terminate);
7141 }
7142
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007143 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007144 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007145 /*
7146 * Don't deauthenticate if WoWLAN is enable and not explicitly
7147 * been configured to disconnect.
7148 */
7149 if (!wpa_drv_get_wowlan(wpa_s) ||
7150 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007151 wpa_supplicant_deauthenticate(
7152 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007153
Hai Shalomfdcde762020-04-02 11:19:20 -07007154 wpa_drv_set_countermeasures(wpa_s, 0);
7155 wpa_clear_keys(wpa_s, NULL);
7156 } else {
7157 wpa_msg(wpa_s, MSG_INFO,
7158 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7159 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007160 }
7161
7162 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007163 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007164
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007165 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007166 radio_remove_interface(wpa_s);
7167
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007168#ifdef CONFIG_FST
7169 if (wpa_s->fst) {
7170 fst_detach(wpa_s->fst);
7171 wpa_s->fst = NULL;
7172 }
7173 if (wpa_s->received_mb_ies) {
7174 wpabuf_free(wpa_s->received_mb_ies);
7175 wpa_s->received_mb_ies = NULL;
7176 }
7177#endif /* CONFIG_FST */
7178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007179 if (wpa_s->drv_priv)
7180 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007181
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007182 if (notify)
7183 wpas_notify_iface_removed(wpa_s);
7184
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007185 if (terminate)
7186 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007187
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007188 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7189 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007190
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007191#ifdef CONFIG_MESH
7192 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007193 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007194 wpa_s->ifmsh = NULL;
7195 }
7196#endif /* CONFIG_MESH */
7197
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007198 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007199 wpa_config_free(wpa_s->conf);
7200 wpa_s->conf = NULL;
7201 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007202
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007203 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007204 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007205
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007206 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007207}
7208
7209
Dmitry Shmidte4663042016-04-04 10:07:49 -07007210#ifdef CONFIG_MATCH_IFACE
7211
7212/**
7213 * wpa_supplicant_match_iface - Match an interface description to a name
7214 * @global: Pointer to global data from wpa_supplicant_init()
7215 * @ifname: Name of the interface to match
7216 * Returns: Pointer to the created interface description or %NULL on failure
7217 */
7218struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7219 const char *ifname)
7220{
7221 int i;
7222 struct wpa_interface *iface, *miface;
7223
7224 for (i = 0; i < global->params.match_iface_count; i++) {
7225 miface = &global->params.match_ifaces[i];
7226 if (!miface->ifname ||
7227 fnmatch(miface->ifname, ifname, 0) == 0) {
7228 iface = os_zalloc(sizeof(*iface));
7229 if (!iface)
7230 return NULL;
7231 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007232 if (!miface->ifname)
7233 iface->matched = WPA_IFACE_MATCHED_NULL;
7234 else
7235 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007236 iface->ifname = ifname;
7237 return iface;
7238 }
7239 }
7240
7241 return NULL;
7242}
7243
7244
7245/**
7246 * wpa_supplicant_match_existing - Match existing interfaces
7247 * @global: Pointer to global data from wpa_supplicant_init()
7248 * Returns: 0 on success, -1 on failure
7249 */
7250static int wpa_supplicant_match_existing(struct wpa_global *global)
7251{
7252 struct if_nameindex *ifi, *ifp;
7253 struct wpa_supplicant *wpa_s;
7254 struct wpa_interface *iface;
7255
7256 ifp = if_nameindex();
7257 if (!ifp) {
7258 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7259 return -1;
7260 }
7261
7262 for (ifi = ifp; ifi->if_name; ifi++) {
7263 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7264 if (wpa_s)
7265 continue;
7266 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7267 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007268 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007269 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007270 }
7271 }
7272
7273 if_freenameindex(ifp);
7274 return 0;
7275}
7276
7277#endif /* CONFIG_MATCH_IFACE */
7278
7279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007280/**
7281 * wpa_supplicant_add_iface - Add a new network interface
7282 * @global: Pointer to global data from wpa_supplicant_init()
7283 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007284 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007285 * Returns: Pointer to the created interface or %NULL on failure
7286 *
7287 * This function is used to add new network interfaces for %wpa_supplicant.
7288 * This can be called before wpa_supplicant_run() to add interfaces before the
7289 * main event loop has been started. In addition, new interfaces can be added
7290 * dynamically while %wpa_supplicant is already running. This could happen,
7291 * e.g., when a hotplug network adapter is inserted.
7292 */
7293struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007294 struct wpa_interface *iface,
7295 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007296{
7297 struct wpa_supplicant *wpa_s;
7298 struct wpa_interface t_iface;
7299 struct wpa_ssid *ssid;
7300
7301 if (global == NULL || iface == NULL)
7302 return NULL;
7303
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007304 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007305 if (wpa_s == NULL)
7306 return NULL;
7307
7308 wpa_s->global = global;
7309
7310 t_iface = *iface;
7311 if (global->params.override_driver) {
7312 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7313 "('%s' -> '%s')",
7314 iface->driver, global->params.override_driver);
7315 t_iface.driver = global->params.override_driver;
7316 }
7317 if (global->params.override_ctrl_interface) {
7318 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7319 "ctrl_interface ('%s' -> '%s')",
7320 iface->ctrl_interface,
7321 global->params.override_ctrl_interface);
7322 t_iface.ctrl_interface =
7323 global->params.override_ctrl_interface;
7324 }
7325 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7326 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7327 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007328 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007329 return NULL;
7330 }
7331
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007332 /* Notify the control interfaces about new iface */
7333 if (wpas_notify_iface_added(wpa_s)) {
7334 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7335 return NULL;
7336 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007337
Jimmy Chene2206be2022-07-10 10:25:21 +08007338 /* Notify the control interfaces about new networks */
7339 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7340 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007341 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007342 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7343 && os_strncmp((const char *) ssid->ssid,
7344 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7345 wpas_notify_persistent_group_added(wpa_s, ssid);
7346 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007347 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007348
7349 wpa_s->next = global->ifaces;
7350 global->ifaces = wpa_s;
7351
7352 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007353 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007354
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007355#ifdef CONFIG_P2P
7356 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007357 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007358 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007359 wpas_p2p_add_p2pdev_interface(
7360 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007361 wpa_printf(MSG_INFO,
7362 "P2P: Failed to enable P2P Device interface");
7363 /* Try to continue without. P2P will be disabled. */
7364 }
7365#endif /* CONFIG_P2P */
7366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007367 return wpa_s;
7368}
7369
7370
7371/**
7372 * wpa_supplicant_remove_iface - Remove a network interface
7373 * @global: Pointer to global data from wpa_supplicant_init()
7374 * @wpa_s: Pointer to the network interface to be removed
7375 * Returns: 0 if interface was removed, -1 if interface was not found
7376 *
7377 * This function can be used to dynamically remove network interfaces from
7378 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7379 * addition, this function is used to remove all remaining interfaces when
7380 * %wpa_supplicant is terminated.
7381 */
7382int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007383 struct wpa_supplicant *wpa_s,
7384 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007385{
7386 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007387#ifdef CONFIG_MESH
7388 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7389 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007390 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007391#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007392
7393 /* Remove interface from the global list of interfaces */
7394 prev = global->ifaces;
7395 if (prev == wpa_s) {
7396 global->ifaces = wpa_s->next;
7397 } else {
7398 while (prev && prev->next != wpa_s)
7399 prev = prev->next;
7400 if (prev == NULL)
7401 return -1;
7402 prev->next = wpa_s->next;
7403 }
7404
7405 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7406
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007407#ifdef CONFIG_MESH
7408 if (mesh_if_created) {
7409 ifname = os_strdup(wpa_s->ifname);
7410 if (ifname == NULL) {
7411 wpa_dbg(wpa_s, MSG_ERROR,
7412 "mesh: Failed to malloc ifname");
7413 return -1;
7414 }
7415 }
7416#endif /* CONFIG_MESH */
7417
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007418 if (global->p2p_group_formation == wpa_s)
7419 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007420 if (global->p2p_invite_group == wpa_s)
7421 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007422 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007423
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007424#ifdef CONFIG_MESH
7425 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007426 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007427 os_free(ifname);
7428 }
7429#endif /* CONFIG_MESH */
7430
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007431 return 0;
7432}
7433
7434
7435/**
7436 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7437 * @wpa_s: Pointer to the network interface
7438 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7439 */
7440const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7441{
7442 const char *eapol_method;
7443
7444 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7445 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7446 return "NO-EAP";
7447 }
7448
7449 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7450 if (eapol_method == NULL)
7451 return "UNKNOWN-EAP";
7452
7453 return eapol_method;
7454}
7455
7456
7457/**
7458 * wpa_supplicant_get_iface - Get a new network interface
7459 * @global: Pointer to global data from wpa_supplicant_init()
7460 * @ifname: Interface name
7461 * Returns: Pointer to the interface or %NULL if not found
7462 */
7463struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7464 const char *ifname)
7465{
7466 struct wpa_supplicant *wpa_s;
7467
7468 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7469 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7470 return wpa_s;
7471 }
7472 return NULL;
7473}
7474
7475
7476#ifndef CONFIG_NO_WPA_MSG
7477static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7478{
7479 struct wpa_supplicant *wpa_s = ctx;
7480 if (wpa_s == NULL)
7481 return NULL;
7482 return wpa_s->ifname;
7483}
7484#endif /* CONFIG_NO_WPA_MSG */
7485
7486
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007487#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7488#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7489#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7490
7491/* Periodic cleanup tasks */
7492static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7493{
7494 struct wpa_global *global = eloop_ctx;
7495 struct wpa_supplicant *wpa_s;
7496
7497 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7498 wpas_periodic, global, NULL);
7499
7500#ifdef CONFIG_P2P
7501 if (global->p2p)
7502 p2p_expire_peers(global->p2p);
7503#endif /* CONFIG_P2P */
7504
7505 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7506 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7507#ifdef CONFIG_AP
7508 ap_periodic(wpa_s);
7509#endif /* CONFIG_AP */
7510 }
7511}
7512
7513
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007514/**
7515 * wpa_supplicant_init - Initialize %wpa_supplicant
7516 * @params: Parameters for %wpa_supplicant
7517 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7518 *
7519 * This function is used to initialize %wpa_supplicant. After successful
7520 * initialization, the returned data pointer can be used to add and remove
7521 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7522 */
7523struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7524{
7525 struct wpa_global *global;
7526 int ret, i;
7527
7528 if (params == NULL)
7529 return NULL;
7530
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007531#ifdef CONFIG_DRIVER_NDIS
7532 {
7533 void driver_ndis_init_ops(void);
7534 driver_ndis_init_ops();
7535 }
7536#endif /* CONFIG_DRIVER_NDIS */
7537
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007538#ifndef CONFIG_NO_WPA_MSG
7539 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7540#endif /* CONFIG_NO_WPA_MSG */
7541
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007542 if (params->wpa_debug_file_path)
7543 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007544 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007545 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007546 if (params->wpa_debug_syslog)
7547 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007548 if (params->wpa_debug_tracing) {
7549 ret = wpa_debug_open_linux_tracing();
7550 if (ret) {
7551 wpa_printf(MSG_ERROR,
7552 "Failed to enable trace logging");
7553 return NULL;
7554 }
7555 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007556
7557 ret = eap_register_methods();
7558 if (ret) {
7559 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7560 if (ret == -2)
7561 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7562 "the same EAP type.");
7563 return NULL;
7564 }
7565
7566 global = os_zalloc(sizeof(*global));
7567 if (global == NULL)
7568 return NULL;
7569 dl_list_init(&global->p2p_srv_bonjour);
7570 dl_list_init(&global->p2p_srv_upnp);
7571 global->params.daemonize = params->daemonize;
7572 global->params.wait_for_monitor = params->wait_for_monitor;
7573 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7574 if (params->pid_file)
7575 global->params.pid_file = os_strdup(params->pid_file);
7576 if (params->ctrl_interface)
7577 global->params.ctrl_interface =
7578 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007579 if (params->ctrl_interface_group)
7580 global->params.ctrl_interface_group =
7581 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007582 if (params->override_driver)
7583 global->params.override_driver =
7584 os_strdup(params->override_driver);
7585 if (params->override_ctrl_interface)
7586 global->params.override_ctrl_interface =
7587 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007588#ifdef CONFIG_MATCH_IFACE
7589 global->params.match_iface_count = params->match_iface_count;
7590 if (params->match_iface_count) {
7591 global->params.match_ifaces =
7592 os_calloc(params->match_iface_count,
7593 sizeof(struct wpa_interface));
7594 os_memcpy(global->params.match_ifaces,
7595 params->match_ifaces,
7596 params->match_iface_count *
7597 sizeof(struct wpa_interface));
7598 }
7599#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007600#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007601 if (params->conf_p2p_dev)
7602 global->params.conf_p2p_dev =
7603 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007604#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007605 wpa_debug_level = global->params.wpa_debug_level =
7606 params->wpa_debug_level;
7607 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7608 params->wpa_debug_show_keys;
7609 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7610 params->wpa_debug_timestamp;
7611
Hai Shalomfdcde762020-04-02 11:19:20 -07007612 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007613
7614 if (eloop_init()) {
7615 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7616 wpa_supplicant_deinit(global);
7617 return NULL;
7618 }
7619
Jouni Malinen75ecf522011-06-27 15:19:46 -07007620 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007621
7622 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7623 if (global->ctrl_iface == NULL) {
7624 wpa_supplicant_deinit(global);
7625 return NULL;
7626 }
7627
7628 if (wpas_notify_supplicant_initialized(global)) {
7629 wpa_supplicant_deinit(global);
7630 return NULL;
7631 }
7632
7633 for (i = 0; wpa_drivers[i]; i++)
7634 global->drv_count++;
7635 if (global->drv_count == 0) {
7636 wpa_printf(MSG_ERROR, "No drivers enabled");
7637 wpa_supplicant_deinit(global);
7638 return NULL;
7639 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007640 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007641 if (global->drv_priv == NULL) {
7642 wpa_supplicant_deinit(global);
7643 return NULL;
7644 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007645
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007646#ifdef CONFIG_WIFI_DISPLAY
7647 if (wifi_display_init(global) < 0) {
7648 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7649 wpa_supplicant_deinit(global);
7650 return NULL;
7651 }
7652#endif /* CONFIG_WIFI_DISPLAY */
7653
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007654 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7655 wpas_periodic, global, NULL);
7656
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007657 return global;
7658}
7659
7660
7661/**
7662 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7663 * @global: Pointer to global data from wpa_supplicant_init()
7664 * Returns: 0 after successful event loop run, -1 on failure
7665 *
7666 * This function starts the main event loop and continues running as long as
7667 * there are any remaining events. In most cases, this function is running as
7668 * long as the %wpa_supplicant process in still in use.
7669 */
7670int wpa_supplicant_run(struct wpa_global *global)
7671{
7672 struct wpa_supplicant *wpa_s;
7673
7674 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007675 (wpa_supplicant_daemon(global->params.pid_file) ||
7676 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007677 return -1;
7678
Dmitry Shmidte4663042016-04-04 10:07:49 -07007679#ifdef CONFIG_MATCH_IFACE
7680 if (wpa_supplicant_match_existing(global))
7681 return -1;
7682#endif
7683
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007684 if (global->params.wait_for_monitor) {
7685 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007686 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007687 wpa_supplicant_ctrl_iface_wait(
7688 wpa_s->ctrl_iface);
7689 }
7690
7691 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7692 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7693
7694 eloop_run();
7695
7696 return 0;
7697}
7698
7699
7700/**
7701 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7702 * @global: Pointer to global data from wpa_supplicant_init()
7703 *
7704 * This function is called to deinitialize %wpa_supplicant and to free all
7705 * allocated resources. Remaining network interfaces will also be removed.
7706 */
7707void wpa_supplicant_deinit(struct wpa_global *global)
7708{
7709 int i;
7710
7711 if (global == NULL)
7712 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007713
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007714 eloop_cancel_timeout(wpas_periodic, global, NULL);
7715
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007716#ifdef CONFIG_WIFI_DISPLAY
7717 wifi_display_deinit(global);
7718#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007719
7720 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007721 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007722
7723 if (global->ctrl_iface)
7724 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7725
7726 wpas_notify_supplicant_deinitialized(global);
7727
7728 eap_peer_unregister_methods();
7729#ifdef CONFIG_AP
7730 eap_server_unregister_methods();
7731#endif /* CONFIG_AP */
7732
7733 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7734 if (!global->drv_priv[i])
7735 continue;
7736 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7737 }
7738 os_free(global->drv_priv);
7739
7740 random_deinit();
7741
7742 eloop_destroy();
7743
7744 if (global->params.pid_file) {
7745 os_daemonize_terminate(global->params.pid_file);
7746 os_free(global->params.pid_file);
7747 }
7748 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007749 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007750 os_free(global->params.override_driver);
7751 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007752#ifdef CONFIG_MATCH_IFACE
7753 os_free(global->params.match_ifaces);
7754#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007755#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007756 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007757#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007758
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007759 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007760 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007761 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007762
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007763 os_free(global);
7764 wpa_debug_close_syslog();
7765 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007766 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007767}
7768
7769
7770void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7771{
7772 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7773 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7774 char country[3];
7775 country[0] = wpa_s->conf->country[0];
7776 country[1] = wpa_s->conf->country[1];
7777 country[2] = '\0';
7778 if (wpa_drv_set_country(wpa_s, country) < 0) {
7779 wpa_printf(MSG_ERROR, "Failed to set country code "
7780 "'%s'", country);
7781 }
7782 }
7783
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007784 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7785 wpas_init_ext_pw(wpa_s);
7786
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007787 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7788 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7789
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007790 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7791 struct wpa_driver_capa capa;
7792 int res = wpa_drv_get_capa(wpa_s, &capa);
7793
7794 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7795 wpa_printf(MSG_ERROR,
7796 "Failed to update wowlan_triggers to '%s'",
7797 wpa_s->conf->wowlan_triggers);
7798 }
7799
Hai Shalom81f62d82019-07-22 12:10:00 -07007800 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7801 wpa_supplicant_set_default_scan_ies(wpa_s);
7802
Hai Shalom899fcc72020-10-19 14:38:18 -07007803#ifdef CONFIG_BGSCAN
7804 /*
7805 * We default to global bgscan parameters only when per-network bgscan
7806 * parameters aren't set. Only bother resetting bgscan parameters if
7807 * this is the case.
7808 */
7809 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7810 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7811 wpa_s->wpa_state == WPA_COMPLETED)
7812 wpa_supplicant_reset_bgscan(wpa_s);
7813#endif /* CONFIG_BGSCAN */
7814
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007815#ifdef CONFIG_WPS
7816 wpas_wps_update_config(wpa_s);
7817#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007818 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007819 wpa_s->conf->changed_parameters = 0;
7820}
7821
7822
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007823void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007824{
7825 int i;
7826
7827 for (i = 0; i < *num_freqs; i++) {
7828 if (freqs[i] == freq)
7829 return;
7830 }
7831
7832 freqs[*num_freqs] = freq;
7833 (*num_freqs)++;
7834}
7835
7836
7837static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7838{
7839 struct wpa_bss *bss, *cbss;
7840 const int max_freqs = 10;
7841 int *freqs;
7842 int num_freqs = 0;
7843
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007844 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007845 if (freqs == NULL)
7846 return NULL;
7847
7848 cbss = wpa_s->current_bss;
7849
7850 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7851 if (bss == cbss)
7852 continue;
7853 if (bss->ssid_len == cbss->ssid_len &&
7854 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007855 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007856 add_freq(freqs, &num_freqs, bss->freq);
7857 if (num_freqs == max_freqs)
7858 break;
7859 }
7860 }
7861
7862 if (num_freqs == 0) {
7863 os_free(freqs);
7864 freqs = NULL;
7865 }
7866
7867 return freqs;
7868}
7869
7870
7871void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7872{
7873 int timeout;
7874 int count;
7875 int *freqs = NULL;
7876
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007877 wpas_connect_work_done(wpa_s);
7878
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007879 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007880 * Remove possible authentication timeout since the connection failed.
7881 */
7882 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7883
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007884 /*
Hai Shalom60840252021-02-19 19:02:11 -08007885 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007886 * generated based on local request to disconnect.
7887 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007888 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007889 wpa_s->own_disconnect_req = 0;
7890 wpa_dbg(wpa_s, MSG_DEBUG,
7891 "Ignore connection failure due to local request to disconnect");
7892 return;
7893 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007894 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007895 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7896 "indication since interface has been put into "
7897 "disconnected state");
7898 return;
7899 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007900 if (wpa_s->auto_reconnect_disabled) {
7901 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7902 "indication since auto connect is disabled");
7903 return;
7904 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007905
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007906 /*
Hai Shalom60840252021-02-19 19:02:11 -08007907 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007908 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007909 */
Hai Shalom60840252021-02-19 19:02:11 -08007910 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007911 if (count == 1 && wpa_s->current_bss) {
7912 /*
Hai Shalom60840252021-02-19 19:02:11 -08007913 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007914 * another BSS available for the same ESS, we should try that
7915 * next. Otherwise, we may as well try this one once more
7916 * before allowing other, likely worse, ESSes to be considered.
7917 */
7918 freqs = get_bss_freqs_in_ess(wpa_s);
7919 if (freqs) {
7920 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7921 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007922 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007923 /*
7924 * On the next scan, go through only the known channels
7925 * used in this ESS based on previous scans to speed up
7926 * common load balancing use case.
7927 */
7928 os_free(wpa_s->next_scan_freqs);
7929 wpa_s->next_scan_freqs = freqs;
7930 }
7931 }
7932
Hai Shalom899fcc72020-10-19 14:38:18 -07007933 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007934
Hai Shalom899fcc72020-10-19 14:38:18 -07007935 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007936 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7937 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007938 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007939 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007940 /*
7941 * Multiple consecutive connection failures mean that other APs are
7942 * either not available or have already been tried, so we can start
7943 * increasing the delay here to avoid constant scanning.
7944 */
7945 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007946 case 1:
7947 timeout = 100;
7948 break;
7949 case 2:
7950 timeout = 500;
7951 break;
7952 case 3:
7953 timeout = 1000;
7954 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007955 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007956 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007957 break;
7958 default:
7959 timeout = 10000;
7960 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007961 }
7962
Hai Shalom899fcc72020-10-19 14:38:18 -07007963 wpa_dbg(wpa_s, MSG_DEBUG,
7964 "Consecutive connection failures: %d --> request scan in %d ms",
7965 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007967 /*
7968 * TODO: if more than one possible AP is available in scan results,
7969 * could try the other ones before requesting a new scan.
7970 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007971
7972 /* speed up the connection attempt with normal scan */
7973 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007974 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7975 1000 * (timeout % 1000));
7976}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007977
7978
Hai Shalomce48b4a2018-09-05 11:41:35 -07007979#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08007980
7981void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
7982{
7983 struct wpa_ssid *ssid = wpa_s->current_ssid;
7984 const u8 *realm, *username, *rrk;
7985 size_t realm_len, username_len, rrk_len;
7986 u16 next_seq_num;
7987
7988 /* Clear the PMKSA cache entry if FILS authentication was rejected.
7989 * Check for ERP keys existing to limit when this can be done since
7990 * the rejection response is not protected and such triggers should
7991 * really not allow internal state to be modified unless required to
7992 * avoid significant issues in functionality. In addition, drop
7993 * externally configure PMKSA entries even without ERP keys since it
7994 * is possible for an external component to add PMKSA entries for FILS
7995 * authentication without restoring previously generated ERP keys.
7996 *
7997 * In this case, this is needed to allow recovery from cases where the
7998 * AP or authentication server has dropped PMKSAs and ERP keys. */
7999 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
8000 return;
8001
8002 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8003 &username, &username_len,
8004 &realm, &realm_len, &next_seq_num,
8005 &rrk, &rrk_len) != 0 ||
8006 !realm) {
8007 wpa_dbg(wpa_s, MSG_DEBUG,
8008 "FILS: Drop external PMKSA cache entry");
8009 wpa_sm_aborted_external_cached(wpa_s->wpa);
8010 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8011 return;
8012 }
8013
8014 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8015 wpa_sm_aborted_cached(wpa_s->wpa);
8016 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8017}
8018
8019
Hai Shalomce48b4a2018-09-05 11:41:35 -07008020void fils_connection_failure(struct wpa_supplicant *wpa_s)
8021{
8022 struct wpa_ssid *ssid = wpa_s->current_ssid;
8023 const u8 *realm, *username, *rrk;
8024 size_t realm_len, username_len, rrk_len;
8025 u16 next_seq_num;
8026
8027 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8028 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8029 &username, &username_len,
8030 &realm, &realm_len, &next_seq_num,
8031 &rrk, &rrk_len) != 0 ||
8032 !realm)
8033 return;
8034
8035 wpa_hexdump_ascii(MSG_DEBUG,
8036 "FILS: Store last connection failure realm",
8037 realm, realm_len);
8038 os_free(wpa_s->last_con_fail_realm);
8039 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8040 if (wpa_s->last_con_fail_realm) {
8041 wpa_s->last_con_fail_realm_len = realm_len;
8042 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8043 }
8044}
8045#endif /* CONFIG_FILS */
8046
8047
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008048int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8049{
8050 return wpa_s->conf->ap_scan == 2 ||
8051 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8052}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008053
Dmitry Shmidt04949592012-07-19 12:16:46 -07008054
Gabriel Biren57ededa2021-09-03 16:08:50 +00008055#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008056int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8057 struct wpa_ssid *ssid,
8058 const char *field,
8059 const char *value)
8060{
8061#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008062 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008063
8064 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8065 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8066 (const u8 *) value, os_strlen(value));
8067
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008068 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008069 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008070#else /* IEEE8021X_EAPOL */
8071 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8072 return -1;
8073#endif /* IEEE8021X_EAPOL */
8074}
8075
8076int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8077 struct wpa_ssid *ssid,
8078 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008079 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008080{
8081#ifdef IEEE8021X_EAPOL
8082 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008083 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008084
8085 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008086 case WPA_CTRL_REQ_EAP_IDENTITY:
8087 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008088 os_free(eap->imsi_identity);
8089 if (value == NULL)
8090 return -1;
8091 identity = os_strchr(value, ':');
8092 if (identity == NULL) {
8093 /* plain identity */
8094 eap->identity = (u8 *)os_strdup(value);
8095 eap->identity_len = os_strlen(value);
8096 } else {
8097 /* have both plain identity and encrypted identity */
8098 imsi_identity = value;
8099 *identity++ = '\0';
8100 /* plain identity */
8101 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8102 eap->imsi_identity_len = strlen(imsi_identity);
8103 /* encrypted identity */
8104 eap->identity = (u8 *)dup_binstr(identity,
8105 value_len - strlen(imsi_identity) - 1);
8106 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8107 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008108 eap->pending_req_identity = 0;
8109 if (ssid == wpa_s->current_ssid)
8110 wpa_s->reassociate = 1;
8111 break;
8112 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008113 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008114 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07008115 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008116 eap->pending_req_password = 0;
8117 if (ssid == wpa_s->current_ssid)
8118 wpa_s->reassociate = 1;
8119 break;
8120 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008121 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008122 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07008123 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008124 eap->pending_req_new_password = 0;
8125 if (ssid == wpa_s->current_ssid)
8126 wpa_s->reassociate = 1;
8127 break;
8128 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008129 str_clear_free(eap->cert.pin);
8130 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008131 eap->pending_req_pin = 0;
8132 if (ssid == wpa_s->current_ssid)
8133 wpa_s->reassociate = 1;
8134 break;
8135 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008136 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008137 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07008138 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008139 os_free(eap->pending_req_otp);
8140 eap->pending_req_otp = NULL;
8141 eap->pending_req_otp_len = 0;
8142 break;
8143 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008144 str_clear_free(eap->cert.private_key_passwd);
8145 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008146 eap->pending_req_passphrase = 0;
8147 if (ssid == wpa_s->current_ssid)
8148 wpa_s->reassociate = 1;
8149 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008150 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008151 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008152 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008153 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008154 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008155 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8156 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8157 return -1;
8158 ssid->mem_only_psk = 1;
8159 if (ssid->passphrase)
8160 wpa_config_update_psk(ssid);
8161 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8162 wpa_supplicant_req_scan(wpa_s, 0, 0);
8163 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008164 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8165 if (eap->pending_ext_cert_check != PENDING_CHECK)
8166 return -1;
8167 if (os_strcmp(value, "good") == 0)
8168 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8169 else if (os_strcmp(value, "bad") == 0)
8170 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8171 else
8172 return -1;
8173 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008174 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008175 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008176 return -1;
8177 }
8178
8179 return 0;
8180#else /* IEEE8021X_EAPOL */
8181 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8182 return -1;
8183#endif /* IEEE8021X_EAPOL */
8184}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008185#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008186
8187
8188int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8189{
Hai Shalomfdcde762020-04-02 11:19:20 -07008190#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008191 int i;
8192 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008193#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008194
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008195 if (wpa_s->p2p_mgmt)
8196 return 1; /* no normal network profiles on p2p_mgmt interface */
8197
Dmitry Shmidt04949592012-07-19 12:16:46 -07008198 if (ssid == NULL)
8199 return 1;
8200
8201 if (ssid->disabled)
8202 return 1;
8203
Hai Shalomfdcde762020-04-02 11:19:20 -07008204#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008205 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008206 drv_enc = wpa_s->drv_enc;
8207 else
8208 drv_enc = (unsigned int) -1;
8209
8210 for (i = 0; i < NUM_WEP_KEYS; i++) {
8211 size_t len = ssid->wep_key_len[i];
8212 if (len == 0)
8213 continue;
8214 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8215 continue;
8216 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8217 continue;
8218 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8219 continue;
8220 return 1; /* invalid WEP key */
8221 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008222#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008223
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008224 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008225 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008226 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008227 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008228 return 1;
8229
Sunil Ravi89eba102022-09-13 21:04:37 -07008230#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008231#ifdef CRYPTO_RSA_OAEP_SHA256
8232 if (ssid->eap.imsi_privacy_cert) {
8233 struct crypto_rsa_key *key;
8234 bool failed = false;
8235
8236 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8237 if (!key)
8238 failed = true;
8239 crypto_rsa_key_free(key);
8240 if (failed) {
8241 wpa_printf(MSG_DEBUG,
8242 "Invalid imsi_privacy_cert (%s) - disable network",
8243 ssid->eap.imsi_privacy_cert);
8244 return 1;
8245 }
8246 }
8247#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008248#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008249
Dmitry Shmidt04949592012-07-19 12:16:46 -07008250 return 0;
8251}
8252
8253
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008254int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8255{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008256 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8257 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8258 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8259 /*
8260 * Driver does not support BIP -- ignore pmf=1 default
8261 * since the connection with PMF would fail and the
8262 * configuration does not require PMF to be enabled.
8263 */
8264 return NO_MGMT_FRAME_PROTECTION;
8265 }
8266
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008267 if (ssid &&
8268 (ssid->key_mgmt &
8269 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8270 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8271 /*
8272 * Do not use the default PMF value for non-RSN networks
8273 * since PMF is available only with RSN and pmf=2
8274 * configuration would otherwise prevent connections to
8275 * all open networks.
8276 */
8277 return NO_MGMT_FRAME_PROTECTION;
8278 }
8279
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008280 return wpa_s->conf->pmf;
8281 }
8282
8283 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008284}
8285
8286
Hai Shalomc1a21442022-02-04 13:43:00 -08008287int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8288{
8289 if (wpa_s->current_ssid == NULL ||
8290 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8291 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8292 return 0;
8293 return wpa_sm_pmf_enabled(wpa_s->wpa);
8294}
8295
8296
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008297int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008298{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008299 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008300 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008301 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008302 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008303 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008304}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008305
8306
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008307void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008308{
8309 struct wpa_ssid *ssid = wpa_s->current_ssid;
8310 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008311 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008312
8313 if (ssid == NULL) {
8314 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8315 "SSID block");
8316 return;
8317 }
8318
8319 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8320 return;
8321
8322 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008323
8324#ifdef CONFIG_P2P
8325 if (ssid->p2p_group &&
8326 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8327 /*
8328 * Skip the wait time since there is a short timeout on the
8329 * connection to a P2P group.
8330 */
8331 return;
8332 }
8333#endif /* CONFIG_P2P */
8334
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008335 if (ssid->auth_failures > 50)
8336 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008337 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008338 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008339 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008340 dur = 90;
8341 else if (ssid->auth_failures > 3)
8342 dur = 60;
8343 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008344 dur = 30;
8345 else if (ssid->auth_failures > 1)
8346 dur = 20;
8347 else
8348 dur = 10;
8349
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008350 if (ssid->auth_failures > 1 &&
8351 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8352 dur += os_random() % (ssid->auth_failures * 10);
8353
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008354 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008355 if (now.sec + dur <= ssid->disabled_until.sec)
8356 return;
8357
8358 ssid->disabled_until.sec = now.sec + dur;
8359
8360 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008361 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008362 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008363 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008364
8365 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8366 int msg_len = snprintf(NULL, 0, format_str,
8367 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8368 ssid->auth_failures, dur, reason) + 1;
8369 char *msg = os_malloc(msg_len);
Narasimha Rao PVSc28a5132022-12-02 18:36:38 +05308370 if (!msg)
8371 return;
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008372 snprintf(msg, msg_len, format_str,
8373 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8374 ssid->auth_failures, dur, reason);
8375 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8376 os_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008377}
8378
8379
8380void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8381 struct wpa_ssid *ssid, int clear_failures)
8382{
8383 if (ssid == NULL)
8384 return;
8385
8386 if (ssid->disabled_until.sec) {
8387 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8388 "id=%d ssid=\"%s\"",
8389 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8390 }
8391 ssid->disabled_until.sec = 0;
8392 ssid->disabled_until.usec = 0;
8393 if (clear_failures)
8394 ssid->auth_failures = 0;
8395}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008396
8397
8398int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8399{
8400 size_t i;
8401
8402 if (wpa_s->disallow_aps_bssid == NULL)
8403 return 0;
8404
8405 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8406 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8407 bssid, ETH_ALEN) == 0)
8408 return 1;
8409 }
8410
8411 return 0;
8412}
8413
8414
8415int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8416 size_t ssid_len)
8417{
8418 size_t i;
8419
8420 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8421 return 0;
8422
8423 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8424 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8425 if (ssid_len == s->ssid_len &&
8426 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8427 return 1;
8428 }
8429
8430 return 0;
8431}
8432
8433
8434/**
8435 * wpas_request_connection - Request a new connection
8436 * @wpa_s: Pointer to the network interface
8437 *
8438 * This function is used to request a new connection to be found. It will mark
8439 * the interface to allow reassociation and request a new scan to find a
8440 * suitable network to connect to.
8441 */
8442void wpas_request_connection(struct wpa_supplicant *wpa_s)
8443{
8444 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008445 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008446 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008447 wpa_s->disconnected = 0;
8448 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008449 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008450
8451 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8452 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008453 else
8454 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008455}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008456
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008457
Roshan Pius02242d72016-08-09 15:31:48 -07008458/**
8459 * wpas_request_disconnection - Request disconnection
8460 * @wpa_s: Pointer to the network interface
8461 *
8462 * This function is used to request disconnection from the currently connected
8463 * network. This will stop any ongoing scans and initiate deauthentication.
8464 */
8465void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8466{
8467#ifdef CONFIG_SME
8468 wpa_s->sme.prev_bssid_set = 0;
8469#endif /* CONFIG_SME */
8470 wpa_s->reassociate = 0;
8471 wpa_s->disconnected = 1;
8472 wpa_supplicant_cancel_sched_scan(wpa_s);
8473 wpa_supplicant_cancel_scan(wpa_s);
8474 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8475 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008476 radio_remove_works(wpa_s, "connect", 0);
8477 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008478 wpa_s->roam_in_progress = false;
8479#ifdef CONFIG_WNM
8480 wpa_s->bss_trans_mgmt_in_progress = false;
8481#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008482}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008483
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008484
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008485void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8486 struct wpa_used_freq_data *freqs_data,
8487 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008488{
8489 unsigned int i;
8490
8491 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8492 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008493 for (i = 0; i < len; i++) {
8494 struct wpa_used_freq_data *cur = &freqs_data[i];
8495 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8496 i, cur->freq, cur->flags);
8497 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008498}
8499
8500
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008501/*
8502 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008503 * are using the same radio as the current interface, and in addition, get
8504 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008505 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008506int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8507 struct wpa_used_freq_data *freqs_data,
8508 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008509{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008510 struct wpa_supplicant *ifs;
8511 u8 bssid[ETH_ALEN];
8512 int freq;
8513 unsigned int idx = 0, i;
8514
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008515 wpa_dbg(wpa_s, MSG_DEBUG,
8516 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008517 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008518
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008519 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8520 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008521 if (idx == len)
8522 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008523
8524 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8525 continue;
8526
8527 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008528 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8529 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008530 freq = ifs->current_ssid->frequency;
8531 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8532 freq = ifs->assoc_freq;
8533 else
8534 continue;
8535
8536 /* Hold only distinct freqs */
8537 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008538 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008539 break;
8540
8541 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008542 freqs_data[idx++].freq = freq;
8543
8544 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008545 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008546 WPA_FREQ_USED_BY_P2P_CLIENT :
8547 WPA_FREQ_USED_BY_INFRA_STATION;
8548 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008549 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008550
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008551 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008552 return idx;
8553}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008554
8555
8556/*
8557 * Find the operating frequencies of any of the virtual interfaces that
8558 * are using the same radio as the current interface.
8559 */
8560int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8561 int *freq_array, unsigned int len)
8562{
8563 struct wpa_used_freq_data *freqs_data;
8564 int num, i;
8565
8566 os_memset(freq_array, 0, sizeof(int) * len);
8567
8568 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8569 if (!freqs_data)
8570 return -1;
8571
8572 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8573 for (i = 0; i < num; i++)
8574 freq_array[i] = freqs_data[i].freq;
8575
8576 os_free(freqs_data);
8577
8578 return num;
8579}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008580
8581
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008582struct wpa_supplicant *
8583wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8584{
8585 switch (frame) {
8586#ifdef CONFIG_P2P
8587 case VENDOR_ELEM_PROBE_REQ_P2P:
8588 case VENDOR_ELEM_PROBE_RESP_P2P:
8589 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8590 case VENDOR_ELEM_BEACON_P2P_GO:
8591 case VENDOR_ELEM_P2P_PD_REQ:
8592 case VENDOR_ELEM_P2P_PD_RESP:
8593 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8594 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8595 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8596 case VENDOR_ELEM_P2P_INV_REQ:
8597 case VENDOR_ELEM_P2P_INV_RESP:
8598 case VENDOR_ELEM_P2P_ASSOC_REQ:
8599 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008600 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008601#endif /* CONFIG_P2P */
8602 default:
8603 return wpa_s;
8604 }
8605}
8606
8607
8608void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8609{
8610 unsigned int i;
8611 char buf[30];
8612
8613 wpa_printf(MSG_DEBUG, "Update vendor elements");
8614
8615 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8616 if (wpa_s->vendor_elem[i]) {
8617 int res;
8618
8619 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8620 if (!os_snprintf_error(sizeof(buf), res)) {
8621 wpa_hexdump_buf(MSG_DEBUG, buf,
8622 wpa_s->vendor_elem[i]);
8623 }
8624 }
8625 }
8626
8627#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008628 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008629 wpa_s->global->p2p &&
8630 !wpa_s->global->p2p_disabled)
8631 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8632#endif /* CONFIG_P2P */
8633}
8634
8635
8636int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8637 const u8 *elem, size_t len)
8638{
8639 u8 *ie, *end;
8640
8641 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8642 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8643
8644 for (; ie + 1 < end; ie += 2 + ie[1]) {
8645 if (ie + len > end)
8646 break;
8647 if (os_memcmp(ie, elem, len) != 0)
8648 continue;
8649
8650 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8651 wpabuf_free(wpa_s->vendor_elem[frame]);
8652 wpa_s->vendor_elem[frame] = NULL;
8653 } else {
8654 os_memmove(ie, ie + len, end - (ie + len));
8655 wpa_s->vendor_elem[frame]->used -= len;
8656 }
8657 wpas_vendor_elem_update(wpa_s);
8658 return 0;
8659 }
8660
8661 return -1;
8662}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008663
8664
8665struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008666 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008667 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008668{
8669 u16 i;
8670
Hai Shalomc1a21442022-02-04 13:43:00 -08008671 if (!modes)
8672 return NULL;
8673
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008674 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008675 if (modes[i].mode != mode ||
8676 !modes[i].num_channels || !modes[i].channels)
8677 continue;
8678 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8679 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008680 return &modes[i];
8681 }
8682
8683 return NULL;
8684}
8685
8686
Hai Shalomc1a21442022-02-04 13:43:00 -08008687struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8688 u16 num_modes, int freq)
8689{
8690 int i, j;
8691
8692 for (i = 0; i < num_modes; i++) {
8693 for (j = 0; j < modes[i].num_channels; j++) {
8694 if (freq == modes[i].channels[j].freq)
8695 return &modes[i];
8696 }
8697 }
8698
8699 return NULL;
8700}
8701
8702
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008703static struct
8704wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8705 const u8 *bssid)
8706{
8707 struct wpa_bss_tmp_disallowed *bss;
8708
8709 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8710 struct wpa_bss_tmp_disallowed, list) {
8711 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8712 return bss;
8713 }
8714
8715 return NULL;
8716}
8717
8718
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008719static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8720{
8721 struct wpa_bss_tmp_disallowed *tmp;
8722 unsigned int num_bssid = 0;
8723 u8 *bssids;
8724 int ret;
8725
8726 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8727 if (!bssids)
8728 return -1;
8729 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8730 struct wpa_bss_tmp_disallowed, list) {
8731 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8732 ETH_ALEN);
8733 num_bssid++;
8734 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008735 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008736 os_free(bssids);
8737 return ret;
8738}
8739
8740
8741static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8742{
8743 struct wpa_supplicant *wpa_s = eloop_ctx;
8744 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8745
8746 /* Make sure the bss is not already freed */
8747 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8748 struct wpa_bss_tmp_disallowed, list) {
8749 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008750 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008751 wpa_set_driver_tmp_disallow_list(wpa_s);
8752 break;
8753 }
8754 }
8755}
8756
8757
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008758void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008759 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008760{
8761 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008762
8763 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8764 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008765 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008766 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008767 }
8768
8769 bss = os_malloc(sizeof(*bss));
8770 if (!bss) {
8771 wpa_printf(MSG_DEBUG,
8772 "Failed to allocate memory for temp disallow BSS");
8773 return;
8774 }
8775
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008776 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8777 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008778 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008779
8780finish:
8781 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008782 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8783 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008784}
8785
8786
Hai Shalom74f70d42019-02-11 14:42:39 -08008787int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8788 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008789{
Hai Shalom74f70d42019-02-11 14:42:39 -08008790 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008791
8792 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8793 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008794 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8795 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008796 break;
8797 }
8798 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008799 if (!disallowed)
8800 return 0;
8801
8802 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008803 bss->level > disallowed->rssi_threshold) {
8804 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8805 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008806 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008807 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008808
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008809 return 1;
8810}
Hai Shalom81f62d82019-07-22 12:10:00 -07008811
8812
8813int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8814 unsigned int type, const u8 *addr,
8815 const u8 *mask)
8816{
8817 if ((addr && !mask) || (!addr && mask)) {
8818 wpa_printf(MSG_INFO,
8819 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8820 return -1;
8821 }
8822
8823 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8824 wpa_printf(MSG_INFO,
8825 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8826 return -1;
8827 }
8828
8829 if (type & MAC_ADDR_RAND_SCAN) {
8830 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8831 addr, mask))
8832 return -1;
8833 }
8834
8835 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8836 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8837 addr, mask))
8838 return -1;
8839
8840 if (wpa_s->sched_scanning && !wpa_s->pno)
8841 wpas_scan_restart_sched_scan(wpa_s);
8842 }
8843
8844 if (type & MAC_ADDR_RAND_PNO) {
8845 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8846 addr, mask))
8847 return -1;
8848
8849 if (wpa_s->pno) {
8850 wpas_stop_pno(wpa_s);
8851 wpas_start_pno(wpa_s);
8852 }
8853 }
8854
8855 return 0;
8856}
8857
8858
8859int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8860 unsigned int type)
8861{
8862 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8863 if (wpa_s->pno) {
8864 if (type & MAC_ADDR_RAND_PNO) {
8865 wpas_stop_pno(wpa_s);
8866 wpas_start_pno(wpa_s);
8867 }
8868 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8869 wpas_scan_restart_sched_scan(wpa_s);
8870 }
8871
8872 return 0;
8873}
Hai Shalomfdcde762020-04-02 11:19:20 -07008874
8875
8876int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8877 struct wpa_signal_info *si)
8878{
8879 int res;
8880
8881 if (!wpa_s->driver->signal_poll)
8882 return -1;
8883
8884 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8885
8886#ifdef CONFIG_TESTING_OPTIONS
8887 if (res == 0) {
8888 struct driver_signal_override *dso;
8889
8890 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8891 struct driver_signal_override, list) {
8892 if (os_memcmp(wpa_s->bssid, dso->bssid,
8893 ETH_ALEN) != 0)
8894 continue;
8895 wpa_printf(MSG_DEBUG,
8896 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8897 si->current_signal,
8898 dso->si_current_signal,
8899 si->avg_signal,
8900 dso->si_avg_signal,
8901 si->avg_beacon_signal,
8902 dso->si_avg_beacon_signal,
8903 si->current_noise,
8904 dso->si_current_noise);
8905 si->current_signal = dso->si_current_signal;
8906 si->avg_signal = dso->si_avg_signal;
8907 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8908 si->current_noise = dso->si_current_noise;
8909 break;
8910 }
8911 }
8912#endif /* CONFIG_TESTING_OPTIONS */
8913
8914 return res;
8915}
8916
8917
8918struct wpa_scan_results *
8919wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8920{
8921 struct wpa_scan_results *scan_res;
8922#ifdef CONFIG_TESTING_OPTIONS
8923 size_t idx;
8924#endif /* CONFIG_TESTING_OPTIONS */
8925
8926 if (!wpa_s->driver->get_scan_results2)
8927 return NULL;
8928
8929 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8930
8931#ifdef CONFIG_TESTING_OPTIONS
8932 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8933 struct driver_signal_override *dso;
8934 struct wpa_scan_res *res = scan_res->res[idx];
8935
8936 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8937 struct driver_signal_override, list) {
8938 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8939 continue;
8940 wpa_printf(MSG_DEBUG,
8941 "Override driver scan signal level %d->%d for "
8942 MACSTR,
8943 res->level, dso->scan_level,
8944 MAC2STR(res->bssid));
8945 res->flags |= WPA_SCAN_QUAL_INVALID;
8946 if (dso->scan_level < 0)
8947 res->flags |= WPA_SCAN_LEVEL_DBM;
8948 else
8949 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8950 res->level = dso->scan_level;
8951 break;
8952 }
8953 }
8954#endif /* CONFIG_TESTING_OPTIONS */
8955
8956 return scan_res;
8957}