blob: 56dd5b905e6ff07d6099b4e0e2451c41b7b0beee [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
Vinayak Yadawad14709082022-03-17 14:25:11 +05302034#ifdef CONFIG_DRIVER_NL80211_BRCM
2035 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) &&
2038 (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP)) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05302039 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
2040 wpa_dbg(wpa_s, MSG_INFO,
2041 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
2042 }
Sunil Ravif42be322022-11-04 03:31:21 +00002043#else
2044 if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
2045 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2046 wpas_update_allowed_key_mgmt(wpa_s, ssid);
Vinayak Yadawad14709082022-03-17 14:25:11 +05302047#endif /* CONFIG_DRIVER_NL80211_BRCM */
2048
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002049 return 0;
2050}
2051
2052
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002053static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
2054{
Hai Shalomc1a21442022-02-04 13:43:00 -08002055 bool scs = true, mscs = true;
2056
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002057 *pos = 0x00;
2058
2059 switch (idx) {
2060 case 0: /* Bits 0-7 */
2061 break;
2062 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002063 if (wpa_s->conf->coloc_intf_reporting) {
2064 /* Bit 13 - Collocated Interference Reporting */
2065 *pos |= 0x20;
2066 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002067 break;
2068 case 2: /* Bits 16-23 */
2069#ifdef CONFIG_WNM
2070 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07002071 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07002072 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002073#endif /* CONFIG_WNM */
2074 break;
2075 case 3: /* Bits 24-31 */
2076#ifdef CONFIG_WNM
2077 *pos |= 0x02; /* Bit 25 - SSID List */
2078#endif /* CONFIG_WNM */
2079#ifdef CONFIG_INTERWORKING
2080 if (wpa_s->conf->interworking)
2081 *pos |= 0x80; /* Bit 31 - Interworking */
2082#endif /* CONFIG_INTERWORKING */
2083 break;
2084 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002085#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07002086 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002087 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002088#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002089 break;
2090 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002091#ifdef CONFIG_HS20
2092 if (wpa_s->conf->hs20)
2093 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2094#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002095#ifdef CONFIG_MBO
2096 *pos |= 0x40; /* Bit 46 - WNM-Notification */
2097#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002098 break;
2099 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002100#ifdef CONFIG_TESTING_OPTIONS
2101 if (wpa_s->disable_scs_support)
2102 scs = false;
2103#endif /* CONFIG_TESTING_OPTIONS */
2104 if (scs)
2105 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002106 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002107 case 7: /* Bits 56-63 */
2108 break;
2109 case 8: /* Bits 64-71 */
2110 if (wpa_s->conf->ftm_responder)
2111 *pos |= 0x40; /* Bit 70 - FTM responder */
2112 if (wpa_s->conf->ftm_initiator)
2113 *pos |= 0x80; /* Bit 71 - FTM initiator */
2114 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002115 case 9: /* Bits 72-79 */
2116#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002117 if (!wpa_s->disable_fils)
2118 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002119#endif /* CONFIG_FILS */
2120 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07002121 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08002122#ifdef CONFIG_TESTING_OPTIONS
2123 if (wpa_s->disable_mscs_support)
2124 mscs = false;
2125#endif /* CONFIG_TESTING_OPTIONS */
2126 if (mscs)
2127 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07002128 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002129 }
2130}
2131
2132
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002133int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002134{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002135 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002136 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002137
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002138 if (len < wpa_s->extended_capa_len)
2139 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002140 if (buflen < (size_t) len + 2) {
2141 wpa_printf(MSG_INFO,
2142 "Not enough room for building extended capabilities element");
2143 return -1;
2144 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002145
2146 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002147 *pos++ = len;
2148 for (i = 0; i < len; i++, pos++) {
2149 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002150
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002151 if (i < wpa_s->extended_capa_len) {
2152 *pos &= ~wpa_s->extended_capa_mask[i];
2153 *pos |= wpa_s->extended_capa[i];
2154 }
2155 }
2156
2157 while (len > 0 && buf[1 + len] == 0) {
2158 len--;
2159 buf[1] = len;
2160 }
2161 if (len == 0)
2162 return 0;
2163
2164 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002165}
2166
2167
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002168static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2169 struct wpa_bss *test_bss)
2170{
2171 struct wpa_bss *bss;
2172
2173 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2174 if (bss == test_bss)
2175 return 1;
2176 }
2177
2178 return 0;
2179}
2180
2181
2182static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2183 struct wpa_ssid *test_ssid)
2184{
2185 struct wpa_ssid *ssid;
2186
2187 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2188 if (ssid == test_ssid)
2189 return 1;
2190 }
2191
2192 return 0;
2193}
2194
2195
2196int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2197 struct wpa_ssid *test_ssid)
2198{
2199 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2200 return 0;
2201
2202 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2203}
2204
2205
2206void wpas_connect_work_free(struct wpa_connect_work *cwork)
2207{
2208 if (cwork == NULL)
2209 return;
2210 os_free(cwork);
2211}
2212
2213
2214void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2215{
2216 struct wpa_connect_work *cwork;
2217 struct wpa_radio_work *work = wpa_s->connect_work;
2218
2219 if (!work)
2220 return;
2221
2222 wpa_s->connect_work = NULL;
2223 cwork = work->ctx;
2224 work->ctx = NULL;
2225 wpas_connect_work_free(cwork);
2226 radio_work_done(work);
2227}
2228
2229
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002230int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2231{
2232 struct os_reltime now;
2233 u8 addr[ETH_ALEN];
2234
2235 os_get_reltime(&now);
2236 if (wpa_s->last_mac_addr_style == style &&
2237 wpa_s->last_mac_addr_change.sec != 0 &&
2238 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2239 wpa_s->conf->rand_addr_lifetime)) {
2240 wpa_msg(wpa_s, MSG_DEBUG,
2241 "Previously selected random MAC address has not yet expired");
2242 return 0;
2243 }
2244
2245 switch (style) {
2246 case 1:
2247 if (random_mac_addr(addr) < 0)
2248 return -1;
2249 break;
2250 case 2:
2251 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2252 if (random_mac_addr_keep_oui(addr) < 0)
2253 return -1;
2254 break;
2255 default:
2256 return -1;
2257 }
2258
2259 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2260 wpa_msg(wpa_s, MSG_INFO,
2261 "Failed to set random MAC address");
2262 return -1;
2263 }
2264
2265 os_get_reltime(&wpa_s->last_mac_addr_change);
2266 wpa_s->mac_addr_changed = 1;
2267 wpa_s->last_mac_addr_style = style;
2268
2269 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2270 wpa_msg(wpa_s, MSG_INFO,
2271 "Could not update MAC address information");
2272 return -1;
2273 }
2274
2275 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2276 MAC2STR(addr));
2277
2278 return 0;
2279}
2280
2281
2282int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2283{
2284 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2285 !wpa_s->conf->preassoc_mac_addr)
2286 return 0;
2287
2288 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2289}
2290
2291
Sunil Ravi89eba102022-09-13 21:04:37 -07002292void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
Hai Shalomc3565922019-10-28 11:58:20 -07002293{
2294#ifdef CONFIG_SAE
2295 int *groups = conf->sae_groups;
2296 int default_groups[] = { 19, 20, 21, 0 };
2297 const char *password;
2298
2299 if (!groups || groups[0] <= 0)
2300 groups = default_groups;
2301
2302 password = ssid->sae_password;
2303 if (!password)
2304 password = ssid->passphrase;
2305
Hai Shalom899fcc72020-10-19 14:38:18 -07002306 if (!password ||
2307 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002308 !wpa_key_mgmt_sae_ext_key(ssid->key_mgmt) &&
Hai Shalom899fcc72020-10-19 14:38:18 -07002309 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002310 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002311 /* PT derivation not needed */
2312 sae_deinit_pt(ssid->pt);
2313 ssid->pt = NULL;
2314 return;
2315 }
2316
2317 if (ssid->pt)
2318 return; /* PT already derived */
2319 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2320 (const u8 *) password, os_strlen(password),
2321 ssid->sae_password_id);
2322#endif /* CONFIG_SAE */
2323}
2324
2325
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002326static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2327{
2328#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2329 os_free(wpa_s->sme.sae_rejected_groups);
2330 wpa_s->sme.sae_rejected_groups = NULL;
2331#ifdef CONFIG_TESTING_OPTIONS
2332 if (wpa_s->extra_sae_rejected_groups) {
2333 int i, *groups = wpa_s->extra_sae_rejected_groups;
2334
2335 for (i = 0; groups[i]; i++) {
2336 wpa_printf(MSG_DEBUG,
2337 "TESTING: Indicate rejection of an extra SAE group %d",
2338 groups[i]);
2339 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2340 groups[i]);
2341 }
2342 }
2343#endif /* CONFIG_TESTING_OPTIONS */
2344#endif /* CONFIG_SAE && CONFIG_SME */
2345}
2346
2347
Hai Shalom60840252021-02-19 19:02:11 -08002348int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2349{
2350 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2351 wpa_msg(wpa_s, MSG_INFO,
2352 "Could not restore permanent MAC address");
2353 return -1;
2354 }
2355 wpa_s->mac_addr_changed = 0;
2356 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2357 wpa_msg(wpa_s, MSG_INFO,
2358 "Could not update MAC address information");
2359 return -1;
2360 }
2361 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2362 return 0;
2363}
2364
2365
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002366static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2367
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002368/**
2369 * wpa_supplicant_associate - Request association
2370 * @wpa_s: Pointer to wpa_supplicant data
2371 * @bss: Scan results for the selected BSS, or %NULL if not available
2372 * @ssid: Configuration data for the selected network
2373 *
2374 * This function is used to request %wpa_supplicant to associate with a BSS.
2375 */
2376void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2377 struct wpa_bss *bss, struct wpa_ssid *ssid)
2378{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002379 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002380 int rand_style;
2381
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002382 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002383 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002384
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002385 /*
2386 * If we are starting a new connection, any previously pending EAPOL
2387 * RX cannot be valid anymore.
2388 */
2389 wpabuf_free(wpa_s->pending_eapol_rx);
2390 wpa_s->pending_eapol_rx = NULL;
2391
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002392 if (ssid->mac_addr == -1)
2393 rand_style = wpa_s->conf->mac_addr;
2394 else
2395 rand_style = ssid->mac_addr;
2396
Sunil Ravia04bd252022-05-02 22:54:18 -07002397 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002398 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002399 wmm_ac_clear_saved_tspecs(wpa_s);
2400 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002401 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002402#ifdef CONFIG_TESTING_OPTIONS
2403 wpa_s->testing_resend_assoc = 0;
2404#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002405
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002406 if (wpa_s->last_ssid == ssid) {
2407 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002408 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002409 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2410 wmm_ac_save_tspecs(wpa_s);
2411 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002412 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2413 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002414 }
Hai Shalomc3565922019-10-28 11:58:20 -07002415 } else {
2416#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002417 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002418#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002419 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002420#ifdef CONFIG_SAE
2421 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2422#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002423
2424 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002425 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2426 return;
2427 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002428 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002429 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002430 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002431 }
2432 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433
2434#ifdef CONFIG_IBSS_RSN
2435 ibss_rsn_deinit(wpa_s->ibss_rsn);
2436 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002437#else /* CONFIG_IBSS_RSN */
2438 if (ssid->mode == WPAS_MODE_IBSS &&
2439 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2440 wpa_msg(wpa_s, MSG_INFO,
2441 "IBSS RSN not supported in the build");
2442 return;
2443 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002444#endif /* CONFIG_IBSS_RSN */
2445
2446 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2447 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2448#ifdef CONFIG_AP
2449 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2450 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2451 "mode");
2452 return;
2453 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002454 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2455 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002456 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2457 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002458 return;
2459 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002460 wpa_s->current_bss = bss;
2461#else /* CONFIG_AP */
2462 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2463 "the build");
2464#endif /* CONFIG_AP */
2465 return;
2466 }
2467
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002468 if (ssid->mode == WPAS_MODE_MESH) {
2469#ifdef CONFIG_MESH
2470 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2471 wpa_msg(wpa_s, MSG_INFO,
2472 "Driver does not support mesh mode");
2473 return;
2474 }
2475 if (bss)
2476 ssid->frequency = bss->freq;
2477 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2478 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2479 return;
2480 }
2481 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002482#else /* CONFIG_MESH */
2483 wpa_msg(wpa_s, MSG_ERROR,
2484 "mesh mode support not included in the build");
2485#endif /* CONFIG_MESH */
2486 return;
2487 }
2488
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002489 /*
2490 * Set WPA state machine configuration to match the selected network now
2491 * so that the information is available before wpas_start_assoc_cb()
2492 * gets called. This is needed at least for RSN pre-authentication where
2493 * candidate APs are added to a list based on scan result processing
2494 * before completion of the first association.
2495 */
2496 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2497
2498#ifdef CONFIG_DPP
2499 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2500 return;
2501#endif /* CONFIG_DPP */
2502
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002503#ifdef CONFIG_TDLS
2504 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002505 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002506#endif /* CONFIG_TDLS */
2507
Hai Shalomc3565922019-10-28 11:58:20 -07002508#ifdef CONFIG_MBO
2509 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2510#endif /* CONFIG_MBO */
2511
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002512 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002513 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 sme_authenticate(wpa_s, bss, ssid);
2515 return;
2516 }
2517
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002518 if (wpa_s->connect_work) {
2519 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2520 return;
2521 }
2522
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002523 if (radio_work_pending(wpa_s, "connect")) {
2524 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2525 return;
2526 }
2527
Dmitry Shmidt29333592017-01-09 12:27:11 -08002528#ifdef CONFIG_SME
2529 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2530 /* Clear possibly set auth_alg, if any, from last attempt. */
2531 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2532 }
2533#endif /* CONFIG_SME */
2534
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002535 wpas_abort_ongoing_scan(wpa_s);
2536
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002537 cwork = os_zalloc(sizeof(*cwork));
2538 if (cwork == NULL)
2539 return;
2540
2541 cwork->bss = bss;
2542 cwork->ssid = ssid;
2543
2544 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2545 wpas_start_assoc_cb, cwork) < 0) {
2546 os_free(cwork);
2547 }
2548}
2549
2550
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002551static int bss_is_ibss(struct wpa_bss *bss)
2552{
2553 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2554 IEEE80211_CAP_IBSS;
2555}
2556
2557
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002558static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2559 const struct wpa_ssid *ssid)
2560{
2561 enum hostapd_hw_mode hw_mode;
2562 struct hostapd_hw_modes *mode = NULL;
2563 u8 channel;
2564 int i;
2565
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002566 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2567 if (hw_mode == NUM_HOSTAPD_MODES)
2568 return 0;
2569 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2570 if (wpa_s->hw.modes[i].mode == hw_mode) {
2571 mode = &wpa_s->hw.modes[i];
2572 break;
2573 }
2574 }
2575
2576 if (!mode)
2577 return 0;
2578
2579 return mode->vht_capab != 0;
2580}
2581
2582
Hai Shalomc1a21442022-02-04 13:43:00 -08002583static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2584{
2585 int i;
2586
2587 for (i = channel; i < channel + 16; i += 4) {
2588 struct hostapd_channel_data *chan;
2589
2590 chan = hw_get_channel_chan(mode, i, NULL);
2591 if (!chan ||
2592 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2593 return false;
2594 }
2595
2596 return true;
2597}
2598
2599
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002600void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2601 const struct wpa_ssid *ssid,
2602 struct hostapd_freq_params *freq)
2603{
Hai Shalom81f62d82019-07-22 12:10:00 -07002604 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002605 enum hostapd_hw_mode hw_mode;
2606 struct hostapd_hw_modes *mode = NULL;
2607 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2608 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002609 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2610 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2611 6595, 6675, 6755, 6835, 6915, 6995 };
2612 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002613 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2614 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002615 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002616 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002617 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002618 int chwidth, seg0, seg1;
2619 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002620 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002621
2622 freq->freq = ssid->frequency;
2623
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002624 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2625 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2626
2627 if (ssid->mode != WPAS_MODE_IBSS)
2628 break;
2629
2630 /* Don't adjust control freq in case of fixed_freq */
2631 if (ssid->fixed_freq)
2632 break;
2633
2634 if (!bss_is_ibss(bss))
2635 continue;
2636
2637 if (ssid->ssid_len == bss->ssid_len &&
2638 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2639 wpa_printf(MSG_DEBUG,
2640 "IBSS already found in scan results, adjust control freq: %d",
2641 bss->freq);
2642 freq->freq = bss->freq;
2643 obss_scan = 0;
2644 break;
2645 }
2646 }
2647
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002648 /* For IBSS check HT_IBSS flag */
2649 if (ssid->mode == WPAS_MODE_IBSS &&
2650 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2651 return;
2652
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002653 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2654 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2655 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2656 wpa_printf(MSG_DEBUG,
2657 "IBSS: WEP/TKIP detected, do not try to enable HT");
2658 return;
2659 }
2660
2661 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002662 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2663 if (wpa_s->hw.modes[i].mode == hw_mode) {
2664 mode = &wpa_s->hw.modes[i];
2665 break;
2666 }
2667 }
2668
2669 if (!mode)
2670 return;
2671
Hai Shalom60840252021-02-19 19:02:11 -08002672 freq->channel = channel;
2673
Hai Shalomc3565922019-10-28 11:58:20 -07002674 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2675 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002676
Hai Shalomc1a21442022-02-04 13:43:00 -08002677 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2678 * However, HE is mandatory for 6 GHz.
2679 */
2680 is_6ghz = is_6ghz_freq(freq->freq);
2681 if (is_6ghz)
2682 goto skip_to_6ghz;
2683
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002684#ifdef CONFIG_HT_OVERRIDES
2685 if (ssid->disable_ht) {
2686 freq->ht_enabled = 0;
2687 return;
2688 }
2689#endif /* CONFIG_HT_OVERRIDES */
2690
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002691 freq->ht_enabled = ht_supported(mode);
2692 if (!freq->ht_enabled)
2693 return;
2694
Hai Shalomc3565922019-10-28 11:58:20 -07002695 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2696 if (is_24ghz)
2697 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002698#ifdef CONFIG_HE_OVERRIDES
2699 if (is_24ghz && ssid->disable_he)
2700 freq->he_enabled = 0;
2701#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002702
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002703 /* Setup higher BW only for 5 GHz */
2704 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2705 return;
2706
2707 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2708 pri_chan = &mode->channels[chan_idx];
2709 if (pri_chan->chan == channel)
2710 break;
2711 pri_chan = NULL;
2712 }
2713 if (!pri_chan)
2714 return;
2715
2716 /* Check primary channel flags */
2717 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2718 return;
2719
Hai Shalom74f70d42019-02-11 14:42:39 -08002720 freq->channel = pri_chan->chan;
2721
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002722#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002723 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002724#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002725 if (ssid->disable_vht)
2726 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002727#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002728 goto skip_ht40;
2729 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002730#endif /* CONFIG_HT_OVERRIDES */
2731
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002732 /* Check/setup HT40+/HT40- */
2733 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2734 if (ht40plus[j] == channel) {
2735 ht40 = 1;
2736 break;
2737 }
2738 }
2739
2740 /* Find secondary channel */
2741 for (i = 0; i < mode->num_channels; i++) {
2742 sec_chan = &mode->channels[i];
2743 if (sec_chan->chan == channel + ht40 * 4)
2744 break;
2745 sec_chan = NULL;
2746 }
2747 if (!sec_chan)
2748 return;
2749
2750 /* Check secondary channel flags */
2751 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2752 return;
2753
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002754 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002755 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2756 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002757 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002758 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2759 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002760 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002761 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002762
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002763 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002764 struct wpa_scan_results *scan_res;
2765
2766 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2767 if (scan_res == NULL) {
2768 /* Back to HT20 */
2769 freq->sec_channel_offset = 0;
2770 return;
2771 }
2772
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002773 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002774 switch (res) {
2775 case 0:
2776 /* Back to HT20 */
2777 freq->sec_channel_offset = 0;
2778 break;
2779 case 1:
2780 /* Configuration allowed */
2781 break;
2782 case 2:
2783 /* Switch pri/sec channels */
2784 freq->freq = hw_get_freq(mode, sec_chan->chan);
2785 freq->sec_channel_offset = -freq->sec_channel_offset;
2786 freq->channel = sec_chan->chan;
2787 break;
2788 default:
2789 freq->sec_channel_offset = 0;
2790 break;
2791 }
2792
2793 wpa_scan_results_free(scan_res);
2794 }
2795
Hai Shalom74f70d42019-02-11 14:42:39 -08002796#ifdef CONFIG_HT_OVERRIDES
2797skip_ht40:
2798#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002799 wpa_printf(MSG_DEBUG,
2800 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2801 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002802
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002803 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002804 return;
2805
2806 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002807 if (ssid->mode == WPAS_MODE_IBSS &&
2808 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002809 return;
2810
Paul Stewart092955c2017-02-06 09:13:09 -08002811#ifdef CONFIG_VHT_OVERRIDES
2812 if (ssid->disable_vht) {
2813 freq->vht_enabled = 0;
2814 return;
2815 }
2816#endif /* CONFIG_VHT_OVERRIDES */
2817
Hai Shalomc1a21442022-02-04 13:43:00 -08002818skip_to_6ghz:
2819 vht_freq = *freq;
2820
2821 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002822 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002823 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002824 return;
2825
Hai Shalomfdcde762020-04-02 11:19:20 -07002826 /* Enable HE with VHT for 5 GHz */
2827 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002828
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002829 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002830 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2831 if (freq->freq >= bw80[j] &&
2832 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002833 break;
2834 }
2835
Hai Shalomc1a21442022-02-04 13:43:00 -08002836 if (j == ARRAY_SIZE(bw80) ||
2837 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002838 return;
2839
Hai Shalomc1a21442022-02-04 13:43:00 -08002840 /* Back to HT configuration if channel not usable */
2841 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2842 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002843
Sunil8cd6f4d2022-06-28 18:40:46 +00002844 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002845 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002846 seg1 = 0;
2847
Hai Shalomc1a21442022-02-04 13:43:00 -08002848 if ((mode->he_capab[ieee80211_mode].phy_cap[
2849 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2850 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2851 /* In 160 MHz, the initial four 20 MHz channels were validated
2852 * above; check the remaining four 20 MHz channels for the total
2853 * of 160 MHz bandwidth.
2854 */
2855 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2856 return;
2857
2858 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2859 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002860 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002861 seg0 = channel + 14;
2862 break;
2863 }
2864 }
2865 }
2866
Sunil8cd6f4d2022-06-28 18:40:46 +00002867 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002868 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002869 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002870 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002871 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002872 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002873
2874 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2875 NUM_HOSTAPD_MODES)
2876 return;
2877
2878 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002879 struct hostapd_channel_data *chan;
2880
2881 chan = hw_get_channel_chan(mode, i, NULL);
2882 if (!chan)
2883 continue;
2884
2885 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2886 HOSTAPD_CHAN_NO_IR |
2887 HOSTAPD_CHAN_RADAR))
2888 continue;
2889
2890 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00002891 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002892 if (!is_6ghz)
2893 vht_caps |=
2894 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2895 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002896 }
2897
Sunil8cd6f4d2022-06-28 18:40:46 +00002898 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002899 break;
2900 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002901 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002902 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002903 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002904 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2905 seg0 = 50;
2906 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002907 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002908 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2909 seg0 = 114;
2910 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002911 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT) {
2912 chwidth = CONF_OPER_CHWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002913 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002914#ifdef CONFIG_HT_OVERRIDES
2915 if (ssid->disable_ht40)
2916 seg0 = 0;
2917#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002918 }
2919
Hai Shalomfdcde762020-04-02 11:19:20 -07002920#ifdef CONFIG_HE_OVERRIDES
2921 if (ssid->disable_he) {
2922 vht_freq.he_enabled = 0;
2923 freq->he_enabled = 0;
2924 }
2925#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002926 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002927 freq->channel, ssid->enable_edmg,
2928 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002929 vht_freq.vht_enabled, freq->he_enabled,
Sunil Ravia04bd252022-05-02 22:54:18 -07002930 false,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002931 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002932 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07002933 &mode->he_capab[ieee80211_mode],
2934 NULL) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002935 return;
2936
2937 *freq = vht_freq;
2938
2939 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2940 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002941}
2942
2943
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002944#ifdef CONFIG_FILS
2945static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2946 size_t ie_buf_len)
2947{
2948 struct fils_hlp_req *req;
2949 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2950 const u8 *pos;
2951 u8 *buf = ie_buf;
2952
2953 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2954 list) {
2955 rem_len = ie_buf_len - ie_len;
2956 pos = wpabuf_head(req->pkt);
2957 hdr_len = 1 + 2 * ETH_ALEN + 6;
2958 hlp_len = wpabuf_len(req->pkt);
2959
2960 if (rem_len < 2 + hdr_len + hlp_len) {
2961 wpa_printf(MSG_ERROR,
2962 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2963 (unsigned long) rem_len,
2964 (unsigned long) (2 + hdr_len + hlp_len));
2965 break;
2966 }
2967
2968 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2969 /* Element ID */
2970 *buf++ = WLAN_EID_EXTENSION;
2971 /* Length */
2972 *buf++ = len;
2973 /* Element ID Extension */
2974 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2975 /* Destination MAC address */
2976 os_memcpy(buf, req->dst, ETH_ALEN);
2977 buf += ETH_ALEN;
2978 /* Source MAC address */
2979 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2980 buf += ETH_ALEN;
2981 /* LLC/SNAP Header */
2982 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2983 buf += 6;
2984 /* HLP Packet */
2985 os_memcpy(buf, pos, len - hdr_len);
2986 buf += len - hdr_len;
2987 pos += len - hdr_len;
2988
2989 hlp_len -= len - hdr_len;
2990 ie_len += 2 + len;
2991 rem_len -= 2 + len;
2992
2993 while (hlp_len) {
2994 len = (hlp_len > 255) ? 255 : hlp_len;
2995 if (rem_len < 2 + len)
2996 break;
2997 *buf++ = WLAN_EID_FRAGMENT;
2998 *buf++ = len;
2999 os_memcpy(buf, pos, len);
3000 buf += len;
3001 pos += len;
3002
3003 hlp_len -= len;
3004 ie_len += 2 + len;
3005 rem_len -= 2 + len;
3006 }
3007 }
3008
3009 return ie_len;
3010}
Roshan Pius3a1667e2018-07-03 15:17:14 -07003011
3012
3013int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
3014{
3015 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3016 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
3017 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3018 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
3019}
3020
3021
3022int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
3023{
3024#ifdef CONFIG_FILS_SK_PFS
3025 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
3026 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
3027#else /* CONFIG_FILS_SK_PFS */
3028 return 0;
3029#endif /* CONFIG_FILS_SK_PFS */
3030}
3031
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003032#endif /* CONFIG_FILS */
3033
3034
Hai Shalomc1a21442022-02-04 13:43:00 -08003035static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
3036 struct wpa_bss *bss,
3037 u8 *wpa_ie, size_t wpa_ie_len,
3038 size_t max_wpa_ie_len)
3039{
3040 struct wpabuf *wfa_ie = NULL;
3041 u8 wfa_capa[1];
3042 size_t wfa_ie_len, buf_len;
3043
3044 os_memset(wfa_capa, 0, sizeof(wfa_capa));
3045 if (wpa_s->enable_dscp_policy_capa)
3046 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
3047
3048 if (!wfa_capa[0])
3049 return wpa_ie_len;
3050
3051 /* Wi-Fi Alliance element */
3052 buf_len = 1 + /* Element ID */
3053 1 + /* Length */
3054 3 + /* OUI */
3055 1 + /* OUI Type */
3056 1 + /* Capabilities Length */
3057 sizeof(wfa_capa); /* Capabilities */
3058 wfa_ie = wpabuf_alloc(buf_len);
3059 if (!wfa_ie)
3060 return wpa_ie_len;
3061
3062 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
3063 wpabuf_put_u8(wfa_ie, buf_len - 2);
3064 wpabuf_put_be24(wfa_ie, OUI_WFA);
3065 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
3066 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
3067 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
3068
3069 wfa_ie_len = wpabuf_len(wfa_ie);
3070 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
3071 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
3072 wfa_ie);
3073 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
3074 wfa_ie_len);
3075 wpa_ie_len += wfa_ie_len;
3076 }
3077
3078 wpabuf_free(wfa_ie);
3079 return wpa_ie_len;
3080}
3081
3082
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003083static u8 * wpas_populate_assoc_ies(
3084 struct wpa_supplicant *wpa_s,
3085 struct wpa_bss *bss, struct wpa_ssid *ssid,
3086 struct wpa_driver_associate_params *params,
3087 enum wpa_drv_update_connect_params_mask *mask)
3088{
3089 u8 *wpa_ie;
3090 size_t max_wpa_ie_len = 500;
3091 size_t wpa_ie_len;
3092 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07003093#ifdef CONFIG_MBO
3094 const u8 *mbo_ie;
3095#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303096#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3097 int pmksa_cached = 0;
3098#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003099#ifdef CONFIG_FILS
3100 const u8 *realm, *username, *rrk;
3101 size_t realm_len, username_len, rrk_len;
3102 u16 next_seq_num;
3103 struct fils_hlp_req *req;
3104
3105 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
3106 list) {
3107 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
3108 2 + 2 * wpabuf_len(req->pkt) / 255;
3109 }
3110#endif /* CONFIG_FILS */
3111
3112 wpa_ie = os_malloc(max_wpa_ie_len);
3113 if (!wpa_ie) {
3114 wpa_printf(MSG_ERROR,
3115 "Failed to allocate connect IE buffer for %lu bytes",
3116 (unsigned long) max_wpa_ie_len);
3117 return NULL;
3118 }
3119
3120 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
3121 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
3122 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
3123 int try_opportunistic;
3124 const u8 *cache_id = NULL;
3125
3126 try_opportunistic = (ssid->proactive_key_caching < 0 ?
3127 wpa_s->conf->okc :
3128 ssid->proactive_key_caching) &&
3129 (ssid->proto & WPA_PROTO_RSN);
3130#ifdef CONFIG_FILS
3131 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3132 cache_id = wpa_bss_get_fils_cache_id(bss);
3133#endif /* CONFIG_FILS */
3134 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
3135 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003136 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003137 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303138#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3139 pmksa_cached = 1;
3140#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003141 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003142 wpa_ie_len = max_wpa_ie_len;
3143 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3144 wpa_ie, &wpa_ie_len)) {
3145 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3146 "key management and encryption suites");
3147 os_free(wpa_ie);
3148 return NULL;
3149 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003150#ifdef CONFIG_HS20
3151 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3152 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3153 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3154 wpa_ie_len = max_wpa_ie_len;
3155 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3156 wpa_ie, &wpa_ie_len)) {
3157 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3158 "key management and encryption suites");
3159 os_free(wpa_ie);
3160 return NULL;
3161 }
3162#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003163 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3164 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3165 /*
3166 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3167 * use non-WPA since the scan results did not indicate that the
3168 * AP is using WPA or WPA2.
3169 */
3170 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3171 wpa_ie_len = 0;
3172 wpa_s->wpa_proto = 0;
3173 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3174 wpa_ie_len = max_wpa_ie_len;
3175 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
3176 wpa_ie, &wpa_ie_len)) {
3177 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3178 "key management and encryption suites (no "
3179 "scan results)");
3180 os_free(wpa_ie);
3181 return NULL;
3182 }
3183#ifdef CONFIG_WPS
3184 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3185 struct wpabuf *wps_ie;
3186 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3187 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3188 wpa_ie_len = wpabuf_len(wps_ie);
3189 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3190 } else
3191 wpa_ie_len = 0;
3192 wpabuf_free(wps_ie);
3193 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3194 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3195 params->wps = WPS_MODE_PRIVACY;
3196 else
3197 params->wps = WPS_MODE_OPEN;
3198 wpa_s->wpa_proto = 0;
3199#endif /* CONFIG_WPS */
3200 } else {
3201 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3202 wpa_ie_len = 0;
3203 wpa_s->wpa_proto = 0;
3204 }
3205
3206#ifdef IEEE8021X_EAPOL
3207 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3208 if (ssid->leap) {
3209 if (ssid->non_leap == 0)
3210 algs = WPA_AUTH_ALG_LEAP;
3211 else
3212 algs |= WPA_AUTH_ALG_LEAP;
3213 }
3214 }
3215
3216#ifdef CONFIG_FILS
3217 /* Clear FILS association */
3218 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3219
3220 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3221 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3222 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3223 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003224 &next_seq_num, &rrk, &rrk_len) == 0 &&
3225 (!wpa_s->last_con_fail_realm ||
3226 wpa_s->last_con_fail_realm_len != realm_len ||
3227 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003228 algs = WPA_AUTH_ALG_FILS;
3229 params->fils_erp_username = username;
3230 params->fils_erp_username_len = username_len;
3231 params->fils_erp_realm = realm;
3232 params->fils_erp_realm_len = realm_len;
3233 params->fils_erp_next_seq_num = next_seq_num;
3234 params->fils_erp_rrk = rrk;
3235 params->fils_erp_rrk_len = rrk_len;
3236
3237 if (mask)
3238 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303239 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3240 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3241 pmksa_cached) {
3242 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003243 }
3244#endif /* CONFIG_FILS */
3245#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003246#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07003247 if (wpa_key_mgmt_sae(wpa_s->key_mgmt))
Roshan Pius3a1667e2018-07-03 15:17:14 -07003248 algs = WPA_AUTH_ALG_SAE;
3249#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003250
3251 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3252 if (ssid->auth_alg) {
3253 algs = ssid->auth_alg;
3254 wpa_dbg(wpa_s, MSG_DEBUG,
3255 "Overriding auth_alg selection: 0x%x", algs);
3256 }
3257
Hai Shalom5f92bc92019-04-18 11:54:11 -07003258#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303259 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003260 wpa_dbg(wpa_s, MSG_DEBUG,
3261 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3262 algs = WPA_AUTH_ALG_OPEN;
3263 }
3264#endif /* CONFIG_SAE */
3265
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003266#ifdef CONFIG_P2P
3267 if (wpa_s->global->p2p) {
3268 u8 *pos;
3269 size_t len;
3270 int res;
3271 pos = wpa_ie + wpa_ie_len;
3272 len = max_wpa_ie_len - wpa_ie_len;
3273 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3274 ssid->p2p_group);
3275 if (res >= 0)
3276 wpa_ie_len += res;
3277 }
3278
3279 wpa_s->cross_connect_disallowed = 0;
3280 if (bss) {
3281 struct wpabuf *p2p;
3282 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3283 if (p2p) {
3284 wpa_s->cross_connect_disallowed =
3285 p2p_get_cross_connect_disallowed(p2p);
3286 wpabuf_free(p2p);
3287 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3288 "connection",
3289 wpa_s->cross_connect_disallowed ?
3290 "disallows" : "allows");
3291 }
3292 }
3293
3294 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3295#endif /* CONFIG_P2P */
3296
3297 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003298 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003299 wpa_ie + wpa_ie_len,
3300 max_wpa_ie_len -
3301 wpa_ie_len);
3302 }
3303
3304 /*
3305 * Workaround: Add Extended Capabilities element only if the AP
3306 * included this element in Beacon/Probe Response frames. Some older
3307 * APs seem to have interoperability issues if this element is
3308 * included, so while the standard may require us to include the
3309 * element in all cases, it is justifiable to skip it to avoid
3310 * interoperability issues.
3311 */
3312 if (ssid->p2p_group)
3313 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3314 else
3315 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3316
3317 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3318 u8 ext_capab[18];
3319 int ext_capab_len;
3320 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3321 sizeof(ext_capab));
3322 if (ext_capab_len > 0 &&
3323 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3324 u8 *pos = wpa_ie;
3325 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3326 pos += 2 + pos[1];
3327 os_memmove(pos + ext_capab_len, pos,
3328 wpa_ie_len - (pos - wpa_ie));
3329 wpa_ie_len += ext_capab_len;
3330 os_memcpy(pos, ext_capab, ext_capab_len);
3331 }
3332 }
3333
3334#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003335 if (is_hs20_network(wpa_s, ssid, bss)
3336#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3337 && is_hs20_config(wpa_s)
3338#endif /* ANDROID */
3339 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003340 struct wpabuf *hs20;
3341
Roshan Pius3a1667e2018-07-03 15:17:14 -07003342 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003343 if (hs20) {
3344 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3345 size_t len;
3346
Hai Shalom74f70d42019-02-11 14:42:39 -08003347 wpas_hs20_add_indication(hs20, pps_mo_id,
3348 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003349 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003350 len = max_wpa_ie_len - wpa_ie_len;
3351 if (wpabuf_len(hs20) <= len) {
3352 os_memcpy(wpa_ie + wpa_ie_len,
3353 wpabuf_head(hs20), wpabuf_len(hs20));
3354 wpa_ie_len += wpabuf_len(hs20);
3355 }
3356 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003357 }
3358 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003359 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003360#endif /* CONFIG_HS20 */
3361
3362 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3363 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3364 size_t len;
3365
3366 len = max_wpa_ie_len - wpa_ie_len;
3367 if (wpabuf_len(buf) <= len) {
3368 os_memcpy(wpa_ie + wpa_ie_len,
3369 wpabuf_head(buf), wpabuf_len(buf));
3370 wpa_ie_len += wpabuf_len(buf);
3371 }
3372 }
3373
3374#ifdef CONFIG_FST
3375 if (wpa_s->fst_ies) {
3376 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3377
3378 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3379 os_memcpy(wpa_ie + wpa_ie_len,
3380 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3381 wpa_ie_len += fst_ies_len;
3382 }
3383 }
3384#endif /* CONFIG_FST */
3385
3386#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003387 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003388 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003389 int len;
3390
3391 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003392 max_wpa_ie_len - wpa_ie_len,
3393 !!mbo_attr_from_mbo_ie(mbo_ie,
3394 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003395 if (len >= 0)
3396 wpa_ie_len += len;
3397 }
3398#endif /* CONFIG_MBO */
3399
3400#ifdef CONFIG_FILS
3401 if (algs == WPA_AUTH_ALG_FILS) {
3402 size_t len;
3403
3404 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3405 max_wpa_ie_len - wpa_ie_len);
3406 wpa_ie_len += len;
3407 }
3408#endif /* CONFIG_FILS */
3409
3410#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003411#ifdef CONFIG_TESTING_OPTIONS
3412 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3413 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3414 } else
3415#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003416 if (algs == WPA_AUTH_ALG_OPEN &&
3417 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3418 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003419 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003420
Roshan Pius3a1667e2018-07-03 15:17:14 -07003421 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003422 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003423 } else if (wpa_s->assoc_status_code ==
3424 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003425 if (wpa_s->last_owe_group == 19)
3426 group = 20;
3427 else if (wpa_s->last_owe_group == 20)
3428 group = 21;
3429 else
3430 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003431 } else {
3432 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003433 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003434
Roshan Pius3a1667e2018-07-03 15:17:14 -07003435 wpa_s->last_owe_group = group;
3436 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003437 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3438 if (owe_ie &&
3439 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3440 os_memcpy(wpa_ie + wpa_ie_len,
3441 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3442 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003443 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003444 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003445 }
3446#endif /* CONFIG_OWE */
3447
Hai Shalom021b0b52019-04-10 11:17:58 -07003448#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003449 if (DPP_VERSION > 1 &&
3450 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003451 ssid->dpp_netaccesskey &&
3452 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003453 struct rsn_pmksa_cache_entry *pmksa;
3454
3455 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3456 if (!pmksa || !pmksa->dpp_pfs)
3457 goto pfs_fail;
3458
Hai Shalom021b0b52019-04-10 11:17:58 -07003459 dpp_pfs_free(wpa_s->dpp_pfs);
3460 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3461 ssid->dpp_netaccesskey_len);
3462 if (!wpa_s->dpp_pfs) {
3463 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3464 /* Try to continue without PFS */
3465 goto pfs_fail;
3466 }
3467 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3468 max_wpa_ie_len - wpa_ie_len) {
3469 os_memcpy(wpa_ie + wpa_ie_len,
3470 wpabuf_head(wpa_s->dpp_pfs->ie),
3471 wpabuf_len(wpa_s->dpp_pfs->ie));
3472 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3473 }
3474 }
3475pfs_fail:
3476#endif /* CONFIG_DPP2 */
3477
Roshan Pius3a1667e2018-07-03 15:17:14 -07003478#ifdef CONFIG_IEEE80211R
3479 /*
3480 * Add MDIE under these conditions: the network profile allows FT,
3481 * the AP supports FT, and the mobility domain ID matches.
3482 */
3483 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3484 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3485
3486 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3487 size_t len = 0;
3488 const u8 *md = mdie + 2;
3489 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3490
3491 if (os_memcmp(md, wpa_md,
3492 MOBILITY_DOMAIN_ID_LEN) == 0) {
3493 /* Add mobility domain IE */
3494 len = wpa_ft_add_mdie(
3495 wpa_s->wpa, wpa_ie + wpa_ie_len,
3496 max_wpa_ie_len - wpa_ie_len, mdie);
3497 wpa_ie_len += len;
3498 }
3499#ifdef CONFIG_SME
3500 if (len > 0 && wpa_s->sme.ft_used &&
3501 wpa_sm_has_ptk(wpa_s->wpa)) {
3502 wpa_dbg(wpa_s, MSG_DEBUG,
3503 "SME: Trying to use FT over-the-air");
3504 algs |= WPA_AUTH_ALG_FT;
3505 }
3506#endif /* CONFIG_SME */
3507 }
3508 }
3509#endif /* CONFIG_IEEE80211R */
3510
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003511#ifdef CONFIG_TESTING_OPTIONS
3512 if (wpa_s->rsnxe_override_assoc &&
3513 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3514 max_wpa_ie_len - wpa_ie_len) {
3515 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3516 os_memcpy(wpa_ie + wpa_ie_len,
3517 wpabuf_head(wpa_s->rsnxe_override_assoc),
3518 wpabuf_len(wpa_s->rsnxe_override_assoc));
3519 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3520 } else
3521#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003522 if (wpa_s->rsnxe_len > 0 &&
3523 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3524 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3525 wpa_ie_len += wpa_s->rsnxe_len;
3526 }
3527
Hai Shalomc1a21442022-02-04 13:43:00 -08003528#ifdef CONFIG_TESTING_OPTIONS
3529 if (wpa_s->disable_mscs_support)
3530 goto mscs_end;
3531#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003532 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3533 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003534 struct wpabuf *mscs_ie;
3535 size_t mscs_ie_len, buf_len;
3536
Hai Shalom899fcc72020-10-19 14:38:18 -07003537 buf_len = 3 + /* MSCS descriptor IE header */
3538 1 + /* Request type */
3539 2 + /* User priority control */
3540 4 + /* Stream timeout */
3541 3 + /* TCLAS Mask IE header */
3542 wpa_s->robust_av.frame_classifier_len;
3543 mscs_ie = wpabuf_alloc(buf_len);
3544 if (!mscs_ie) {
3545 wpa_printf(MSG_INFO,
3546 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003547 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003548 }
3549
3550 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3551 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3552 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3553 mscs_ie_len = wpabuf_len(mscs_ie);
3554 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3555 mscs_ie_len);
3556 wpa_ie_len += mscs_ie_len;
3557 }
3558
3559 wpabuf_free(mscs_ie);
3560 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003561mscs_end:
3562
3563 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3564 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003565
Hai Shalom74f70d42019-02-11 14:42:39 -08003566 if (ssid->multi_ap_backhaul_sta) {
3567 size_t multi_ap_ie_len;
3568
3569 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3570 max_wpa_ie_len - wpa_ie_len,
3571 MULTI_AP_BACKHAUL_STA);
3572 if (multi_ap_ie_len == 0) {
3573 wpa_printf(MSG_ERROR,
3574 "Multi-AP: Failed to build Multi-AP IE");
3575 os_free(wpa_ie);
3576 return NULL;
3577 }
3578 wpa_ie_len += multi_ap_ie_len;
3579 }
3580
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003581 params->wpa_ie = wpa_ie;
3582 params->wpa_ie_len = wpa_ie_len;
3583 params->auth_alg = algs;
3584 if (mask)
3585 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3586
3587 return wpa_ie;
3588}
3589
3590
Hai Shalomc3565922019-10-28 11:58:20 -07003591#ifdef CONFIG_OWE
3592static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3593{
3594 struct wpa_driver_associate_params params;
3595 u8 *wpa_ie;
3596
3597 os_memset(&params, 0, sizeof(params));
3598 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3599 wpa_s->current_ssid, &params, NULL);
3600 if (!wpa_ie)
3601 return;
3602
3603 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3604 os_free(wpa_ie);
3605}
3606#endif /* CONFIG_OWE */
3607
3608
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003609#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3610static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3611{
3612 struct wpa_driver_associate_params params;
3613 enum wpa_drv_update_connect_params_mask mask = 0;
3614 u8 *wpa_ie;
3615
3616 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3617 return; /* nothing to do */
3618
3619 os_memset(&params, 0, sizeof(params));
3620 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3621 wpa_s->current_ssid, &params, &mask);
3622 if (!wpa_ie)
3623 return;
3624
Hai Shalomc1a21442022-02-04 13:43:00 -08003625 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3626 wpa_s->auth_alg = params.auth_alg;
3627 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003628 }
3629
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003630 os_free(wpa_ie);
3631}
3632#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3633
3634
Hai Shalomc3565922019-10-28 11:58:20 -07003635static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3636{
3637 if (!edmg_ie || edmg_ie[1] < 6)
3638 return 0;
3639 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3640}
3641
3642
3643static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3644{
3645 if (!edmg_ie || edmg_ie[1] < 6)
3646 return 0;
3647 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3648}
3649
3650
3651/* Returns the intersection of two EDMG configurations.
3652 * Note: The current implementation is limited to CB2 only (CB1 included),
3653 * i.e., the implementation supports up to 2 contiguous channels.
3654 * For supporting non-contiguous (aggregated) channels and for supporting
3655 * CB3 and above, this function will need to be extended.
3656 */
3657static struct ieee80211_edmg_config
3658get_edmg_intersection(struct ieee80211_edmg_config a,
3659 struct ieee80211_edmg_config b,
3660 u8 primary_channel)
3661{
3662 struct ieee80211_edmg_config result;
3663 int i, contiguous = 0;
3664 int max_contiguous = 0;
3665
3666 result.channels = b.channels & a.channels;
3667 if (!result.channels) {
3668 wpa_printf(MSG_DEBUG,
3669 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3670 a.channels, b.channels);
3671 goto fail;
3672 }
3673
3674 if (!(result.channels & BIT(primary_channel - 1))) {
3675 wpa_printf(MSG_DEBUG,
3676 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3677 primary_channel, result.channels);
3678 goto fail;
3679 }
3680
3681 /* Find max contiguous channels */
3682 for (i = 0; i < 6; i++) {
3683 if (result.channels & BIT(i))
3684 contiguous++;
3685 else
3686 contiguous = 0;
3687
3688 if (contiguous > max_contiguous)
3689 max_contiguous = contiguous;
3690 }
3691
3692 /* Assuming AP and STA supports ONLY contiguous channels,
3693 * bw configuration can have value between 4-7.
3694 */
3695 if ((b.bw_config < a.bw_config))
3696 result.bw_config = b.bw_config;
3697 else
3698 result.bw_config = a.bw_config;
3699
3700 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3701 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3702 wpa_printf(MSG_DEBUG,
3703 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3704 max_contiguous);
3705 goto fail;
3706 }
3707
3708 return result;
3709
3710fail:
3711 result.channels = 0;
3712 result.bw_config = 0;
3713 return result;
3714}
3715
3716
3717static struct ieee80211_edmg_config
3718get_supported_edmg(struct wpa_supplicant *wpa_s,
3719 struct hostapd_freq_params *freq,
3720 struct ieee80211_edmg_config request_edmg)
3721{
3722 enum hostapd_hw_mode hw_mode;
3723 struct hostapd_hw_modes *mode = NULL;
3724 u8 primary_channel;
3725
3726 if (!wpa_s->hw.modes)
3727 goto fail;
3728
3729 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3730 if (hw_mode == NUM_HOSTAPD_MODES)
3731 goto fail;
3732
Hai Shalom60840252021-02-19 19:02:11 -08003733 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003734 if (!mode)
3735 goto fail;
3736
3737 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3738
3739fail:
3740 request_edmg.channels = 0;
3741 request_edmg.bw_config = 0;
3742 return request_edmg;
3743}
3744
3745
Hai Shalom021b0b52019-04-10 11:17:58 -07003746#ifdef CONFIG_MBO
3747void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3748{
3749 struct wpa_driver_associate_params params;
3750 u8 *wpa_ie;
3751
3752 /*
3753 * Update MBO connect params only in case of change of MBO attributes
3754 * when connected, if the AP support MBO.
3755 */
3756
3757 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3758 !wpa_s->current_bss ||
3759 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3760 return;
3761
3762 os_memset(&params, 0, sizeof(params));
3763 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3764 wpa_s->current_ssid, &params, NULL);
3765 if (!wpa_ie)
3766 return;
3767
3768 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3769 os_free(wpa_ie);
3770}
3771#endif /* CONFIG_MBO */
3772
3773
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003774static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3775{
3776 struct wpa_connect_work *cwork = work->ctx;
3777 struct wpa_bss *bss = cwork->bss;
3778 struct wpa_ssid *ssid = cwork->ssid;
3779 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003780 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003781 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003782 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003783 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003784 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003785#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003786 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003787#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003788 int assoc_failed = 0;
3789 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003790 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003791#ifdef CONFIG_HT_OVERRIDES
3792 struct ieee80211_ht_capabilities htcaps;
3793 struct ieee80211_ht_capabilities htcaps_mask;
3794#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003795#ifdef CONFIG_VHT_OVERRIDES
3796 struct ieee80211_vht_capabilities vhtcaps;
3797 struct ieee80211_vht_capabilities vhtcaps_mask;
3798#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003799
Hai Shalomc1a21442022-02-04 13:43:00 -08003800 wpa_s->roam_in_progress = false;
3801#ifdef CONFIG_WNM
3802 wpa_s->bss_trans_mgmt_in_progress = false;
3803#endif /* CONFIG_WNM */
3804
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003805 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003806 if (work->started) {
3807 wpa_s->connect_work = NULL;
3808
3809 /* cancel possible auth. timeout */
3810 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3811 NULL);
3812 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003813 wpas_connect_work_free(cwork);
3814 return;
3815 }
3816
3817 wpa_s->connect_work = work;
3818
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003819 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3820 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003821 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3822 wpas_connect_work_done(wpa_s);
3823 return;
3824 }
3825
Dmitry Shmidte4663042016-04-04 10:07:49 -07003826 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003827 os_memset(&params, 0, sizeof(params));
3828 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003829 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003830
3831 /* Starting new association, so clear the possibly used WPA IE from the
3832 * previous association. */
3833 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3834 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3835 wpa_s->rsnxe_len = 0;
3836 wpa_s->mscs_setup_done = false;
3837
3838 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3839 if (!wpa_ie) {
3840 wpas_connect_work_done(wpa_s);
3841 return;
3842 }
3843
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003844 if (bss &&
3845 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003846#ifdef CONFIG_IEEE80211R
3847 const u8 *ie, *md = NULL;
3848#endif /* CONFIG_IEEE80211R */
3849 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3850 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3851 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3852 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3853 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3854 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3855 if (bssid_changed)
3856 wpas_notify_bssid_changed(wpa_s);
3857#ifdef CONFIG_IEEE80211R
3858 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3859 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3860 md = ie + 2;
3861 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3862 if (md) {
3863 /* Prepare for the next transition */
3864 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3865 }
3866#endif /* CONFIG_IEEE80211R */
3867#ifdef CONFIG_WPS
3868 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3869 wpa_s->conf->ap_scan == 2 &&
3870 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3871 /* Use ap_scan==1 style network selection to find the network
3872 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003873 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003874 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003875 wpa_s->reassociate = 1;
3876 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003877 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003878 return;
3879#endif /* CONFIG_WPS */
3880 } else {
3881 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3882 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003883 if (bss)
3884 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3885 else
3886 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003887 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003888 if (!wpa_s->pno)
3889 wpa_supplicant_cancel_sched_scan(wpa_s);
3890
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003891 wpa_supplicant_cancel_scan(wpa_s);
3892
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003893 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3894 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003895 cipher_pairwise = wpa_s->pairwise_cipher;
3896 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003897 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003898 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3899 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3900 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3901 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003902#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003903 if (wpa_set_wep_keys(wpa_s, ssid)) {
3904 use_crypt = 1;
3905 wep_keys_set = 1;
3906 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003907#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003908 }
3909 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3910 use_crypt = 0;
3911
3912#ifdef IEEE8021X_EAPOL
3913 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3914 if ((ssid->eapol_flags &
3915 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3916 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3917 !wep_keys_set) {
3918 use_crypt = 0;
3919 } else {
3920 /* Assume that dynamic WEP-104 keys will be used and
3921 * set cipher suites in order for drivers to expect
3922 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003923 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003924 }
3925 }
3926#endif /* IEEE8021X_EAPOL */
3927
3928 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3929 /* Set the key before (and later after) association */
3930 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3931 }
3932
Sunil8cd6f4d2022-06-28 18:40:46 +00003933 /* Set current_ssid before changing state to ASSOCIATING, so that the
3934 * selected SSID is available to wpas_notify_state_changed(). */
3935 old_ssid = wpa_s->current_ssid;
3936 wpa_s->current_ssid = ssid;
3937
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003938 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3939 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003940 params.ssid = bss->ssid;
3941 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003942 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3943 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003944 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3945 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003946 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003947 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003948 ssid->bssid_set,
3949 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003950 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003951 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003952 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003953 params.bssid_hint = bss->bssid;
3954 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003955 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003956 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003957 if (ssid->bssid_hint_set)
3958 params.bssid_hint = ssid->bssid_hint;
3959
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003960 params.ssid = ssid->ssid;
3961 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003962 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003963 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003964
3965 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3966 wpa_s->conf->ap_scan == 2) {
3967 params.bssid = ssid->bssid;
3968 params.fixed_bssid = 1;
3969 }
3970
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003971 /* Initial frequency for IBSS/mesh */
3972 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003973 ssid->frequency > 0 && params.freq.freq == 0)
3974 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003975
3976 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003977 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003978 if (ssid->beacon_int)
3979 params.beacon_int = ssid->beacon_int;
3980 else
3981 params.beacon_int = wpa_s->conf->beacon_int;
3982 }
3983
Hai Shalomc3565922019-10-28 11:58:20 -07003984 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003985 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3986 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003987 else
3988 edmg_ie_oper = NULL;
3989
3990 if (edmg_ie_oper) {
3991 params.freq.edmg.channels =
3992 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3993 params.freq.edmg.bw_config =
3994 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3995 wpa_printf(MSG_DEBUG,
3996 "AP supports EDMG channels 0x%x, bw_config %d",
3997 params.freq.edmg.channels,
3998 params.freq.edmg.bw_config);
3999
4000 /* User may ask for specific EDMG channel for EDMG connection
4001 * (must be supported by AP)
4002 */
4003 if (ssid->edmg_channel) {
4004 struct ieee80211_edmg_config configured_edmg;
4005 enum hostapd_hw_mode hw_mode;
4006 u8 primary_channel;
4007
4008 hw_mode = ieee80211_freq_to_chan(bss->freq,
4009 &primary_channel);
4010 if (hw_mode == NUM_HOSTAPD_MODES)
4011 goto edmg_fail;
4012
4013 hostapd_encode_edmg_chan(ssid->enable_edmg,
4014 ssid->edmg_channel,
4015 primary_channel,
4016 &configured_edmg);
4017
4018 if (ieee802_edmg_is_allowed(params.freq.edmg,
4019 configured_edmg)) {
4020 params.freq.edmg = configured_edmg;
4021 wpa_printf(MSG_DEBUG,
4022 "Use EDMG channel %d for connection",
4023 ssid->edmg_channel);
4024 } else {
4025 edmg_fail:
4026 params.freq.edmg.channels = 0;
4027 params.freq.edmg.bw_config = 0;
4028 wpa_printf(MSG_WARNING,
4029 "EDMG channel %d not supported by AP, fallback to DMG",
4030 ssid->edmg_channel);
4031 }
4032 }
4033
4034 if (params.freq.edmg.channels) {
4035 wpa_printf(MSG_DEBUG,
4036 "EDMG before: channels 0x%x, bw_config %d",
4037 params.freq.edmg.channels,
4038 params.freq.edmg.bw_config);
4039 params.freq.edmg = get_supported_edmg(wpa_s,
4040 &params.freq,
4041 params.freq.edmg);
4042 wpa_printf(MSG_DEBUG,
4043 "EDMG after: channels 0x%x, bw_config %d",
4044 params.freq.edmg.channels,
4045 params.freq.edmg.bw_config);
4046 }
4047 }
4048
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004049 params.pairwise_suite = cipher_pairwise;
4050 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004051 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004052 params.key_mgmt_suite = wpa_s->key_mgmt;
Sunil Ravi89eba102022-09-13 21:04:37 -07004053 params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004054 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004055 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004056 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004057 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07004058#ifdef CONFIG_WEP
4059 {
4060 int i;
4061
4062 for (i = 0; i < NUM_WEP_KEYS; i++) {
4063 if (ssid->wep_key_len[i])
4064 params.wep_key[i] = ssid->wep_key[i];
4065 params.wep_key_len[i] = ssid->wep_key_len[i];
4066 }
4067 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004068 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004069#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004070
Hai Shalom74f70d42019-02-11 14:42:39 -08004071 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Vinayak Yadawad14709082022-03-17 14:25:11 +05304072#ifdef CONFIG_DRIVER_NL80211_BRCM
Sunil Ravi89eba102022-09-13 21:04:37 -07004073 ((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
4074 (params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304075#else
Sunil Ravi89eba102022-09-13 21:04:37 -07004076 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4077 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
4078 (params.allowed_key_mgmts &
4079 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
Vinayak Yadawad14709082022-03-17 14:25:11 +05304080#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004081 params.passphrase = ssid->passphrase;
4082 if (ssid->psk_set)
4083 params.psk = ssid->psk;
4084 }
4085
Hai Shalom74f70d42019-02-11 14:42:39 -08004086 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
4087 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4088 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4089 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4090 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07004091 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08004092
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004093 if (wpa_s->conf->key_mgmt_offload) {
4094 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4095 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004096 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
4097 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004098 params.req_key_mgmt_offload =
4099 ssid->proactive_key_caching < 0 ?
4100 wpa_s->conf->okc : ssid->proactive_key_caching;
4101 else
4102 params.req_key_mgmt_offload = 1;
4103
Vinayak Yadawad14709082022-03-17 14:25:11 +05304104#ifdef CONFIG_DRIVER_NL80211_BRCM
Sunil Ravi89eba102022-09-13 21:04:37 -07004105 if (((params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004106 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4107 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
Sunil Ravi89eba102022-09-13 21:04:37 -07004108#else
4109 if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
4110 wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
4111#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004112 ssid->psk_set)
4113 params.psk = ssid->psk;
4114 }
4115
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116 params.drop_unencrypted = use_crypt;
4117
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004118 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004119 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004120 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4121 struct wpa_ie_data ie;
4122 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
4123 ie.capabilities &
4124 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
4125 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
4126 "MFP: require MFP");
4127 params.mgmt_frame_protection =
4128 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004129#ifdef CONFIG_OWE
4130 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
4131 !ssid->owe_only) {
4132 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
4133#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004134 }
4135 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004136
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004137 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004138
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004139 if (wpa_s->p2pdev->set_sta_uapsd)
4140 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004141 else
4142 params.uapsd = -1;
4143
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004144#ifdef CONFIG_HT_OVERRIDES
4145 os_memset(&htcaps, 0, sizeof(htcaps));
4146 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4147 params.htcaps = (u8 *) &htcaps;
4148 params.htcaps_mask = (u8 *) &htcaps_mask;
4149 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4150#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004151#ifdef CONFIG_VHT_OVERRIDES
4152 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4153 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4154 params.vhtcaps = &vhtcaps;
4155 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004156 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004157#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004158#ifdef CONFIG_HE_OVERRIDES
4159 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4160#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004161
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004162#ifdef CONFIG_P2P
4163 /*
4164 * If multi-channel concurrency is not supported, check for any
4165 * frequency conflict. In case of any frequency conflict, remove the
4166 * least prioritized connection.
4167 */
4168 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004169 int freq, num;
4170 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004171 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004172 wpa_printf(MSG_DEBUG,
4173 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004174 freq, params.freq.freq);
4175 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004176 wpa_s, params.freq.freq, ssid) < 0) {
4177 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004178 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004179 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004180 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004181 }
4182 }
4183#endif /* CONFIG_P2P */
4184
Dmitry Shmidte4663042016-04-04 10:07:49 -07004185 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004186 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004187 params.prev_bssid = prev_bssid;
4188
Hai Shalom60840252021-02-19 19:02:11 -08004189#ifdef CONFIG_SAE
4190 params.sae_pwe = wpa_s->conf->sae_pwe;
4191#endif /* CONFIG_SAE */
4192
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004193 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004194 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004195 if (ret < 0) {
4196 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4197 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004198 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004199 /*
4200 * The driver is known to mean what is saying, so we
4201 * can stop right here; the association will not
4202 * succeed.
4203 */
4204 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004205 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004206 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004207 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004208 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4209 return;
4210 }
4211 /* try to continue anyway; new association will be tried again
4212 * after timeout */
4213 assoc_failed = 1;
4214 }
4215
4216 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4217 /* Set the key after the association just in case association
4218 * cleared the previously configured key. */
4219 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4220 /* No need to timeout authentication since there is no key
4221 * management. */
4222 wpa_supplicant_cancel_auth_timeout(wpa_s);
4223 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4224#ifdef CONFIG_IBSS_RSN
4225 } else if (ssid->mode == WPAS_MODE_IBSS &&
4226 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4227 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4228 /*
4229 * RSN IBSS authentication is per-STA and we can disable the
4230 * per-BSSID authentication.
4231 */
4232 wpa_supplicant_cancel_auth_timeout(wpa_s);
4233#endif /* CONFIG_IBSS_RSN */
4234 } else {
4235 /* Timeout for IEEE 802.11 authentication and association */
4236 int timeout = 60;
4237
4238 if (assoc_failed) {
4239 /* give IBSS a bit more time */
4240 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4241 } else if (wpa_s->conf->ap_scan == 1) {
4242 /* give IBSS a bit more time */
4243 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4244 }
4245 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4246 }
4247
Hai Shalomfdcde762020-04-02 11:19:20 -07004248#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004249 if (wep_keys_set &&
4250 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004251 /* Set static WEP keys again */
4252 wpa_set_wep_keys(wpa_s, ssid);
4253 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004254#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004255
Sunil8cd6f4d2022-06-28 18:40:46 +00004256 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004257 /*
4258 * Do not allow EAP session resumption between different
4259 * network configurations.
4260 */
4261 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4262 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004263
4264 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004265 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004266#ifdef CONFIG_HS20
4267 hs20_configure_frame_filters(wpa_s);
4268#endif /* CONFIG_HS20 */
4269 }
4270
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004271 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4272 wpa_supplicant_initiate_eapol(wpa_s);
4273 if (old_ssid != wpa_s->current_ssid)
4274 wpas_notify_network_changed(wpa_s);
4275}
4276
4277
4278static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4279 const u8 *addr)
4280{
4281 struct wpa_ssid *old_ssid;
4282
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004283 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004284 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004286 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004287 wpa_sm_set_config(wpa_s->wpa, NULL);
4288 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4289 if (old_ssid != wpa_s->current_ssid)
4290 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004291
4292 wpas_scs_deinit(wpa_s);
4293 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004294 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4295}
4296
4297
4298/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004299 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4300 * @wpa_s: Pointer to wpa_supplicant data
4301 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4302 *
4303 * This function is used to request %wpa_supplicant to deauthenticate from the
4304 * current AP.
4305 */
4306void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004307 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004308{
4309 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004310 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004311 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004312
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004313 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004314 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004315 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004316 reason_code, reason2str(reason_code),
4317 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004318
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004319 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4320 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4321 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004322 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004323 else if (!is_zero_ether_addr(wpa_s->bssid))
4324 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004325 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4326 /*
4327 * When using driver-based BSS selection, we may not know the
4328 * BSSID with which we are currently trying to associate. We
4329 * need to notify the driver of this disconnection even in such
4330 * a case, so use the all zeros address here.
4331 */
4332 addr = wpa_s->bssid;
4333 zero_addr = 1;
4334 }
4335
Hai Shalom74f70d42019-02-11 14:42:39 -08004336 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4337 wpa_s->enabled_4addr_mode = 0;
4338
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004339#ifdef CONFIG_TDLS
4340 wpa_tdls_teardown_peers(wpa_s->wpa);
4341#endif /* CONFIG_TDLS */
4342
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004343#ifdef CONFIG_MESH
4344 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004345 struct mesh_conf *mconf;
4346
4347 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004348 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4349 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004350 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4351 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004352 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004353 }
4354#endif /* CONFIG_MESH */
4355
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004356 if (addr) {
4357 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004358 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004359 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004360 event.deauth_info.locally_generated = 1;
4361 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004362 if (zero_addr)
4363 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004364 }
4365
4366 wpa_supplicant_clear_connection(wpa_s, addr);
4367}
4368
Hai Shalomfdcde762020-04-02 11:19:20 -07004369
4370void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4371{
4372 wpa_s->own_reconnect_req = 1;
4373 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4374
4375}
4376
4377
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004378static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4379 struct wpa_ssid *ssid)
4380{
4381 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4382 return;
4383
4384 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004385 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004386 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4387 wpas_notify_network_enabled_changed(wpa_s, ssid);
4388
4389 /*
4390 * Try to reassociate since there is no current configuration and a new
4391 * network was made available.
4392 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004393 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004394 wpa_s->reassociate = 1;
4395}
4396
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004397
Roshan Pius950bec92016-07-19 09:49:24 -07004398/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004399 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004400 * @wpa_s: wpa_supplicant structure for a network interface
4401 * Returns: The new network configuration or %NULL if operation failed
4402 *
4403 * This function performs the following operations:
4404 * 1. Adds a new network.
4405 * 2. Send network addition notification.
4406 * 3. Marks the network disabled.
4407 * 4. Set network default parameters.
4408 */
4409struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4410{
4411 struct wpa_ssid *ssid;
4412
4413 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004414 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004415 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004416 wpas_notify_network_added(wpa_s, ssid);
4417 ssid->disabled = 1;
4418 wpa_config_set_network_defaults(ssid);
4419
4420 return ssid;
4421}
4422
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004423
Roshan Pius950bec92016-07-19 09:49:24 -07004424/**
4425 * wpa_supplicant_remove_network - Remove a configured network based on id
4426 * @wpa_s: wpa_supplicant structure for a network interface
4427 * @id: Unique network id to search for
4428 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4429 * could not be removed
4430 *
4431 * This function performs the following operations:
4432 * 1. Removes the network.
4433 * 2. Send network removal notification.
4434 * 3. Update internal state machines.
4435 * 4. Stop any running sched scans.
4436 */
4437int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4438{
Sunil Ravia04bd252022-05-02 22:54:18 -07004439 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004440 int was_disabled;
4441
4442 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004443 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004444 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004445 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004446
Sunil Ravia04bd252022-05-02 22:54:18 -07004447 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004448#ifdef CONFIG_SME
4449 wpa_s->sme.prev_bssid_set = 0;
4450#endif /* CONFIG_SME */
4451 /*
4452 * Invalidate the EAP session cache if the current or
4453 * previously used network is removed.
4454 */
4455 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4456 }
4457
Sunil Ravia04bd252022-05-02 22:54:18 -07004458 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004459 wpa_sm_set_config(wpa_s->wpa, NULL);
4460 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4461
4462 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4463 wpa_s->own_disconnect_req = 1;
4464 wpa_supplicant_deauthenticate(wpa_s,
4465 WLAN_REASON_DEAUTH_LEAVING);
4466 }
4467
4468 was_disabled = ssid->disabled;
4469
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004470 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004471 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004472
4473 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004474 wpa_printf(MSG_DEBUG,
4475 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004476 wpa_supplicant_cancel_sched_scan(wpa_s);
4477 wpa_supplicant_req_scan(wpa_s, 0, 0);
4478 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004479
Roshan Pius950bec92016-07-19 09:49:24 -07004480 return 0;
4481}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004482
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004483
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004484/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004485 * wpa_supplicant_remove_all_networks - Remove all configured networks
4486 * @wpa_s: wpa_supplicant structure for a network interface
4487 * Returns: 0 on success (errors are currently ignored)
4488 *
4489 * This function performs the following operations:
4490 * 1. Remove all networks.
4491 * 2. Send network removal notifications.
4492 * 3. Update internal state machines.
4493 * 4. Stop any running sched scans.
4494 */
4495int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4496{
4497 struct wpa_ssid *ssid;
4498
4499 if (wpa_s->sched_scanning)
4500 wpa_supplicant_cancel_sched_scan(wpa_s);
4501
4502 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4503 if (wpa_s->current_ssid) {
4504#ifdef CONFIG_SME
4505 wpa_s->sme.prev_bssid_set = 0;
4506#endif /* CONFIG_SME */
4507 wpa_sm_set_config(wpa_s->wpa, NULL);
4508 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4509 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4510 wpa_s->own_disconnect_req = 1;
4511 wpa_supplicant_deauthenticate(
4512 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4513 }
4514 ssid = wpa_s->conf->ssid;
4515 while (ssid) {
4516 struct wpa_ssid *remove_ssid = ssid;
4517 int id;
4518
4519 id = ssid->id;
4520 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004521 wpas_notify_network_removed(wpa_s, remove_ssid);
4522 wpa_config_remove_network(wpa_s->conf, id);
4523 }
4524 return 0;
4525}
4526
4527
4528/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004529 * wpa_supplicant_enable_network - Mark a configured network as enabled
4530 * @wpa_s: wpa_supplicant structure for a network interface
4531 * @ssid: wpa_ssid structure for a configured network or %NULL
4532 *
4533 * Enables the specified network or all networks if no network specified.
4534 */
4535void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4536 struct wpa_ssid *ssid)
4537{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004538 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004539 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4540 wpa_supplicant_enable_one_network(wpa_s, ssid);
4541 } else
4542 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004543
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004544 if (wpa_s->reassociate && !wpa_s->disconnected &&
4545 (!wpa_s->current_ssid ||
4546 wpa_s->wpa_state == WPA_DISCONNECTED ||
4547 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004548 if (wpa_s->sched_scanning) {
4549 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4550 "new network to scan filters");
4551 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004552 }
4553
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004554 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4555 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004556 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004557 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004558 }
4559}
4560
4561
4562/**
4563 * wpa_supplicant_disable_network - Mark a configured network as disabled
4564 * @wpa_s: wpa_supplicant structure for a network interface
4565 * @ssid: wpa_ssid structure for a configured network or %NULL
4566 *
4567 * Disables the specified network or all networks if no network specified.
4568 */
4569void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4570 struct wpa_ssid *ssid)
4571{
4572 struct wpa_ssid *other_ssid;
4573 int was_disabled;
4574
4575 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004576 if (wpa_s->sched_scanning)
4577 wpa_supplicant_cancel_sched_scan(wpa_s);
4578
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004579 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4580 other_ssid = other_ssid->next) {
4581 was_disabled = other_ssid->disabled;
4582 if (was_disabled == 2)
4583 continue; /* do not change persistent P2P group
4584 * data */
4585
4586 other_ssid->disabled = 1;
4587
4588 if (was_disabled != other_ssid->disabled)
4589 wpas_notify_network_enabled_changed(
4590 wpa_s, other_ssid);
4591 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004592 if (wpa_s->current_ssid) {
4593 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4594 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004595 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004596 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004597 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004598 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004599 if (ssid == wpa_s->current_ssid) {
4600 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4601 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004602 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004603 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004604 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004605
4606 was_disabled = ssid->disabled;
4607
4608 ssid->disabled = 1;
4609
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004610 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004611 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004612 if (wpa_s->sched_scanning) {
4613 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4614 "to remove network from filters");
4615 wpa_supplicant_cancel_sched_scan(wpa_s);
4616 wpa_supplicant_req_scan(wpa_s, 0, 0);
4617 }
4618 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004619 }
4620}
4621
4622
4623/**
4624 * wpa_supplicant_select_network - Attempt association with a network
4625 * @wpa_s: wpa_supplicant structure for a network interface
4626 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4627 */
4628void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4629 struct wpa_ssid *ssid)
4630{
4631
4632 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004633 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004634
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004635 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004636 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4637 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004638 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004639 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004640 disconnected = 1;
4641 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004643 if (ssid)
4644 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004646 /*
4647 * Mark all other networks disabled or mark all networks enabled if no
4648 * network specified.
4649 */
4650 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4651 other_ssid = other_ssid->next) {
4652 int was_disabled = other_ssid->disabled;
4653 if (was_disabled == 2)
4654 continue; /* do not change persistent P2P group data */
4655
4656 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004657 if (was_disabled && !other_ssid->disabled)
4658 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004659
4660 if (was_disabled != other_ssid->disabled)
4661 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4662 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004663
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004664 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4665 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004666 /* We are already associated with the selected network */
4667 wpa_printf(MSG_DEBUG, "Already associated with the "
4668 "selected network - do nothing");
4669 return;
4670 }
4671
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004672 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004673 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004674 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004675 wpa_s->connect_without_scan =
4676 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004677
4678 /*
4679 * Don't optimize next scan freqs since a new ESS has been
4680 * selected.
4681 */
4682 os_free(wpa_s->next_scan_freqs);
4683 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004684 } else {
4685 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004686 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004687
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004688 wpa_s->disconnected = 0;
4689 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004690 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004691 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004692 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004693 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004694 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4695 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004696
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004697 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004698 wpa_supplicant_fast_associate(wpa_s) != 1) {
4699 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004700 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004701 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004702 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004703
4704 if (ssid)
4705 wpas_notify_network_selected(wpa_s, ssid);
4706}
4707
4708
4709/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004710 * wpas_remove_cred - Remove the specified credential and all the network
4711 * entries created based on the removed credential
4712 * @wpa_s: wpa_supplicant structure for a network interface
4713 * @cred: The credential to remove
4714 * Returns: 0 on success, -1 on failure
4715 */
4716int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4717{
4718 struct wpa_ssid *ssid, *next;
4719 int id;
4720
4721 if (!cred) {
4722 wpa_printf(MSG_DEBUG, "Could not find cred");
4723 return -1;
4724 }
4725
4726 id = cred->id;
4727 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4728 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4729 return -1;
4730 }
4731
4732 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4733
4734 /* Remove any network entry created based on the removed credential */
4735 ssid = wpa_s->conf->ssid;
4736 while (ssid) {
4737 next = ssid->next;
4738
4739 if (ssid->parent_cred == cred) {
4740 wpa_printf(MSG_DEBUG,
4741 "Remove network id %d since it used the removed credential",
4742 ssid->id);
4743 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4744 -1) {
4745 wpa_printf(MSG_DEBUG,
4746 "Could not find network id=%d",
4747 ssid->id);
4748 }
4749 }
4750
4751 ssid = next;
4752 }
4753
4754 return 0;
4755}
4756
4757
4758/**
4759 * wpas_remove_cred - Remove all the Interworking credentials
4760 * @wpa_s: wpa_supplicant structure for a network interface
4761 * Returns: 0 on success, -1 on failure
4762 */
4763int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4764{
4765 int res, ret = 0;
4766 struct wpa_cred *cred, *prev;
4767
4768 cred = wpa_s->conf->cred;
4769 while (cred) {
4770 prev = cred;
4771 cred = cred->next;
4772 res = wpas_remove_cred(wpa_s, prev);
4773 if (res < 0) {
4774 wpa_printf(MSG_DEBUG,
4775 "Removal of all credentials failed - failed to remove credential id=%d",
4776 prev->id);
4777 ret = -1;
4778 }
4779 }
4780
4781 return ret;
4782}
4783
4784
4785/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004786 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4787 * @wpa_s: wpa_supplicant structure for a network interface
4788 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4789 * @pkcs11_module_path: PKCS #11 module path or NULL
4790 * Returns: 0 on success; -1 on failure
4791 *
4792 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4793 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4794 * module path fails the paths will be reset to the default value (NULL).
4795 */
4796int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4797 const char *pkcs11_engine_path,
4798 const char *pkcs11_module_path)
4799{
4800 char *pkcs11_engine_path_copy = NULL;
4801 char *pkcs11_module_path_copy = NULL;
4802
4803 if (pkcs11_engine_path != NULL) {
4804 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4805 if (pkcs11_engine_path_copy == NULL)
4806 return -1;
4807 }
4808 if (pkcs11_module_path != NULL) {
4809 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004810 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004811 os_free(pkcs11_engine_path_copy);
4812 return -1;
4813 }
4814 }
4815
4816 os_free(wpa_s->conf->pkcs11_engine_path);
4817 os_free(wpa_s->conf->pkcs11_module_path);
4818 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4819 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4820
4821 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4822 eapol_sm_deinit(wpa_s->eapol);
4823 wpa_s->eapol = NULL;
4824 if (wpa_supplicant_init_eapol(wpa_s)) {
4825 /* Error -> Reset paths to the default value (NULL) once. */
4826 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4827 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4828 NULL);
4829
4830 return -1;
4831 }
4832 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4833
4834 return 0;
4835}
4836
4837
4838/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004839 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4840 * @wpa_s: wpa_supplicant structure for a network interface
4841 * @ap_scan: AP scan mode
4842 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4843 *
4844 */
4845int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4846{
4847
4848 int old_ap_scan;
4849
4850 if (ap_scan < 0 || ap_scan > 2)
4851 return -1;
4852
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004853 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4854 wpa_printf(MSG_INFO,
4855 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4856 }
4857
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004858#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004859 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4860 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4861 wpa_s->wpa_state < WPA_COMPLETED) {
4862 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4863 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004864 return 0;
4865 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004866#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004867
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004868 old_ap_scan = wpa_s->conf->ap_scan;
4869 wpa_s->conf->ap_scan = ap_scan;
4870
4871 if (old_ap_scan != wpa_s->conf->ap_scan)
4872 wpas_notify_ap_scan_changed(wpa_s);
4873
4874 return 0;
4875}
4876
4877
4878/**
4879 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4880 * @wpa_s: wpa_supplicant structure for a network interface
4881 * @expire_age: Expiration age in seconds
4882 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4883 *
4884 */
4885int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4886 unsigned int bss_expire_age)
4887{
4888 if (bss_expire_age < 10) {
4889 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4890 bss_expire_age);
4891 return -1;
4892 }
4893 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4894 bss_expire_age);
4895 wpa_s->conf->bss_expiration_age = bss_expire_age;
4896
4897 return 0;
4898}
4899
4900
4901/**
4902 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4903 * @wpa_s: wpa_supplicant structure for a network interface
4904 * @expire_count: number of scans after which an unseen BSS is reclaimed
4905 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4906 *
4907 */
4908int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4909 unsigned int bss_expire_count)
4910{
4911 if (bss_expire_count < 1) {
4912 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4913 bss_expire_count);
4914 return -1;
4915 }
4916 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4917 bss_expire_count);
4918 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4919
4920 return 0;
4921}
4922
4923
4924/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004925 * wpa_supplicant_set_scan_interval - Set scan interval
4926 * @wpa_s: wpa_supplicant structure for a network interface
4927 * @scan_interval: scan interval in seconds
4928 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4929 *
4930 */
4931int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4932 int scan_interval)
4933{
4934 if (scan_interval < 0) {
4935 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4936 scan_interval);
4937 return -1;
4938 }
4939 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4940 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004941 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004942
4943 return 0;
4944}
4945
4946
4947/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004948 * wpa_supplicant_set_debug_params - Set global debug params
4949 * @global: wpa_global structure
4950 * @debug_level: debug level
4951 * @debug_timestamp: determines if show timestamp in debug data
4952 * @debug_show_keys: determines if show keys in debug data
4953 * Returns: 0 if succeed or -1 if debug_level has wrong value
4954 */
4955int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4956 int debug_timestamp, int debug_show_keys)
4957{
4958
4959 int old_level, old_timestamp, old_show_keys;
4960
4961 /* check for allowed debuglevels */
4962 if (debug_level != MSG_EXCESSIVE &&
4963 debug_level != MSG_MSGDUMP &&
4964 debug_level != MSG_DEBUG &&
4965 debug_level != MSG_INFO &&
4966 debug_level != MSG_WARNING &&
4967 debug_level != MSG_ERROR)
4968 return -1;
4969
4970 old_level = wpa_debug_level;
4971 old_timestamp = wpa_debug_timestamp;
4972 old_show_keys = wpa_debug_show_keys;
4973
4974 wpa_debug_level = debug_level;
4975 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4976 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4977
4978 if (wpa_debug_level != old_level)
4979 wpas_notify_debug_level_changed(global);
4980 if (wpa_debug_timestamp != old_timestamp)
4981 wpas_notify_debug_timestamp_changed(global);
4982 if (wpa_debug_show_keys != old_show_keys)
4983 wpas_notify_debug_show_keys_changed(global);
4984
4985 return 0;
4986}
4987
4988
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004989#ifdef CONFIG_OWE
4990static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4991 const u8 *entry_ssid, size_t entry_ssid_len)
4992{
4993 const u8 *owe, *pos, *end;
4994 u8 ssid_len;
4995 struct wpa_bss *bss;
4996
4997 /* Check network profile SSID aganst the SSID in the
4998 * OWE Transition Mode element. */
4999
5000 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
5001 if (!bss)
5002 return 0;
5003
5004 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
5005 if (!owe)
5006 return 0;
5007
5008 pos = owe + 6;
5009 end = owe + 2 + owe[1];
5010
5011 if (end - pos < ETH_ALEN + 1)
5012 return 0;
5013 pos += ETH_ALEN;
5014 ssid_len = *pos++;
5015 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
5016 return 0;
5017
5018 return entry_ssid_len == ssid_len &&
5019 os_memcmp(pos, entry_ssid, ssid_len) == 0;
5020}
5021#endif /* CONFIG_OWE */
5022
5023
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005024/**
5025 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
5026 * @wpa_s: Pointer to wpa_supplicant data
5027 * Returns: A pointer to the current network structure or %NULL on failure
5028 */
5029struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
5030{
5031 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07005032 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005033 int res;
5034 size_t ssid_len;
5035 u8 bssid[ETH_ALEN];
5036 int wired;
5037
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005038 res = wpa_drv_get_ssid(wpa_s, ssid);
5039 if (res < 0) {
5040 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
5041 "driver");
5042 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005043 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005044 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005045
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005046 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005047 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
5048 "driver");
5049 return NULL;
5050 }
5051
5052 wired = wpa_s->conf->ap_scan == 0 &&
5053 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
5054
5055 entry = wpa_s->conf->ssid;
5056 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005057 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005058 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07005059 (!entry->ssid ||
5060 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
5061 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005062 (!entry->bssid_set ||
5063 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5064 return entry;
5065#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07005066 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005067 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
5068 (entry->ssid == NULL || entry->ssid_len == 0) &&
5069 (!entry->bssid_set ||
5070 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5071 return entry;
5072#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005073
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005074#ifdef CONFIG_OWE
5075 if (!wpas_network_disabled(wpa_s, entry) &&
5076 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
5077 entry->ssid_len) &&
5078 (!entry->bssid_set ||
5079 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
5080 return entry;
5081#endif /* CONFIG_OWE */
5082
Dmitry Shmidt04949592012-07-19 12:16:46 -07005083 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005084 entry->ssid_len == 0 &&
5085 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
5086 return entry;
5087
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005088 entry = entry->next;
5089 }
5090
5091 return NULL;
5092}
5093
5094
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005095static int select_driver(struct wpa_supplicant *wpa_s, int i)
5096{
5097 struct wpa_global *global = wpa_s->global;
5098
5099 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07005100 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005101 if (global->drv_priv[i] == NULL) {
5102 wpa_printf(MSG_ERROR, "Failed to initialize driver "
5103 "'%s'", wpa_drivers[i]->name);
5104 return -1;
5105 }
5106 }
5107
5108 wpa_s->driver = wpa_drivers[i];
5109 wpa_s->global_drv_priv = global->drv_priv[i];
5110
5111 return 0;
5112}
5113
5114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005115static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
5116 const char *name)
5117{
5118 int i;
5119 size_t len;
5120 const char *pos, *driver = name;
5121
5122 if (wpa_s == NULL)
5123 return -1;
5124
5125 if (wpa_drivers[0] == NULL) {
5126 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
5127 "wpa_supplicant");
5128 return -1;
5129 }
5130
5131 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08005132 /* Default to first successful driver in the list */
5133 for (i = 0; wpa_drivers[i]; i++) {
5134 if (select_driver(wpa_s, i) == 0)
5135 return 0;
5136 }
5137 /* Drivers have each reported failure, so no wpa_msg() here. */
5138 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005139 }
5140
5141 do {
5142 pos = os_strchr(driver, ',');
5143 if (pos)
5144 len = pos - driver;
5145 else
5146 len = os_strlen(driver);
5147
5148 for (i = 0; wpa_drivers[i]; i++) {
5149 if (os_strlen(wpa_drivers[i]->name) == len &&
5150 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005151 0) {
5152 /* First driver that succeeds wins */
5153 if (select_driver(wpa_s, i) == 0)
5154 return 0;
5155 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005156 }
5157
5158 driver = pos + 1;
5159 } while (pos);
5160
5161 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5162 return -1;
5163}
5164
5165
5166/**
5167 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5168 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5169 * with struct wpa_driver_ops::init()
5170 * @src_addr: Source address of the EAPOL frame
5171 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5172 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005173 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005174 *
5175 * This function is called for each received EAPOL frame. Most driver
5176 * interfaces rely on more generic OS mechanism for receiving frames through
5177 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5178 * take care of received EAPOL frames and deliver them to the core supplicant
5179 * code by calling this function.
5180 */
5181void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005182 const u8 *buf, size_t len,
5183 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005184{
5185 struct wpa_supplicant *wpa_s = ctx;
5186
Sunil8cd6f4d2022-06-28 18:40:46 +00005187 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5188 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005189 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5190
Hai Shalomc1a21442022-02-04 13:43:00 -08005191 if (wpa_s->own_disconnect_req) {
5192 wpa_printf(MSG_DEBUG,
5193 "Drop received EAPOL frame as we are disconnecting");
5194 return;
5195 }
5196
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005197#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005198 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5199 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005200 if (wpa_s->ignore_auth_resp) {
5201 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5202 return;
5203 }
5204#endif /* CONFIG_TESTING_OPTIONS */
5205
Jouni Malinena05074c2012-12-21 21:35:35 +02005206 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5207 (wpa_s->last_eapol_matches_bssid &&
5208#ifdef CONFIG_AP
5209 !wpa_s->ap_iface &&
5210#endif /* CONFIG_AP */
5211 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005212 /*
5213 * There is possible race condition between receiving the
5214 * association event and the EAPOL frame since they are coming
5215 * through different paths from the driver. In order to avoid
5216 * issues in trying to process the EAPOL frame before receiving
5217 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005218 * the association event is received. This may also be needed in
5219 * driver-based roaming case, so also use src_addr != BSSID as a
5220 * trigger if we have previously confirmed that the
5221 * Authenticator uses BSSID as the src_addr (which is not the
5222 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005223 */
5224 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02005225 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
5226 wpa_supplicant_state_txt(wpa_s->wpa_state),
5227 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005228 wpabuf_free(wpa_s->pending_eapol_rx);
5229 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5230 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005231 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005232 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5233 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005234 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005235 }
5236 return;
5237 }
5238
Jouni Malinena05074c2012-12-21 21:35:35 +02005239 wpa_s->last_eapol_matches_bssid =
5240 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
5241
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005242#ifdef CONFIG_AP
5243 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005244 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5245 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005246 return;
5247 }
5248#endif /* CONFIG_AP */
5249
5250 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5251 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5252 "no key management is configured");
5253 return;
5254 }
5255
5256 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005257 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005258 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5259 wpa_s->wpa_state != WPA_COMPLETED) &&
5260 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005261 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005262 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005263 int timeout = 10;
5264
5265 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5266 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5267 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5268 /* Use longer timeout for IEEE 802.1X/EAP */
5269 timeout = 70;
5270 }
5271
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005272#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005273 if (wpa_s->current_ssid && wpa_s->current_bss &&
5274 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5275 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5276 /*
5277 * Use shorter timeout if going through WPS AP iteration
5278 * for PIN config method with an AP that does not
5279 * advertise Selected Registrar.
5280 */
5281 struct wpabuf *wps_ie;
5282
5283 wps_ie = wpa_bss_get_vendor_ie_multi(
5284 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5285 if (wps_ie &&
5286 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5287 timeout = 10;
5288 wpabuf_free(wps_ie);
5289 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005290#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005291
5292 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005293 }
5294 wpa_s->eapol_received++;
5295
5296 if (wpa_s->countermeasures) {
5297 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5298 "EAPOL packet");
5299 return;
5300 }
5301
5302#ifdef CONFIG_IBSS_RSN
5303 if (wpa_s->current_ssid &&
5304 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005305 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5306 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005307 return;
5308 }
5309#endif /* CONFIG_IBSS_RSN */
5310
5311 /* Source address of the incoming EAPOL frame could be compared to the
5312 * current BSSID. However, it is possible that a centralized
5313 * Authenticator could be using another MAC address than the BSSID of
5314 * an AP, so just allow any address to be used for now. The replies are
5315 * still sent to the current BSSID (if available), though. */
5316
5317 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5318 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005319 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5320 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005321 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5322 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005323 return;
5324 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005325 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005326 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005327 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5328 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005329 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005330 * handshake processing which would normally set portValid. We
5331 * need this to allow the EAPOL state machines to be completed
5332 * without going through EAPOL-Key handshake.
5333 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005334 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005335 }
5336}
5337
5338
Sunil8cd6f4d2022-06-28 18:40:46 +00005339static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5340 const u8 *buf, size_t len)
5341{
5342 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5343 FRAME_ENCRYPTION_UNKNOWN);
5344}
5345
5346
Hai Shalomb755a2a2020-04-23 21:49:02 -07005347static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5348{
5349 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5350 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5351}
5352
5353
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005354int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005355{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005356 if ((!wpa_s->p2p_mgmt ||
5357 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5358 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005359 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005360 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5361 wpa_drv_get_mac_addr(wpa_s),
5362 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005363 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005364 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005365 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005366 if (wpa_s->l2 == NULL)
5367 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005368
5369 if (l2_packet_set_packet_filter(wpa_s->l2,
5370 L2_PACKET_FILTER_PKTTYPE))
5371 wpa_dbg(wpa_s, MSG_DEBUG,
5372 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005373
5374 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5375 wpa_msg(wpa_s, MSG_ERROR,
5376 "Failed to get own L2 address");
5377 return -1;
5378 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005379 } else {
5380 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5381 if (addr)
5382 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5383 }
5384
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005385 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005386 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005387
Hai Shalomc3565922019-10-28 11:58:20 -07005388#ifdef CONFIG_FST
5389 if (wpa_s->fst)
5390 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5391#endif /* CONFIG_FST */
5392
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005393 return 0;
5394}
5395
5396
Dmitry Shmidt04949592012-07-19 12:16:46 -07005397static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5398 const u8 *buf, size_t len)
5399{
5400 struct wpa_supplicant *wpa_s = ctx;
5401 const struct l2_ethhdr *eth;
5402
5403 if (len < sizeof(*eth))
5404 return;
5405 eth = (const struct l2_ethhdr *) buf;
5406
5407 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5408 !(eth->h_dest[0] & 0x01)) {
5409 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5410 " (bridge - not for this interface - ignore)",
5411 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5412 return;
5413 }
5414
5415 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5416 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5417 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005418 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005419}
5420
5421
Hai Shalom899fcc72020-10-19 14:38:18 -07005422int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5423 const char *bridge_ifname)
5424{
5425 if (wpa_s->wpa_state > WPA_SCANNING)
5426 return -EBUSY;
5427
5428 if (bridge_ifname &&
5429 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5430 return -EINVAL;
5431
5432 if (!bridge_ifname)
5433 bridge_ifname = "";
5434
5435 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5436 return 0;
5437
5438 if (wpa_s->l2_br) {
5439 l2_packet_deinit(wpa_s->l2_br);
5440 wpa_s->l2_br = NULL;
5441 }
5442
5443 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5444 sizeof(wpa_s->bridge_ifname));
5445
5446 if (wpa_s->bridge_ifname[0]) {
5447 wpa_dbg(wpa_s, MSG_DEBUG,
5448 "Receiving packets from bridge interface '%s'",
5449 wpa_s->bridge_ifname);
5450 wpa_s->l2_br = l2_packet_init_bridge(
5451 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5452 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5453 if (!wpa_s->l2_br) {
5454 wpa_msg(wpa_s, MSG_ERROR,
5455 "Failed to open l2_packet connection for the bridge interface '%s'",
5456 wpa_s->bridge_ifname);
5457 goto fail;
5458 }
5459 }
5460
5461#ifdef CONFIG_TDLS
5462 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5463 goto fail;
5464#endif /* CONFIG_TDLS */
5465
5466 return 0;
5467fail:
5468 wpa_s->bridge_ifname[0] = 0;
5469 if (wpa_s->l2_br) {
5470 l2_packet_deinit(wpa_s->l2_br);
5471 wpa_s->l2_br = NULL;
5472 }
5473#ifdef CONFIG_TDLS
5474 if (!wpa_s->p2p_mgmt)
5475 wpa_tdls_init(wpa_s->wpa);
5476#endif /* CONFIG_TDLS */
5477 return -EIO;
5478}
5479
5480
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005481/**
5482 * wpa_supplicant_driver_init - Initialize driver interface parameters
5483 * @wpa_s: Pointer to wpa_supplicant data
5484 * Returns: 0 on success, -1 on failure
5485 *
5486 * This function is called to initialize driver interface parameters.
5487 * wpa_drv_init() must have been called before this function to initialize the
5488 * driver interface.
5489 */
5490int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5491{
5492 static int interface_count = 0;
5493
5494 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5495 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005496
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005497 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5498 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005499 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005500 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5501
Hai Shalomb755a2a2020-04-23 21:49:02 -07005502 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005503 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5504 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005505 wpa_s->l2_br = l2_packet_init_bridge(
5506 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5507 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005508 if (wpa_s->l2_br == NULL) {
5509 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5510 "connection for the bridge interface '%s'",
5511 wpa_s->bridge_ifname);
5512 return -1;
5513 }
5514 }
5515
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005516 if (wpa_s->conf->ap_scan == 2 &&
5517 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5518 wpa_printf(MSG_INFO,
5519 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5520 }
5521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005522 wpa_clear_keys(wpa_s, NULL);
5523
5524 /* Make sure that TKIP countermeasures are not left enabled (could
5525 * happen if wpa_supplicant is killed during countermeasures. */
5526 wpa_drv_set_countermeasures(wpa_s, 0);
5527
5528 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5529 wpa_drv_flush_pmkid(wpa_s);
5530
5531 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005532 wpa_s->prev_scan_wildcard = 0;
5533
Dmitry Shmidt04949592012-07-19 12:16:46 -07005534 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005535 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5536 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5537 interface_count = 0;
5538 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005539#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005540 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005541 wpa_supplicant_delayed_sched_scan(wpa_s,
5542 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005543 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005544 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005545 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005546#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005547 interface_count++;
5548 } else
5549 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5550
5551 return 0;
5552}
5553
5554
5555static int wpa_supplicant_daemon(const char *pid_file)
5556{
5557 wpa_printf(MSG_DEBUG, "Daemonize..");
5558 return os_daemonize(pid_file);
5559}
5560
5561
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005562static struct wpa_supplicant *
5563wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005564{
5565 struct wpa_supplicant *wpa_s;
5566
5567 wpa_s = os_zalloc(sizeof(*wpa_s));
5568 if (wpa_s == NULL)
5569 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005570 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005571 wpa_s->scan_interval = 5;
5572 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005573 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005574 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005575 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005576 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005577
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005578 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005579 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005580#ifdef CONFIG_TESTING_OPTIONS
5581 dl_list_init(&wpa_s->drv_signal_override);
5582#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005583 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005584
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005585 return wpa_s;
5586}
5587
5588
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005589#ifdef CONFIG_HT_OVERRIDES
5590
5591static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5592 struct ieee80211_ht_capabilities *htcaps,
5593 struct ieee80211_ht_capabilities *htcaps_mask,
5594 const char *ht_mcs)
5595{
5596 /* parse ht_mcs into hex array */
5597 int i;
5598 const char *tmp = ht_mcs;
5599 char *end = NULL;
5600
5601 /* If ht_mcs is null, do not set anything */
5602 if (!ht_mcs)
5603 return 0;
5604
5605 /* This is what we are setting in the kernel */
5606 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5607
5608 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5609
5610 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005611 long v;
5612
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005613 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005614 v = strtol(tmp, &end, 16);
5615
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005616 if (errno == 0) {
5617 wpa_msg(wpa_s, MSG_DEBUG,
5618 "htcap value[%i]: %ld end: %p tmp: %p",
5619 i, v, end, tmp);
5620 if (end == tmp)
5621 break;
5622
5623 htcaps->supported_mcs_set[i] = v;
5624 tmp = end;
5625 } else {
5626 wpa_msg(wpa_s, MSG_ERROR,
5627 "Failed to parse ht-mcs: %s, error: %s\n",
5628 ht_mcs, strerror(errno));
5629 return -1;
5630 }
5631 }
5632
5633 /*
5634 * If we were able to parse any values, then set mask for the MCS set.
5635 */
5636 if (i) {
5637 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5638 IEEE80211_HT_MCS_MASK_LEN - 1);
5639 /* skip the 3 reserved bits */
5640 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5641 0x1f;
5642 }
5643
5644 return 0;
5645}
5646
5647
5648static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5649 struct ieee80211_ht_capabilities *htcaps,
5650 struct ieee80211_ht_capabilities *htcaps_mask,
5651 int disabled)
5652{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005653 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005654
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005655 if (disabled == -1)
5656 return 0;
5657
Hai Shalom74f70d42019-02-11 14:42:39 -08005658 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5659
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005660 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5661 htcaps_mask->ht_capabilities_info |= msk;
5662 if (disabled)
5663 htcaps->ht_capabilities_info &= msk;
5664 else
5665 htcaps->ht_capabilities_info |= msk;
5666
5667 return 0;
5668}
5669
5670
5671static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5672 struct ieee80211_ht_capabilities *htcaps,
5673 struct ieee80211_ht_capabilities *htcaps_mask,
5674 int factor)
5675{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005676 if (factor == -1)
5677 return 0;
5678
Hai Shalom74f70d42019-02-11 14:42:39 -08005679 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5680
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005681 if (factor < 0 || factor > 3) {
5682 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5683 "Must be 0-3 or -1", factor);
5684 return -EINVAL;
5685 }
5686
5687 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5688 htcaps->a_mpdu_params &= ~0x3;
5689 htcaps->a_mpdu_params |= factor & 0x3;
5690
5691 return 0;
5692}
5693
5694
5695static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5696 struct ieee80211_ht_capabilities *htcaps,
5697 struct ieee80211_ht_capabilities *htcaps_mask,
5698 int density)
5699{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005700 if (density == -1)
5701 return 0;
5702
Hai Shalom74f70d42019-02-11 14:42:39 -08005703 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5704
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005705 if (density < 0 || density > 7) {
5706 wpa_msg(wpa_s, MSG_ERROR,
5707 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5708 density);
5709 return -EINVAL;
5710 }
5711
5712 htcaps_mask->a_mpdu_params |= 0x1C;
5713 htcaps->a_mpdu_params &= ~(0x1C);
5714 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5715
5716 return 0;
5717}
5718
5719
5720static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5721 struct ieee80211_ht_capabilities *htcaps,
5722 struct ieee80211_ht_capabilities *htcaps_mask,
5723 int disabled)
5724{
Hai Shalom74f70d42019-02-11 14:42:39 -08005725 if (disabled)
5726 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005727
Paul Stewart092955c2017-02-06 09:13:09 -08005728 set_disable_ht40(htcaps, disabled);
5729 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005730
5731 return 0;
5732}
5733
5734
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005735static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5736 struct ieee80211_ht_capabilities *htcaps,
5737 struct ieee80211_ht_capabilities *htcaps_mask,
5738 int disabled)
5739{
5740 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005741 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5742 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005743
Hai Shalom74f70d42019-02-11 14:42:39 -08005744 if (disabled)
5745 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005746
5747 if (disabled)
5748 htcaps->ht_capabilities_info &= ~msk;
5749 else
5750 htcaps->ht_capabilities_info |= msk;
5751
5752 htcaps_mask->ht_capabilities_info |= msk;
5753
5754 return 0;
5755}
5756
5757
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005758static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5759 struct ieee80211_ht_capabilities *htcaps,
5760 struct ieee80211_ht_capabilities *htcaps_mask,
5761 int disabled)
5762{
5763 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005764 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005765
Hai Shalom74f70d42019-02-11 14:42:39 -08005766 if (disabled)
5767 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005768
5769 if (disabled)
5770 htcaps->ht_capabilities_info &= ~msk;
5771 else
5772 htcaps->ht_capabilities_info |= msk;
5773
5774 htcaps_mask->ht_capabilities_info |= msk;
5775
5776 return 0;
5777}
5778
5779
Hai Shalom74f70d42019-02-11 14:42:39 -08005780static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5781 struct ieee80211_ht_capabilities *htcaps,
5782 struct ieee80211_ht_capabilities *htcaps_mask,
5783 int tx_stbc)
5784{
5785 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5786
5787 if (tx_stbc == -1)
5788 return 0;
5789
5790 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5791
5792 if (tx_stbc < 0 || tx_stbc > 1) {
5793 wpa_msg(wpa_s, MSG_ERROR,
5794 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5795 return -EINVAL;
5796 }
5797
5798 htcaps_mask->ht_capabilities_info |= msk;
5799 htcaps->ht_capabilities_info &= ~msk;
5800 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5801
5802 return 0;
5803}
5804
5805
5806static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5807 struct ieee80211_ht_capabilities *htcaps,
5808 struct ieee80211_ht_capabilities *htcaps_mask,
5809 int rx_stbc)
5810{
5811 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5812
5813 if (rx_stbc == -1)
5814 return 0;
5815
5816 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5817
5818 if (rx_stbc < 0 || rx_stbc > 3) {
5819 wpa_msg(wpa_s, MSG_ERROR,
5820 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5821 return -EINVAL;
5822 }
5823
5824 htcaps_mask->ht_capabilities_info |= msk;
5825 htcaps->ht_capabilities_info &= ~msk;
5826 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5827
5828 return 0;
5829}
5830
5831
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005832void wpa_supplicant_apply_ht_overrides(
5833 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5834 struct wpa_driver_associate_params *params)
5835{
5836 struct ieee80211_ht_capabilities *htcaps;
5837 struct ieee80211_ht_capabilities *htcaps_mask;
5838
5839 if (!ssid)
5840 return;
5841
5842 params->disable_ht = ssid->disable_ht;
5843 if (!params->htcaps || !params->htcaps_mask)
5844 return;
5845
5846 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5847 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5848 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5849 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5850 ssid->disable_max_amsdu);
5851 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5852 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5853 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005854 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005855 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005856 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5857 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005858
5859 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005860 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005861 htcaps->ht_capabilities_info |= bit;
5862 htcaps_mask->ht_capabilities_info |= bit;
5863 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005864}
5865
5866#endif /* CONFIG_HT_OVERRIDES */
5867
5868
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005869#ifdef CONFIG_VHT_OVERRIDES
5870void wpa_supplicant_apply_vht_overrides(
5871 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5872 struct wpa_driver_associate_params *params)
5873{
5874 struct ieee80211_vht_capabilities *vhtcaps;
5875 struct ieee80211_vht_capabilities *vhtcaps_mask;
5876
5877 if (!ssid)
5878 return;
5879
5880 params->disable_vht = ssid->disable_vht;
5881
5882 vhtcaps = (void *) params->vhtcaps;
5883 vhtcaps_mask = (void *) params->vhtcaps_mask;
5884
5885 if (!vhtcaps || !vhtcaps_mask)
5886 return;
5887
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005888 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5889 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005890
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005891#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005892 if (ssid->disable_sgi) {
5893 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5894 VHT_CAP_SHORT_GI_160);
5895 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5896 VHT_CAP_SHORT_GI_160);
5897 wpa_msg(wpa_s, MSG_DEBUG,
5898 "disable-sgi override specified, vht-caps: 0x%x",
5899 vhtcaps->vht_capabilities_info);
5900 }
5901
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005902 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005903 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5904 int max_ampdu;
5905
5906 max_ampdu = (ssid->vht_capa &
5907 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5908 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005909
5910 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5911 wpa_set_ampdu_factor(wpa_s,
5912 (void *) params->htcaps,
5913 (void *) params->htcaps_mask,
5914 max_ampdu);
5915 }
5916#endif /* CONFIG_HT_OVERRIDES */
5917
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005918#define OVERRIDE_MCS(i) \
5919 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5920 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005921 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005922 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005923 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5924 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005925 } \
5926 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5927 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005928 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005929 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005930 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5931 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005932 }
5933
5934 OVERRIDE_MCS(1);
5935 OVERRIDE_MCS(2);
5936 OVERRIDE_MCS(3);
5937 OVERRIDE_MCS(4);
5938 OVERRIDE_MCS(5);
5939 OVERRIDE_MCS(6);
5940 OVERRIDE_MCS(7);
5941 OVERRIDE_MCS(8);
5942}
5943#endif /* CONFIG_VHT_OVERRIDES */
5944
5945
Hai Shalomfdcde762020-04-02 11:19:20 -07005946#ifdef CONFIG_HE_OVERRIDES
5947void wpa_supplicant_apply_he_overrides(
5948 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5949 struct wpa_driver_associate_params *params)
5950{
5951 if (!ssid)
5952 return;
5953
5954 params->disable_he = ssid->disable_he;
5955}
5956#endif /* CONFIG_HE_OVERRIDES */
5957
5958
Dmitry Shmidt04949592012-07-19 12:16:46 -07005959static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5960{
5961#ifdef PCSC_FUNCS
5962 size_t len;
5963
5964 if (!wpa_s->conf->pcsc_reader)
5965 return 0;
5966
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005967 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005968 if (!wpa_s->scard)
5969 return 1;
5970
5971 if (wpa_s->conf->pcsc_pin &&
5972 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5973 scard_deinit(wpa_s->scard);
5974 wpa_s->scard = NULL;
5975 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5976 return -1;
5977 }
5978
5979 len = sizeof(wpa_s->imsi) - 1;
5980 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5981 scard_deinit(wpa_s->scard);
5982 wpa_s->scard = NULL;
5983 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5984 return -1;
5985 }
5986 wpa_s->imsi[len] = '\0';
5987
5988 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5989
5990 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5991 wpa_s->imsi, wpa_s->mnc_len);
5992
5993 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5994 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5995#endif /* PCSC_FUNCS */
5996
5997 return 0;
5998}
5999
6000
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006001int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
6002{
6003 char *val, *pos;
6004
6005 ext_password_deinit(wpa_s->ext_pw);
6006 wpa_s->ext_pw = NULL;
6007 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
6008
6009 if (!wpa_s->conf->ext_password_backend)
6010 return 0;
6011
6012 val = os_strdup(wpa_s->conf->ext_password_backend);
6013 if (val == NULL)
6014 return -1;
6015 pos = os_strchr(val, ':');
6016 if (pos)
6017 *pos++ = '\0';
6018
6019 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
6020
6021 wpa_s->ext_pw = ext_password_init(val, pos);
6022 os_free(val);
6023 if (wpa_s->ext_pw == NULL) {
6024 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
6025 return -1;
6026 }
6027 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
6028
6029 return 0;
6030}
6031
6032
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006033#ifdef CONFIG_FST
6034
6035static const u8 * wpas_fst_get_bssid_cb(void *ctx)
6036{
6037 struct wpa_supplicant *wpa_s = ctx;
6038
6039 return (is_zero_ether_addr(wpa_s->bssid) ||
6040 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
6041}
6042
6043
6044static void wpas_fst_get_channel_info_cb(void *ctx,
6045 enum hostapd_hw_mode *hw_mode,
6046 u8 *channel)
6047{
6048 struct wpa_supplicant *wpa_s = ctx;
6049
6050 if (wpa_s->current_bss) {
6051 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
6052 channel);
6053 } else if (wpa_s->hw.num_modes) {
6054 *hw_mode = wpa_s->hw.modes[0].mode;
6055 } else {
6056 WPA_ASSERT(0);
6057 *hw_mode = 0;
6058 }
6059}
6060
6061
6062static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
6063{
6064 struct wpa_supplicant *wpa_s = ctx;
6065
6066 *modes = wpa_s->hw.modes;
6067 return wpa_s->hw.num_modes;
6068}
6069
6070
6071static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
6072{
6073 struct wpa_supplicant *wpa_s = ctx;
6074
6075 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
6076 wpa_s->fst_ies = fst_ies;
6077}
6078
6079
6080static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
6081{
6082 struct wpa_supplicant *wpa_s = ctx;
6083
Paul Stewart092955c2017-02-06 09:13:09 -08006084 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
6085 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
6086 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
6087 return -1;
6088 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006089 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08006090 wpa_s->own_addr, wpa_s->bssid,
6091 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006092 0);
6093}
6094
6095
6096static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
6097{
6098 struct wpa_supplicant *wpa_s = ctx;
6099
6100 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6101 return wpa_s->received_mb_ies;
6102}
6103
6104
6105static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
6106 const u8 *buf, size_t size)
6107{
6108 struct wpa_supplicant *wpa_s = ctx;
6109 struct mb_ies_info info;
6110
6111 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
6112
6113 if (!mb_ies_info_by_ies(&info, buf, size)) {
6114 wpabuf_free(wpa_s->received_mb_ies);
6115 wpa_s->received_mb_ies = mb_ies_by_info(&info);
6116 }
6117}
6118
6119
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006120static const u8 * wpas_fst_get_peer_first(void *ctx,
6121 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006122 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006123{
6124 struct wpa_supplicant *wpa_s = ctx;
6125
6126 *get_ctx = NULL;
6127 if (!is_zero_ether_addr(wpa_s->bssid))
6128 return (wpa_s->received_mb_ies || !mb_only) ?
6129 wpa_s->bssid : NULL;
6130 return NULL;
6131}
6132
6133
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07006134static const u8 * wpas_fst_get_peer_next(void *ctx,
6135 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006136 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006137{
6138 return NULL;
6139}
6140
6141void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6142 struct fst_wpa_obj *iface_obj)
6143{
Sunil8cd6f4d2022-06-28 18:40:46 +00006144 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006145 iface_obj->ctx = wpa_s;
6146 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6147 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6148 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6149 iface_obj->set_ies = wpas_fst_set_ies_cb;
6150 iface_obj->send_action = wpas_fst_send_action_cb;
6151 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6152 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6153 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6154 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6155}
6156#endif /* CONFIG_FST */
6157
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006158static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006159 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006160{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006161 struct wowlan_triggers *triggers;
6162 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006163
6164 if (!wpa_s->conf->wowlan_triggers)
6165 return 0;
6166
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006167 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6168 if (triggers) {
6169 ret = wpa_drv_wowlan(wpa_s, triggers);
6170 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006171 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006172 return ret;
6173}
6174
6175
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006176enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006177{
6178 if (freq < 3000)
6179 return BAND_2_4_GHZ;
6180 if (freq > 50000)
6181 return BAND_60_GHZ;
6182 return BAND_5_GHZ;
6183}
6184
6185
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006186unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006187{
6188 int i;
6189 unsigned int band = 0;
6190
6191 if (freqs) {
6192 /* freqs are specified for the radio work */
6193 for (i = 0; freqs[i]; i++)
6194 band |= wpas_freq_to_band(freqs[i]);
6195 } else {
6196 /*
6197 * freqs are not specified, implies all
6198 * the supported freqs by HW
6199 */
6200 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6201 if (wpa_s->hw.modes[i].num_channels != 0) {
6202 if (wpa_s->hw.modes[i].mode ==
6203 HOSTAPD_MODE_IEEE80211B ||
6204 wpa_s->hw.modes[i].mode ==
6205 HOSTAPD_MODE_IEEE80211G)
6206 band |= BAND_2_4_GHZ;
6207 else if (wpa_s->hw.modes[i].mode ==
6208 HOSTAPD_MODE_IEEE80211A)
6209 band |= BAND_5_GHZ;
6210 else if (wpa_s->hw.modes[i].mode ==
6211 HOSTAPD_MODE_IEEE80211AD)
6212 band |= BAND_60_GHZ;
6213 else if (wpa_s->hw.modes[i].mode ==
6214 HOSTAPD_MODE_IEEE80211ANY)
6215 band = BAND_2_4_GHZ | BAND_5_GHZ |
6216 BAND_60_GHZ;
6217 }
6218 }
6219 }
6220
6221 return band;
6222}
6223
6224
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006225static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6226 const char *rn)
6227{
6228 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6229 struct wpa_radio *radio;
6230
6231 while (rn && iface) {
6232 radio = iface->radio;
6233 if (radio && os_strcmp(rn, radio->name) == 0) {
6234 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6235 wpa_s->ifname, rn);
6236 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6237 return radio;
6238 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006239
6240 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006241 }
6242
6243 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6244 wpa_s->ifname, rn ? rn : "N/A");
6245 radio = os_zalloc(sizeof(*radio));
6246 if (radio == NULL)
6247 return NULL;
6248
6249 if (rn)
6250 os_strlcpy(radio->name, rn, sizeof(radio->name));
6251 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006252 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006253 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6254
6255 return radio;
6256}
6257
6258
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006259static void radio_work_free(struct wpa_radio_work *work)
6260{
6261 if (work->wpa_s->scan_work == work) {
6262 /* This should not really happen. */
6263 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6264 work->type, work, work->started);
6265 work->wpa_s->scan_work = NULL;
6266 }
6267
6268#ifdef CONFIG_P2P
6269 if (work->wpa_s->p2p_scan_work == work) {
6270 /* This should not really happen. */
6271 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6272 work->type, work, work->started);
6273 work->wpa_s->p2p_scan_work = NULL;
6274 }
6275#endif /* CONFIG_P2P */
6276
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006277 if (work->started) {
6278 work->wpa_s->radio->num_active_works--;
6279 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006280 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006281 work->type, work,
6282 work->wpa_s->radio->num_active_works);
6283 }
6284
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006285 dl_list_del(&work->list);
6286 os_free(work);
6287}
6288
6289
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006290static int radio_work_is_connect(struct wpa_radio_work *work)
6291{
6292 return os_strcmp(work->type, "sme-connect") == 0 ||
6293 os_strcmp(work->type, "connect") == 0;
6294}
6295
6296
6297static int radio_work_is_scan(struct wpa_radio_work *work)
6298{
6299 return os_strcmp(work->type, "scan") == 0 ||
6300 os_strcmp(work->type, "p2p-scan") == 0;
6301}
6302
6303
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006304static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6305{
6306 struct wpa_radio_work *active_work = NULL;
6307 struct wpa_radio_work *tmp;
6308
6309 /* Get the active work to know the type and band. */
6310 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6311 if (tmp->started) {
6312 active_work = tmp;
6313 break;
6314 }
6315 }
6316
6317 if (!active_work) {
6318 /* No active work, start one */
6319 radio->num_active_works = 0;
6320 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6321 list) {
6322 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006323 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006324 (((struct wpa_driver_scan_params *)
6325 tmp->ctx)->only_new_results ||
6326 tmp->wpa_s->clear_driver_scan_cache))
6327 continue;
6328 return tmp;
6329 }
6330 return NULL;
6331 }
6332
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006333 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006334 /*
6335 * If the active work is either connect or sme-connect,
6336 * do not parallelize them with other radio works.
6337 */
6338 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6339 "Do not parallelize radio work with %s",
6340 active_work->type);
6341 return NULL;
6342 }
6343
6344 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6345 if (tmp->started)
6346 continue;
6347
6348 /*
6349 * If connect or sme-connect are enqueued, parallelize only
6350 * those operations ahead of them in the queue.
6351 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006352 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006353 break;
6354
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006355 /* Serialize parallel scan and p2p_scan operations on the same
6356 * interface since the driver_nl80211 mechanism for tracking
6357 * scan cookies does not yet have support for this. */
6358 if (active_work->wpa_s == tmp->wpa_s &&
6359 radio_work_is_scan(active_work) &&
6360 radio_work_is_scan(tmp)) {
6361 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6362 "Do not start work '%s' when another work '%s' is already scheduled",
6363 tmp->type, active_work->type);
6364 continue;
6365 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006366 /*
6367 * Check that the radio works are distinct and
6368 * on different bands.
6369 */
6370 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6371 (active_work->bands != tmp->bands)) {
6372 /*
6373 * If a scan has to be scheduled through nl80211 scan
6374 * interface and if an external scan is already running,
6375 * do not schedule the scan since it is likely to get
6376 * rejected by kernel.
6377 */
6378 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006379 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006380 (((struct wpa_driver_scan_params *)
6381 tmp->ctx)->only_new_results ||
6382 tmp->wpa_s->clear_driver_scan_cache))
6383 continue;
6384
6385 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6386 "active_work:%s new_work:%s",
6387 active_work->type, tmp->type);
6388 return tmp;
6389 }
6390 }
6391
6392 /* Did not find a radio work to schedule in parallel. */
6393 return NULL;
6394}
6395
6396
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006397static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6398{
6399 struct wpa_radio *radio = eloop_ctx;
6400 struct wpa_radio_work *work;
6401 struct os_reltime now, diff;
6402 struct wpa_supplicant *wpa_s;
6403
6404 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006405 if (work == NULL) {
6406 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006407 return;
6408 }
6409
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006410 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6411 radio_list);
6412
6413 if (!(wpa_s &&
6414 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6415 if (work->started)
6416 return; /* already started and still in progress */
6417
Hai Shalom60840252021-02-19 19:02:11 -08006418 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006419 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6420 return;
6421 }
6422 } else {
6423 work = NULL;
6424 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6425 /* get the work to schedule next */
6426 work = radio_work_get_next_work(radio);
6427 }
6428 if (!work)
6429 return;
6430 }
6431
6432 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006433 os_get_reltime(&now);
6434 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006435 wpa_dbg(wpa_s, MSG_DEBUG,
6436 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006437 work->type, work, diff.sec, diff.usec);
6438 work->started = 1;
6439 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006440 radio->num_active_works++;
6441
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006442 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006443
6444 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6445 radio->num_active_works < MAX_ACTIVE_WORKS)
6446 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006447}
6448
6449
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006450/*
6451 * This function removes both started and pending radio works running on
6452 * the provided interface's radio.
6453 * Prior to the removal of the radio work, its callback (cb) is called with
6454 * deinit set to be 1. Each work's callback is responsible for clearing its
6455 * internal data and restoring to a correct state.
6456 * @wpa_s: wpa_supplicant data
6457 * @type: type of works to be removed
6458 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6459 * this interface's works.
6460 */
6461void radio_remove_works(struct wpa_supplicant *wpa_s,
6462 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006463{
6464 struct wpa_radio_work *work, *tmp;
6465 struct wpa_radio *radio = wpa_s->radio;
6466
6467 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6468 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006469 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006470 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006471
6472 /* skip other ifaces' works */
6473 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006474 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006475
6476 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6477 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006478 work->cb(work, 1);
6479 radio_work_free(work);
6480 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006481
6482 /* in case we removed the started work */
6483 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006484}
6485
6486
Roshan Pius3a1667e2018-07-03 15:17:14 -07006487void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6488{
6489 struct wpa_radio_work *work;
6490 struct wpa_radio *radio = wpa_s->radio;
6491
6492 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6493 if (work->ctx != ctx)
6494 continue;
6495 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6496 work->type, work, work->started ? " (started)" : "");
6497 radio_work_free(work);
6498 break;
6499 }
6500}
6501
6502
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006503static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6504{
6505 struct wpa_radio *radio = wpa_s->radio;
6506
6507 if (!radio)
6508 return;
6509
6510 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6511 wpa_s->ifname, radio->name);
6512 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006513 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006514 /* If the interface that triggered the external scan was removed, the
6515 * external scan is no longer running. */
6516 if (wpa_s == radio->external_scan_req_interface)
6517 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006518 wpa_s->radio = NULL;
6519 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006520 return; /* Interfaces remain for this radio */
6521
6522 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006523 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006524 os_free(radio);
6525}
6526
6527
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006528void radio_work_check_next(struct wpa_supplicant *wpa_s)
6529{
6530 struct wpa_radio *radio = wpa_s->radio;
6531
6532 if (dl_list_empty(&radio->work))
6533 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006534 if (wpa_s->ext_work_in_progress) {
6535 wpa_printf(MSG_DEBUG,
6536 "External radio work in progress - delay start of pending item");
6537 return;
6538 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006539 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6540 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6541}
6542
6543
6544/**
6545 * radio_add_work - Add a radio work item
6546 * @wpa_s: Pointer to wpa_supplicant data
6547 * @freq: Frequency of the offchannel operation in MHz or 0
6548 * @type: Unique identifier for each type of work
6549 * @next: Force as the next work to be executed
6550 * @cb: Callback function for indicating when radio is available
6551 * @ctx: Context pointer for the work (work->ctx in cb())
6552 * Returns: 0 on success, -1 on failure
6553 *
6554 * This function is used to request time for an operation that requires
6555 * exclusive radio control. Once the radio is available, the registered callback
6556 * function will be called. radio_work_done() must be called once the exclusive
6557 * radio operation has been completed, so that the radio is freed for other
6558 * operations. The special case of deinit=1 is used to free the context data
6559 * during interface removal. That does not allow the callback function to start
6560 * the radio operation, i.e., it must free any resources allocated for the radio
6561 * work and return.
6562 *
6563 * The @freq parameter can be used to indicate a single channel on which the
6564 * offchannel operation will occur. This may allow multiple radio work
6565 * operations to be performed in parallel if they apply for the same channel.
6566 * Setting this to 0 indicates that the work item may use multiple channels or
6567 * requires exclusive control of the radio.
6568 */
6569int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6570 const char *type, int next,
6571 void (*cb)(struct wpa_radio_work *work, int deinit),
6572 void *ctx)
6573{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006574 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006575 struct wpa_radio_work *work;
6576 int was_empty;
6577
6578 work = os_zalloc(sizeof(*work));
6579 if (work == NULL)
6580 return -1;
6581 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6582 os_get_reltime(&work->time);
6583 work->freq = freq;
6584 work->type = type;
6585 work->wpa_s = wpa_s;
6586 work->cb = cb;
6587 work->ctx = ctx;
6588
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006589 if (freq)
6590 work->bands = wpas_freq_to_band(freq);
6591 else if (os_strcmp(type, "scan") == 0 ||
6592 os_strcmp(type, "p2p-scan") == 0)
6593 work->bands = wpas_get_bands(wpa_s,
6594 ((struct wpa_driver_scan_params *)
6595 ctx)->freqs);
6596 else
6597 work->bands = wpas_get_bands(wpa_s, NULL);
6598
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006599 was_empty = dl_list_empty(&wpa_s->radio->work);
6600 if (next)
6601 dl_list_add(&wpa_s->radio->work, &work->list);
6602 else
6603 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6604 if (was_empty) {
6605 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6606 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006607 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6608 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6609 wpa_dbg(wpa_s, MSG_DEBUG,
6610 "Try to schedule a radio work (num_active_works=%u)",
6611 radio->num_active_works);
6612 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006613 }
6614
6615 return 0;
6616}
6617
6618
6619/**
6620 * radio_work_done - Indicate that a radio work item has been completed
6621 * @work: Completed work
6622 *
6623 * This function is called once the callback function registered with
6624 * radio_add_work() has completed its work.
6625 */
6626void radio_work_done(struct wpa_radio_work *work)
6627{
6628 struct wpa_supplicant *wpa_s = work->wpa_s;
6629 struct os_reltime now, diff;
6630 unsigned int started = work->started;
6631
6632 os_get_reltime(&now);
6633 os_reltime_sub(&now, &work->time, &diff);
6634 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6635 work->type, work, started ? "done" : "canceled",
6636 diff.sec, diff.usec);
6637 radio_work_free(work);
6638 if (started)
6639 radio_work_check_next(wpa_s);
6640}
6641
6642
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006643struct wpa_radio_work *
6644radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006645{
6646 struct wpa_radio_work *work;
6647 struct wpa_radio *radio = wpa_s->radio;
6648
6649 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6650 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006651 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006652 }
6653
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006654 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006655}
6656
6657
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006658static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006659 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006660{
6661 const char *ifname, *driver, *rn;
6662
6663 driver = iface->driver;
6664next_driver:
6665 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6666 return -1;
6667
6668 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6669 if (wpa_s->drv_priv == NULL) {
6670 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006671 int level = MSG_ERROR;
6672
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006673 pos = driver ? os_strchr(driver, ',') : NULL;
6674 if (pos) {
6675 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6676 "driver interface - try next driver wrapper");
6677 driver = pos + 1;
6678 goto next_driver;
6679 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006680
6681#ifdef CONFIG_MATCH_IFACE
6682 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6683 level = MSG_DEBUG;
6684#endif /* CONFIG_MATCH_IFACE */
6685 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006686 return -1;
6687 }
6688 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6689 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6690 "driver_param '%s'", wpa_s->conf->driver_param);
6691 return -1;
6692 }
6693
6694 ifname = wpa_drv_get_ifname(wpa_s);
6695 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6696 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6697 "interface name with '%s'", ifname);
6698 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6699 }
6700
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006701 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006702 if (rn && rn[0] == '\0')
6703 rn = NULL;
6704
6705 wpa_s->radio = radio_add_interface(wpa_s, rn);
6706 if (wpa_s->radio == NULL)
6707 return -1;
6708
6709 return 0;
6710}
6711
6712
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006713#ifdef CONFIG_GAS_SERVER
6714
6715static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6716 unsigned int freq, const u8 *dst,
6717 const u8 *src, const u8 *bssid,
6718 const u8 *data, size_t data_len,
6719 enum offchannel_send_action_result result)
6720{
6721 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6722 " result=%s",
6723 freq, MAC2STR(dst),
6724 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6725 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6726 "FAILED"));
6727 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6728 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6729}
6730
6731
6732static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6733 struct wpabuf *buf, unsigned int wait_time)
6734{
6735 struct wpa_supplicant *wpa_s = ctx;
6736 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6737
6738 if (wait_time > wpa_s->max_remain_on_chan)
6739 wait_time = wpa_s->max_remain_on_chan;
6740
6741 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6742 wpabuf_head(buf), wpabuf_len(buf),
6743 wait_time, wpas_gas_server_tx_status, 0);
6744}
6745
6746#endif /* CONFIG_GAS_SERVER */
6747
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006748static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006749 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006750{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006751 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006752 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006753 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006754
6755 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6756 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6757 iface->confname ? iface->confname : "N/A",
6758 iface->driver ? iface->driver : "default",
6759 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6760 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6761
6762 if (iface->confname) {
6763#ifdef CONFIG_BACKEND_FILE
6764 wpa_s->confname = os_rel2abs_path(iface->confname);
6765 if (wpa_s->confname == NULL) {
6766 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6767 "for configuration file '%s'.",
6768 iface->confname);
6769 return -1;
6770 }
6771 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6772 iface->confname, wpa_s->confname);
6773#else /* CONFIG_BACKEND_FILE */
6774 wpa_s->confname = os_strdup(iface->confname);
6775#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006776 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006777 if (wpa_s->conf == NULL) {
6778 wpa_printf(MSG_ERROR, "Failed to read or parse "
6779 "configuration '%s'.", wpa_s->confname);
6780 return -1;
6781 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006782 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006783 if (wpa_s->confanother &&
6784 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6785 wpa_printf(MSG_ERROR,
6786 "Failed to read or parse configuration '%s'.",
6787 wpa_s->confanother);
6788 return -1;
6789 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006790
6791 /*
6792 * Override ctrl_interface and driver_param if set on command
6793 * line.
6794 */
6795 if (iface->ctrl_interface) {
6796 os_free(wpa_s->conf->ctrl_interface);
6797 wpa_s->conf->ctrl_interface =
6798 os_strdup(iface->ctrl_interface);
6799 }
6800
6801 if (iface->driver_param) {
6802 os_free(wpa_s->conf->driver_param);
6803 wpa_s->conf->driver_param =
6804 os_strdup(iface->driver_param);
6805 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006806
6807 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6808 os_free(wpa_s->conf->ctrl_interface);
6809 wpa_s->conf->ctrl_interface = NULL;
6810 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006811 } else
6812 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6813 iface->driver_param);
6814
6815 if (wpa_s->conf == NULL) {
6816 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6817 return -1;
6818 }
6819
6820 if (iface->ifname == NULL) {
6821 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6822 return -1;
6823 }
6824 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6825 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6826 iface->ifname);
6827 return -1;
6828 }
6829 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006830#ifdef CONFIG_MATCH_IFACE
6831 wpa_s->matched = iface->matched;
6832#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006833
6834 if (iface->bridge_ifname) {
6835 if (os_strlen(iface->bridge_ifname) >=
6836 sizeof(wpa_s->bridge_ifname)) {
6837 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6838 "name '%s'.", iface->bridge_ifname);
6839 return -1;
6840 }
6841 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6842 sizeof(wpa_s->bridge_ifname));
6843 }
6844
6845 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006846 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6847 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006848
6849 /* Initialize driver interface and register driver event handler before
6850 * L2 receive handler so that association events are processed before
6851 * EAPOL-Key packets if both become available for the same select()
6852 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006853 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006854 return -1;
6855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006856 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6857 return -1;
6858
6859 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6860 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6861 NULL);
6862 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6863
6864 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6865 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6866 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6867 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6868 "dot11RSNAConfigPMKLifetime");
6869 return -1;
6870 }
6871
6872 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6873 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6874 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6875 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6876 "dot11RSNAConfigPMKReauthThreshold");
6877 return -1;
6878 }
6879
6880 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6881 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6882 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6883 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6884 "dot11RSNAConfigSATimeout");
6885 return -1;
6886 }
6887
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006888 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6889 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006890 &wpa_s->hw.flags,
6891 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006892 if (wpa_s->hw.modes) {
6893 u16 i;
6894
6895 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6896 if (wpa_s->hw.modes[i].vht_capab) {
6897 wpa_s->hw_capab = CAPAB_VHT;
6898 break;
6899 }
6900
6901 if (wpa_s->hw.modes[i].ht_capab &
6902 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6903 wpa_s->hw_capab = CAPAB_HT40;
6904 else if (wpa_s->hw.modes[i].ht_capab &&
6905 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6906 wpa_s->hw_capab = CAPAB_HT;
6907 }
6908 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006909
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006910 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6911 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006912 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006913 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006914 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006915 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006916 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07006917 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006918 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006919 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006920 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006921 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6922 wpa_s->max_sched_scan_plan_interval =
6923 capa.max_sched_scan_plan_interval;
6924 wpa_s->max_sched_scan_plan_iterations =
6925 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006926 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6927 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006928 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6929 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006930 wpa_s->extended_capa = capa.extended_capa;
6931 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6932 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006933 wpa_s->num_multichan_concurrent =
6934 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006935 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
Sunil Ravi89eba102022-09-13 21:04:37 -07006936 wpa_s->max_num_akms = capa.max_num_akms;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006937
6938 if (capa.mac_addr_rand_scan_supported)
6939 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6940 if (wpa_s->sched_scan_supported &&
6941 capa.mac_addr_rand_sched_scan_supported)
6942 wpa_s->mac_addr_rand_supported |=
6943 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006944
6945 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6946 if (wpa_s->extended_capa &&
6947 wpa_s->extended_capa_len >= 3 &&
6948 wpa_s->extended_capa[2] & 0x40)
6949 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006950 }
Sunil Ravi89eba102022-09-13 21:04:37 -07006951#ifdef CONFIG_PASN
6952 wpa_pasn_sm_set_caps(wpa_s->wpa, wpa_s->drv_flags2);
6953#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006954 if (wpa_s->max_remain_on_chan == 0)
6955 wpa_s->max_remain_on_chan = 1000;
6956
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006957 /*
6958 * Only take p2p_mgmt parameters when P2P Device is supported.
6959 * Doing it here as it determines whether l2_packet_init() will be done
6960 * during wpa_supplicant_driver_init().
6961 */
6962 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6963 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006964
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006965 if (wpa_s->num_multichan_concurrent == 0)
6966 wpa_s->num_multichan_concurrent = 1;
6967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006968 if (wpa_supplicant_driver_init(wpa_s) < 0)
6969 return -1;
6970
6971#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006972 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006973 return -1;
6974#endif /* CONFIG_TDLS */
6975
6976 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6977 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6978 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6979 return -1;
6980 }
6981
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006982#ifdef CONFIG_FST
6983 if (wpa_s->conf->fst_group_id) {
6984 struct fst_iface_cfg cfg;
6985 struct fst_wpa_obj iface_obj;
6986
6987 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6988 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6989 sizeof(cfg.group_id));
6990 cfg.priority = wpa_s->conf->fst_priority;
6991 cfg.llt = wpa_s->conf->fst_llt;
6992
6993 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6994 &iface_obj, &cfg);
6995 if (!wpa_s->fst) {
6996 wpa_msg(wpa_s, MSG_ERROR,
6997 "FST: Cannot attach iface %s to group %s",
6998 wpa_s->ifname, cfg.group_id);
6999 return -1;
7000 }
7001 }
7002#endif /* CONFIG_FST */
7003
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007004 if (wpas_wps_init(wpa_s))
7005 return -1;
7006
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007007#ifdef CONFIG_GAS_SERVER
7008 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
7009 if (!wpa_s->gas_server) {
7010 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
7011 return -1;
7012 }
7013#endif /* CONFIG_GAS_SERVER */
7014
7015#ifdef CONFIG_DPP
7016 if (wpas_dpp_init(wpa_s) < 0)
7017 return -1;
7018#endif /* CONFIG_DPP */
7019
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007020 if (wpa_supplicant_init_eapol(wpa_s) < 0)
7021 return -1;
7022 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
7023
7024 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
7025 if (wpa_s->ctrl_iface == NULL) {
7026 wpa_printf(MSG_ERROR,
7027 "Failed to initialize control interface '%s'.\n"
7028 "You may have another wpa_supplicant process "
7029 "already running or the file was\n"
7030 "left by an unclean termination of wpa_supplicant "
7031 "in which case you will need\n"
7032 "to manually remove this file before starting "
7033 "wpa_supplicant again.\n",
7034 wpa_s->conf->ctrl_interface);
7035 return -1;
7036 }
7037
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007038 wpa_s->gas = gas_query_init(wpa_s);
7039 if (wpa_s->gas == NULL) {
7040 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
7041 return -1;
7042 }
7043
Roshan Pius3a1667e2018-07-03 15:17:14 -07007044 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
7045 wpa_s->p2p_mgmt) &&
7046 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007047 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
7048 return -1;
7049 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007050
7051 if (wpa_bss_init(wpa_s) < 0)
7052 return -1;
7053
Paul Stewart092955c2017-02-06 09:13:09 -08007054#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
7055#ifdef CONFIG_MESH
7056 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
7057#endif /* CONFIG_MESH */
7058#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
7059
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007060 /*
7061 * Set Wake-on-WLAN triggers, if configured.
7062 * Note: We don't restore/remove the triggers on shutdown (it doesn't
7063 * have effect anyway when the interface is down).
7064 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007065 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007066 return -1;
7067
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007068#ifdef CONFIG_EAP_PROXY
7069{
7070 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007071 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
7072 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007073 if (wpa_s->mnc_len > 0) {
7074 wpa_s->imsi[len] = '\0';
7075 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
7076 wpa_s->imsi, wpa_s->mnc_len);
7077 } else {
7078 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
7079 }
7080}
7081#endif /* CONFIG_EAP_PROXY */
7082
Dmitry Shmidt04949592012-07-19 12:16:46 -07007083 if (pcsc_reader_init(wpa_s) < 0)
7084 return -1;
7085
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007086 if (wpas_init_ext_pw(wpa_s) < 0)
7087 return -1;
7088
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007089 wpas_rrm_reset(wpa_s);
7090
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007091 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7092
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007093#ifdef CONFIG_HS20
7094 hs20_init(wpa_s);
7095#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007096#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07007097 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007098 if ((wpa_s->conf->oce & OCE_STA) &&
7099 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
7100 wpa_s->enable_oce = OCE_STA;
7101 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
7102 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
7103 /* TODO: Need to add STA-CFON support */
7104 wpa_printf(MSG_ERROR,
7105 "OCE STA-CFON feature is not yet supported");
7106 }
7107 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007108 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
7109#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007110
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007111 wpa_supplicant_set_default_scan_ies(wpa_s);
7112
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007113 return 0;
7114}
7115
7116
7117static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007118 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007119{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007120 struct wpa_global *global = wpa_s->global;
7121 struct wpa_supplicant *iface, *prev;
7122
Jimmy Chen0e73c002021-08-18 13:21:30 +08007123 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007124 wpas_p2p_group_remove(wpa_s, "*");
7125
7126 iface = global->ifaces;
7127 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007128 if (iface->p2pdev == wpa_s)
7129 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007130 if (iface == wpa_s || iface->parent != wpa_s) {
7131 iface = iface->next;
7132 continue;
7133 }
7134 wpa_printf(MSG_DEBUG,
7135 "Remove remaining child interface %s from parent %s",
7136 iface->ifname, wpa_s->ifname);
7137 prev = iface;
7138 iface = iface->next;
7139 wpa_supplicant_remove_iface(global, prev, terminate);
7140 }
7141
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007142 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007143 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007144 /*
7145 * Don't deauthenticate if WoWLAN is enable and not explicitly
7146 * been configured to disconnect.
7147 */
7148 if (!wpa_drv_get_wowlan(wpa_s) ||
7149 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007150 wpa_supplicant_deauthenticate(
7151 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007152
Hai Shalomfdcde762020-04-02 11:19:20 -07007153 wpa_drv_set_countermeasures(wpa_s, 0);
7154 wpa_clear_keys(wpa_s, NULL);
7155 } else {
7156 wpa_msg(wpa_s, MSG_INFO,
7157 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7158 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007159 }
7160
7161 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007162 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007163
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007164 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007165 radio_remove_interface(wpa_s);
7166
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007167#ifdef CONFIG_FST
7168 if (wpa_s->fst) {
7169 fst_detach(wpa_s->fst);
7170 wpa_s->fst = NULL;
7171 }
7172 if (wpa_s->received_mb_ies) {
7173 wpabuf_free(wpa_s->received_mb_ies);
7174 wpa_s->received_mb_ies = NULL;
7175 }
7176#endif /* CONFIG_FST */
7177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007178 if (wpa_s->drv_priv)
7179 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007180
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007181 if (notify)
7182 wpas_notify_iface_removed(wpa_s);
7183
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007184 if (terminate)
7185 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007186
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007187 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7188 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007189
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007190#ifdef CONFIG_MESH
7191 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007192 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007193 wpa_s->ifmsh = NULL;
7194 }
7195#endif /* CONFIG_MESH */
7196
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007197 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007198 wpa_config_free(wpa_s->conf);
7199 wpa_s->conf = NULL;
7200 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007201
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007202 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007203 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007204
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007205 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007206}
7207
7208
Dmitry Shmidte4663042016-04-04 10:07:49 -07007209#ifdef CONFIG_MATCH_IFACE
7210
7211/**
7212 * wpa_supplicant_match_iface - Match an interface description to a name
7213 * @global: Pointer to global data from wpa_supplicant_init()
7214 * @ifname: Name of the interface to match
7215 * Returns: Pointer to the created interface description or %NULL on failure
7216 */
7217struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7218 const char *ifname)
7219{
7220 int i;
7221 struct wpa_interface *iface, *miface;
7222
7223 for (i = 0; i < global->params.match_iface_count; i++) {
7224 miface = &global->params.match_ifaces[i];
7225 if (!miface->ifname ||
7226 fnmatch(miface->ifname, ifname, 0) == 0) {
7227 iface = os_zalloc(sizeof(*iface));
7228 if (!iface)
7229 return NULL;
7230 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007231 if (!miface->ifname)
7232 iface->matched = WPA_IFACE_MATCHED_NULL;
7233 else
7234 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007235 iface->ifname = ifname;
7236 return iface;
7237 }
7238 }
7239
7240 return NULL;
7241}
7242
7243
7244/**
7245 * wpa_supplicant_match_existing - Match existing interfaces
7246 * @global: Pointer to global data from wpa_supplicant_init()
7247 * Returns: 0 on success, -1 on failure
7248 */
7249static int wpa_supplicant_match_existing(struct wpa_global *global)
7250{
7251 struct if_nameindex *ifi, *ifp;
7252 struct wpa_supplicant *wpa_s;
7253 struct wpa_interface *iface;
7254
7255 ifp = if_nameindex();
7256 if (!ifp) {
7257 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7258 return -1;
7259 }
7260
7261 for (ifi = ifp; ifi->if_name; ifi++) {
7262 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7263 if (wpa_s)
7264 continue;
7265 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7266 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007267 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007268 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007269 }
7270 }
7271
7272 if_freenameindex(ifp);
7273 return 0;
7274}
7275
7276#endif /* CONFIG_MATCH_IFACE */
7277
7278
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007279/**
7280 * wpa_supplicant_add_iface - Add a new network interface
7281 * @global: Pointer to global data from wpa_supplicant_init()
7282 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007283 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007284 * Returns: Pointer to the created interface or %NULL on failure
7285 *
7286 * This function is used to add new network interfaces for %wpa_supplicant.
7287 * This can be called before wpa_supplicant_run() to add interfaces before the
7288 * main event loop has been started. In addition, new interfaces can be added
7289 * dynamically while %wpa_supplicant is already running. This could happen,
7290 * e.g., when a hotplug network adapter is inserted.
7291 */
7292struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007293 struct wpa_interface *iface,
7294 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007295{
7296 struct wpa_supplicant *wpa_s;
7297 struct wpa_interface t_iface;
7298 struct wpa_ssid *ssid;
7299
7300 if (global == NULL || iface == NULL)
7301 return NULL;
7302
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007303 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007304 if (wpa_s == NULL)
7305 return NULL;
7306
7307 wpa_s->global = global;
7308
7309 t_iface = *iface;
7310 if (global->params.override_driver) {
7311 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7312 "('%s' -> '%s')",
7313 iface->driver, global->params.override_driver);
7314 t_iface.driver = global->params.override_driver;
7315 }
7316 if (global->params.override_ctrl_interface) {
7317 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7318 "ctrl_interface ('%s' -> '%s')",
7319 iface->ctrl_interface,
7320 global->params.override_ctrl_interface);
7321 t_iface.ctrl_interface =
7322 global->params.override_ctrl_interface;
7323 }
7324 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7325 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7326 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007327 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007328 return NULL;
7329 }
7330
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007331 /* Notify the control interfaces about new iface */
7332 if (wpas_notify_iface_added(wpa_s)) {
7333 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7334 return NULL;
7335 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007336
Jimmy Chene2206be2022-07-10 10:25:21 +08007337 /* Notify the control interfaces about new networks */
7338 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
7339 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007340 wpas_notify_network_added(wpa_s, ssid);
Jimmy Chene2206be2022-07-10 10:25:21 +08007341 } else if (ssid->ssid_len > P2P_WILDCARD_SSID_LEN
7342 && os_strncmp((const char *) ssid->ssid,
7343 P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) {
7344 wpas_notify_persistent_group_added(wpa_s, ssid);
7345 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007346 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007347
7348 wpa_s->next = global->ifaces;
7349 global->ifaces = wpa_s;
7350
7351 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007352 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007353
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007354#ifdef CONFIG_P2P
7355 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007356 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007357 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007358 wpas_p2p_add_p2pdev_interface(
7359 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007360 wpa_printf(MSG_INFO,
7361 "P2P: Failed to enable P2P Device interface");
7362 /* Try to continue without. P2P will be disabled. */
7363 }
7364#endif /* CONFIG_P2P */
7365
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007366 return wpa_s;
7367}
7368
7369
7370/**
7371 * wpa_supplicant_remove_iface - Remove a network interface
7372 * @global: Pointer to global data from wpa_supplicant_init()
7373 * @wpa_s: Pointer to the network interface to be removed
7374 * Returns: 0 if interface was removed, -1 if interface was not found
7375 *
7376 * This function can be used to dynamically remove network interfaces from
7377 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7378 * addition, this function is used to remove all remaining interfaces when
7379 * %wpa_supplicant is terminated.
7380 */
7381int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007382 struct wpa_supplicant *wpa_s,
7383 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007384{
7385 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007386#ifdef CONFIG_MESH
7387 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7388 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007389 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007390#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007391
7392 /* Remove interface from the global list of interfaces */
7393 prev = global->ifaces;
7394 if (prev == wpa_s) {
7395 global->ifaces = wpa_s->next;
7396 } else {
7397 while (prev && prev->next != wpa_s)
7398 prev = prev->next;
7399 if (prev == NULL)
7400 return -1;
7401 prev->next = wpa_s->next;
7402 }
7403
7404 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7405
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007406#ifdef CONFIG_MESH
7407 if (mesh_if_created) {
7408 ifname = os_strdup(wpa_s->ifname);
7409 if (ifname == NULL) {
7410 wpa_dbg(wpa_s, MSG_ERROR,
7411 "mesh: Failed to malloc ifname");
7412 return -1;
7413 }
7414 }
7415#endif /* CONFIG_MESH */
7416
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007417 if (global->p2p_group_formation == wpa_s)
7418 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007419 if (global->p2p_invite_group == wpa_s)
7420 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007421 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007422
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007423#ifdef CONFIG_MESH
7424 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007425 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007426 os_free(ifname);
7427 }
7428#endif /* CONFIG_MESH */
7429
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007430 return 0;
7431}
7432
7433
7434/**
7435 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7436 * @wpa_s: Pointer to the network interface
7437 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7438 */
7439const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7440{
7441 const char *eapol_method;
7442
7443 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7444 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7445 return "NO-EAP";
7446 }
7447
7448 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7449 if (eapol_method == NULL)
7450 return "UNKNOWN-EAP";
7451
7452 return eapol_method;
7453}
7454
7455
7456/**
7457 * wpa_supplicant_get_iface - Get a new network interface
7458 * @global: Pointer to global data from wpa_supplicant_init()
7459 * @ifname: Interface name
7460 * Returns: Pointer to the interface or %NULL if not found
7461 */
7462struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7463 const char *ifname)
7464{
7465 struct wpa_supplicant *wpa_s;
7466
7467 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7468 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7469 return wpa_s;
7470 }
7471 return NULL;
7472}
7473
7474
7475#ifndef CONFIG_NO_WPA_MSG
7476static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7477{
7478 struct wpa_supplicant *wpa_s = ctx;
7479 if (wpa_s == NULL)
7480 return NULL;
7481 return wpa_s->ifname;
7482}
7483#endif /* CONFIG_NO_WPA_MSG */
7484
7485
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007486#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7487#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7488#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7489
7490/* Periodic cleanup tasks */
7491static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7492{
7493 struct wpa_global *global = eloop_ctx;
7494 struct wpa_supplicant *wpa_s;
7495
7496 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7497 wpas_periodic, global, NULL);
7498
7499#ifdef CONFIG_P2P
7500 if (global->p2p)
7501 p2p_expire_peers(global->p2p);
7502#endif /* CONFIG_P2P */
7503
7504 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7505 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7506#ifdef CONFIG_AP
7507 ap_periodic(wpa_s);
7508#endif /* CONFIG_AP */
7509 }
7510}
7511
7512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007513/**
7514 * wpa_supplicant_init - Initialize %wpa_supplicant
7515 * @params: Parameters for %wpa_supplicant
7516 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7517 *
7518 * This function is used to initialize %wpa_supplicant. After successful
7519 * initialization, the returned data pointer can be used to add and remove
7520 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7521 */
7522struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7523{
7524 struct wpa_global *global;
7525 int ret, i;
7526
7527 if (params == NULL)
7528 return NULL;
7529
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007530#ifdef CONFIG_DRIVER_NDIS
7531 {
7532 void driver_ndis_init_ops(void);
7533 driver_ndis_init_ops();
7534 }
7535#endif /* CONFIG_DRIVER_NDIS */
7536
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007537#ifndef CONFIG_NO_WPA_MSG
7538 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7539#endif /* CONFIG_NO_WPA_MSG */
7540
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007541 if (params->wpa_debug_file_path)
7542 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007543 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007544 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007545 if (params->wpa_debug_syslog)
7546 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007547 if (params->wpa_debug_tracing) {
7548 ret = wpa_debug_open_linux_tracing();
7549 if (ret) {
7550 wpa_printf(MSG_ERROR,
7551 "Failed to enable trace logging");
7552 return NULL;
7553 }
7554 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007555
7556 ret = eap_register_methods();
7557 if (ret) {
7558 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7559 if (ret == -2)
7560 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7561 "the same EAP type.");
7562 return NULL;
7563 }
7564
7565 global = os_zalloc(sizeof(*global));
7566 if (global == NULL)
7567 return NULL;
7568 dl_list_init(&global->p2p_srv_bonjour);
7569 dl_list_init(&global->p2p_srv_upnp);
7570 global->params.daemonize = params->daemonize;
7571 global->params.wait_for_monitor = params->wait_for_monitor;
7572 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7573 if (params->pid_file)
7574 global->params.pid_file = os_strdup(params->pid_file);
7575 if (params->ctrl_interface)
7576 global->params.ctrl_interface =
7577 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007578 if (params->ctrl_interface_group)
7579 global->params.ctrl_interface_group =
7580 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007581 if (params->override_driver)
7582 global->params.override_driver =
7583 os_strdup(params->override_driver);
7584 if (params->override_ctrl_interface)
7585 global->params.override_ctrl_interface =
7586 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007587#ifdef CONFIG_MATCH_IFACE
7588 global->params.match_iface_count = params->match_iface_count;
7589 if (params->match_iface_count) {
7590 global->params.match_ifaces =
7591 os_calloc(params->match_iface_count,
7592 sizeof(struct wpa_interface));
7593 os_memcpy(global->params.match_ifaces,
7594 params->match_ifaces,
7595 params->match_iface_count *
7596 sizeof(struct wpa_interface));
7597 }
7598#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007599#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007600 if (params->conf_p2p_dev)
7601 global->params.conf_p2p_dev =
7602 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007603#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007604 wpa_debug_level = global->params.wpa_debug_level =
7605 params->wpa_debug_level;
7606 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7607 params->wpa_debug_show_keys;
7608 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7609 params->wpa_debug_timestamp;
7610
Hai Shalomfdcde762020-04-02 11:19:20 -07007611 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007612
7613 if (eloop_init()) {
7614 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7615 wpa_supplicant_deinit(global);
7616 return NULL;
7617 }
7618
Jouni Malinen75ecf522011-06-27 15:19:46 -07007619 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007620
7621 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7622 if (global->ctrl_iface == NULL) {
7623 wpa_supplicant_deinit(global);
7624 return NULL;
7625 }
7626
7627 if (wpas_notify_supplicant_initialized(global)) {
7628 wpa_supplicant_deinit(global);
7629 return NULL;
7630 }
7631
7632 for (i = 0; wpa_drivers[i]; i++)
7633 global->drv_count++;
7634 if (global->drv_count == 0) {
7635 wpa_printf(MSG_ERROR, "No drivers enabled");
7636 wpa_supplicant_deinit(global);
7637 return NULL;
7638 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007639 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007640 if (global->drv_priv == NULL) {
7641 wpa_supplicant_deinit(global);
7642 return NULL;
7643 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007644
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007645#ifdef CONFIG_WIFI_DISPLAY
7646 if (wifi_display_init(global) < 0) {
7647 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7648 wpa_supplicant_deinit(global);
7649 return NULL;
7650 }
7651#endif /* CONFIG_WIFI_DISPLAY */
7652
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007653 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7654 wpas_periodic, global, NULL);
7655
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007656 return global;
7657}
7658
7659
7660/**
7661 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7662 * @global: Pointer to global data from wpa_supplicant_init()
7663 * Returns: 0 after successful event loop run, -1 on failure
7664 *
7665 * This function starts the main event loop and continues running as long as
7666 * there are any remaining events. In most cases, this function is running as
7667 * long as the %wpa_supplicant process in still in use.
7668 */
7669int wpa_supplicant_run(struct wpa_global *global)
7670{
7671 struct wpa_supplicant *wpa_s;
7672
7673 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007674 (wpa_supplicant_daemon(global->params.pid_file) ||
7675 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007676 return -1;
7677
Dmitry Shmidte4663042016-04-04 10:07:49 -07007678#ifdef CONFIG_MATCH_IFACE
7679 if (wpa_supplicant_match_existing(global))
7680 return -1;
7681#endif
7682
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007683 if (global->params.wait_for_monitor) {
7684 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007685 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007686 wpa_supplicant_ctrl_iface_wait(
7687 wpa_s->ctrl_iface);
7688 }
7689
7690 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7691 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7692
7693 eloop_run();
7694
7695 return 0;
7696}
7697
7698
7699/**
7700 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7701 * @global: Pointer to global data from wpa_supplicant_init()
7702 *
7703 * This function is called to deinitialize %wpa_supplicant and to free all
7704 * allocated resources. Remaining network interfaces will also be removed.
7705 */
7706void wpa_supplicant_deinit(struct wpa_global *global)
7707{
7708 int i;
7709
7710 if (global == NULL)
7711 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007712
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007713 eloop_cancel_timeout(wpas_periodic, global, NULL);
7714
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007715#ifdef CONFIG_WIFI_DISPLAY
7716 wifi_display_deinit(global);
7717#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007718
7719 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007720 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007721
7722 if (global->ctrl_iface)
7723 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7724
7725 wpas_notify_supplicant_deinitialized(global);
7726
7727 eap_peer_unregister_methods();
7728#ifdef CONFIG_AP
7729 eap_server_unregister_methods();
7730#endif /* CONFIG_AP */
7731
7732 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7733 if (!global->drv_priv[i])
7734 continue;
7735 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7736 }
7737 os_free(global->drv_priv);
7738
7739 random_deinit();
7740
7741 eloop_destroy();
7742
7743 if (global->params.pid_file) {
7744 os_daemonize_terminate(global->params.pid_file);
7745 os_free(global->params.pid_file);
7746 }
7747 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007748 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007749 os_free(global->params.override_driver);
7750 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007751#ifdef CONFIG_MATCH_IFACE
7752 os_free(global->params.match_ifaces);
7753#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007754#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007755 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007756#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007757
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007758 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007759 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007760 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007761
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007762 os_free(global);
7763 wpa_debug_close_syslog();
7764 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007765 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007766}
7767
7768
7769void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7770{
7771 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7772 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7773 char country[3];
7774 country[0] = wpa_s->conf->country[0];
7775 country[1] = wpa_s->conf->country[1];
7776 country[2] = '\0';
7777 if (wpa_drv_set_country(wpa_s, country) < 0) {
7778 wpa_printf(MSG_ERROR, "Failed to set country code "
7779 "'%s'", country);
7780 }
7781 }
7782
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007783 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7784 wpas_init_ext_pw(wpa_s);
7785
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007786 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7787 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7788
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007789 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7790 struct wpa_driver_capa capa;
7791 int res = wpa_drv_get_capa(wpa_s, &capa);
7792
7793 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7794 wpa_printf(MSG_ERROR,
7795 "Failed to update wowlan_triggers to '%s'",
7796 wpa_s->conf->wowlan_triggers);
7797 }
7798
Hai Shalom81f62d82019-07-22 12:10:00 -07007799 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7800 wpa_supplicant_set_default_scan_ies(wpa_s);
7801
Hai Shalom899fcc72020-10-19 14:38:18 -07007802#ifdef CONFIG_BGSCAN
7803 /*
7804 * We default to global bgscan parameters only when per-network bgscan
7805 * parameters aren't set. Only bother resetting bgscan parameters if
7806 * this is the case.
7807 */
7808 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7809 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7810 wpa_s->wpa_state == WPA_COMPLETED)
7811 wpa_supplicant_reset_bgscan(wpa_s);
7812#endif /* CONFIG_BGSCAN */
7813
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007814#ifdef CONFIG_WPS
7815 wpas_wps_update_config(wpa_s);
7816#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007817 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007818 wpa_s->conf->changed_parameters = 0;
7819}
7820
7821
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007822void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007823{
7824 int i;
7825
7826 for (i = 0; i < *num_freqs; i++) {
7827 if (freqs[i] == freq)
7828 return;
7829 }
7830
7831 freqs[*num_freqs] = freq;
7832 (*num_freqs)++;
7833}
7834
7835
7836static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7837{
7838 struct wpa_bss *bss, *cbss;
7839 const int max_freqs = 10;
7840 int *freqs;
7841 int num_freqs = 0;
7842
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007843 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007844 if (freqs == NULL)
7845 return NULL;
7846
7847 cbss = wpa_s->current_bss;
7848
7849 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7850 if (bss == cbss)
7851 continue;
7852 if (bss->ssid_len == cbss->ssid_len &&
7853 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007854 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007855 add_freq(freqs, &num_freqs, bss->freq);
7856 if (num_freqs == max_freqs)
7857 break;
7858 }
7859 }
7860
7861 if (num_freqs == 0) {
7862 os_free(freqs);
7863 freqs = NULL;
7864 }
7865
7866 return freqs;
7867}
7868
7869
7870void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7871{
7872 int timeout;
7873 int count;
7874 int *freqs = NULL;
7875
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007876 wpas_connect_work_done(wpa_s);
7877
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007878 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007879 * Remove possible authentication timeout since the connection failed.
7880 */
7881 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7882
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007883 /*
Hai Shalom60840252021-02-19 19:02:11 -08007884 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007885 * generated based on local request to disconnect.
7886 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007887 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007888 wpa_s->own_disconnect_req = 0;
7889 wpa_dbg(wpa_s, MSG_DEBUG,
7890 "Ignore connection failure due to local request to disconnect");
7891 return;
7892 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007893 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007894 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7895 "indication since interface has been put into "
7896 "disconnected state");
7897 return;
7898 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007899 if (wpa_s->auto_reconnect_disabled) {
7900 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7901 "indication since auto connect is disabled");
7902 return;
7903 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007904
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007905 /*
Hai Shalom60840252021-02-19 19:02:11 -08007906 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007907 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007908 */
Hai Shalom60840252021-02-19 19:02:11 -08007909 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007910 if (count == 1 && wpa_s->current_bss) {
7911 /*
Hai Shalom60840252021-02-19 19:02:11 -08007912 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007913 * another BSS available for the same ESS, we should try that
7914 * next. Otherwise, we may as well try this one once more
7915 * before allowing other, likely worse, ESSes to be considered.
7916 */
7917 freqs = get_bss_freqs_in_ess(wpa_s);
7918 if (freqs) {
7919 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7920 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007921 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007922 /*
7923 * On the next scan, go through only the known channels
7924 * used in this ESS based on previous scans to speed up
7925 * common load balancing use case.
7926 */
7927 os_free(wpa_s->next_scan_freqs);
7928 wpa_s->next_scan_freqs = freqs;
7929 }
7930 }
7931
Hai Shalom899fcc72020-10-19 14:38:18 -07007932 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007933
Hai Shalom899fcc72020-10-19 14:38:18 -07007934 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007935 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7936 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007937 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007938 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007939 /*
7940 * Multiple consecutive connection failures mean that other APs are
7941 * either not available or have already been tried, so we can start
7942 * increasing the delay here to avoid constant scanning.
7943 */
7944 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007945 case 1:
7946 timeout = 100;
7947 break;
7948 case 2:
7949 timeout = 500;
7950 break;
7951 case 3:
7952 timeout = 1000;
7953 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007954 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007955 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007956 break;
7957 default:
7958 timeout = 10000;
7959 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007960 }
7961
Hai Shalom899fcc72020-10-19 14:38:18 -07007962 wpa_dbg(wpa_s, MSG_DEBUG,
7963 "Consecutive connection failures: %d --> request scan in %d ms",
7964 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007965
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007966 /*
7967 * TODO: if more than one possible AP is available in scan results,
7968 * could try the other ones before requesting a new scan.
7969 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007970
7971 /* speed up the connection attempt with normal scan */
7972 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007973 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7974 1000 * (timeout % 1000));
7975}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007976
7977
Hai Shalomce48b4a2018-09-05 11:41:35 -07007978#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08007979
7980void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
7981{
7982 struct wpa_ssid *ssid = wpa_s->current_ssid;
7983 const u8 *realm, *username, *rrk;
7984 size_t realm_len, username_len, rrk_len;
7985 u16 next_seq_num;
7986
7987 /* Clear the PMKSA cache entry if FILS authentication was rejected.
7988 * Check for ERP keys existing to limit when this can be done since
7989 * the rejection response is not protected and such triggers should
7990 * really not allow internal state to be modified unless required to
7991 * avoid significant issues in functionality. In addition, drop
7992 * externally configure PMKSA entries even without ERP keys since it
7993 * is possible for an external component to add PMKSA entries for FILS
7994 * authentication without restoring previously generated ERP keys.
7995 *
7996 * In this case, this is needed to allow recovery from cases where the
7997 * AP or authentication server has dropped PMKSAs and ERP keys. */
7998 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
7999 return;
8000
8001 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8002 &username, &username_len,
8003 &realm, &realm_len, &next_seq_num,
8004 &rrk, &rrk_len) != 0 ||
8005 !realm) {
8006 wpa_dbg(wpa_s, MSG_DEBUG,
8007 "FILS: Drop external PMKSA cache entry");
8008 wpa_sm_aborted_external_cached(wpa_s->wpa);
8009 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
8010 return;
8011 }
8012
8013 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
8014 wpa_sm_aborted_cached(wpa_s->wpa);
8015 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
8016}
8017
8018
Hai Shalomce48b4a2018-09-05 11:41:35 -07008019void fils_connection_failure(struct wpa_supplicant *wpa_s)
8020{
8021 struct wpa_ssid *ssid = wpa_s->current_ssid;
8022 const u8 *realm, *username, *rrk;
8023 size_t realm_len, username_len, rrk_len;
8024 u16 next_seq_num;
8025
8026 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
8027 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
8028 &username, &username_len,
8029 &realm, &realm_len, &next_seq_num,
8030 &rrk, &rrk_len) != 0 ||
8031 !realm)
8032 return;
8033
8034 wpa_hexdump_ascii(MSG_DEBUG,
8035 "FILS: Store last connection failure realm",
8036 realm, realm_len);
8037 os_free(wpa_s->last_con_fail_realm);
8038 wpa_s->last_con_fail_realm = os_malloc(realm_len);
8039 if (wpa_s->last_con_fail_realm) {
8040 wpa_s->last_con_fail_realm_len = realm_len;
8041 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
8042 }
8043}
8044#endif /* CONFIG_FILS */
8045
8046
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008047int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
8048{
8049 return wpa_s->conf->ap_scan == 2 ||
8050 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
8051}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008052
Dmitry Shmidt04949592012-07-19 12:16:46 -07008053
Gabriel Biren57ededa2021-09-03 16:08:50 +00008054#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008055int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8056 struct wpa_ssid *ssid,
8057 const char *field,
8058 const char *value)
8059{
8060#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008061 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008062
8063 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
8064 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
8065 (const u8 *) value, os_strlen(value));
8066
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008067 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07008068 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008069#else /* IEEE8021X_EAPOL */
8070 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8071 return -1;
8072#endif /* IEEE8021X_EAPOL */
8073}
8074
8075int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
8076 struct wpa_ssid *ssid,
8077 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07008078 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008079{
8080#ifdef IEEE8021X_EAPOL
8081 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08008082 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008083
8084 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008085 case WPA_CTRL_REQ_EAP_IDENTITY:
8086 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08008087 os_free(eap->imsi_identity);
8088 if (value == NULL)
8089 return -1;
8090 identity = os_strchr(value, ':');
8091 if (identity == NULL) {
8092 /* plain identity */
8093 eap->identity = (u8 *)os_strdup(value);
8094 eap->identity_len = os_strlen(value);
8095 } else {
8096 /* have both plain identity and encrypted identity */
8097 imsi_identity = value;
8098 *identity++ = '\0';
8099 /* plain identity */
8100 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
8101 eap->imsi_identity_len = strlen(imsi_identity);
8102 /* encrypted identity */
8103 eap->identity = (u8 *)dup_binstr(identity,
8104 value_len - strlen(imsi_identity) - 1);
8105 eap->identity_len = value_len - strlen(imsi_identity) - 1;
8106 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008107 eap->pending_req_identity = 0;
8108 if (ssid == wpa_s->current_ssid)
8109 wpa_s->reassociate = 1;
8110 break;
8111 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008112 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008113 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07008114 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008115 eap->pending_req_password = 0;
8116 if (ssid == wpa_s->current_ssid)
8117 wpa_s->reassociate = 1;
8118 break;
8119 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008120 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008121 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07008122 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008123 eap->pending_req_new_password = 0;
8124 if (ssid == wpa_s->current_ssid)
8125 wpa_s->reassociate = 1;
8126 break;
8127 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07008128 str_clear_free(eap->cert.pin);
8129 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008130 eap->pending_req_pin = 0;
8131 if (ssid == wpa_s->current_ssid)
8132 wpa_s->reassociate = 1;
8133 break;
8134 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008135 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008136 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07008137 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008138 os_free(eap->pending_req_otp);
8139 eap->pending_req_otp = NULL;
8140 eap->pending_req_otp_len = 0;
8141 break;
8142 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008143 str_clear_free(eap->cert.private_key_passwd);
8144 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008145 eap->pending_req_passphrase = 0;
8146 if (ssid == wpa_s->current_ssid)
8147 wpa_s->reassociate = 1;
8148 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008149 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008150 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008151 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008152 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008153 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008154 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8155 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8156 return -1;
8157 ssid->mem_only_psk = 1;
8158 if (ssid->passphrase)
8159 wpa_config_update_psk(ssid);
8160 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8161 wpa_supplicant_req_scan(wpa_s, 0, 0);
8162 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008163 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8164 if (eap->pending_ext_cert_check != PENDING_CHECK)
8165 return -1;
8166 if (os_strcmp(value, "good") == 0)
8167 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8168 else if (os_strcmp(value, "bad") == 0)
8169 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8170 else
8171 return -1;
8172 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008173 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008174 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008175 return -1;
8176 }
8177
8178 return 0;
8179#else /* IEEE8021X_EAPOL */
8180 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8181 return -1;
8182#endif /* IEEE8021X_EAPOL */
8183}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008184#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008185
8186
8187int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8188{
Hai Shalomfdcde762020-04-02 11:19:20 -07008189#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008190 int i;
8191 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008192#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008193
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008194 if (wpa_s->p2p_mgmt)
8195 return 1; /* no normal network profiles on p2p_mgmt interface */
8196
Dmitry Shmidt04949592012-07-19 12:16:46 -07008197 if (ssid == NULL)
8198 return 1;
8199
8200 if (ssid->disabled)
8201 return 1;
8202
Hai Shalomfdcde762020-04-02 11:19:20 -07008203#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008204 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008205 drv_enc = wpa_s->drv_enc;
8206 else
8207 drv_enc = (unsigned int) -1;
8208
8209 for (i = 0; i < NUM_WEP_KEYS; i++) {
8210 size_t len = ssid->wep_key_len[i];
8211 if (len == 0)
8212 continue;
8213 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8214 continue;
8215 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8216 continue;
8217 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8218 continue;
8219 return 1; /* invalid WEP key */
8220 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008221#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008222
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008223 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008224 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008225 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008226 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008227 return 1;
8228
Sunil Ravi89eba102022-09-13 21:04:37 -07008229#ifdef IEEE8021X_EAPOL
Sunil8cd6f4d2022-06-28 18:40:46 +00008230#ifdef CRYPTO_RSA_OAEP_SHA256
8231 if (ssid->eap.imsi_privacy_cert) {
8232 struct crypto_rsa_key *key;
8233 bool failed = false;
8234
8235 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8236 if (!key)
8237 failed = true;
8238 crypto_rsa_key_free(key);
8239 if (failed) {
8240 wpa_printf(MSG_DEBUG,
8241 "Invalid imsi_privacy_cert (%s) - disable network",
8242 ssid->eap.imsi_privacy_cert);
8243 return 1;
8244 }
8245 }
8246#endif /* CRYPTO_RSA_OAEP_SHA256 */
Sunil Ravi89eba102022-09-13 21:04:37 -07008247#endif /* IEEE8021X_EAPOL */
Sunil8cd6f4d2022-06-28 18:40:46 +00008248
Dmitry Shmidt04949592012-07-19 12:16:46 -07008249 return 0;
8250}
8251
8252
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008253int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8254{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008255 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8256 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8257 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8258 /*
8259 * Driver does not support BIP -- ignore pmf=1 default
8260 * since the connection with PMF would fail and the
8261 * configuration does not require PMF to be enabled.
8262 */
8263 return NO_MGMT_FRAME_PROTECTION;
8264 }
8265
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008266 if (ssid &&
8267 (ssid->key_mgmt &
8268 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8269 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8270 /*
8271 * Do not use the default PMF value for non-RSN networks
8272 * since PMF is available only with RSN and pmf=2
8273 * configuration would otherwise prevent connections to
8274 * all open networks.
8275 */
8276 return NO_MGMT_FRAME_PROTECTION;
8277 }
8278
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008279 return wpa_s->conf->pmf;
8280 }
8281
8282 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008283}
8284
8285
Hai Shalomc1a21442022-02-04 13:43:00 -08008286int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8287{
8288 if (wpa_s->current_ssid == NULL ||
8289 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8290 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8291 return 0;
8292 return wpa_sm_pmf_enabled(wpa_s->wpa);
8293}
8294
8295
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008296int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008297{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008298 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008299 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008300 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008301 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008302 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008303}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008304
8305
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008306void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008307{
8308 struct wpa_ssid *ssid = wpa_s->current_ssid;
8309 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008310 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008311
8312 if (ssid == NULL) {
8313 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8314 "SSID block");
8315 return;
8316 }
8317
8318 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8319 return;
8320
8321 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008322
8323#ifdef CONFIG_P2P
8324 if (ssid->p2p_group &&
8325 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8326 /*
8327 * Skip the wait time since there is a short timeout on the
8328 * connection to a P2P group.
8329 */
8330 return;
8331 }
8332#endif /* CONFIG_P2P */
8333
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008334 if (ssid->auth_failures > 50)
8335 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008336 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008337 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008338 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008339 dur = 90;
8340 else if (ssid->auth_failures > 3)
8341 dur = 60;
8342 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008343 dur = 30;
8344 else if (ssid->auth_failures > 1)
8345 dur = 20;
8346 else
8347 dur = 10;
8348
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008349 if (ssid->auth_failures > 1 &&
8350 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8351 dur += os_random() % (ssid->auth_failures * 10);
8352
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008353 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008354 if (now.sec + dur <= ssid->disabled_until.sec)
8355 return;
8356
8357 ssid->disabled_until.sec = now.sec + dur;
8358
8359 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008360 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008361 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008362 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008363
8364 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8365 int msg_len = snprintf(NULL, 0, format_str,
8366 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8367 ssid->auth_failures, dur, reason) + 1;
8368 char *msg = os_malloc(msg_len);
8369 snprintf(msg, msg_len, format_str,
8370 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8371 ssid->auth_failures, dur, reason);
8372 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8373 os_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008374}
8375
8376
8377void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8378 struct wpa_ssid *ssid, int clear_failures)
8379{
8380 if (ssid == NULL)
8381 return;
8382
8383 if (ssid->disabled_until.sec) {
8384 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8385 "id=%d ssid=\"%s\"",
8386 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8387 }
8388 ssid->disabled_until.sec = 0;
8389 ssid->disabled_until.usec = 0;
8390 if (clear_failures)
8391 ssid->auth_failures = 0;
8392}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008393
8394
8395int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8396{
8397 size_t i;
8398
8399 if (wpa_s->disallow_aps_bssid == NULL)
8400 return 0;
8401
8402 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8403 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8404 bssid, ETH_ALEN) == 0)
8405 return 1;
8406 }
8407
8408 return 0;
8409}
8410
8411
8412int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8413 size_t ssid_len)
8414{
8415 size_t i;
8416
8417 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8418 return 0;
8419
8420 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8421 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8422 if (ssid_len == s->ssid_len &&
8423 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8424 return 1;
8425 }
8426
8427 return 0;
8428}
8429
8430
8431/**
8432 * wpas_request_connection - Request a new connection
8433 * @wpa_s: Pointer to the network interface
8434 *
8435 * This function is used to request a new connection to be found. It will mark
8436 * the interface to allow reassociation and request a new scan to find a
8437 * suitable network to connect to.
8438 */
8439void wpas_request_connection(struct wpa_supplicant *wpa_s)
8440{
8441 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008442 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008443 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008444 wpa_s->disconnected = 0;
8445 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008446 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008447
8448 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8449 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008450 else
8451 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008452}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008453
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008454
Roshan Pius02242d72016-08-09 15:31:48 -07008455/**
8456 * wpas_request_disconnection - Request disconnection
8457 * @wpa_s: Pointer to the network interface
8458 *
8459 * This function is used to request disconnection from the currently connected
8460 * network. This will stop any ongoing scans and initiate deauthentication.
8461 */
8462void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8463{
8464#ifdef CONFIG_SME
8465 wpa_s->sme.prev_bssid_set = 0;
8466#endif /* CONFIG_SME */
8467 wpa_s->reassociate = 0;
8468 wpa_s->disconnected = 1;
8469 wpa_supplicant_cancel_sched_scan(wpa_s);
8470 wpa_supplicant_cancel_scan(wpa_s);
8471 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8472 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008473 radio_remove_works(wpa_s, "connect", 0);
8474 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008475 wpa_s->roam_in_progress = false;
8476#ifdef CONFIG_WNM
8477 wpa_s->bss_trans_mgmt_in_progress = false;
8478#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008479}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008480
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008481
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008482void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8483 struct wpa_used_freq_data *freqs_data,
8484 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008485{
8486 unsigned int i;
8487
8488 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8489 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008490 for (i = 0; i < len; i++) {
8491 struct wpa_used_freq_data *cur = &freqs_data[i];
8492 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8493 i, cur->freq, cur->flags);
8494 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008495}
8496
8497
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008498/*
8499 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008500 * are using the same radio as the current interface, and in addition, get
8501 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008502 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008503int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8504 struct wpa_used_freq_data *freqs_data,
8505 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008506{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008507 struct wpa_supplicant *ifs;
8508 u8 bssid[ETH_ALEN];
8509 int freq;
8510 unsigned int idx = 0, i;
8511
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008512 wpa_dbg(wpa_s, MSG_DEBUG,
8513 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008514 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008515
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008516 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8517 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008518 if (idx == len)
8519 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008520
8521 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8522 continue;
8523
8524 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008525 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8526 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008527 freq = ifs->current_ssid->frequency;
8528 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8529 freq = ifs->assoc_freq;
8530 else
8531 continue;
8532
8533 /* Hold only distinct freqs */
8534 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008535 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008536 break;
8537
8538 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008539 freqs_data[idx++].freq = freq;
8540
8541 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008542 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008543 WPA_FREQ_USED_BY_P2P_CLIENT :
8544 WPA_FREQ_USED_BY_INFRA_STATION;
8545 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008546 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008547
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008548 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008549 return idx;
8550}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008551
8552
8553/*
8554 * Find the operating frequencies of any of the virtual interfaces that
8555 * are using the same radio as the current interface.
8556 */
8557int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8558 int *freq_array, unsigned int len)
8559{
8560 struct wpa_used_freq_data *freqs_data;
8561 int num, i;
8562
8563 os_memset(freq_array, 0, sizeof(int) * len);
8564
8565 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8566 if (!freqs_data)
8567 return -1;
8568
8569 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8570 for (i = 0; i < num; i++)
8571 freq_array[i] = freqs_data[i].freq;
8572
8573 os_free(freqs_data);
8574
8575 return num;
8576}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008577
8578
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008579struct wpa_supplicant *
8580wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8581{
8582 switch (frame) {
8583#ifdef CONFIG_P2P
8584 case VENDOR_ELEM_PROBE_REQ_P2P:
8585 case VENDOR_ELEM_PROBE_RESP_P2P:
8586 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8587 case VENDOR_ELEM_BEACON_P2P_GO:
8588 case VENDOR_ELEM_P2P_PD_REQ:
8589 case VENDOR_ELEM_P2P_PD_RESP:
8590 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8591 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8592 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8593 case VENDOR_ELEM_P2P_INV_REQ:
8594 case VENDOR_ELEM_P2P_INV_RESP:
8595 case VENDOR_ELEM_P2P_ASSOC_REQ:
8596 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008597 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008598#endif /* CONFIG_P2P */
8599 default:
8600 return wpa_s;
8601 }
8602}
8603
8604
8605void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8606{
8607 unsigned int i;
8608 char buf[30];
8609
8610 wpa_printf(MSG_DEBUG, "Update vendor elements");
8611
8612 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8613 if (wpa_s->vendor_elem[i]) {
8614 int res;
8615
8616 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8617 if (!os_snprintf_error(sizeof(buf), res)) {
8618 wpa_hexdump_buf(MSG_DEBUG, buf,
8619 wpa_s->vendor_elem[i]);
8620 }
8621 }
8622 }
8623
8624#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008625 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008626 wpa_s->global->p2p &&
8627 !wpa_s->global->p2p_disabled)
8628 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8629#endif /* CONFIG_P2P */
8630}
8631
8632
8633int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8634 const u8 *elem, size_t len)
8635{
8636 u8 *ie, *end;
8637
8638 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8639 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8640
8641 for (; ie + 1 < end; ie += 2 + ie[1]) {
8642 if (ie + len > end)
8643 break;
8644 if (os_memcmp(ie, elem, len) != 0)
8645 continue;
8646
8647 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8648 wpabuf_free(wpa_s->vendor_elem[frame]);
8649 wpa_s->vendor_elem[frame] = NULL;
8650 } else {
8651 os_memmove(ie, ie + len, end - (ie + len));
8652 wpa_s->vendor_elem[frame]->used -= len;
8653 }
8654 wpas_vendor_elem_update(wpa_s);
8655 return 0;
8656 }
8657
8658 return -1;
8659}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008660
8661
8662struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008663 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008664 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008665{
8666 u16 i;
8667
Hai Shalomc1a21442022-02-04 13:43:00 -08008668 if (!modes)
8669 return NULL;
8670
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008671 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008672 if (modes[i].mode != mode ||
8673 !modes[i].num_channels || !modes[i].channels)
8674 continue;
8675 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8676 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008677 return &modes[i];
8678 }
8679
8680 return NULL;
8681}
8682
8683
Hai Shalomc1a21442022-02-04 13:43:00 -08008684struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8685 u16 num_modes, int freq)
8686{
8687 int i, j;
8688
8689 for (i = 0; i < num_modes; i++) {
8690 for (j = 0; j < modes[i].num_channels; j++) {
8691 if (freq == modes[i].channels[j].freq)
8692 return &modes[i];
8693 }
8694 }
8695
8696 return NULL;
8697}
8698
8699
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008700static struct
8701wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8702 const u8 *bssid)
8703{
8704 struct wpa_bss_tmp_disallowed *bss;
8705
8706 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8707 struct wpa_bss_tmp_disallowed, list) {
8708 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8709 return bss;
8710 }
8711
8712 return NULL;
8713}
8714
8715
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008716static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8717{
8718 struct wpa_bss_tmp_disallowed *tmp;
8719 unsigned int num_bssid = 0;
8720 u8 *bssids;
8721 int ret;
8722
8723 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8724 if (!bssids)
8725 return -1;
8726 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8727 struct wpa_bss_tmp_disallowed, list) {
8728 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8729 ETH_ALEN);
8730 num_bssid++;
8731 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008732 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008733 os_free(bssids);
8734 return ret;
8735}
8736
8737
8738static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8739{
8740 struct wpa_supplicant *wpa_s = eloop_ctx;
8741 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8742
8743 /* Make sure the bss is not already freed */
8744 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8745 struct wpa_bss_tmp_disallowed, list) {
8746 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008747 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008748 wpa_set_driver_tmp_disallow_list(wpa_s);
8749 break;
8750 }
8751 }
8752}
8753
8754
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008755void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008756 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008757{
8758 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008759
8760 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8761 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008762 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008763 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008764 }
8765
8766 bss = os_malloc(sizeof(*bss));
8767 if (!bss) {
8768 wpa_printf(MSG_DEBUG,
8769 "Failed to allocate memory for temp disallow BSS");
8770 return;
8771 }
8772
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008773 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8774 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008775 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008776
8777finish:
8778 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008779 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8780 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008781}
8782
8783
Hai Shalom74f70d42019-02-11 14:42:39 -08008784int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8785 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008786{
Hai Shalom74f70d42019-02-11 14:42:39 -08008787 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008788
8789 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8790 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008791 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8792 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008793 break;
8794 }
8795 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008796 if (!disallowed)
8797 return 0;
8798
8799 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008800 bss->level > disallowed->rssi_threshold) {
8801 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8802 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008803 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008804 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008805
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008806 return 1;
8807}
Hai Shalom81f62d82019-07-22 12:10:00 -07008808
8809
8810int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8811 unsigned int type, const u8 *addr,
8812 const u8 *mask)
8813{
8814 if ((addr && !mask) || (!addr && mask)) {
8815 wpa_printf(MSG_INFO,
8816 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8817 return -1;
8818 }
8819
8820 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8821 wpa_printf(MSG_INFO,
8822 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8823 return -1;
8824 }
8825
8826 if (type & MAC_ADDR_RAND_SCAN) {
8827 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8828 addr, mask))
8829 return -1;
8830 }
8831
8832 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8833 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8834 addr, mask))
8835 return -1;
8836
8837 if (wpa_s->sched_scanning && !wpa_s->pno)
8838 wpas_scan_restart_sched_scan(wpa_s);
8839 }
8840
8841 if (type & MAC_ADDR_RAND_PNO) {
8842 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8843 addr, mask))
8844 return -1;
8845
8846 if (wpa_s->pno) {
8847 wpas_stop_pno(wpa_s);
8848 wpas_start_pno(wpa_s);
8849 }
8850 }
8851
8852 return 0;
8853}
8854
8855
8856int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8857 unsigned int type)
8858{
8859 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8860 if (wpa_s->pno) {
8861 if (type & MAC_ADDR_RAND_PNO) {
8862 wpas_stop_pno(wpa_s);
8863 wpas_start_pno(wpa_s);
8864 }
8865 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8866 wpas_scan_restart_sched_scan(wpa_s);
8867 }
8868
8869 return 0;
8870}
Hai Shalomfdcde762020-04-02 11:19:20 -07008871
8872
8873int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8874 struct wpa_signal_info *si)
8875{
8876 int res;
8877
8878 if (!wpa_s->driver->signal_poll)
8879 return -1;
8880
8881 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8882
8883#ifdef CONFIG_TESTING_OPTIONS
8884 if (res == 0) {
8885 struct driver_signal_override *dso;
8886
8887 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8888 struct driver_signal_override, list) {
8889 if (os_memcmp(wpa_s->bssid, dso->bssid,
8890 ETH_ALEN) != 0)
8891 continue;
8892 wpa_printf(MSG_DEBUG,
8893 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8894 si->current_signal,
8895 dso->si_current_signal,
8896 si->avg_signal,
8897 dso->si_avg_signal,
8898 si->avg_beacon_signal,
8899 dso->si_avg_beacon_signal,
8900 si->current_noise,
8901 dso->si_current_noise);
8902 si->current_signal = dso->si_current_signal;
8903 si->avg_signal = dso->si_avg_signal;
8904 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8905 si->current_noise = dso->si_current_noise;
8906 break;
8907 }
8908 }
8909#endif /* CONFIG_TESTING_OPTIONS */
8910
8911 return res;
8912}
8913
8914
8915struct wpa_scan_results *
8916wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8917{
8918 struct wpa_scan_results *scan_res;
8919#ifdef CONFIG_TESTING_OPTIONS
8920 size_t idx;
8921#endif /* CONFIG_TESTING_OPTIONS */
8922
8923 if (!wpa_s->driver->get_scan_results2)
8924 return NULL;
8925
8926 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8927
8928#ifdef CONFIG_TESTING_OPTIONS
8929 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8930 struct driver_signal_override *dso;
8931 struct wpa_scan_res *res = scan_res->res[idx];
8932
8933 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8934 struct driver_signal_override, list) {
8935 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8936 continue;
8937 wpa_printf(MSG_DEBUG,
8938 "Override driver scan signal level %d->%d for "
8939 MACSTR,
8940 res->level, dso->scan_level,
8941 MAC2STR(res->bssid));
8942 res->flags |= WPA_SCAN_QUAL_INVALID;
8943 if (dso->scan_level < 0)
8944 res->flags |= WPA_SCAN_LEVEL_DBM;
8945 else
8946 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8947 res->level = dso->scan_level;
8948 break;
8949 }
8950 }
8951#endif /* CONFIG_TESTING_OPTIONS */
8952
8953 return scan_res;
8954}