blob: 8ee8ca6330fc93e4dcfd44bfe807e167fa6790de [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalomc1a21442022-02-04 13:43:00 -08003 * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
Sunil8cd6f4d2022-06-28 18:40:46 +000020#include "crypto/crypto.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080022#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070023#include "eapol_supp/eapol_supp_sm.h"
24#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070025#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "eap_server/eap_methods.h"
27#include "rsn_supp/wpa.h"
28#include "eloop.h"
29#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070030#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070031#include "l2_packet/l2_packet.h"
32#include "wpa_supplicant_i.h"
33#include "driver_i.h"
34#include "ctrl_iface.h"
35#include "pcsc_funcs.h"
36#include "common/version.h"
37#include "rsn_supp/preauth.h"
38#include "rsn_supp/pmksa_cache.h"
39#include "common/wpa_ctrl.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070040#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080042#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070043#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070044#include "common/dpp.h"
Hai Shalom60840252021-02-19 19:02:11 -080045#include "common/ptksa_cache.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080047#include "fst/fst.h"
Hai Shalom60840252021-02-19 19:02:11 -080048#include "bssid_ignore.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "wpas_glue.h"
50#include "wps_supplicant.h"
51#include "ibss_rsn.h"
52#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080053#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070054#include "ap.h"
55#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070056#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070057#include "notify.h"
58#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070059#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070060#include "bss.h"
61#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080062#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070063#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070064#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070065#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080066#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070067#include "dpp_supplicant.h"
68#ifdef CONFIG_MESH
69#include "ap/ap_config.h"
70#include "ap/hostapd.h"
71#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070073const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074"wpa_supplicant v" VERSION_STR "\n"
Hai Shalomc1a21442022-02-04 13:43:00 -080075"Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070077const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080078"This software may be distributed under the terms of the BSD license.\n"
79"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070080#ifdef EAP_TLS_OPENSSL
81"\nThis product includes software developed by the OpenSSL Project\n"
82"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
83#endif /* EAP_TLS_OPENSSL */
84;
85
86#ifndef CONFIG_NO_STDOUT_DEBUG
87/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070088const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080089"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070090const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080091"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070092"\n"
93"Redistribution and use in source and binary forms, with or without\n"
94"modification, are permitted provided that the following conditions are\n"
95"met:\n"
96"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070097const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098"1. Redistributions of source code must retain the above copyright\n"
99" notice, this list of conditions and the following disclaimer.\n"
100"\n"
101"2. Redistributions in binary form must reproduce the above copyright\n"
102" notice, this list of conditions and the following disclaimer in the\n"
103" documentation and/or other materials provided with the distribution.\n"
104"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700105const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700106"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
107" names of its contributors may be used to endorse or promote products\n"
108" derived from this software without specific prior written permission.\n"
109"\n"
110"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
111"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
112"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
113"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700114const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700115"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
116"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
117"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
118"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
119"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
120"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
121"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
122"\n";
123#endif /* CONFIG_NO_STDOUT_DEBUG */
124
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700125
126static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
127#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
128static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
129#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700130#ifdef CONFIG_OWE
131static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
132#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700133
134
Hai Shalomfdcde762020-04-02 11:19:20 -0700135#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136/* Configure default/group WEP keys for static WEP */
137int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
138{
139 int i, set = 0;
140
141 for (i = 0; i < NUM_WEP_KEYS; i++) {
142 if (ssid->wep_key_len[i] == 0)
143 continue;
144
145 set = 1;
146 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
147 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700148 ssid->wep_key[i], ssid->wep_key_len[i],
149 i == ssid->wep_tx_keyidx ?
150 KEY_FLAG_GROUP_RX_TX_DEFAULT :
151 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700152 }
153
154 return set;
155}
Hai Shalomfdcde762020-04-02 11:19:20 -0700156#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700157
158
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700159int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
160 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700161{
162 u8 key[32];
163 size_t keylen;
164 enum wpa_alg alg;
165 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800166 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700167
168 /* IBSS/WPA-None uses only one key (Group) for both receiving and
169 * sending unicast and multicast packets. */
170
171 if (ssid->mode != WPAS_MODE_IBSS) {
172 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
173 "IBSS/ad-hoc) for WPA-None", ssid->mode);
174 return -1;
175 }
176
177 if (!ssid->psk_set) {
178 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
179 "WPA-None");
180 return -1;
181 }
182
183 switch (wpa_s->group_cipher) {
184 case WPA_CIPHER_CCMP:
185 os_memcpy(key, ssid->psk, 16);
186 keylen = 16;
187 alg = WPA_ALG_CCMP;
188 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700189 case WPA_CIPHER_GCMP:
190 os_memcpy(key, ssid->psk, 16);
191 keylen = 16;
192 alg = WPA_ALG_GCMP;
193 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700194 case WPA_CIPHER_TKIP:
195 /* WPA-None uses the same Michael MIC key for both TX and RX */
196 os_memcpy(key, ssid->psk, 16 + 8);
197 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
198 keylen = 32;
199 alg = WPA_ALG_TKIP;
200 break;
201 default:
202 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
203 "WPA-None", wpa_s->group_cipher);
204 return -1;
205 }
206
207 /* TODO: should actually remember the previously used seq#, both for TX
208 * and RX from each STA.. */
209
Hai Shalomfdcde762020-04-02 11:19:20 -0700210 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen,
211 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800212 os_memset(key, 0, sizeof(key));
213 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700214}
215
216
217static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
218{
219 struct wpa_supplicant *wpa_s = eloop_ctx;
220 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700221 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
222 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
223 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700224 bssid = wpa_s->pending_bssid;
225 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
226 MAC2STR(bssid));
Hai Shalom60840252021-02-19 19:02:11 -0800227 wpa_bssid_ignore_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700228 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700229 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800230 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231 wpa_s->reassociate = 1;
232
233 /*
234 * If we timed out, the AP or the local radio may be busy.
235 * So, wait a second until scanning again.
236 */
237 wpa_supplicant_req_scan(wpa_s, 1, 0);
238}
239
240
241/**
242 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
243 * @wpa_s: Pointer to wpa_supplicant data
244 * @sec: Number of seconds after which to time out authentication
245 * @usec: Number of microseconds after which to time out authentication
246 *
247 * This function is used to schedule a timeout for the current authentication
248 * attempt.
249 */
250void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
251 int sec, int usec)
252{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700253 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
255 return;
256
257 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
258 "%d usec", sec, usec);
259 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700260 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700261 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
262}
263
264
Roshan Pius3a1667e2018-07-03 15:17:14 -0700265/*
266 * wpas_auth_timeout_restart - Restart and change timeout for authentication
267 * @wpa_s: Pointer to wpa_supplicant data
268 * @sec_diff: difference in seconds applied to original timeout value
269 */
270void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
271{
272 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
273
274 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
275 wpa_dbg(wpa_s, MSG_DEBUG,
276 "Authentication timeout restart: %d sec", new_sec);
277 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
278 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
279 wpa_s, NULL);
280 }
281}
282
283
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700284/**
285 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
286 * @wpa_s: Pointer to wpa_supplicant data
287 *
288 * This function is used to cancel authentication timeout scheduled with
289 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
290 * been completed.
291 */
292void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
293{
294 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
295 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800296 wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700297 os_free(wpa_s->last_con_fail_realm);
298 wpa_s->last_con_fail_realm = NULL;
299 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700300}
301
302
303/**
304 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
305 * @wpa_s: Pointer to wpa_supplicant data
306 *
307 * This function is used to configure EAPOL state machine based on the selected
308 * authentication mode.
309 */
310void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
311{
312#ifdef IEEE8021X_EAPOL
313 struct eapol_config eapol_conf;
314 struct wpa_ssid *ssid = wpa_s->current_ssid;
315
316#ifdef CONFIG_IBSS_RSN
317 if (ssid->mode == WPAS_MODE_IBSS &&
318 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
319 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
320 /*
321 * RSN IBSS authentication is per-STA and we can disable the
322 * per-BSSID EAPOL authentication.
323 */
324 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700325 eapol_sm_notify_eap_success(wpa_s->eapol, true);
326 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700327 return;
328 }
329#endif /* CONFIG_IBSS_RSN */
330
Hai Shalome21d4e82020-04-29 16:34:06 -0700331 eapol_sm_notify_eap_success(wpa_s->eapol, false);
332 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700333
334 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
335 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
336 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
337 else
338 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
339
340 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
341 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
342 eapol_conf.accept_802_1x_keys = 1;
343 eapol_conf.required_keys = 0;
344 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
345 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
346 }
347 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
348 eapol_conf.required_keys |=
349 EAPOL_REQUIRE_KEY_BROADCAST;
350 }
351
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700352 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700353 eapol_conf.required_keys = 0;
354 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700355 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700356 eapol_conf.workaround = ssid->eap_workaround;
357 eapol_conf.eap_disabled =
358 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
359 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
360 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700361 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800362
363#ifdef CONFIG_WPS
364 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
365 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
366 if (wpa_s->current_bss) {
367 struct wpabuf *ie;
368 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
369 WPS_IE_VENDOR_TYPE);
370 if (ie) {
371 if (wps_is_20(ie))
372 eapol_conf.wps |=
373 EAPOL_PEER_IS_WPS20_AP;
374 wpabuf_free(ie);
375 }
376 }
377 }
378#endif /* CONFIG_WPS */
379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700380 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700381
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800382#ifdef CONFIG_MACSEC
383 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
384 ieee802_1x_create_preshared_mka(wpa_s, ssid);
385 else
386 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
387#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800388#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700389}
390
391
392/**
393 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
394 * @wpa_s: Pointer to wpa_supplicant data
395 * @ssid: Configuration data for the network
396 *
397 * This function is used to configure WPA state machine and related parameters
398 * to a mode where WPA is not enabled. This is called as part of the
399 * authentication configuration when the selected network does not use WPA.
400 */
401void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
402 struct wpa_ssid *ssid)
403{
Hai Shalomfdcde762020-04-02 11:19:20 -0700404#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700405 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700406#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700407
408 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
409 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
410 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
411 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
412 else
413 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
414 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
415 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700416 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700417 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700418 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
419 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700420 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
421 wpa_s->group_cipher = WPA_CIPHER_NONE;
422 wpa_s->mgmt_group_cipher = 0;
423
Hai Shalomfdcde762020-04-02 11:19:20 -0700424#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700425 for (i = 0; i < NUM_WEP_KEYS; i++) {
426 if (ssid->wep_key_len[i] > 5) {
427 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
428 wpa_s->group_cipher = WPA_CIPHER_WEP104;
429 break;
430 } else if (ssid->wep_key_len[i] > 0) {
431 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
432 wpa_s->group_cipher = WPA_CIPHER_WEP40;
433 break;
434 }
435 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700436#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700437
438 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
439 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
440 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
441 wpa_s->pairwise_cipher);
442 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
444 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700445
446 pmksa_cache_clear_current(wpa_s->wpa);
447}
448
449
Dmitry Shmidt04949592012-07-19 12:16:46 -0700450void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800451{
452 int i;
453 if (wpa_s->hw.modes == NULL)
454 return;
455
456 for (i = 0; i < wpa_s->hw.num_modes; i++) {
457 os_free(wpa_s->hw.modes[i].channels);
458 os_free(wpa_s->hw.modes[i].rates);
459 }
460
461 os_free(wpa_s->hw.modes);
462 wpa_s->hw.modes = NULL;
463}
464
465
Hai Shalomc1a21442022-02-04 13:43:00 -0800466static void remove_bss_tmp_disallowed_entry(struct wpa_supplicant *wpa_s,
467 struct wpa_bss_tmp_disallowed *bss)
468{
469 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
470 dl_list_del(&bss->list);
471 os_free(bss);
472}
473
474
Hai Shalom74f70d42019-02-11 14:42:39 -0800475void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800476{
477 struct wpa_bss_tmp_disallowed *bss, *prev;
478
479 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
Hai Shalomc1a21442022-02-04 13:43:00 -0800480 struct wpa_bss_tmp_disallowed, list)
481 remove_bss_tmp_disallowed_entry(wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800482}
483
484
Paul Stewart092955c2017-02-06 09:13:09 -0800485void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
486{
487 struct fils_hlp_req *req;
488
489 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
490 list)) != NULL) {
491 dl_list_del(&req->list);
492 wpabuf_free(req->pkt);
493 os_free(req);
494 }
495}
496
497
Hai Shalomfdcde762020-04-02 11:19:20 -0700498void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
499{
500 struct wpa_supplicant *wpa_s = eloop_ctx;
501
502 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
503 return;
504 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
505 wpa_bss_flush(wpa_s);
506}
507
508
509#ifdef CONFIG_TESTING_OPTIONS
510void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
511{
512 struct driver_signal_override *dso;
513
514 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
515 struct driver_signal_override, list))) {
516 dl_list_del(&dso->list);
517 os_free(dso);
518 }
519}
520#endif /* CONFIG_TESTING_OPTIONS */
521
522
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700523static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
524{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700525 int i;
526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700527 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700528 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700529 scard_deinit(wpa_s->scard);
530 wpa_s->scard = NULL;
531 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
532 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
533 l2_packet_deinit(wpa_s->l2);
534 wpa_s->l2 = NULL;
535 if (wpa_s->l2_br) {
536 l2_packet_deinit(wpa_s->l2_br);
537 wpa_s->l2_br = NULL;
538 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800539#ifdef CONFIG_TESTING_OPTIONS
540 l2_packet_deinit(wpa_s->l2_test);
541 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800542 os_free(wpa_s->get_pref_freq_list_override);
543 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700544 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
545 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800546 os_free(wpa_s->extra_sae_rejected_groups);
547 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700548 wpabuf_free(wpa_s->rsne_override_eapol);
549 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800550 wpabuf_free(wpa_s->rsnxe_override_assoc);
551 wpa_s->rsnxe_override_assoc = NULL;
552 wpabuf_free(wpa_s->rsnxe_override_eapol);
553 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700554 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800555#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557 if (wpa_s->conf != NULL) {
558 struct wpa_ssid *ssid;
559 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
560 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561 }
562
563 os_free(wpa_s->confname);
564 wpa_s->confname = NULL;
565
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700566 os_free(wpa_s->confanother);
567 wpa_s->confanother = NULL;
568
Hai Shalomce48b4a2018-09-05 11:41:35 -0700569 os_free(wpa_s->last_con_fail_realm);
570 wpa_s->last_con_fail_realm = NULL;
571 wpa_s->last_con_fail_realm_len = 0;
572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573 wpa_sm_set_eapol(wpa_s->wpa, NULL);
574 eapol_sm_deinit(wpa_s->eapol);
575 wpa_s->eapol = NULL;
576
577 rsn_preauth_deinit(wpa_s->wpa);
578
579#ifdef CONFIG_TDLS
580 wpa_tdls_deinit(wpa_s->wpa);
581#endif /* CONFIG_TDLS */
582
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800583 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700584 pmksa_candidate_free(wpa_s->wpa);
Hai Shalom60840252021-02-19 19:02:11 -0800585 ptksa_cache_deinit(wpa_s->ptksa);
586 wpa_s->ptksa = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587 wpa_sm_deinit(wpa_s->wpa);
588 wpa_s->wpa = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800589 wpa_bssid_ignore_clear(wpa_s);
590
591#ifdef CONFIG_PASN
592 wpas_pasn_auth_stop(wpa_s);
593#endif /* CONFIG_PASN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700594
595 wpa_bss_deinit(wpa_s);
596
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700597 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598 wpa_supplicant_cancel_scan(wpa_s);
599 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800600 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
601#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
602 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
603 wpa_s, NULL);
604#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700605
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700606 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700607 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700608
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700609 wpas_wps_deinit(wpa_s);
610
611 wpabuf_free(wpa_s->pending_eapol_rx);
612 wpa_s->pending_eapol_rx = NULL;
613
614#ifdef CONFIG_IBSS_RSN
615 ibss_rsn_deinit(wpa_s->ibss_rsn);
616 wpa_s->ibss_rsn = NULL;
617#endif /* CONFIG_IBSS_RSN */
618
619 sme_deinit(wpa_s);
620
621#ifdef CONFIG_AP
622 wpa_supplicant_ap_deinit(wpa_s);
623#endif /* CONFIG_AP */
624
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700625 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700626
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800627#ifdef CONFIG_OFFCHANNEL
628 offchannel_deinit(wpa_s);
629#endif /* CONFIG_OFFCHANNEL */
630
631 wpa_supplicant_cancel_sched_scan(wpa_s);
632
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700633 os_free(wpa_s->next_scan_freqs);
634 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800635
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800636 os_free(wpa_s->manual_scan_freqs);
637 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700638 os_free(wpa_s->select_network_scan_freqs);
639 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800640
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700641 os_free(wpa_s->manual_sched_scan_freqs);
642 wpa_s->manual_sched_scan_freqs = NULL;
643
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800644 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
645
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700646 /*
647 * Need to remove any pending gas-query radio work before the
648 * gas_query_deinit() call because gas_query::work has not yet been set
649 * for works that have not been started. gas_query_free() will be unable
650 * to cancel such pending radio works and once the pending gas-query
651 * radio work eventually gets removed, the deinit notification call to
652 * gas_query_start_cb() would result in dereferencing freed memory.
653 */
654 if (wpa_s->radio)
655 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800656 gas_query_deinit(wpa_s->gas);
657 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700658 gas_server_deinit(wpa_s->gas_server);
659 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800660
661 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700662
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700663 ieee802_1x_dealloc_kay_sm(wpa_s);
664
Dmitry Shmidt04949592012-07-19 12:16:46 -0700665 os_free(wpa_s->bssid_filter);
666 wpa_s->bssid_filter = NULL;
667
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800668 os_free(wpa_s->disallow_aps_bssid);
669 wpa_s->disallow_aps_bssid = NULL;
670 os_free(wpa_s->disallow_aps_ssid);
671 wpa_s->disallow_aps_ssid = NULL;
672
Dmitry Shmidt04949592012-07-19 12:16:46 -0700673 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700674#ifdef CONFIG_WNM
675 wnm_deallocate_memory(wpa_s);
676#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700677
678 ext_password_deinit(wpa_s->ext_pw);
679 wpa_s->ext_pw = NULL;
680
681 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800682 wpa_s->last_gas_resp = NULL;
683 wpabuf_free(wpa_s->prev_gas_resp);
684 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700685
686 os_free(wpa_s->last_scan_res);
687 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800688
689#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700690 if (wpa_s->drv_priv)
691 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700692 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800693#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700694
695 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
696 wpabuf_free(wpa_s->vendor_elem[i]);
697 wpa_s->vendor_elem[i] = NULL;
698 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800699
700 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800701
702 wpa_s->sched_scan_plans_num = 0;
703 os_free(wpa_s->sched_scan_plans);
704 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800705
706#ifdef CONFIG_MBO
707 wpa_s->non_pref_chan_num = 0;
708 os_free(wpa_s->non_pref_chan);
709 wpa_s->non_pref_chan = NULL;
710#endif /* CONFIG_MBO */
711
712 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700713
714 wpabuf_free(wpa_s->lci);
715 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800716 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800717
718#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
719#ifdef CONFIG_MESH
720 {
721 struct external_pmksa_cache *entry;
722
723 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
724 struct external_pmksa_cache,
725 list)) != NULL) {
726 dl_list_del(&entry->list);
727 os_free(entry->pmksa_cache);
728 os_free(entry);
729 }
730 }
731#endif /* CONFIG_MESH */
732#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
733
734 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800735
736 wpabuf_free(wpa_s->ric_ies);
737 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700738
739#ifdef CONFIG_DPP
740 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700741 dpp_global_deinit(wpa_s->dpp);
742 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700743#endif /* CONFIG_DPP */
Hai Shalom60840252021-02-19 19:02:11 -0800744
745#ifdef CONFIG_PASN
746 wpas_pasn_auth_stop(wpa_s);
747#endif /* CONFIG_PASN */
Hai Shalomc1a21442022-02-04 13:43:00 -0800748 wpas_scs_deinit(wpa_s);
749 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700750}
751
752
753/**
754 * wpa_clear_keys - Clear keys configured for the driver
755 * @wpa_s: Pointer to wpa_supplicant data
756 * @addr: Previously used BSSID or %NULL if not available
757 *
758 * This function clears the encryption keys that has been previously configured
759 * for the driver.
760 */
761void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
762{
Hai Shalomc3565922019-10-28 11:58:20 -0700763 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700764
765 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800766 for (i = 0; i < max; i++) {
767 if (wpa_s->keys_cleared & BIT(i))
768 continue;
769 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700770 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800771 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700772 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
773 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800774 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700775 if (!(wpa_s->keys_cleared & BIT(0)))
776 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
777 0, NULL, 0, KEY_FLAG_PAIRWISE);
778 if (!(wpa_s->keys_cleared & BIT(15)))
779 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
780 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781 /* MLME-SETPROTECTION.request(None) */
782 wpa_drv_mlme_setprotection(
783 wpa_s, addr,
784 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
785 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
786 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800787 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700788}
789
790
791/**
792 * wpa_supplicant_state_txt - Get the connection state name as a text string
793 * @state: State (wpa_state; WPA_*)
794 * Returns: The state name as a printable text string
795 */
796const char * wpa_supplicant_state_txt(enum wpa_states state)
797{
798 switch (state) {
799 case WPA_DISCONNECTED:
800 return "DISCONNECTED";
801 case WPA_INACTIVE:
802 return "INACTIVE";
803 case WPA_INTERFACE_DISABLED:
804 return "INTERFACE_DISABLED";
805 case WPA_SCANNING:
806 return "SCANNING";
807 case WPA_AUTHENTICATING:
808 return "AUTHENTICATING";
809 case WPA_ASSOCIATING:
810 return "ASSOCIATING";
811 case WPA_ASSOCIATED:
812 return "ASSOCIATED";
813 case WPA_4WAY_HANDSHAKE:
814 return "4WAY_HANDSHAKE";
815 case WPA_GROUP_HANDSHAKE:
816 return "GROUP_HANDSHAKE";
817 case WPA_COMPLETED:
818 return "COMPLETED";
819 default:
820 return "UNKNOWN";
821 }
822}
823
824
825#ifdef CONFIG_BGSCAN
826
Hai Shalom899fcc72020-10-19 14:38:18 -0700827static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
828{
829 if (wpa_s->bgscan_ssid) {
830 bgscan_deinit(wpa_s);
831 wpa_s->bgscan_ssid = NULL;
832 }
833}
834
835
836/**
837 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
838 * @wpa_s: Pointer to the wpa_supplicant data
839 *
840 * Stop, start, or reconfigure the scan parameters depending on the method.
841 */
842void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700843{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800844 const char *name;
845
846 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
847 name = wpa_s->current_ssid->bgscan;
848 else
849 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700850 if (!name || name[0] == '\0') {
851 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800852 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700853 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800854 if (wpas_driver_bss_selection(wpa_s))
855 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800856#ifdef CONFIG_P2P
857 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
858 return;
859#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700860
861 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800862 if (wpa_s->current_ssid) {
863 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700864 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
865 "bgscan");
866 /*
867 * Live without bgscan; it is only used as a roaming
868 * optimization, so the initial connection is not
869 * affected.
870 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700871 } else {
872 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700873 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700874 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
875 0);
876 if (scan_res) {
877 bgscan_notify_scan(wpa_s, scan_res);
878 wpa_scan_results_free(scan_res);
879 }
880 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700881 } else
882 wpa_s->bgscan_ssid = NULL;
883}
884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885#endif /* CONFIG_BGSCAN */
886
887
Dmitry Shmidt04949592012-07-19 12:16:46 -0700888static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
889{
890 if (autoscan_init(wpa_s, 0))
891 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
892}
893
894
895static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
896{
897 autoscan_deinit(wpa_s);
898}
899
900
901void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
902{
903 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
904 wpa_s->wpa_state == WPA_SCANNING) {
905 autoscan_deinit(wpa_s);
906 wpa_supplicant_start_autoscan(wpa_s);
907 }
908}
909
910
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700911/**
912 * wpa_supplicant_set_state - Set current connection state
913 * @wpa_s: Pointer to wpa_supplicant data
914 * @state: The new connection state
915 *
916 * This function is called whenever the connection state changes, e.g.,
917 * association is completed for WPA/WPA2 4-Way Handshake is started.
918 */
919void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
920 enum wpa_states state)
921{
922 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700923#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700924 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700925#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700926
927 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
928 wpa_supplicant_state_txt(wpa_s->wpa_state),
929 wpa_supplicant_state_txt(state));
930
Hai Shalom74f70d42019-02-11 14:42:39 -0800931 if (state == WPA_COMPLETED &&
932 os_reltime_initialized(&wpa_s->roam_start)) {
933 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
934 wpa_s->roam_start.sec = 0;
935 wpa_s->roam_start.usec = 0;
936 wpas_notify_auth_changed(wpa_s);
937 wpas_notify_roam_time(wpa_s);
938 wpas_notify_roam_complete(wpa_s);
939 } else if (state == WPA_DISCONNECTED &&
940 os_reltime_initialized(&wpa_s->roam_start)) {
941 wpa_s->roam_start.sec = 0;
942 wpa_s->roam_start.usec = 0;
943 wpa_s->roam_time.sec = 0;
944 wpa_s->roam_time.usec = 0;
945 wpas_notify_roam_complete(wpa_s);
946 }
947
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800948 if (state == WPA_INTERFACE_DISABLED) {
949 /* Assure normal scan when interface is restored */
950 wpa_s->normal_scans = 0;
951 }
952
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700953 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800954 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700955 /* Reinitialize normal_scan counter */
956 wpa_s->normal_scans = 0;
957 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800958
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700959#ifdef CONFIG_P2P
960 /*
961 * P2PS client has to reply to Probe Request frames received on the
962 * group operating channel. Enable Probe Request frame reporting for
963 * P2P connected client in case p2p_cli_probe configuration property is
964 * set to 1.
965 */
966 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
967 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
968 wpa_s->current_ssid->p2p_group) {
969 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
970 wpa_dbg(wpa_s, MSG_DEBUG,
971 "P2P: Enable CLI Probe Request RX reporting");
972 wpa_s->p2p_cli_probe =
973 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
974 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
975 wpa_dbg(wpa_s, MSG_DEBUG,
976 "P2P: Disable CLI Probe Request RX reporting");
977 wpa_s->p2p_cli_probe = 0;
978 wpa_drv_probe_req_report(wpa_s, 0);
979 }
980 }
981#endif /* CONFIG_P2P */
982
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700983 if (state != WPA_SCANNING)
984 wpa_supplicant_notify_scanning(wpa_s, 0);
985
986 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700988 int fils_hlp_sent = 0;
989
990#ifdef CONFIG_SME
991 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
992 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
993 fils_hlp_sent = 1;
994#endif /* CONFIG_SME */
995 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
996 wpa_auth_alg_fils(wpa_s->auth_alg))
997 fils_hlp_sent = 1;
998
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700999#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001001 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001002 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001004 ssid && ssid->id_str ? ssid->id_str : "",
1005 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001007 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -07001008 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010 wpa_drv_set_operstate(wpa_s, 1);
1011#ifndef IEEE8021X_EAPOL
1012 wpa_drv_set_supp_port(wpa_s, 1);
1013#endif /* IEEE8021X_EAPOL */
1014 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001015 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001017
1018 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001019
1020#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1021 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001022 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001023#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001024#ifdef CONFIG_OWE
1025 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1026 wpas_update_owe_connect_params(wpa_s);
1027#endif /* CONFIG_OWE */
Hai Shalom2cbbcd12021-03-08 18:33:38 -08001028#ifdef CONFIG_HS20
1029 hs20_configure_frame_filters(wpa_s);
1030#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001031 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1032 state == WPA_ASSOCIATED) {
1033 wpa_s->new_connection = 1;
1034 wpa_drv_set_operstate(wpa_s, 0);
1035#ifndef IEEE8021X_EAPOL
1036 wpa_drv_set_supp_port(wpa_s, 0);
1037#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001038 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 }
1040 wpa_s->wpa_state = state;
1041
1042#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001043 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1044 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001045 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 wpa_supplicant_stop_bgscan(wpa_s);
1047#endif /* CONFIG_BGSCAN */
1048
Hai Shalom5f92bc92019-04-18 11:54:11 -07001049 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001050 wpa_supplicant_stop_autoscan(wpa_s);
1051
1052 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1053 wpa_supplicant_start_autoscan(wpa_s);
1054
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001055 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1056 wmm_ac_notify_disassoc(wpa_s);
1057
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 if (wpa_s->wpa_state != old_state) {
1059 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1060
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001061 /*
1062 * Notify the P2P Device interface about a state change in one
1063 * of the interfaces.
1064 */
1065 wpas_p2p_indicate_state_change(wpa_s);
1066
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001067 if (wpa_s->wpa_state == WPA_COMPLETED ||
1068 old_state == WPA_COMPLETED)
1069 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001070#ifdef CONFIG_DPP2
1071 if (wpa_s->wpa_state == WPA_COMPLETED)
1072 wpas_dpp_connected(wpa_s);
1073#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074 }
Hai Shalomc3565922019-10-28 11:58:20 -07001075#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1076 if (update_fils_connect_params)
1077 wpas_update_fils_connect_params(wpa_s);
1078#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001079}
1080
1081
1082void wpa_supplicant_terminate_proc(struct wpa_global *global)
1083{
1084 int pending = 0;
1085#ifdef CONFIG_WPS
1086 struct wpa_supplicant *wpa_s = global->ifaces;
1087 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001088 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001089 if (wpas_wps_terminate_pending(wpa_s) == 1)
1090 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001091#ifdef CONFIG_P2P
1092 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1093 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1094 wpas_p2p_disconnect(wpa_s);
1095#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001096 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001097 }
1098#endif /* CONFIG_WPS */
1099 if (pending)
1100 return;
1101 eloop_terminate();
1102}
1103
1104
1105static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1106{
1107 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108 wpa_supplicant_terminate_proc(global);
1109}
1110
1111
1112void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1113{
1114 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalom60840252021-02-19 19:02:11 -08001115 enum wpa_states new_state;
1116
1117 if (old_state == WPA_SCANNING)
1118 new_state = WPA_SCANNING;
1119 else
1120 new_state = WPA_DISCONNECTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121
1122 wpa_s->pairwise_cipher = 0;
1123 wpa_s->group_cipher = 0;
1124 wpa_s->mgmt_group_cipher = 0;
1125 wpa_s->key_mgmt = 0;
1126 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Hai Shalom60840252021-02-19 19:02:11 -08001127 wpa_supplicant_set_state(wpa_s, new_state);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128
1129 if (wpa_s->wpa_state != old_state)
1130 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1131}
1132
1133
1134/**
1135 * wpa_supplicant_reload_configuration - Reload configuration data
1136 * @wpa_s: Pointer to wpa_supplicant data
1137 * Returns: 0 on success or -1 if configuration parsing failed
1138 *
1139 * This function can be used to request that the configuration data is reloaded
1140 * (e.g., after configuration file change). This function is reloading
1141 * configuration only for one interface, so this may need to be called multiple
1142 * times if %wpa_supplicant is controlling multiple interfaces and all
1143 * interfaces need reconfiguration.
1144 */
1145int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1146{
1147 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001148 int reconf_ctrl;
1149 int old_ap_scan;
1150
1151 if (wpa_s->confname == NULL)
1152 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001153 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001154 if (conf == NULL) {
1155 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1156 "file '%s' - exiting", wpa_s->confname);
1157 return -1;
1158 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001159 if (wpa_s->confanother &&
1160 !wpa_config_read(wpa_s->confanother, conf)) {
1161 wpa_msg(wpa_s, MSG_ERROR,
1162 "Failed to parse the configuration file '%s' - exiting",
1163 wpa_s->confanother);
1164 return -1;
1165 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001166
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001167 conf->changed_parameters = (unsigned int) -1;
1168
1169 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1170 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1171 os_strcmp(conf->ctrl_interface,
1172 wpa_s->conf->ctrl_interface) != 0);
1173
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02001174 if (reconf_ctrl) {
1175 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001176 wpa_s->ctrl_iface = NULL;
1177 }
1178
1179 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001180 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001181 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1182 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001183 wpa_supplicant_deauthenticate(wpa_s,
1184 WLAN_REASON_DEAUTH_LEAVING);
1185 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001186
1187 /*
1188 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001189 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001191 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1192 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1193 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194 /*
1195 * Clear forced success to clear EAP state for next
1196 * authentication.
1197 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001198 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001199 }
1200 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1201 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001202 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001203 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1204 rsn_preauth_deinit(wpa_s->wpa);
1205
1206 old_ap_scan = wpa_s->conf->ap_scan;
1207 wpa_config_free(wpa_s->conf);
1208 wpa_s->conf = conf;
1209 if (old_ap_scan != wpa_s->conf->ap_scan)
1210 wpas_notify_ap_scan_changed(wpa_s);
1211
1212 if (reconf_ctrl)
1213 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1214
1215 wpa_supplicant_update_config(wpa_s);
1216
1217 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001218 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001219 wpa_s->reassociate = 1;
1220 wpa_supplicant_req_scan(wpa_s, 0, 0);
1221 }
Hai Shalom60840252021-02-19 19:02:11 -08001222 wpa_bssid_ignore_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001223 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1224 return 0;
1225}
1226
1227
1228static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1229{
1230 struct wpa_global *global = signal_ctx;
1231 struct wpa_supplicant *wpa_s;
1232 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1233 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1234 sig);
1235 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1236 wpa_supplicant_terminate_proc(global);
1237 }
1238 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001239
1240 if (wpa_debug_reopen_file() < 0) {
1241 /* Ignore errors since we cannot really do much to fix this */
1242 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1243 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001244}
1245
1246
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001247static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1248 struct wpa_ssid *ssid,
1249 struct wpa_ie_data *ie)
1250{
1251 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1252 if (ret) {
1253 if (ret == -2) {
1254 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1255 "from association info");
1256 }
1257 return -1;
1258 }
1259
1260 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1261 "cipher suites");
1262 if (!(ie->group_cipher & ssid->group_cipher)) {
1263 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1264 "cipher 0x%x (mask 0x%x) - reject",
1265 ie->group_cipher, ssid->group_cipher);
1266 return -1;
1267 }
1268 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1269 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1270 "cipher 0x%x (mask 0x%x) - reject",
1271 ie->pairwise_cipher, ssid->pairwise_cipher);
1272 return -1;
1273 }
1274 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1275 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1276 "management 0x%x (mask 0x%x) - reject",
1277 ie->key_mgmt, ssid->key_mgmt);
1278 return -1;
1279 }
1280
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001281 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001282 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001283 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1284 "that does not support management frame protection - "
1285 "reject");
1286 return -1;
1287 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288
1289 return 0;
1290}
1291
1292
Hai Shalom021b0b52019-04-10 11:17:58 -07001293static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1294 int freq)
1295{
1296 if (!ie->has_group)
1297 ie->group_cipher = wpa_default_rsn_cipher(freq);
1298 if (!ie->has_pairwise)
1299 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1300 return (ie->group_cipher & ssid->group_cipher) &&
1301 (ie->pairwise_cipher & ssid->pairwise_cipher);
1302}
1303
1304
Hai Shalomc1a21442022-02-04 13:43:00 -08001305void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
1306 struct wpa_ssid *ssid, struct wpa_ie_data *ie)
1307{
1308 int sel;
1309
1310 sel = ie->mgmt_group_cipher;
1311 if (ssid->group_mgmt_cipher)
1312 sel &= ssid->group_mgmt_cipher;
1313 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
1314 !(ie->capabilities & WPA_CAPABILITY_MFPC))
1315 sel = 0;
1316 wpa_dbg(wpa_s, MSG_DEBUG,
1317 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1318 ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
1319 if (sel & WPA_CIPHER_AES_128_CMAC) {
1320 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1321 wpa_dbg(wpa_s, MSG_DEBUG,
1322 "WPA: using MGMT group cipher AES-128-CMAC");
1323 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1324 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1325 wpa_dbg(wpa_s, MSG_DEBUG,
1326 "WPA: using MGMT group cipher BIP-GMAC-128");
1327 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1328 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1329 wpa_dbg(wpa_s, MSG_DEBUG,
1330 "WPA: using MGMT group cipher BIP-GMAC-256");
1331 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1332 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1333 wpa_dbg(wpa_s, MSG_DEBUG,
1334 "WPA: using MGMT group cipher BIP-CMAC-256");
1335 } else {
1336 wpa_s->mgmt_group_cipher = 0;
1337 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1338 }
1339 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1340 wpa_s->mgmt_group_cipher);
1341 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1342 wpas_get_ssid_pmf(wpa_s, ssid));
1343}
1344
1345
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346/**
1347 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1348 * @wpa_s: Pointer to wpa_supplicant data
1349 * @bss: Scan results for the selected BSS, or %NULL if not available
1350 * @ssid: Configuration data for the selected network
1351 * @wpa_ie: Buffer for the WPA/RSN IE
1352 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1353 * used buffer length in case the functions returns success.
1354 * Returns: 0 on success or -1 on failure
1355 *
1356 * This function is used to configure authentication and encryption parameters
1357 * based on the network configuration and scan result for the selected BSS (if
1358 * available).
1359 */
1360int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1361 struct wpa_bss *bss, struct wpa_ssid *ssid,
1362 u8 *wpa_ie, size_t *wpa_ie_len)
1363{
1364 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001365 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001366 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001367
1368 if (bss) {
1369 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1370 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001371 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001372 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001373 } else {
1374 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1375 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001376
1377 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1378 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001379 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001380 (ie.key_mgmt & ssid->key_mgmt)) {
1381 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1382 proto = WPA_PROTO_RSN;
1383 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001384 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001385 (ie.group_cipher & ssid->group_cipher) &&
1386 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1387 (ie.key_mgmt & ssid->key_mgmt)) {
1388 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1389 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001390#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001391 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1392 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1393 (ie.group_cipher & ssid->group_cipher) &&
1394 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1395 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001396 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001397 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001398 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1399 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1400 (ie.group_cipher & ssid->group_cipher) &&
1401 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1402 (ie.key_mgmt & ssid->key_mgmt)) {
1403 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1404 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001405#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001406 } else if (bss) {
1407 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001408 wpa_dbg(wpa_s, MSG_DEBUG,
1409 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1410 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1411 ssid->key_mgmt);
1412 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1413 MAC2STR(bss->bssid),
1414 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1415 bss_wpa ? " WPA" : "",
1416 bss_rsn ? " RSN" : "",
1417 bss_osen ? " OSEN" : "");
1418 if (bss_rsn) {
1419 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1420 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1421 wpa_dbg(wpa_s, MSG_DEBUG,
1422 "Could not parse RSN element");
1423 } else {
1424 wpa_dbg(wpa_s, MSG_DEBUG,
1425 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1426 ie.pairwise_cipher, ie.group_cipher,
1427 ie.key_mgmt);
1428 }
1429 }
1430 if (bss_wpa) {
1431 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1432 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1433 wpa_dbg(wpa_s, MSG_DEBUG,
1434 "Could not parse WPA element");
1435 } else {
1436 wpa_dbg(wpa_s, MSG_DEBUG,
1437 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1438 ie.pairwise_cipher, ie.group_cipher,
1439 ie.key_mgmt);
1440 }
1441 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442 return -1;
1443 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001444 if (ssid->proto & WPA_PROTO_OSEN)
1445 proto = WPA_PROTO_OSEN;
1446 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001447 proto = WPA_PROTO_RSN;
1448 else
1449 proto = WPA_PROTO_WPA;
1450 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1451 os_memset(&ie, 0, sizeof(ie));
1452 ie.group_cipher = ssid->group_cipher;
1453 ie.pairwise_cipher = ssid->pairwise_cipher;
1454 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001455 ie.mgmt_group_cipher = 0;
1456 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1457 if (ssid->group_mgmt_cipher &
1458 WPA_CIPHER_BIP_GMAC_256)
1459 ie.mgmt_group_cipher =
1460 WPA_CIPHER_BIP_GMAC_256;
1461 else if (ssid->group_mgmt_cipher &
1462 WPA_CIPHER_BIP_CMAC_256)
1463 ie.mgmt_group_cipher =
1464 WPA_CIPHER_BIP_CMAC_256;
1465 else if (ssid->group_mgmt_cipher &
1466 WPA_CIPHER_BIP_GMAC_128)
1467 ie.mgmt_group_cipher =
1468 WPA_CIPHER_BIP_GMAC_128;
1469 else
1470 ie.mgmt_group_cipher =
1471 WPA_CIPHER_AES_128_CMAC;
1472 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001473#ifdef CONFIG_OWE
1474 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1475 !ssid->owe_only &&
1476 !bss_wpa && !bss_rsn && !bss_osen) {
1477 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1478 wpa_s->wpa_proto = 0;
1479 *wpa_ie_len = 0;
1480 return 0;
1481 }
1482#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001483 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1484 "based on configuration");
1485 } else
1486 proto = ie.proto;
1487 }
1488
1489 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1490 "pairwise %d key_mgmt %d proto %d",
1491 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001492 if (ssid->ieee80211w) {
1493 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1494 ie.mgmt_group_cipher);
1495 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001496
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001497 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001498 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1499 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001500 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001501
1502 if (bss || !wpa_s->ap_ies_from_associnfo) {
1503 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1504 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1505 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001506 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1507 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1508 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001509 return -1;
1510 }
1511
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001512#ifdef CONFIG_NO_WPA
1513 wpa_s->group_cipher = WPA_CIPHER_NONE;
1514 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1515#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001516 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001517 wpa_dbg(wpa_s, MSG_DEBUG,
1518 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1519 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001520 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1521 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001522 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1523 "cipher");
1524 return -1;
1525 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001526 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1527 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001528
1529 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001530 wpa_dbg(wpa_s, MSG_DEBUG,
1531 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1532 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001533 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1534 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001535 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1536 "cipher");
1537 return -1;
1538 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001539 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1540 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001541#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001542
1543 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001544#ifdef CONFIG_SAE
1545 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1546 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1547#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001548#ifdef CONFIG_IEEE80211R
1549 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1550 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1551 sel &= ~WPA_KEY_MGMT_FT;
1552#endif /* CONFIG_IEEE80211R */
1553 wpa_dbg(wpa_s, MSG_DEBUG,
1554 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1555 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001556 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001557#ifdef CONFIG_IEEE80211R
1558#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001559 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1560 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001561 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1562 wpa_dbg(wpa_s, MSG_DEBUG,
1563 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001564 if (!ssid->ft_eap_pmksa_caching &&
1565 pmksa_cache_get_current(wpa_s->wpa)) {
1566 /* PMKSA caching with FT may have interoperability
1567 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001568 wpa_dbg(wpa_s, MSG_DEBUG,
1569 "WPA: Disable PMKSA caching for FT/802.1X connection");
1570 pmksa_cache_clear_current(wpa_s->wpa);
1571 }
1572#endif /* CONFIG_SHA384 */
1573#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001574#ifdef CONFIG_SUITEB192
1575 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1576 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1577 wpa_dbg(wpa_s, MSG_DEBUG,
1578 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1579#endif /* CONFIG_SUITEB192 */
1580#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001581 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1582 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1583 wpa_dbg(wpa_s, MSG_DEBUG,
1584 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001585#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001586#ifdef CONFIG_FILS
1587#ifdef CONFIG_IEEE80211R
1588 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1589 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1590 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1591 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1592 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1593 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1594#endif /* CONFIG_IEEE80211R */
1595 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1596 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1597 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1598 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1599 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1600 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1601#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001602#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001603 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1604 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1606 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001607 if (!ssid->ft_eap_pmksa_caching &&
1608 pmksa_cache_get_current(wpa_s->wpa)) {
1609 /* PMKSA caching with FT may have interoperability
1610 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001611 wpa_dbg(wpa_s, MSG_DEBUG,
1612 "WPA: Disable PMKSA caching for FT/802.1X connection");
1613 pmksa_cache_clear_current(wpa_s->wpa);
1614 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001615#endif /* CONFIG_IEEE80211R */
1616#ifdef CONFIG_DPP
1617 } else if (sel & WPA_KEY_MGMT_DPP) {
1618 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1619 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1620#endif /* CONFIG_DPP */
1621#ifdef CONFIG_SAE
1622 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1623 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1624 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1625 } else if (sel & WPA_KEY_MGMT_SAE) {
1626 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1627 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1628#endif /* CONFIG_SAE */
1629#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001630 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1631 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1632 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1633#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001634 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1635 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1636 wpa_dbg(wpa_s, MSG_DEBUG,
1637 "WPA: using KEY_MGMT 802.1X with SHA256");
1638 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1639 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1640 wpa_dbg(wpa_s, MSG_DEBUG,
1641 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001642 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1643 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1644 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1645 } else if (sel & WPA_KEY_MGMT_PSK) {
1646 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1647 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1648 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1649 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1650 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001651#ifdef CONFIG_HS20
1652 } else if (sel & WPA_KEY_MGMT_OSEN) {
1653 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1654 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1655#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001656#ifdef CONFIG_OWE
1657 } else if (sel & WPA_KEY_MGMT_OWE) {
1658 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1659 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1660#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661 } else {
1662 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1663 "authenticated key management type");
1664 return -1;
1665 }
1666
1667 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1668 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1669 wpa_s->pairwise_cipher);
1670 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1671
Hai Shalomc3565922019-10-28 11:58:20 -07001672 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1673 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1674 wpa_msg(wpa_s, MSG_INFO,
1675 "RSN: Management frame protection required but the selected AP does not enable it");
1676 return -1;
1677 }
1678
Hai Shalomc1a21442022-02-04 13:43:00 -08001679 wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
Hai Shalom74f70d42019-02-11 14:42:39 -08001680#ifdef CONFIG_OCV
Hai Shalom60840252021-02-19 19:02:11 -08001681 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1682 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
1683 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
Hai Shalom74f70d42019-02-11 14:42:39 -08001684#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001685 sae_pwe = wpa_s->conf->sae_pwe;
1686 if (ssid->sae_password_id && sae_pwe != 3)
1687 sae_pwe = 1;
Jimmy Chenaace8cd2021-04-13 14:55:52 +08001688 if (bss && is_6ghz_freq(bss->freq)) {
1689 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hash-to-element mode for 6GHz BSS.");
1690 sae_pwe = 1;
1691 }
1692#ifdef CONFIG_TESTING_OPTIONS
1693 if (wpa_s->force_hunting_and_pecking_pwe) {
1694 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: force hunting and pecking mode.");
1695 sae_pwe = 0;
1696 }
1697#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001698 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001699#ifdef CONFIG_SAE_PK
1700 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1701 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1702 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1703 ((ssid->sae_password &&
1704 sae_pk_valid_password(ssid->sae_password)) ||
1705 (!ssid->sae_password && ssid->passphrase &&
1706 sae_pk_valid_password(ssid->passphrase))));
1707#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001708#ifdef CONFIG_TESTING_OPTIONS
1709 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1710 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001711 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1712 wpa_s->oci_freq_override_eapol);
1713 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1714 wpa_s->oci_freq_override_eapol_g2);
1715 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1716 wpa_s->oci_freq_override_ft_assoc);
1717 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1718 wpa_s->oci_freq_override_fils_assoc);
Sunil Ravia04bd252022-05-02 22:54:18 -07001719 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX,
1720 wpa_s->disable_eapol_g2_tx);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001721#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001722
1723 /* Extended Key ID is only supported in infrastructure BSS so far */
1724 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1725 (ssid->proto & WPA_PROTO_RSN) &&
1726 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1727 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1728 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1729 int use_ext_key_id = 0;
1730
1731 wpa_msg(wpa_s, MSG_DEBUG,
1732 "WPA: Enable Extended Key ID support");
1733 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1734 wpa_s->conf->extended_key_id);
1735 if (bss_rsn &&
1736 wpa_s->conf->extended_key_id &&
1737 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1738 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1739 use_ext_key_id = 1;
1740 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1741 use_ext_key_id);
1742 } else {
1743 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1744 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1745 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746
1747 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1748 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1749 return -1;
1750 }
1751
Hai Shalomc3565922019-10-28 11:58:20 -07001752 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1753 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1754 &wpa_s->rsnxe_len)) {
1755 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1756 return -1;
1757 }
1758
Hai Shalom021b0b52019-04-10 11:17:58 -07001759 if (0) {
1760#ifdef CONFIG_DPP
1761 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1762 /* Use PMK from DPP network introduction (PMKSA entry) */
1763 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001764#ifdef CONFIG_DPP2
1765 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1766#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001767#endif /* CONFIG_DPP */
1768 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001769 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001770 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001771
Roshan Pius3a1667e2018-07-03 15:17:14 -07001772 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1773 WPA_KEY_MGMT_FT_PSK |
1774 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1775
1776 if (ssid->psk_set && !sae_only) {
1777 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1778 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001779 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1780 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001781 psk_set = 1;
1782 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001783
Roshan Pius3a1667e2018-07-03 15:17:14 -07001784 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1785 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001786 psk_set = 1;
1787
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001788#ifndef CONFIG_NO_PBKDF2
1789 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001790 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001791 u8 psk[PMK_LEN];
Sunil Ravia04bd252022-05-02 22:54:18 -07001792
1793 if (pbkdf2_sha1(ssid->passphrase, bss->ssid,
1794 bss->ssid_len,
1795 4096, psk, PMK_LEN) != 0) {
1796 wpa_msg(wpa_s, MSG_WARNING,
1797 "Error in pbkdf2_sha1()");
1798 return -1;
1799 }
1800 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001801 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001802 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001803 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001804 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001805 }
1806#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001807#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001808 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001809 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1810 ssid->ext_psk);
1811 char pw_str[64 + 1];
1812 u8 psk[PMK_LEN];
1813
1814 if (pw == NULL) {
1815 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1816 "found from external storage");
1817 return -1;
1818 }
1819
1820 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1821 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1822 "PSK length %d in external storage",
1823 (int) wpabuf_len(pw));
1824 ext_password_free(pw);
1825 return -1;
1826 }
1827
1828 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1829 pw_str[wpabuf_len(pw)] = '\0';
1830
1831#ifndef CONFIG_NO_PBKDF2
1832 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1833 {
Sunil Ravia04bd252022-05-02 22:54:18 -07001834 if (pbkdf2_sha1(pw_str, bss->ssid,
1835 bss->ssid_len,
1836 4096, psk, PMK_LEN) != 0) {
1837 wpa_msg(wpa_s, MSG_WARNING,
1838 "Error in pbkdf2_sha1()");
1839 ext_password_free(pw);
1840 return -1;
1841 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001842 os_memset(pw_str, 0, sizeof(pw_str));
1843 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1844 "external passphrase)",
1845 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001846 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1847 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001848 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001849 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001850 } else
1851#endif /* CONFIG_NO_PBKDF2 */
1852 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1853 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1854 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1855 "Invalid PSK hex string");
1856 os_memset(pw_str, 0, sizeof(pw_str));
1857 ext_password_free(pw);
1858 return -1;
1859 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001860 wpa_hexdump_key(MSG_MSGDUMP,
1861 "PSK (from external PSK)",
1862 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001863 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1864 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001865 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001866 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001867 } else {
1868 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1869 "PSK available");
1870 os_memset(pw_str, 0, sizeof(pw_str));
1871 ext_password_free(pw);
1872 return -1;
1873 }
1874
1875 os_memset(pw_str, 0, sizeof(pw_str));
1876 ext_password_free(pw);
1877 }
1878#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001879
1880 if (!psk_set) {
1881 wpa_msg(wpa_s, MSG_INFO,
1882 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001883 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001884 return -1;
1885 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001886#ifdef CONFIG_OWE
1887 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1888 /* OWE Diffie-Hellman exchange in (Re)Association
1889 * Request/Response frames set the PMK, so do not override it
1890 * here. */
1891#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001892 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1894
Hai Shalomfdcde762020-04-02 11:19:20 -07001895 if (ssid->mode != WPAS_MODE_IBSS &&
1896 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1897 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1898 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1899 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1900 wpa_msg(wpa_s, MSG_INFO,
1901 "Disable PTK0 rekey support - replaced with reconnect");
1902 wpa_s->deny_ptk0_rekey = 1;
1903 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1904 } else {
1905 wpa_s->deny_ptk0_rekey = 0;
1906 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1907 }
1908
Vinayak Yadawad14709082022-03-17 14:25:11 +05301909#ifdef CONFIG_DRIVER_NL80211_BRCM
1910 if ((wpa_s->key_mgmt & WPA_KEY_MGMT_CROSS_AKM_ROAM) &&
1911 IS_CROSS_AKM_ROAM_KEY_MGMT(ssid->key_mgmt)) {
1912 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_PSK;
1913 wpa_dbg(wpa_s, MSG_INFO,
1914 "WPA: Updating to KEY_MGMT SAE+PSK for seamless roaming");
1915 }
1916#endif /* CONFIG_DRIVER_NL80211_BRCM */
1917
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001918 return 0;
1919}
1920
1921
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001922static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1923{
Hai Shalomc1a21442022-02-04 13:43:00 -08001924 bool scs = true, mscs = true;
1925
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001926 *pos = 0x00;
1927
1928 switch (idx) {
1929 case 0: /* Bits 0-7 */
1930 break;
1931 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001932 if (wpa_s->conf->coloc_intf_reporting) {
1933 /* Bit 13 - Collocated Interference Reporting */
1934 *pos |= 0x20;
1935 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001936 break;
1937 case 2: /* Bits 16-23 */
1938#ifdef CONFIG_WNM
1939 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001940 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001941 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001942#endif /* CONFIG_WNM */
1943 break;
1944 case 3: /* Bits 24-31 */
1945#ifdef CONFIG_WNM
1946 *pos |= 0x02; /* Bit 25 - SSID List */
1947#endif /* CONFIG_WNM */
1948#ifdef CONFIG_INTERWORKING
1949 if (wpa_s->conf->interworking)
1950 *pos |= 0x80; /* Bit 31 - Interworking */
1951#endif /* CONFIG_INTERWORKING */
1952 break;
1953 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001954#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001955 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001956 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001957#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001958 break;
1959 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001960#ifdef CONFIG_HS20
1961 if (wpa_s->conf->hs20)
1962 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1963#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001964#ifdef CONFIG_MBO
1965 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1966#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001967 break;
1968 case 6: /* Bits 48-55 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001969#ifdef CONFIG_TESTING_OPTIONS
1970 if (wpa_s->disable_scs_support)
1971 scs = false;
1972#endif /* CONFIG_TESTING_OPTIONS */
1973 if (scs)
1974 *pos |= 0x40; /* Bit 54 - SCS */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001975 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001976 case 7: /* Bits 56-63 */
1977 break;
1978 case 8: /* Bits 64-71 */
1979 if (wpa_s->conf->ftm_responder)
1980 *pos |= 0x40; /* Bit 70 - FTM responder */
1981 if (wpa_s->conf->ftm_initiator)
1982 *pos |= 0x80; /* Bit 71 - FTM initiator */
1983 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001984 case 9: /* Bits 72-79 */
1985#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001986 if (!wpa_s->disable_fils)
1987 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001988#endif /* CONFIG_FILS */
1989 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001990 case 10: /* Bits 80-87 */
Hai Shalomc1a21442022-02-04 13:43:00 -08001991#ifdef CONFIG_TESTING_OPTIONS
1992 if (wpa_s->disable_mscs_support)
1993 mscs = false;
1994#endif /* CONFIG_TESTING_OPTIONS */
1995 if (mscs)
1996 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
Hai Shalom899fcc72020-10-19 14:38:18 -07001997 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001998 }
1999}
2000
2001
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002002int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002003{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002004 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07002005 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002006
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002007 if (len < wpa_s->extended_capa_len)
2008 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002009 if (buflen < (size_t) len + 2) {
2010 wpa_printf(MSG_INFO,
2011 "Not enough room for building extended capabilities element");
2012 return -1;
2013 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002014
2015 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002016 *pos++ = len;
2017 for (i = 0; i < len; i++, pos++) {
2018 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002019
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002020 if (i < wpa_s->extended_capa_len) {
2021 *pos &= ~wpa_s->extended_capa_mask[i];
2022 *pos |= wpa_s->extended_capa[i];
2023 }
2024 }
2025
2026 while (len > 0 && buf[1 + len] == 0) {
2027 len--;
2028 buf[1] = len;
2029 }
2030 if (len == 0)
2031 return 0;
2032
2033 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002034}
2035
2036
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002037static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
2038 struct wpa_bss *test_bss)
2039{
2040 struct wpa_bss *bss;
2041
2042 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2043 if (bss == test_bss)
2044 return 1;
2045 }
2046
2047 return 0;
2048}
2049
2050
2051static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
2052 struct wpa_ssid *test_ssid)
2053{
2054 struct wpa_ssid *ssid;
2055
2056 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2057 if (ssid == test_ssid)
2058 return 1;
2059 }
2060
2061 return 0;
2062}
2063
2064
2065int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
2066 struct wpa_ssid *test_ssid)
2067{
2068 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
2069 return 0;
2070
2071 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
2072}
2073
2074
2075void wpas_connect_work_free(struct wpa_connect_work *cwork)
2076{
2077 if (cwork == NULL)
2078 return;
2079 os_free(cwork);
2080}
2081
2082
2083void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
2084{
2085 struct wpa_connect_work *cwork;
2086 struct wpa_radio_work *work = wpa_s->connect_work;
2087
2088 if (!work)
2089 return;
2090
2091 wpa_s->connect_work = NULL;
2092 cwork = work->ctx;
2093 work->ctx = NULL;
2094 wpas_connect_work_free(cwork);
2095 radio_work_done(work);
2096}
2097
2098
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002099int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2100{
2101 struct os_reltime now;
2102 u8 addr[ETH_ALEN];
2103
2104 os_get_reltime(&now);
2105 if (wpa_s->last_mac_addr_style == style &&
2106 wpa_s->last_mac_addr_change.sec != 0 &&
2107 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2108 wpa_s->conf->rand_addr_lifetime)) {
2109 wpa_msg(wpa_s, MSG_DEBUG,
2110 "Previously selected random MAC address has not yet expired");
2111 return 0;
2112 }
2113
2114 switch (style) {
2115 case 1:
2116 if (random_mac_addr(addr) < 0)
2117 return -1;
2118 break;
2119 case 2:
2120 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2121 if (random_mac_addr_keep_oui(addr) < 0)
2122 return -1;
2123 break;
2124 default:
2125 return -1;
2126 }
2127
2128 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2129 wpa_msg(wpa_s, MSG_INFO,
2130 "Failed to set random MAC address");
2131 return -1;
2132 }
2133
2134 os_get_reltime(&wpa_s->last_mac_addr_change);
2135 wpa_s->mac_addr_changed = 1;
2136 wpa_s->last_mac_addr_style = style;
2137
2138 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2139 wpa_msg(wpa_s, MSG_INFO,
2140 "Could not update MAC address information");
2141 return -1;
2142 }
2143
2144 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2145 MAC2STR(addr));
2146
2147 return 0;
2148}
2149
2150
2151int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2152{
2153 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2154 !wpa_s->conf->preassoc_mac_addr)
2155 return 0;
2156
2157 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2158}
2159
2160
Hai Shalomc3565922019-10-28 11:58:20 -07002161static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2162{
2163#ifdef CONFIG_SAE
2164 int *groups = conf->sae_groups;
2165 int default_groups[] = { 19, 20, 21, 0 };
2166 const char *password;
2167
2168 if (!groups || groups[0] <= 0)
2169 groups = default_groups;
2170
2171 password = ssid->sae_password;
2172 if (!password)
2173 password = ssid->passphrase;
2174
Hai Shalom899fcc72020-10-19 14:38:18 -07002175 if (!password ||
2176 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2177 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002178 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002179 /* PT derivation not needed */
2180 sae_deinit_pt(ssid->pt);
2181 ssid->pt = NULL;
2182 return;
2183 }
2184
2185 if (ssid->pt)
2186 return; /* PT already derived */
2187 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2188 (const u8 *) password, os_strlen(password),
2189 ssid->sae_password_id);
2190#endif /* CONFIG_SAE */
2191}
2192
2193
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002194static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2195{
2196#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2197 os_free(wpa_s->sme.sae_rejected_groups);
2198 wpa_s->sme.sae_rejected_groups = NULL;
2199#ifdef CONFIG_TESTING_OPTIONS
2200 if (wpa_s->extra_sae_rejected_groups) {
2201 int i, *groups = wpa_s->extra_sae_rejected_groups;
2202
2203 for (i = 0; groups[i]; i++) {
2204 wpa_printf(MSG_DEBUG,
2205 "TESTING: Indicate rejection of an extra SAE group %d",
2206 groups[i]);
2207 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2208 groups[i]);
2209 }
2210 }
2211#endif /* CONFIG_TESTING_OPTIONS */
2212#endif /* CONFIG_SAE && CONFIG_SME */
2213}
2214
2215
Hai Shalom60840252021-02-19 19:02:11 -08002216int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
2217{
2218 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2219 wpa_msg(wpa_s, MSG_INFO,
2220 "Could not restore permanent MAC address");
2221 return -1;
2222 }
2223 wpa_s->mac_addr_changed = 0;
2224 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2225 wpa_msg(wpa_s, MSG_INFO,
2226 "Could not update MAC address information");
2227 return -1;
2228 }
2229 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2230 return 0;
2231}
2232
2233
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002234static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2235
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002236/**
2237 * wpa_supplicant_associate - Request association
2238 * @wpa_s: Pointer to wpa_supplicant data
2239 * @bss: Scan results for the selected BSS, or %NULL if not available
2240 * @ssid: Configuration data for the selected network
2241 *
2242 * This function is used to request %wpa_supplicant to associate with a BSS.
2243 */
2244void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2245 struct wpa_bss *bss, struct wpa_ssid *ssid)
2246{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002247 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002248 int rand_style;
2249
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002250 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002251 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002252
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002253 /*
2254 * If we are starting a new connection, any previously pending EAPOL
2255 * RX cannot be valid anymore.
2256 */
2257 wpabuf_free(wpa_s->pending_eapol_rx);
2258 wpa_s->pending_eapol_rx = NULL;
2259
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002260 if (ssid->mac_addr == -1)
2261 rand_style = wpa_s->conf->mac_addr;
2262 else
2263 rand_style = ssid->mac_addr;
2264
Sunil Ravia04bd252022-05-02 22:54:18 -07002265 wpa_s->eapol_failed = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002266 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002267 wmm_ac_clear_saved_tspecs(wpa_s);
2268 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002269 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002270#ifdef CONFIG_TESTING_OPTIONS
2271 wpa_s->testing_resend_assoc = 0;
2272#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002273
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002274 if (wpa_s->last_ssid == ssid) {
2275 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002276 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002277 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2278 wmm_ac_save_tspecs(wpa_s);
2279 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002280 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2281 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002282 }
Hai Shalomc3565922019-10-28 11:58:20 -07002283 } else {
2284#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002285 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002286#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002287 }
Hai Shalomc1a21442022-02-04 13:43:00 -08002288#ifdef CONFIG_SAE
2289 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2290#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002291
2292 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002293 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2294 return;
2295 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002296 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Hai Shalom60840252021-02-19 19:02:11 -08002297 if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002298 return;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002299 }
2300 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301
2302#ifdef CONFIG_IBSS_RSN
2303 ibss_rsn_deinit(wpa_s->ibss_rsn);
2304 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002305#else /* CONFIG_IBSS_RSN */
2306 if (ssid->mode == WPAS_MODE_IBSS &&
2307 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2308 wpa_msg(wpa_s, MSG_INFO,
2309 "IBSS RSN not supported in the build");
2310 return;
2311 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002312#endif /* CONFIG_IBSS_RSN */
2313
2314 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2315 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2316#ifdef CONFIG_AP
2317 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2318 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2319 "mode");
2320 return;
2321 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002322 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2323 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002324 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2325 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002326 return;
2327 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002328 wpa_s->current_bss = bss;
2329#else /* CONFIG_AP */
2330 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2331 "the build");
2332#endif /* CONFIG_AP */
2333 return;
2334 }
2335
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002336 if (ssid->mode == WPAS_MODE_MESH) {
2337#ifdef CONFIG_MESH
2338 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2339 wpa_msg(wpa_s, MSG_INFO,
2340 "Driver does not support mesh mode");
2341 return;
2342 }
2343 if (bss)
2344 ssid->frequency = bss->freq;
2345 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2346 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2347 return;
2348 }
2349 wpa_s->current_bss = bss;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002350#else /* CONFIG_MESH */
2351 wpa_msg(wpa_s, MSG_ERROR,
2352 "mesh mode support not included in the build");
2353#endif /* CONFIG_MESH */
2354 return;
2355 }
2356
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002357 /*
2358 * Set WPA state machine configuration to match the selected network now
2359 * so that the information is available before wpas_start_assoc_cb()
2360 * gets called. This is needed at least for RSN pre-authentication where
2361 * candidate APs are added to a list based on scan result processing
2362 * before completion of the first association.
2363 */
2364 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2365
2366#ifdef CONFIG_DPP
2367 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2368 return;
2369#endif /* CONFIG_DPP */
2370
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002371#ifdef CONFIG_TDLS
2372 if (bss)
Hai Shalom60840252021-02-19 19:02:11 -08002373 wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002374#endif /* CONFIG_TDLS */
2375
Hai Shalomc3565922019-10-28 11:58:20 -07002376#ifdef CONFIG_MBO
2377 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2378#endif /* CONFIG_MBO */
2379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002380 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002381 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002382 sme_authenticate(wpa_s, bss, ssid);
2383 return;
2384 }
2385
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002386 if (wpa_s->connect_work) {
2387 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2388 return;
2389 }
2390
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002391 if (radio_work_pending(wpa_s, "connect")) {
2392 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2393 return;
2394 }
2395
Dmitry Shmidt29333592017-01-09 12:27:11 -08002396#ifdef CONFIG_SME
2397 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2398 /* Clear possibly set auth_alg, if any, from last attempt. */
2399 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2400 }
2401#endif /* CONFIG_SME */
2402
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002403 wpas_abort_ongoing_scan(wpa_s);
2404
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002405 cwork = os_zalloc(sizeof(*cwork));
2406 if (cwork == NULL)
2407 return;
2408
2409 cwork->bss = bss;
2410 cwork->ssid = ssid;
2411
2412 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2413 wpas_start_assoc_cb, cwork) < 0) {
2414 os_free(cwork);
2415 }
2416}
2417
2418
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002419static int bss_is_ibss(struct wpa_bss *bss)
2420{
2421 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2422 IEEE80211_CAP_IBSS;
2423}
2424
2425
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002426static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2427 const struct wpa_ssid *ssid)
2428{
2429 enum hostapd_hw_mode hw_mode;
2430 struct hostapd_hw_modes *mode = NULL;
2431 u8 channel;
2432 int i;
2433
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002434 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2435 if (hw_mode == NUM_HOSTAPD_MODES)
2436 return 0;
2437 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2438 if (wpa_s->hw.modes[i].mode == hw_mode) {
2439 mode = &wpa_s->hw.modes[i];
2440 break;
2441 }
2442 }
2443
2444 if (!mode)
2445 return 0;
2446
2447 return mode->vht_capab != 0;
2448}
2449
2450
Hai Shalomc1a21442022-02-04 13:43:00 -08002451static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
2452{
2453 int i;
2454
2455 for (i = channel; i < channel + 16; i += 4) {
2456 struct hostapd_channel_data *chan;
2457
2458 chan = hw_get_channel_chan(mode, i, NULL);
2459 if (!chan ||
2460 chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2461 return false;
2462 }
2463
2464 return true;
2465}
2466
2467
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002468void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2469 const struct wpa_ssid *ssid,
2470 struct hostapd_freq_params *freq)
2471{
Hai Shalom81f62d82019-07-22 12:10:00 -07002472 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002473 enum hostapd_hw_mode hw_mode;
2474 struct hostapd_hw_modes *mode = NULL;
2475 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2476 184, 192 };
Hai Shalomc1a21442022-02-04 13:43:00 -08002477 int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
2478 6035, 6115, 6195, 6275, 6355, 6435, 6515,
2479 6595, 6675, 6755, 6835, 6915, 6995 };
2480 int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002481 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2482 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002483 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002484 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002485 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002486 int chwidth, seg0, seg1;
2487 u32 vht_caps = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08002488 bool is_24ghz, is_6ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002489
2490 freq->freq = ssid->frequency;
2491
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002492 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2493 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2494
2495 if (ssid->mode != WPAS_MODE_IBSS)
2496 break;
2497
2498 /* Don't adjust control freq in case of fixed_freq */
2499 if (ssid->fixed_freq)
2500 break;
2501
2502 if (!bss_is_ibss(bss))
2503 continue;
2504
2505 if (ssid->ssid_len == bss->ssid_len &&
2506 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2507 wpa_printf(MSG_DEBUG,
2508 "IBSS already found in scan results, adjust control freq: %d",
2509 bss->freq);
2510 freq->freq = bss->freq;
2511 obss_scan = 0;
2512 break;
2513 }
2514 }
2515
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002516 /* For IBSS check HT_IBSS flag */
2517 if (ssid->mode == WPAS_MODE_IBSS &&
2518 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2519 return;
2520
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002521 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2522 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2523 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2524 wpa_printf(MSG_DEBUG,
2525 "IBSS: WEP/TKIP detected, do not try to enable HT");
2526 return;
2527 }
2528
2529 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002530 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2531 if (wpa_s->hw.modes[i].mode == hw_mode) {
2532 mode = &wpa_s->hw.modes[i];
2533 break;
2534 }
2535 }
2536
2537 if (!mode)
2538 return;
2539
Hai Shalom60840252021-02-19 19:02:11 -08002540 freq->channel = channel;
2541
Hai Shalomc3565922019-10-28 11:58:20 -07002542 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2543 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002544
Hai Shalomc1a21442022-02-04 13:43:00 -08002545 /* HT/VHT and corresponding overrides are not applicable to 6 GHz.
2546 * However, HE is mandatory for 6 GHz.
2547 */
2548 is_6ghz = is_6ghz_freq(freq->freq);
2549 if (is_6ghz)
2550 goto skip_to_6ghz;
2551
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002552#ifdef CONFIG_HT_OVERRIDES
2553 if (ssid->disable_ht) {
2554 freq->ht_enabled = 0;
2555 return;
2556 }
2557#endif /* CONFIG_HT_OVERRIDES */
2558
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002559 freq->ht_enabled = ht_supported(mode);
2560 if (!freq->ht_enabled)
2561 return;
2562
Hai Shalomc3565922019-10-28 11:58:20 -07002563 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2564 if (is_24ghz)
2565 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002566#ifdef CONFIG_HE_OVERRIDES
2567 if (is_24ghz && ssid->disable_he)
2568 freq->he_enabled = 0;
2569#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002570
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002571 /* Setup higher BW only for 5 GHz */
2572 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2573 return;
2574
2575 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2576 pri_chan = &mode->channels[chan_idx];
2577 if (pri_chan->chan == channel)
2578 break;
2579 pri_chan = NULL;
2580 }
2581 if (!pri_chan)
2582 return;
2583
2584 /* Check primary channel flags */
2585 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2586 return;
2587
Hai Shalom74f70d42019-02-11 14:42:39 -08002588 freq->channel = pri_chan->chan;
2589
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002590#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002591 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002592#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002593 if (ssid->disable_vht)
2594 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002595#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002596 goto skip_ht40;
2597 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002598#endif /* CONFIG_HT_OVERRIDES */
2599
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002600 /* Check/setup HT40+/HT40- */
2601 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2602 if (ht40plus[j] == channel) {
2603 ht40 = 1;
2604 break;
2605 }
2606 }
2607
2608 /* Find secondary channel */
2609 for (i = 0; i < mode->num_channels; i++) {
2610 sec_chan = &mode->channels[i];
2611 if (sec_chan->chan == channel + ht40 * 4)
2612 break;
2613 sec_chan = NULL;
2614 }
2615 if (!sec_chan)
2616 return;
2617
2618 /* Check secondary channel flags */
2619 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2620 return;
2621
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002622 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002623 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2624 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002625 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002626 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2627 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002628 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002629 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002630
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002631 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002632 struct wpa_scan_results *scan_res;
2633
2634 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2635 if (scan_res == NULL) {
2636 /* Back to HT20 */
2637 freq->sec_channel_offset = 0;
2638 return;
2639 }
2640
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002641 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002642 switch (res) {
2643 case 0:
2644 /* Back to HT20 */
2645 freq->sec_channel_offset = 0;
2646 break;
2647 case 1:
2648 /* Configuration allowed */
2649 break;
2650 case 2:
2651 /* Switch pri/sec channels */
2652 freq->freq = hw_get_freq(mode, sec_chan->chan);
2653 freq->sec_channel_offset = -freq->sec_channel_offset;
2654 freq->channel = sec_chan->chan;
2655 break;
2656 default:
2657 freq->sec_channel_offset = 0;
2658 break;
2659 }
2660
2661 wpa_scan_results_free(scan_res);
2662 }
2663
Hai Shalom74f70d42019-02-11 14:42:39 -08002664#ifdef CONFIG_HT_OVERRIDES
2665skip_ht40:
2666#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002667 wpa_printf(MSG_DEBUG,
2668 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2669 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002670
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002671 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002672 return;
2673
2674 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002675 if (ssid->mode == WPAS_MODE_IBSS &&
2676 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002677 return;
2678
Paul Stewart092955c2017-02-06 09:13:09 -08002679#ifdef CONFIG_VHT_OVERRIDES
2680 if (ssid->disable_vht) {
2681 freq->vht_enabled = 0;
2682 return;
2683 }
2684#endif /* CONFIG_VHT_OVERRIDES */
2685
Hai Shalomc1a21442022-02-04 13:43:00 -08002686skip_to_6ghz:
2687 vht_freq = *freq;
2688
2689 /* 6 GHz does not have VHT enabled, so allow that exception here. */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002690 vht_freq.vht_enabled = vht_supported(mode);
Hai Shalomc1a21442022-02-04 13:43:00 -08002691 if (!vht_freq.vht_enabled && !is_6ghz)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002692 return;
2693
Hai Shalomfdcde762020-04-02 11:19:20 -07002694 /* Enable HE with VHT for 5 GHz */
2695 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002696
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002697 /* setup center_freq1, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002698 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
2699 if (freq->freq >= bw80[j] &&
2700 freq->freq < bw80[j] + 80)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002701 break;
2702 }
2703
Hai Shalomc1a21442022-02-04 13:43:00 -08002704 if (j == ARRAY_SIZE(bw80) ||
2705 ieee80211_freq_to_chan(bw80[j], &channel) == NUM_HOSTAPD_MODES)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002706 return;
2707
Hai Shalomc1a21442022-02-04 13:43:00 -08002708 /* Back to HT configuration if channel not usable */
2709 if (!ibss_mesh_is_80mhz_avail(channel, mode))
2710 return;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002711
Sunil8cd6f4d2022-06-28 18:40:46 +00002712 chwidth = CONF_OPER_CHWIDTH_80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002713 seg0 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002714 seg1 = 0;
2715
Hai Shalomc1a21442022-02-04 13:43:00 -08002716 if ((mode->he_capab[ieee80211_mode].phy_cap[
2717 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
2718 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz) {
2719 /* In 160 MHz, the initial four 20 MHz channels were validated
2720 * above; check the remaining four 20 MHz channels for the total
2721 * of 160 MHz bandwidth.
2722 */
2723 if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
2724 return;
2725
2726 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
2727 if (freq->freq == bw160[j]) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002728 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002729 seg0 = channel + 14;
2730 break;
2731 }
2732 }
2733 }
2734
Sunil8cd6f4d2022-06-28 18:40:46 +00002735 if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002736 /* setup center_freq2, bandwidth */
Hai Shalomc1a21442022-02-04 13:43:00 -08002737 for (k = 0; k < ARRAY_SIZE(bw80); k++) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002738 /* Only accept 80 MHz segments separated by a gap */
Hai Shalomc1a21442022-02-04 13:43:00 -08002739 if (j == k || abs(bw80[j] - bw80[k]) == 80)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002740 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08002741
2742 if (ieee80211_freq_to_chan(bw80[k], &channel) ==
2743 NUM_HOSTAPD_MODES)
2744 return;
2745
2746 for (i = channel; i < channel + 16; i += 4) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002747 struct hostapd_channel_data *chan;
2748
2749 chan = hw_get_channel_chan(mode, i, NULL);
2750 if (!chan)
2751 continue;
2752
2753 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2754 HOSTAPD_CHAN_NO_IR |
2755 HOSTAPD_CHAN_RADAR))
2756 continue;
2757
2758 /* Found a suitable second segment for 80+80 */
Sunil8cd6f4d2022-06-28 18:40:46 +00002759 chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
Hai Shalomc1a21442022-02-04 13:43:00 -08002760 if (!is_6ghz)
2761 vht_caps |=
2762 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2763 seg1 = channel + 6;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002764 }
2765
Sunil8cd6f4d2022-06-28 18:40:46 +00002766 if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002767 break;
2768 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002769 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002770 if (freq->freq == 5180) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002771 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002772 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2773 seg0 = 50;
2774 } else if (freq->freq == 5520) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002775 chwidth = CONF_OPER_CHWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002776 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2777 seg0 = 114;
2778 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002779 } else if (ssid->max_oper_chwidth == CONF_OPER_CHWIDTH_USE_HT) {
2780 chwidth = CONF_OPER_CHWIDTH_USE_HT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002781 seg0 = channel + 2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002782#ifdef CONFIG_HT_OVERRIDES
2783 if (ssid->disable_ht40)
2784 seg0 = 0;
2785#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002786 }
2787
Hai Shalomfdcde762020-04-02 11:19:20 -07002788#ifdef CONFIG_HE_OVERRIDES
2789 if (ssid->disable_he) {
2790 vht_freq.he_enabled = 0;
2791 freq->he_enabled = 0;
2792 }
2793#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002794 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002795 freq->channel, ssid->enable_edmg,
2796 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002797 vht_freq.vht_enabled, freq->he_enabled,
Sunil Ravia04bd252022-05-02 22:54:18 -07002798 false,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002799 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002800 chwidth, seg0, seg1, vht_caps,
Sunil Ravia04bd252022-05-02 22:54:18 -07002801 &mode->he_capab[ieee80211_mode],
2802 NULL) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002803 return;
2804
2805 *freq = vht_freq;
2806
2807 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2808 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002809}
2810
2811
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002812#ifdef CONFIG_FILS
2813static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2814 size_t ie_buf_len)
2815{
2816 struct fils_hlp_req *req;
2817 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2818 const u8 *pos;
2819 u8 *buf = ie_buf;
2820
2821 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2822 list) {
2823 rem_len = ie_buf_len - ie_len;
2824 pos = wpabuf_head(req->pkt);
2825 hdr_len = 1 + 2 * ETH_ALEN + 6;
2826 hlp_len = wpabuf_len(req->pkt);
2827
2828 if (rem_len < 2 + hdr_len + hlp_len) {
2829 wpa_printf(MSG_ERROR,
2830 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2831 (unsigned long) rem_len,
2832 (unsigned long) (2 + hdr_len + hlp_len));
2833 break;
2834 }
2835
2836 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2837 /* Element ID */
2838 *buf++ = WLAN_EID_EXTENSION;
2839 /* Length */
2840 *buf++ = len;
2841 /* Element ID Extension */
2842 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2843 /* Destination MAC address */
2844 os_memcpy(buf, req->dst, ETH_ALEN);
2845 buf += ETH_ALEN;
2846 /* Source MAC address */
2847 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2848 buf += ETH_ALEN;
2849 /* LLC/SNAP Header */
2850 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2851 buf += 6;
2852 /* HLP Packet */
2853 os_memcpy(buf, pos, len - hdr_len);
2854 buf += len - hdr_len;
2855 pos += len - hdr_len;
2856
2857 hlp_len -= len - hdr_len;
2858 ie_len += 2 + len;
2859 rem_len -= 2 + len;
2860
2861 while (hlp_len) {
2862 len = (hlp_len > 255) ? 255 : hlp_len;
2863 if (rem_len < 2 + len)
2864 break;
2865 *buf++ = WLAN_EID_FRAGMENT;
2866 *buf++ = len;
2867 os_memcpy(buf, pos, len);
2868 buf += len;
2869 pos += len;
2870
2871 hlp_len -= len;
2872 ie_len += 2 + len;
2873 rem_len -= 2 + len;
2874 }
2875 }
2876
2877 return ie_len;
2878}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002879
2880
2881int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2882{
2883 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2884 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2885 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2886 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2887}
2888
2889
2890int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2891{
2892#ifdef CONFIG_FILS_SK_PFS
2893 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2894 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2895#else /* CONFIG_FILS_SK_PFS */
2896 return 0;
2897#endif /* CONFIG_FILS_SK_PFS */
2898}
2899
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002900#endif /* CONFIG_FILS */
2901
2902
Hai Shalomc1a21442022-02-04 13:43:00 -08002903static int wpas_populate_wfa_capa(struct wpa_supplicant *wpa_s,
2904 struct wpa_bss *bss,
2905 u8 *wpa_ie, size_t wpa_ie_len,
2906 size_t max_wpa_ie_len)
2907{
2908 struct wpabuf *wfa_ie = NULL;
2909 u8 wfa_capa[1];
2910 size_t wfa_ie_len, buf_len;
2911
2912 os_memset(wfa_capa, 0, sizeof(wfa_capa));
2913 if (wpa_s->enable_dscp_policy_capa)
2914 wfa_capa[0] |= WFA_CAPA_QM_DSCP_POLICY;
2915
2916 if (!wfa_capa[0])
2917 return wpa_ie_len;
2918
2919 /* Wi-Fi Alliance element */
2920 buf_len = 1 + /* Element ID */
2921 1 + /* Length */
2922 3 + /* OUI */
2923 1 + /* OUI Type */
2924 1 + /* Capabilities Length */
2925 sizeof(wfa_capa); /* Capabilities */
2926 wfa_ie = wpabuf_alloc(buf_len);
2927 if (!wfa_ie)
2928 return wpa_ie_len;
2929
2930 wpabuf_put_u8(wfa_ie, WLAN_EID_VENDOR_SPECIFIC);
2931 wpabuf_put_u8(wfa_ie, buf_len - 2);
2932 wpabuf_put_be24(wfa_ie, OUI_WFA);
2933 wpabuf_put_u8(wfa_ie, WFA_CAPA_OUI_TYPE);
2934 wpabuf_put_u8(wfa_ie, sizeof(wfa_capa));
2935 wpabuf_put_data(wfa_ie, wfa_capa, sizeof(wfa_capa));
2936
2937 wfa_ie_len = wpabuf_len(wfa_ie);
2938 if (wpa_ie_len + wfa_ie_len <= max_wpa_ie_len) {
2939 wpa_hexdump_buf(MSG_MSGDUMP, "WFA Capabilities element",
2940 wfa_ie);
2941 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wfa_ie),
2942 wfa_ie_len);
2943 wpa_ie_len += wfa_ie_len;
2944 }
2945
2946 wpabuf_free(wfa_ie);
2947 return wpa_ie_len;
2948}
2949
2950
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002951static u8 * wpas_populate_assoc_ies(
2952 struct wpa_supplicant *wpa_s,
2953 struct wpa_bss *bss, struct wpa_ssid *ssid,
2954 struct wpa_driver_associate_params *params,
2955 enum wpa_drv_update_connect_params_mask *mask)
2956{
2957 u8 *wpa_ie;
2958 size_t max_wpa_ie_len = 500;
2959 size_t wpa_ie_len;
2960 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002961#ifdef CONFIG_MBO
2962 const u8 *mbo_ie;
2963#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302964#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2965 int pmksa_cached = 0;
2966#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002967#ifdef CONFIG_FILS
2968 const u8 *realm, *username, *rrk;
2969 size_t realm_len, username_len, rrk_len;
2970 u16 next_seq_num;
2971 struct fils_hlp_req *req;
2972
2973 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2974 list) {
2975 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2976 2 + 2 * wpabuf_len(req->pkt) / 255;
2977 }
2978#endif /* CONFIG_FILS */
2979
2980 wpa_ie = os_malloc(max_wpa_ie_len);
2981 if (!wpa_ie) {
2982 wpa_printf(MSG_ERROR,
2983 "Failed to allocate connect IE buffer for %lu bytes",
2984 (unsigned long) max_wpa_ie_len);
2985 return NULL;
2986 }
2987
2988 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2989 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2990 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2991 int try_opportunistic;
2992 const u8 *cache_id = NULL;
2993
2994 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2995 wpa_s->conf->okc :
2996 ssid->proactive_key_caching) &&
2997 (ssid->proto & WPA_PROTO_RSN);
2998#ifdef CONFIG_FILS
2999 if (wpa_key_mgmt_fils(ssid->key_mgmt))
3000 cache_id = wpa_bss_get_fils_cache_id(bss);
3001#endif /* CONFIG_FILS */
3002 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
3003 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07003004 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003005 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303006#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
3007 pmksa_cached = 1;
3008#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07003009 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003010 wpa_ie_len = max_wpa_ie_len;
3011 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3012 wpa_ie, &wpa_ie_len)) {
3013 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3014 "key management and encryption suites");
3015 os_free(wpa_ie);
3016 return NULL;
3017 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003018#ifdef CONFIG_HS20
3019 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
3020 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
3021 /* No PMKSA caching, but otherwise similar to RSN/WPA */
3022 wpa_ie_len = max_wpa_ie_len;
3023 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
3024 wpa_ie, &wpa_ie_len)) {
3025 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3026 "key management and encryption suites");
3027 os_free(wpa_ie);
3028 return NULL;
3029 }
3030#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003031 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
3032 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
3033 /*
3034 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
3035 * use non-WPA since the scan results did not indicate that the
3036 * AP is using WPA or WPA2.
3037 */
3038 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3039 wpa_ie_len = 0;
3040 wpa_s->wpa_proto = 0;
3041 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
3042 wpa_ie_len = max_wpa_ie_len;
3043 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
3044 wpa_ie, &wpa_ie_len)) {
3045 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
3046 "key management and encryption suites (no "
3047 "scan results)");
3048 os_free(wpa_ie);
3049 return NULL;
3050 }
3051#ifdef CONFIG_WPS
3052 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
3053 struct wpabuf *wps_ie;
3054 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
3055 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
3056 wpa_ie_len = wpabuf_len(wps_ie);
3057 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
3058 } else
3059 wpa_ie_len = 0;
3060 wpabuf_free(wps_ie);
3061 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3062 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
3063 params->wps = WPS_MODE_PRIVACY;
3064 else
3065 params->wps = WPS_MODE_OPEN;
3066 wpa_s->wpa_proto = 0;
3067#endif /* CONFIG_WPS */
3068 } else {
3069 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
3070 wpa_ie_len = 0;
3071 wpa_s->wpa_proto = 0;
3072 }
3073
3074#ifdef IEEE8021X_EAPOL
3075 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3076 if (ssid->leap) {
3077 if (ssid->non_leap == 0)
3078 algs = WPA_AUTH_ALG_LEAP;
3079 else
3080 algs |= WPA_AUTH_ALG_LEAP;
3081 }
3082 }
3083
3084#ifdef CONFIG_FILS
3085 /* Clear FILS association */
3086 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
3087
3088 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3089 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3090 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
3091 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003092 &next_seq_num, &rrk, &rrk_len) == 0 &&
3093 (!wpa_s->last_con_fail_realm ||
3094 wpa_s->last_con_fail_realm_len != realm_len ||
3095 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003096 algs = WPA_AUTH_ALG_FILS;
3097 params->fils_erp_username = username;
3098 params->fils_erp_username_len = username_len;
3099 params->fils_erp_realm = realm;
3100 params->fils_erp_realm_len = realm_len;
3101 params->fils_erp_next_seq_num = next_seq_num;
3102 params->fils_erp_rrk = rrk;
3103 params->fils_erp_rrk_len = rrk_len;
3104
3105 if (mask)
3106 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303107 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
3108 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
3109 pmksa_cached) {
3110 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003111 }
3112#endif /* CONFIG_FILS */
3113#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003114#ifdef CONFIG_SAE
3115 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
3116 algs = WPA_AUTH_ALG_SAE;
3117#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003118
3119 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
3120 if (ssid->auth_alg) {
3121 algs = ssid->auth_alg;
3122 wpa_dbg(wpa_s, MSG_DEBUG,
3123 "Overriding auth_alg selection: 0x%x", algs);
3124 }
3125
Hai Shalom5f92bc92019-04-18 11:54:11 -07003126#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05303127 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07003128 wpa_dbg(wpa_s, MSG_DEBUG,
3129 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
3130 algs = WPA_AUTH_ALG_OPEN;
3131 }
3132#endif /* CONFIG_SAE */
3133
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003134#ifdef CONFIG_P2P
3135 if (wpa_s->global->p2p) {
3136 u8 *pos;
3137 size_t len;
3138 int res;
3139 pos = wpa_ie + wpa_ie_len;
3140 len = max_wpa_ie_len - wpa_ie_len;
3141 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
3142 ssid->p2p_group);
3143 if (res >= 0)
3144 wpa_ie_len += res;
3145 }
3146
3147 wpa_s->cross_connect_disallowed = 0;
3148 if (bss) {
3149 struct wpabuf *p2p;
3150 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
3151 if (p2p) {
3152 wpa_s->cross_connect_disallowed =
3153 p2p_get_cross_connect_disallowed(p2p);
3154 wpabuf_free(p2p);
3155 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
3156 "connection",
3157 wpa_s->cross_connect_disallowed ?
3158 "disallows" : "allows");
3159 }
3160 }
3161
3162 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
3163#endif /* CONFIG_P2P */
3164
3165 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003166 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003167 wpa_ie + wpa_ie_len,
3168 max_wpa_ie_len -
3169 wpa_ie_len);
3170 }
3171
3172 /*
3173 * Workaround: Add Extended Capabilities element only if the AP
3174 * included this element in Beacon/Probe Response frames. Some older
3175 * APs seem to have interoperability issues if this element is
3176 * included, so while the standard may require us to include the
3177 * element in all cases, it is justifiable to skip it to avoid
3178 * interoperability issues.
3179 */
3180 if (ssid->p2p_group)
3181 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
3182 else
3183 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
3184
3185 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
3186 u8 ext_capab[18];
3187 int ext_capab_len;
3188 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
3189 sizeof(ext_capab));
3190 if (ext_capab_len > 0 &&
3191 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3192 u8 *pos = wpa_ie;
3193 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3194 pos += 2 + pos[1];
3195 os_memmove(pos + ext_capab_len, pos,
3196 wpa_ie_len - (pos - wpa_ie));
3197 wpa_ie_len += ext_capab_len;
3198 os_memcpy(pos, ext_capab, ext_capab_len);
3199 }
3200 }
3201
3202#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08003203 if (is_hs20_network(wpa_s, ssid, bss)
3204#ifndef ANDROID /* Android does not use the native HS 2.0 config */
3205 && is_hs20_config(wpa_s)
3206#endif /* ANDROID */
3207 ) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003208 struct wpabuf *hs20;
3209
Roshan Pius3a1667e2018-07-03 15:17:14 -07003210 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003211 if (hs20) {
3212 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3213 size_t len;
3214
Hai Shalom74f70d42019-02-11 14:42:39 -08003215 wpas_hs20_add_indication(hs20, pps_mo_id,
3216 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003217 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003218 len = max_wpa_ie_len - wpa_ie_len;
3219 if (wpabuf_len(hs20) <= len) {
3220 os_memcpy(wpa_ie + wpa_ie_len,
3221 wpabuf_head(hs20), wpabuf_len(hs20));
3222 wpa_ie_len += wpabuf_len(hs20);
3223 }
3224 wpabuf_free(hs20);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003225 }
3226 }
Hai Shalom2cbbcd12021-03-08 18:33:38 -08003227 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003228#endif /* CONFIG_HS20 */
3229
3230 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3231 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3232 size_t len;
3233
3234 len = max_wpa_ie_len - wpa_ie_len;
3235 if (wpabuf_len(buf) <= len) {
3236 os_memcpy(wpa_ie + wpa_ie_len,
3237 wpabuf_head(buf), wpabuf_len(buf));
3238 wpa_ie_len += wpabuf_len(buf);
3239 }
3240 }
3241
3242#ifdef CONFIG_FST
3243 if (wpa_s->fst_ies) {
3244 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3245
3246 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3247 os_memcpy(wpa_ie + wpa_ie_len,
3248 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3249 wpa_ie_len += fst_ies_len;
3250 }
3251 }
3252#endif /* CONFIG_FST */
3253
3254#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003255 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003256 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003257 int len;
3258
3259 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003260 max_wpa_ie_len - wpa_ie_len,
3261 !!mbo_attr_from_mbo_ie(mbo_ie,
3262 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003263 if (len >= 0)
3264 wpa_ie_len += len;
3265 }
3266#endif /* CONFIG_MBO */
3267
3268#ifdef CONFIG_FILS
3269 if (algs == WPA_AUTH_ALG_FILS) {
3270 size_t len;
3271
3272 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3273 max_wpa_ie_len - wpa_ie_len);
3274 wpa_ie_len += len;
3275 }
3276#endif /* CONFIG_FILS */
3277
3278#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003279#ifdef CONFIG_TESTING_OPTIONS
3280 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3281 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3282 } else
3283#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003284 if (algs == WPA_AUTH_ALG_OPEN &&
3285 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3286 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003287 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003288
Roshan Pius3a1667e2018-07-03 15:17:14 -07003289 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003290 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003291 } else if (wpa_s->assoc_status_code ==
3292 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003293 if (wpa_s->last_owe_group == 19)
3294 group = 20;
3295 else if (wpa_s->last_owe_group == 20)
3296 group = 21;
3297 else
3298 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003299 } else {
3300 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003301 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003302
Roshan Pius3a1667e2018-07-03 15:17:14 -07003303 wpa_s->last_owe_group = group;
3304 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003305 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3306 if (owe_ie &&
3307 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3308 os_memcpy(wpa_ie + wpa_ie_len,
3309 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3310 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003311 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003312 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003313 }
3314#endif /* CONFIG_OWE */
3315
Hai Shalom021b0b52019-04-10 11:17:58 -07003316#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003317 if (DPP_VERSION > 1 &&
3318 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003319 ssid->dpp_netaccesskey &&
3320 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003321 struct rsn_pmksa_cache_entry *pmksa;
3322
3323 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3324 if (!pmksa || !pmksa->dpp_pfs)
3325 goto pfs_fail;
3326
Hai Shalom021b0b52019-04-10 11:17:58 -07003327 dpp_pfs_free(wpa_s->dpp_pfs);
3328 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3329 ssid->dpp_netaccesskey_len);
3330 if (!wpa_s->dpp_pfs) {
3331 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3332 /* Try to continue without PFS */
3333 goto pfs_fail;
3334 }
3335 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3336 max_wpa_ie_len - wpa_ie_len) {
3337 os_memcpy(wpa_ie + wpa_ie_len,
3338 wpabuf_head(wpa_s->dpp_pfs->ie),
3339 wpabuf_len(wpa_s->dpp_pfs->ie));
3340 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3341 }
3342 }
3343pfs_fail:
3344#endif /* CONFIG_DPP2 */
3345
Roshan Pius3a1667e2018-07-03 15:17:14 -07003346#ifdef CONFIG_IEEE80211R
3347 /*
3348 * Add MDIE under these conditions: the network profile allows FT,
3349 * the AP supports FT, and the mobility domain ID matches.
3350 */
3351 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3352 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3353
3354 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3355 size_t len = 0;
3356 const u8 *md = mdie + 2;
3357 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3358
3359 if (os_memcmp(md, wpa_md,
3360 MOBILITY_DOMAIN_ID_LEN) == 0) {
3361 /* Add mobility domain IE */
3362 len = wpa_ft_add_mdie(
3363 wpa_s->wpa, wpa_ie + wpa_ie_len,
3364 max_wpa_ie_len - wpa_ie_len, mdie);
3365 wpa_ie_len += len;
3366 }
3367#ifdef CONFIG_SME
3368 if (len > 0 && wpa_s->sme.ft_used &&
3369 wpa_sm_has_ptk(wpa_s->wpa)) {
3370 wpa_dbg(wpa_s, MSG_DEBUG,
3371 "SME: Trying to use FT over-the-air");
3372 algs |= WPA_AUTH_ALG_FT;
3373 }
3374#endif /* CONFIG_SME */
3375 }
3376 }
3377#endif /* CONFIG_IEEE80211R */
3378
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003379#ifdef CONFIG_TESTING_OPTIONS
3380 if (wpa_s->rsnxe_override_assoc &&
3381 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3382 max_wpa_ie_len - wpa_ie_len) {
3383 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3384 os_memcpy(wpa_ie + wpa_ie_len,
3385 wpabuf_head(wpa_s->rsnxe_override_assoc),
3386 wpabuf_len(wpa_s->rsnxe_override_assoc));
3387 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3388 } else
3389#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003390 if (wpa_s->rsnxe_len > 0 &&
3391 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3392 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3393 wpa_ie_len += wpa_s->rsnxe_len;
3394 }
3395
Hai Shalomc1a21442022-02-04 13:43:00 -08003396#ifdef CONFIG_TESTING_OPTIONS
3397 if (wpa_s->disable_mscs_support)
3398 goto mscs_end;
3399#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom60840252021-02-19 19:02:11 -08003400 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
3401 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003402 struct wpabuf *mscs_ie;
3403 size_t mscs_ie_len, buf_len;
3404
Hai Shalom899fcc72020-10-19 14:38:18 -07003405 buf_len = 3 + /* MSCS descriptor IE header */
3406 1 + /* Request type */
3407 2 + /* User priority control */
3408 4 + /* Stream timeout */
3409 3 + /* TCLAS Mask IE header */
3410 wpa_s->robust_av.frame_classifier_len;
3411 mscs_ie = wpabuf_alloc(buf_len);
3412 if (!mscs_ie) {
3413 wpa_printf(MSG_INFO,
3414 "MSCS: Failed to allocate MSCS IE");
Hai Shalomc1a21442022-02-04 13:43:00 -08003415 goto mscs_end;
Hai Shalom899fcc72020-10-19 14:38:18 -07003416 }
3417
3418 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3419 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3420 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3421 mscs_ie_len = wpabuf_len(mscs_ie);
3422 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3423 mscs_ie_len);
3424 wpa_ie_len += mscs_ie_len;
3425 }
3426
3427 wpabuf_free(mscs_ie);
3428 }
Hai Shalomc1a21442022-02-04 13:43:00 -08003429mscs_end:
3430
3431 wpa_ie_len = wpas_populate_wfa_capa(wpa_s, bss, wpa_ie, wpa_ie_len,
3432 max_wpa_ie_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003433
Hai Shalom74f70d42019-02-11 14:42:39 -08003434 if (ssid->multi_ap_backhaul_sta) {
3435 size_t multi_ap_ie_len;
3436
3437 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3438 max_wpa_ie_len - wpa_ie_len,
3439 MULTI_AP_BACKHAUL_STA);
3440 if (multi_ap_ie_len == 0) {
3441 wpa_printf(MSG_ERROR,
3442 "Multi-AP: Failed to build Multi-AP IE");
3443 os_free(wpa_ie);
3444 return NULL;
3445 }
3446 wpa_ie_len += multi_ap_ie_len;
3447 }
3448
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003449 params->wpa_ie = wpa_ie;
3450 params->wpa_ie_len = wpa_ie_len;
3451 params->auth_alg = algs;
3452 if (mask)
3453 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3454
3455 return wpa_ie;
3456}
3457
3458
Hai Shalomc3565922019-10-28 11:58:20 -07003459#ifdef CONFIG_OWE
3460static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3461{
3462 struct wpa_driver_associate_params params;
3463 u8 *wpa_ie;
3464
3465 os_memset(&params, 0, sizeof(params));
3466 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3467 wpa_s->current_ssid, &params, NULL);
3468 if (!wpa_ie)
3469 return;
3470
3471 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3472 os_free(wpa_ie);
3473}
3474#endif /* CONFIG_OWE */
3475
3476
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003477#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3478static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3479{
3480 struct wpa_driver_associate_params params;
3481 enum wpa_drv_update_connect_params_mask mask = 0;
3482 u8 *wpa_ie;
3483
3484 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3485 return; /* nothing to do */
3486
3487 os_memset(&params, 0, sizeof(params));
3488 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3489 wpa_s->current_ssid, &params, &mask);
3490 if (!wpa_ie)
3491 return;
3492
Hai Shalomc1a21442022-02-04 13:43:00 -08003493 if (params.auth_alg == WPA_AUTH_ALG_FILS) {
3494 wpa_s->auth_alg = params.auth_alg;
3495 wpa_drv_update_connect_params(wpa_s, &params, mask);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003496 }
3497
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003498 os_free(wpa_ie);
3499}
3500#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3501
3502
Hai Shalomc3565922019-10-28 11:58:20 -07003503static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3504{
3505 if (!edmg_ie || edmg_ie[1] < 6)
3506 return 0;
3507 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3508}
3509
3510
3511static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3512{
3513 if (!edmg_ie || edmg_ie[1] < 6)
3514 return 0;
3515 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3516}
3517
3518
3519/* Returns the intersection of two EDMG configurations.
3520 * Note: The current implementation is limited to CB2 only (CB1 included),
3521 * i.e., the implementation supports up to 2 contiguous channels.
3522 * For supporting non-contiguous (aggregated) channels and for supporting
3523 * CB3 and above, this function will need to be extended.
3524 */
3525static struct ieee80211_edmg_config
3526get_edmg_intersection(struct ieee80211_edmg_config a,
3527 struct ieee80211_edmg_config b,
3528 u8 primary_channel)
3529{
3530 struct ieee80211_edmg_config result;
3531 int i, contiguous = 0;
3532 int max_contiguous = 0;
3533
3534 result.channels = b.channels & a.channels;
3535 if (!result.channels) {
3536 wpa_printf(MSG_DEBUG,
3537 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3538 a.channels, b.channels);
3539 goto fail;
3540 }
3541
3542 if (!(result.channels & BIT(primary_channel - 1))) {
3543 wpa_printf(MSG_DEBUG,
3544 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3545 primary_channel, result.channels);
3546 goto fail;
3547 }
3548
3549 /* Find max contiguous channels */
3550 for (i = 0; i < 6; i++) {
3551 if (result.channels & BIT(i))
3552 contiguous++;
3553 else
3554 contiguous = 0;
3555
3556 if (contiguous > max_contiguous)
3557 max_contiguous = contiguous;
3558 }
3559
3560 /* Assuming AP and STA supports ONLY contiguous channels,
3561 * bw configuration can have value between 4-7.
3562 */
3563 if ((b.bw_config < a.bw_config))
3564 result.bw_config = b.bw_config;
3565 else
3566 result.bw_config = a.bw_config;
3567
3568 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3569 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3570 wpa_printf(MSG_DEBUG,
3571 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3572 max_contiguous);
3573 goto fail;
3574 }
3575
3576 return result;
3577
3578fail:
3579 result.channels = 0;
3580 result.bw_config = 0;
3581 return result;
3582}
3583
3584
3585static struct ieee80211_edmg_config
3586get_supported_edmg(struct wpa_supplicant *wpa_s,
3587 struct hostapd_freq_params *freq,
3588 struct ieee80211_edmg_config request_edmg)
3589{
3590 enum hostapd_hw_mode hw_mode;
3591 struct hostapd_hw_modes *mode = NULL;
3592 u8 primary_channel;
3593
3594 if (!wpa_s->hw.modes)
3595 goto fail;
3596
3597 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3598 if (hw_mode == NUM_HOSTAPD_MODES)
3599 goto fail;
3600
Hai Shalom60840252021-02-19 19:02:11 -08003601 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
Hai Shalomc3565922019-10-28 11:58:20 -07003602 if (!mode)
3603 goto fail;
3604
3605 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3606
3607fail:
3608 request_edmg.channels = 0;
3609 request_edmg.bw_config = 0;
3610 return request_edmg;
3611}
3612
3613
Hai Shalom021b0b52019-04-10 11:17:58 -07003614#ifdef CONFIG_MBO
3615void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3616{
3617 struct wpa_driver_associate_params params;
3618 u8 *wpa_ie;
3619
3620 /*
3621 * Update MBO connect params only in case of change of MBO attributes
3622 * when connected, if the AP support MBO.
3623 */
3624
3625 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3626 !wpa_s->current_bss ||
3627 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3628 return;
3629
3630 os_memset(&params, 0, sizeof(params));
3631 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3632 wpa_s->current_ssid, &params, NULL);
3633 if (!wpa_ie)
3634 return;
3635
3636 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3637 os_free(wpa_ie);
3638}
3639#endif /* CONFIG_MBO */
3640
3641
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003642static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3643{
3644 struct wpa_connect_work *cwork = work->ctx;
3645 struct wpa_bss *bss = cwork->bss;
3646 struct wpa_ssid *ssid = cwork->ssid;
3647 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003648 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003649 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003650 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003651 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003652 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003653#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003654 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003655#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003656 int assoc_failed = 0;
3657 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003658 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003659#ifdef CONFIG_HT_OVERRIDES
3660 struct ieee80211_ht_capabilities htcaps;
3661 struct ieee80211_ht_capabilities htcaps_mask;
3662#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003663#ifdef CONFIG_VHT_OVERRIDES
3664 struct ieee80211_vht_capabilities vhtcaps;
3665 struct ieee80211_vht_capabilities vhtcaps_mask;
3666#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003667
Hai Shalomc1a21442022-02-04 13:43:00 -08003668 wpa_s->roam_in_progress = false;
3669#ifdef CONFIG_WNM
3670 wpa_s->bss_trans_mgmt_in_progress = false;
3671#endif /* CONFIG_WNM */
3672
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003673 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003674 if (work->started) {
3675 wpa_s->connect_work = NULL;
3676
3677 /* cancel possible auth. timeout */
3678 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3679 NULL);
3680 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003681 wpas_connect_work_free(cwork);
3682 return;
3683 }
3684
3685 wpa_s->connect_work = work;
3686
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003687 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3688 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003689 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3690 wpas_connect_work_done(wpa_s);
3691 return;
3692 }
3693
Dmitry Shmidte4663042016-04-04 10:07:49 -07003694 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003695 os_memset(&params, 0, sizeof(params));
3696 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003697 wpa_s->eap_expected_failure = 0;
Hai Shalom60840252021-02-19 19:02:11 -08003698
3699 /* Starting new association, so clear the possibly used WPA IE from the
3700 * previous association. */
3701 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3702 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3703 wpa_s->rsnxe_len = 0;
3704 wpa_s->mscs_setup_done = false;
3705
3706 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3707 if (!wpa_ie) {
3708 wpas_connect_work_done(wpa_s);
3709 return;
3710 }
3711
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003712 if (bss &&
3713 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003714#ifdef CONFIG_IEEE80211R
3715 const u8 *ie, *md = NULL;
3716#endif /* CONFIG_IEEE80211R */
3717 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3718 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3719 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3720 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3721 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3722 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3723 if (bssid_changed)
3724 wpas_notify_bssid_changed(wpa_s);
3725#ifdef CONFIG_IEEE80211R
3726 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3727 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3728 md = ie + 2;
3729 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3730 if (md) {
3731 /* Prepare for the next transition */
3732 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3733 }
3734#endif /* CONFIG_IEEE80211R */
3735#ifdef CONFIG_WPS
3736 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3737 wpa_s->conf->ap_scan == 2 &&
3738 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3739 /* Use ap_scan==1 style network selection to find the network
3740 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003741 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003742 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743 wpa_s->reassociate = 1;
3744 wpa_supplicant_req_scan(wpa_s, 0, 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08003745 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003746 return;
3747#endif /* CONFIG_WPS */
3748 } else {
3749 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3750 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003751 if (bss)
3752 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3753 else
3754 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003755 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003756 if (!wpa_s->pno)
3757 wpa_supplicant_cancel_sched_scan(wpa_s);
3758
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003759 wpa_supplicant_cancel_scan(wpa_s);
3760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003761 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3762 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003763 cipher_pairwise = wpa_s->pairwise_cipher;
3764 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003765 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003766 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3767 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3768 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3769 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003770#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003771 if (wpa_set_wep_keys(wpa_s, ssid)) {
3772 use_crypt = 1;
3773 wep_keys_set = 1;
3774 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003775#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003776 }
3777 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3778 use_crypt = 0;
3779
3780#ifdef IEEE8021X_EAPOL
3781 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3782 if ((ssid->eapol_flags &
3783 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3784 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3785 !wep_keys_set) {
3786 use_crypt = 0;
3787 } else {
3788 /* Assume that dynamic WEP-104 keys will be used and
3789 * set cipher suites in order for drivers to expect
3790 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003791 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003792 }
3793 }
3794#endif /* IEEE8021X_EAPOL */
3795
3796 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3797 /* Set the key before (and later after) association */
3798 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3799 }
3800
Sunil8cd6f4d2022-06-28 18:40:46 +00003801 /* Set current_ssid before changing state to ASSOCIATING, so that the
3802 * selected SSID is available to wpas_notify_state_changed(). */
3803 old_ssid = wpa_s->current_ssid;
3804 wpa_s->current_ssid = ssid;
3805
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003806 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3807 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003808 params.ssid = bss->ssid;
3809 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003810 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3811 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003812 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3813 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003814 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003815 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003816 ssid->bssid_set,
3817 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003818 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003819 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003820 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003821 params.bssid_hint = bss->bssid;
3822 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003823 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003824 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003825 if (ssid->bssid_hint_set)
3826 params.bssid_hint = ssid->bssid_hint;
3827
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003828 params.ssid = ssid->ssid;
3829 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003830 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003831 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003832
3833 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3834 wpa_s->conf->ap_scan == 2) {
3835 params.bssid = ssid->bssid;
3836 params.fixed_bssid = 1;
3837 }
3838
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003839 /* Initial frequency for IBSS/mesh */
3840 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003841 ssid->frequency > 0 && params.freq.freq == 0)
3842 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003843
3844 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003845 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003846 if (ssid->beacon_int)
3847 params.beacon_int = ssid->beacon_int;
3848 else
3849 params.beacon_int = wpa_s->conf->beacon_int;
3850 }
3851
Hai Shalomc3565922019-10-28 11:58:20 -07003852 if (bss && ssid->enable_edmg)
Hai Shalom60840252021-02-19 19:02:11 -08003853 edmg_ie_oper = wpa_bss_get_ie_ext(bss,
3854 WLAN_EID_EXT_EDMG_OPERATION);
Hai Shalomc3565922019-10-28 11:58:20 -07003855 else
3856 edmg_ie_oper = NULL;
3857
3858 if (edmg_ie_oper) {
3859 params.freq.edmg.channels =
3860 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3861 params.freq.edmg.bw_config =
3862 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3863 wpa_printf(MSG_DEBUG,
3864 "AP supports EDMG channels 0x%x, bw_config %d",
3865 params.freq.edmg.channels,
3866 params.freq.edmg.bw_config);
3867
3868 /* User may ask for specific EDMG channel for EDMG connection
3869 * (must be supported by AP)
3870 */
3871 if (ssid->edmg_channel) {
3872 struct ieee80211_edmg_config configured_edmg;
3873 enum hostapd_hw_mode hw_mode;
3874 u8 primary_channel;
3875
3876 hw_mode = ieee80211_freq_to_chan(bss->freq,
3877 &primary_channel);
3878 if (hw_mode == NUM_HOSTAPD_MODES)
3879 goto edmg_fail;
3880
3881 hostapd_encode_edmg_chan(ssid->enable_edmg,
3882 ssid->edmg_channel,
3883 primary_channel,
3884 &configured_edmg);
3885
3886 if (ieee802_edmg_is_allowed(params.freq.edmg,
3887 configured_edmg)) {
3888 params.freq.edmg = configured_edmg;
3889 wpa_printf(MSG_DEBUG,
3890 "Use EDMG channel %d for connection",
3891 ssid->edmg_channel);
3892 } else {
3893 edmg_fail:
3894 params.freq.edmg.channels = 0;
3895 params.freq.edmg.bw_config = 0;
3896 wpa_printf(MSG_WARNING,
3897 "EDMG channel %d not supported by AP, fallback to DMG",
3898 ssid->edmg_channel);
3899 }
3900 }
3901
3902 if (params.freq.edmg.channels) {
3903 wpa_printf(MSG_DEBUG,
3904 "EDMG before: channels 0x%x, bw_config %d",
3905 params.freq.edmg.channels,
3906 params.freq.edmg.bw_config);
3907 params.freq.edmg = get_supported_edmg(wpa_s,
3908 &params.freq,
3909 params.freq.edmg);
3910 wpa_printf(MSG_DEBUG,
3911 "EDMG after: channels 0x%x, bw_config %d",
3912 params.freq.edmg.channels,
3913 params.freq.edmg.bw_config);
3914 }
3915 }
3916
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003917 params.pairwise_suite = cipher_pairwise;
3918 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003919 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003920 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003921 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003922 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003924 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003925#ifdef CONFIG_WEP
3926 {
3927 int i;
3928
3929 for (i = 0; i < NUM_WEP_KEYS; i++) {
3930 if (ssid->wep_key_len[i])
3931 params.wep_key[i] = ssid->wep_key[i];
3932 params.wep_key_len[i] = ssid->wep_key_len[i];
3933 }
3934 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003935 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003936#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003937
Hai Shalom74f70d42019-02-11 14:42:39 -08003938 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Vinayak Yadawad14709082022-03-17 14:25:11 +05303939 (
3940#ifdef CONFIG_DRIVER_NL80211_BRCM
3941 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3942#else
3943 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3944#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003945 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946 params.passphrase = ssid->passphrase;
3947 if (ssid->psk_set)
3948 params.psk = ssid->psk;
3949 }
3950
Hai Shalom74f70d42019-02-11 14:42:39 -08003951 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3952 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3953 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3954 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3955 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003956 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003957
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003958 if (wpa_s->conf->key_mgmt_offload) {
3959 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3960 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003961 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3962 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003963 params.req_key_mgmt_offload =
3964 ssid->proactive_key_caching < 0 ?
3965 wpa_s->conf->okc : ssid->proactive_key_caching;
3966 else
3967 params.req_key_mgmt_offload = 1;
3968
Vinayak Yadawad14709082022-03-17 14:25:11 +05303969 if ((
3970#ifdef CONFIG_DRIVER_NL80211_BRCM
3971 (params.key_mgmt_suite & WPA_KEY_MGMT_PSK) ||
3972#else
3973 params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3974#endif /* CONFIG_DRIVER_NL80211_BRCM */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003975 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3976 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3977 ssid->psk_set)
3978 params.psk = ssid->psk;
3979 }
3980
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003981 params.drop_unencrypted = use_crypt;
3982
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003983 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003984 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003985 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3986 struct wpa_ie_data ie;
3987 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3988 ie.capabilities &
3989 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3990 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3991 "MFP: require MFP");
3992 params.mgmt_frame_protection =
3993 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003994#ifdef CONFIG_OWE
3995 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3996 !ssid->owe_only) {
3997 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3998#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003999 }
4000 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004001
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004002 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004003
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004004 if (wpa_s->p2pdev->set_sta_uapsd)
4005 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004006 else
4007 params.uapsd = -1;
4008
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004009#ifdef CONFIG_HT_OVERRIDES
4010 os_memset(&htcaps, 0, sizeof(htcaps));
4011 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
4012 params.htcaps = (u8 *) &htcaps;
4013 params.htcaps_mask = (u8 *) &htcaps_mask;
4014 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
4015#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004016#ifdef CONFIG_VHT_OVERRIDES
4017 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
4018 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
4019 params.vhtcaps = &vhtcaps;
4020 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004021 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004022#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07004023#ifdef CONFIG_HE_OVERRIDES
4024 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
4025#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004026
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004027#ifdef CONFIG_P2P
4028 /*
4029 * If multi-channel concurrency is not supported, check for any
4030 * frequency conflict. In case of any frequency conflict, remove the
4031 * least prioritized connection.
4032 */
4033 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004034 int freq, num;
4035 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004036 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07004037 wpa_printf(MSG_DEBUG,
4038 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004039 freq, params.freq.freq);
4040 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004041 wpa_s, params.freq.freq, ssid) < 0) {
4042 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004043 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004044 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004045 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08004046 }
4047 }
4048#endif /* CONFIG_P2P */
4049
Dmitry Shmidte4663042016-04-04 10:07:49 -07004050 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
Sunil8cd6f4d2022-06-28 18:40:46 +00004051 old_ssid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004052 params.prev_bssid = prev_bssid;
4053
Hai Shalom60840252021-02-19 19:02:11 -08004054#ifdef CONFIG_SAE
4055 params.sae_pwe = wpa_s->conf->sae_pwe;
4056#endif /* CONFIG_SAE */
4057
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004058 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004059 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004060 if (ret < 0) {
4061 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
4062 "failed");
Hai Shalomc1a21442022-02-04 13:43:00 -08004063 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_VALID_ERROR_CODES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004064 /*
4065 * The driver is known to mean what is saying, so we
4066 * can stop right here; the association will not
4067 * succeed.
4068 */
4069 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08004070 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
Sunil Ravie06118e2021-01-03 08:39:46 -08004071 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004072 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004073 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
4074 return;
4075 }
4076 /* try to continue anyway; new association will be tried again
4077 * after timeout */
4078 assoc_failed = 1;
4079 }
4080
4081 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
4082 /* Set the key after the association just in case association
4083 * cleared the previously configured key. */
4084 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
4085 /* No need to timeout authentication since there is no key
4086 * management. */
4087 wpa_supplicant_cancel_auth_timeout(wpa_s);
4088 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
4089#ifdef CONFIG_IBSS_RSN
4090 } else if (ssid->mode == WPAS_MODE_IBSS &&
4091 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
4092 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
4093 /*
4094 * RSN IBSS authentication is per-STA and we can disable the
4095 * per-BSSID authentication.
4096 */
4097 wpa_supplicant_cancel_auth_timeout(wpa_s);
4098#endif /* CONFIG_IBSS_RSN */
4099 } else {
4100 /* Timeout for IEEE 802.11 authentication and association */
4101 int timeout = 60;
4102
4103 if (assoc_failed) {
4104 /* give IBSS a bit more time */
4105 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
4106 } else if (wpa_s->conf->ap_scan == 1) {
4107 /* give IBSS a bit more time */
4108 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
4109 }
4110 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
4111 }
4112
Hai Shalomfdcde762020-04-02 11:19:20 -07004113#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004114 if (wep_keys_set &&
4115 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116 /* Set static WEP keys again */
4117 wpa_set_wep_keys(wpa_s, ssid);
4118 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004119#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004120
Sunil8cd6f4d2022-06-28 18:40:46 +00004121 if (old_ssid && old_ssid != ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004122 /*
4123 * Do not allow EAP session resumption between different
4124 * network configurations.
4125 */
4126 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4127 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004128
4129 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07004130 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004131#ifdef CONFIG_HS20
4132 hs20_configure_frame_filters(wpa_s);
4133#endif /* CONFIG_HS20 */
4134 }
4135
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004136 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
4137 wpa_supplicant_initiate_eapol(wpa_s);
4138 if (old_ssid != wpa_s->current_ssid)
4139 wpas_notify_network_changed(wpa_s);
4140}
4141
4142
4143static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
4144 const u8 *addr)
4145{
4146 struct wpa_ssid *old_ssid;
4147
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004148 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004149 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004150 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004151 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004152 wpa_sm_set_config(wpa_s->wpa, NULL);
4153 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4154 if (old_ssid != wpa_s->current_ssid)
4155 wpas_notify_network_changed(wpa_s);
Hai Shalomc1a21442022-02-04 13:43:00 -08004156
4157 wpas_scs_deinit(wpa_s);
4158 wpas_dscp_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004159 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4160}
4161
4162
4163/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004164 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
4165 * @wpa_s: Pointer to wpa_supplicant data
4166 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
4167 *
4168 * This function is used to request %wpa_supplicant to deauthenticate from the
4169 * current AP.
4170 */
4171void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07004172 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004173{
4174 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004175 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004176 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004177
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004178 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07004179 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004180 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07004181 reason_code, reason2str(reason_code),
4182 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004183
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004184 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
4185 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
4186 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004187 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004188 else if (!is_zero_ether_addr(wpa_s->bssid))
4189 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004190 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
4191 /*
4192 * When using driver-based BSS selection, we may not know the
4193 * BSSID with which we are currently trying to associate. We
4194 * need to notify the driver of this disconnection even in such
4195 * a case, so use the all zeros address here.
4196 */
4197 addr = wpa_s->bssid;
4198 zero_addr = 1;
4199 }
4200
Hai Shalom74f70d42019-02-11 14:42:39 -08004201 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
4202 wpa_s->enabled_4addr_mode = 0;
4203
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004204#ifdef CONFIG_TDLS
4205 wpa_tdls_teardown_peers(wpa_s->wpa);
4206#endif /* CONFIG_TDLS */
4207
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004208#ifdef CONFIG_MESH
4209 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004210 struct mesh_conf *mconf;
4211
4212 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004213 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
4214 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004215 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
4216 mconf->meshid_len, reason_code);
Hai Shalom60840252021-02-19 19:02:11 -08004217 wpa_supplicant_leave_mesh(wpa_s, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004218 }
4219#endif /* CONFIG_MESH */
4220
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004221 if (addr) {
4222 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004223 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004224 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004225 event.deauth_info.locally_generated = 1;
4226 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004227 if (zero_addr)
4228 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004229 }
4230
4231 wpa_supplicant_clear_connection(wpa_s, addr);
4232}
4233
Hai Shalomfdcde762020-04-02 11:19:20 -07004234
4235void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4236{
4237 wpa_s->own_reconnect_req = 1;
4238 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4239
4240}
4241
4242
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004243static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4244 struct wpa_ssid *ssid)
4245{
4246 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4247 return;
4248
4249 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004250 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004251 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4252 wpas_notify_network_enabled_changed(wpa_s, ssid);
4253
4254 /*
4255 * Try to reassociate since there is no current configuration and a new
4256 * network was made available.
4257 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004258 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004259 wpa_s->reassociate = 1;
4260}
4261
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004262
Roshan Pius950bec92016-07-19 09:49:24 -07004263/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004264 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004265 * @wpa_s: wpa_supplicant structure for a network interface
4266 * Returns: The new network configuration or %NULL if operation failed
4267 *
4268 * This function performs the following operations:
4269 * 1. Adds a new network.
4270 * 2. Send network addition notification.
4271 * 3. Marks the network disabled.
4272 * 4. Set network default parameters.
4273 */
4274struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4275{
4276 struct wpa_ssid *ssid;
4277
4278 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004279 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004280 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004281 wpas_notify_network_added(wpa_s, ssid);
4282 ssid->disabled = 1;
4283 wpa_config_set_network_defaults(ssid);
4284
4285 return ssid;
4286}
4287
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004288
Roshan Pius950bec92016-07-19 09:49:24 -07004289/**
4290 * wpa_supplicant_remove_network - Remove a configured network based on id
4291 * @wpa_s: wpa_supplicant structure for a network interface
4292 * @id: Unique network id to search for
4293 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4294 * could not be removed
4295 *
4296 * This function performs the following operations:
4297 * 1. Removes the network.
4298 * 2. Send network removal notification.
4299 * 3. Update internal state machines.
4300 * 4. Stop any running sched scans.
4301 */
4302int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4303{
Sunil Ravia04bd252022-05-02 22:54:18 -07004304 struct wpa_ssid *ssid, *prev = wpa_s->current_ssid;
Roshan Pius950bec92016-07-19 09:49:24 -07004305 int was_disabled;
4306
4307 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004308 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004309 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004310 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004311
Sunil Ravia04bd252022-05-02 22:54:18 -07004312 if (ssid == prev || !prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004313#ifdef CONFIG_SME
4314 wpa_s->sme.prev_bssid_set = 0;
4315#endif /* CONFIG_SME */
4316 /*
4317 * Invalidate the EAP session cache if the current or
4318 * previously used network is removed.
4319 */
4320 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4321 }
4322
Sunil Ravia04bd252022-05-02 22:54:18 -07004323 if (ssid == prev) {
Roshan Pius950bec92016-07-19 09:49:24 -07004324 wpa_sm_set_config(wpa_s->wpa, NULL);
4325 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4326
4327 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4328 wpa_s->own_disconnect_req = 1;
4329 wpa_supplicant_deauthenticate(wpa_s,
4330 WLAN_REASON_DEAUTH_LEAVING);
4331 }
4332
4333 was_disabled = ssid->disabled;
4334
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004335 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004336 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004337
4338 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004339 wpa_printf(MSG_DEBUG,
4340 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004341 wpa_supplicant_cancel_sched_scan(wpa_s);
4342 wpa_supplicant_req_scan(wpa_s, 0, 0);
4343 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004344
Roshan Pius950bec92016-07-19 09:49:24 -07004345 return 0;
4346}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004348
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004350 * wpa_supplicant_remove_all_networks - Remove all configured networks
4351 * @wpa_s: wpa_supplicant structure for a network interface
4352 * Returns: 0 on success (errors are currently ignored)
4353 *
4354 * This function performs the following operations:
4355 * 1. Remove all networks.
4356 * 2. Send network removal notifications.
4357 * 3. Update internal state machines.
4358 * 4. Stop any running sched scans.
4359 */
4360int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4361{
4362 struct wpa_ssid *ssid;
4363
4364 if (wpa_s->sched_scanning)
4365 wpa_supplicant_cancel_sched_scan(wpa_s);
4366
4367 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4368 if (wpa_s->current_ssid) {
4369#ifdef CONFIG_SME
4370 wpa_s->sme.prev_bssid_set = 0;
4371#endif /* CONFIG_SME */
4372 wpa_sm_set_config(wpa_s->wpa, NULL);
4373 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4374 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4375 wpa_s->own_disconnect_req = 1;
4376 wpa_supplicant_deauthenticate(
4377 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4378 }
4379 ssid = wpa_s->conf->ssid;
4380 while (ssid) {
4381 struct wpa_ssid *remove_ssid = ssid;
4382 int id;
4383
4384 id = ssid->id;
4385 ssid = ssid->next;
Hai Shalom899fcc72020-10-19 14:38:18 -07004386 wpas_notify_network_removed(wpa_s, remove_ssid);
4387 wpa_config_remove_network(wpa_s->conf, id);
4388 }
4389 return 0;
4390}
4391
4392
4393/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004394 * wpa_supplicant_enable_network - Mark a configured network as enabled
4395 * @wpa_s: wpa_supplicant structure for a network interface
4396 * @ssid: wpa_ssid structure for a configured network or %NULL
4397 *
4398 * Enables the specified network or all networks if no network specified.
4399 */
4400void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4401 struct wpa_ssid *ssid)
4402{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004403 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004404 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4405 wpa_supplicant_enable_one_network(wpa_s, ssid);
4406 } else
4407 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004408
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004409 if (wpa_s->reassociate && !wpa_s->disconnected &&
4410 (!wpa_s->current_ssid ||
4411 wpa_s->wpa_state == WPA_DISCONNECTED ||
4412 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004413 if (wpa_s->sched_scanning) {
4414 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4415 "new network to scan filters");
4416 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004417 }
4418
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004419 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4420 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004421 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004422 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004423 }
4424}
4425
4426
4427/**
4428 * wpa_supplicant_disable_network - Mark a configured network as disabled
4429 * @wpa_s: wpa_supplicant structure for a network interface
4430 * @ssid: wpa_ssid structure for a configured network or %NULL
4431 *
4432 * Disables the specified network or all networks if no network specified.
4433 */
4434void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4435 struct wpa_ssid *ssid)
4436{
4437 struct wpa_ssid *other_ssid;
4438 int was_disabled;
4439
4440 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004441 if (wpa_s->sched_scanning)
4442 wpa_supplicant_cancel_sched_scan(wpa_s);
4443
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004444 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4445 other_ssid = other_ssid->next) {
4446 was_disabled = other_ssid->disabled;
4447 if (was_disabled == 2)
4448 continue; /* do not change persistent P2P group
4449 * data */
4450
4451 other_ssid->disabled = 1;
4452
4453 if (was_disabled != other_ssid->disabled)
4454 wpas_notify_network_enabled_changed(
4455 wpa_s, other_ssid);
4456 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004457 if (wpa_s->current_ssid) {
4458 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4459 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004460 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004461 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004462 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004463 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004464 if (ssid == wpa_s->current_ssid) {
4465 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4466 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004467 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004468 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004469 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004470
4471 was_disabled = ssid->disabled;
4472
4473 ssid->disabled = 1;
4474
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004475 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004476 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004477 if (wpa_s->sched_scanning) {
4478 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4479 "to remove network from filters");
4480 wpa_supplicant_cancel_sched_scan(wpa_s);
4481 wpa_supplicant_req_scan(wpa_s, 0, 0);
4482 }
4483 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004484 }
4485}
4486
4487
4488/**
4489 * wpa_supplicant_select_network - Attempt association with a network
4490 * @wpa_s: wpa_supplicant structure for a network interface
4491 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4492 */
4493void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4494 struct wpa_ssid *ssid)
4495{
4496
4497 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004498 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004499
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004500 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004501 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4502 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004503 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004504 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004505 disconnected = 1;
4506 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004507
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004508 if (ssid)
4509 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4510
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004511 /*
4512 * Mark all other networks disabled or mark all networks enabled if no
4513 * network specified.
4514 */
4515 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4516 other_ssid = other_ssid->next) {
4517 int was_disabled = other_ssid->disabled;
4518 if (was_disabled == 2)
4519 continue; /* do not change persistent P2P group data */
4520
4521 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004522 if (was_disabled && !other_ssid->disabled)
4523 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004524
4525 if (was_disabled != other_ssid->disabled)
4526 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4527 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004528
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004529 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4530 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004531 /* We are already associated with the selected network */
4532 wpa_printf(MSG_DEBUG, "Already associated with the "
4533 "selected network - do nothing");
4534 return;
4535 }
4536
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004537 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004538 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004539 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004540 wpa_s->connect_without_scan =
4541 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004542
4543 /*
4544 * Don't optimize next scan freqs since a new ESS has been
4545 * selected.
4546 */
4547 os_free(wpa_s->next_scan_freqs);
4548 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004549 } else {
4550 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004551 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004552
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004553 wpa_s->disconnected = 0;
4554 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004555 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004556 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004557 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004558 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004559 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4560 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004561
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004562 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004563 wpa_supplicant_fast_associate(wpa_s) != 1) {
4564 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004565 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004566 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004567 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004568
4569 if (ssid)
4570 wpas_notify_network_selected(wpa_s, ssid);
4571}
4572
4573
4574/**
Hai Shalomc1a21442022-02-04 13:43:00 -08004575 * wpas_remove_cred - Remove the specified credential and all the network
4576 * entries created based on the removed credential
4577 * @wpa_s: wpa_supplicant structure for a network interface
4578 * @cred: The credential to remove
4579 * Returns: 0 on success, -1 on failure
4580 */
4581int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred)
4582{
4583 struct wpa_ssid *ssid, *next;
4584 int id;
4585
4586 if (!cred) {
4587 wpa_printf(MSG_DEBUG, "Could not find cred");
4588 return -1;
4589 }
4590
4591 id = cred->id;
4592 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
4593 wpa_printf(MSG_DEBUG, "Could not find cred %d", id);
4594 return -1;
4595 }
4596
4597 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
4598
4599 /* Remove any network entry created based on the removed credential */
4600 ssid = wpa_s->conf->ssid;
4601 while (ssid) {
4602 next = ssid->next;
4603
4604 if (ssid->parent_cred == cred) {
4605 wpa_printf(MSG_DEBUG,
4606 "Remove network id %d since it used the removed credential",
4607 ssid->id);
4608 if (wpa_supplicant_remove_network(wpa_s, ssid->id) ==
4609 -1) {
4610 wpa_printf(MSG_DEBUG,
4611 "Could not find network id=%d",
4612 ssid->id);
4613 }
4614 }
4615
4616 ssid = next;
4617 }
4618
4619 return 0;
4620}
4621
4622
4623/**
4624 * wpas_remove_cred - Remove all the Interworking credentials
4625 * @wpa_s: wpa_supplicant structure for a network interface
4626 * Returns: 0 on success, -1 on failure
4627 */
4628int wpas_remove_all_creds(struct wpa_supplicant *wpa_s)
4629{
4630 int res, ret = 0;
4631 struct wpa_cred *cred, *prev;
4632
4633 cred = wpa_s->conf->cred;
4634 while (cred) {
4635 prev = cred;
4636 cred = cred->next;
4637 res = wpas_remove_cred(wpa_s, prev);
4638 if (res < 0) {
4639 wpa_printf(MSG_DEBUG,
4640 "Removal of all credentials failed - failed to remove credential id=%d",
4641 prev->id);
4642 ret = -1;
4643 }
4644 }
4645
4646 return ret;
4647}
4648
4649
4650/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004651 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4652 * @wpa_s: wpa_supplicant structure for a network interface
4653 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4654 * @pkcs11_module_path: PKCS #11 module path or NULL
4655 * Returns: 0 on success; -1 on failure
4656 *
4657 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4658 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4659 * module path fails the paths will be reset to the default value (NULL).
4660 */
4661int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4662 const char *pkcs11_engine_path,
4663 const char *pkcs11_module_path)
4664{
4665 char *pkcs11_engine_path_copy = NULL;
4666 char *pkcs11_module_path_copy = NULL;
4667
4668 if (pkcs11_engine_path != NULL) {
4669 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4670 if (pkcs11_engine_path_copy == NULL)
4671 return -1;
4672 }
4673 if (pkcs11_module_path != NULL) {
4674 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004675 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004676 os_free(pkcs11_engine_path_copy);
4677 return -1;
4678 }
4679 }
4680
4681 os_free(wpa_s->conf->pkcs11_engine_path);
4682 os_free(wpa_s->conf->pkcs11_module_path);
4683 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4684 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4685
4686 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4687 eapol_sm_deinit(wpa_s->eapol);
4688 wpa_s->eapol = NULL;
4689 if (wpa_supplicant_init_eapol(wpa_s)) {
4690 /* Error -> Reset paths to the default value (NULL) once. */
4691 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4692 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4693 NULL);
4694
4695 return -1;
4696 }
4697 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4698
4699 return 0;
4700}
4701
4702
4703/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004704 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4705 * @wpa_s: wpa_supplicant structure for a network interface
4706 * @ap_scan: AP scan mode
4707 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4708 *
4709 */
4710int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4711{
4712
4713 int old_ap_scan;
4714
4715 if (ap_scan < 0 || ap_scan > 2)
4716 return -1;
4717
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004718 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4719 wpa_printf(MSG_INFO,
4720 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4721 }
4722
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004723#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004724 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4725 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4726 wpa_s->wpa_state < WPA_COMPLETED) {
4727 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4728 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004729 return 0;
4730 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004731#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004732
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004733 old_ap_scan = wpa_s->conf->ap_scan;
4734 wpa_s->conf->ap_scan = ap_scan;
4735
4736 if (old_ap_scan != wpa_s->conf->ap_scan)
4737 wpas_notify_ap_scan_changed(wpa_s);
4738
4739 return 0;
4740}
4741
4742
4743/**
4744 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4745 * @wpa_s: wpa_supplicant structure for a network interface
4746 * @expire_age: Expiration age in seconds
4747 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4748 *
4749 */
4750int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4751 unsigned int bss_expire_age)
4752{
4753 if (bss_expire_age < 10) {
4754 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4755 bss_expire_age);
4756 return -1;
4757 }
4758 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4759 bss_expire_age);
4760 wpa_s->conf->bss_expiration_age = bss_expire_age;
4761
4762 return 0;
4763}
4764
4765
4766/**
4767 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4768 * @wpa_s: wpa_supplicant structure for a network interface
4769 * @expire_count: number of scans after which an unseen BSS is reclaimed
4770 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4771 *
4772 */
4773int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4774 unsigned int bss_expire_count)
4775{
4776 if (bss_expire_count < 1) {
4777 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4778 bss_expire_count);
4779 return -1;
4780 }
4781 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4782 bss_expire_count);
4783 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4784
4785 return 0;
4786}
4787
4788
4789/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004790 * wpa_supplicant_set_scan_interval - Set scan interval
4791 * @wpa_s: wpa_supplicant structure for a network interface
4792 * @scan_interval: scan interval in seconds
4793 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4794 *
4795 */
4796int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4797 int scan_interval)
4798{
4799 if (scan_interval < 0) {
4800 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4801 scan_interval);
4802 return -1;
4803 }
4804 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4805 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004806 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004807
4808 return 0;
4809}
4810
4811
4812/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004813 * wpa_supplicant_set_debug_params - Set global debug params
4814 * @global: wpa_global structure
4815 * @debug_level: debug level
4816 * @debug_timestamp: determines if show timestamp in debug data
4817 * @debug_show_keys: determines if show keys in debug data
4818 * Returns: 0 if succeed or -1 if debug_level has wrong value
4819 */
4820int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4821 int debug_timestamp, int debug_show_keys)
4822{
4823
4824 int old_level, old_timestamp, old_show_keys;
4825
4826 /* check for allowed debuglevels */
4827 if (debug_level != MSG_EXCESSIVE &&
4828 debug_level != MSG_MSGDUMP &&
4829 debug_level != MSG_DEBUG &&
4830 debug_level != MSG_INFO &&
4831 debug_level != MSG_WARNING &&
4832 debug_level != MSG_ERROR)
4833 return -1;
4834
4835 old_level = wpa_debug_level;
4836 old_timestamp = wpa_debug_timestamp;
4837 old_show_keys = wpa_debug_show_keys;
4838
4839 wpa_debug_level = debug_level;
4840 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4841 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4842
4843 if (wpa_debug_level != old_level)
4844 wpas_notify_debug_level_changed(global);
4845 if (wpa_debug_timestamp != old_timestamp)
4846 wpas_notify_debug_timestamp_changed(global);
4847 if (wpa_debug_show_keys != old_show_keys)
4848 wpas_notify_debug_show_keys_changed(global);
4849
4850 return 0;
4851}
4852
4853
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004854#ifdef CONFIG_OWE
4855static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4856 const u8 *entry_ssid, size_t entry_ssid_len)
4857{
4858 const u8 *owe, *pos, *end;
4859 u8 ssid_len;
4860 struct wpa_bss *bss;
4861
4862 /* Check network profile SSID aganst the SSID in the
4863 * OWE Transition Mode element. */
4864
4865 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4866 if (!bss)
4867 return 0;
4868
4869 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4870 if (!owe)
4871 return 0;
4872
4873 pos = owe + 6;
4874 end = owe + 2 + owe[1];
4875
4876 if (end - pos < ETH_ALEN + 1)
4877 return 0;
4878 pos += ETH_ALEN;
4879 ssid_len = *pos++;
4880 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4881 return 0;
4882
4883 return entry_ssid_len == ssid_len &&
4884 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4885}
4886#endif /* CONFIG_OWE */
4887
4888
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004889/**
4890 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4891 * @wpa_s: Pointer to wpa_supplicant data
4892 * Returns: A pointer to the current network structure or %NULL on failure
4893 */
4894struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4895{
4896 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004897 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004898 int res;
4899 size_t ssid_len;
4900 u8 bssid[ETH_ALEN];
4901 int wired;
4902
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004903 res = wpa_drv_get_ssid(wpa_s, ssid);
4904 if (res < 0) {
4905 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4906 "driver");
4907 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004908 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004909 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004910
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004911 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004912 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4913 "driver");
4914 return NULL;
4915 }
4916
4917 wired = wpa_s->conf->ap_scan == 0 &&
4918 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4919
4920 entry = wpa_s->conf->ssid;
4921 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004922 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004923 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004924 (!entry->ssid ||
4925 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4926 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004927 (!entry->bssid_set ||
4928 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4929 return entry;
4930#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004931 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004932 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4933 (entry->ssid == NULL || entry->ssid_len == 0) &&
4934 (!entry->bssid_set ||
4935 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4936 return entry;
4937#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004938
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004939#ifdef CONFIG_OWE
4940 if (!wpas_network_disabled(wpa_s, entry) &&
4941 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4942 entry->ssid_len) &&
4943 (!entry->bssid_set ||
4944 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4945 return entry;
4946#endif /* CONFIG_OWE */
4947
Dmitry Shmidt04949592012-07-19 12:16:46 -07004948 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004949 entry->ssid_len == 0 &&
4950 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4951 return entry;
4952
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004953 entry = entry->next;
4954 }
4955
4956 return NULL;
4957}
4958
4959
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004960static int select_driver(struct wpa_supplicant *wpa_s, int i)
4961{
4962 struct wpa_global *global = wpa_s->global;
4963
4964 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004965 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004966 if (global->drv_priv[i] == NULL) {
4967 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4968 "'%s'", wpa_drivers[i]->name);
4969 return -1;
4970 }
4971 }
4972
4973 wpa_s->driver = wpa_drivers[i];
4974 wpa_s->global_drv_priv = global->drv_priv[i];
4975
4976 return 0;
4977}
4978
4979
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004980static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4981 const char *name)
4982{
4983 int i;
4984 size_t len;
4985 const char *pos, *driver = name;
4986
4987 if (wpa_s == NULL)
4988 return -1;
4989
4990 if (wpa_drivers[0] == NULL) {
4991 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4992 "wpa_supplicant");
4993 return -1;
4994 }
4995
4996 if (name == NULL) {
Hai Shalomc1a21442022-02-04 13:43:00 -08004997 /* Default to first successful driver in the list */
4998 for (i = 0; wpa_drivers[i]; i++) {
4999 if (select_driver(wpa_s, i) == 0)
5000 return 0;
5001 }
5002 /* Drivers have each reported failure, so no wpa_msg() here. */
5003 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005004 }
5005
5006 do {
5007 pos = os_strchr(driver, ',');
5008 if (pos)
5009 len = pos - driver;
5010 else
5011 len = os_strlen(driver);
5012
5013 for (i = 0; wpa_drivers[i]; i++) {
5014 if (os_strlen(wpa_drivers[i]->name) == len &&
5015 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005016 0) {
5017 /* First driver that succeeds wins */
5018 if (select_driver(wpa_s, i) == 0)
5019 return 0;
5020 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005021 }
5022
5023 driver = pos + 1;
5024 } while (pos);
5025
5026 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
5027 return -1;
5028}
5029
5030
5031/**
5032 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
5033 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
5034 * with struct wpa_driver_ops::init()
5035 * @src_addr: Source address of the EAPOL frame
5036 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
5037 * @len: Length of the EAPOL data
Sunil8cd6f4d2022-06-28 18:40:46 +00005038 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005039 *
5040 * This function is called for each received EAPOL frame. Most driver
5041 * interfaces rely on more generic OS mechanism for receiving frames through
5042 * l2_packet, but if such a mechanism is not available, the driver wrapper may
5043 * take care of received EAPOL frames and deliver them to the core supplicant
5044 * code by calling this function.
5045 */
5046void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00005047 const u8 *buf, size_t len,
5048 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005049{
5050 struct wpa_supplicant *wpa_s = ctx;
5051
Sunil8cd6f4d2022-06-28 18:40:46 +00005052 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " (encrypted=%d)",
5053 MAC2STR(src_addr), encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005054 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
5055
Hai Shalomc1a21442022-02-04 13:43:00 -08005056 if (wpa_s->own_disconnect_req) {
5057 wpa_printf(MSG_DEBUG,
5058 "Drop received EAPOL frame as we are disconnecting");
5059 return;
5060 }
5061
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005062#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomc1a21442022-02-04 13:43:00 -08005063 wpa_msg_ctrl(wpa_s, MSG_INFO, "EAPOL-RX " MACSTR " %zu",
5064 MAC2STR(src_addr), len);
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07005065 if (wpa_s->ignore_auth_resp) {
5066 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
5067 return;
5068 }
5069#endif /* CONFIG_TESTING_OPTIONS */
5070
Jouni Malinena05074c2012-12-21 21:35:35 +02005071 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
5072 (wpa_s->last_eapol_matches_bssid &&
5073#ifdef CONFIG_AP
5074 !wpa_s->ap_iface &&
5075#endif /* CONFIG_AP */
5076 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005077 /*
5078 * There is possible race condition between receiving the
5079 * association event and the EAPOL frame since they are coming
5080 * through different paths from the driver. In order to avoid
5081 * issues in trying to process the EAPOL frame before receiving
5082 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02005083 * the association event is received. This may also be needed in
5084 * driver-based roaming case, so also use src_addr != BSSID as a
5085 * trigger if we have previously confirmed that the
5086 * Authenticator uses BSSID as the src_addr (which is not the
5087 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005088 */
5089 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02005090 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
5091 wpa_supplicant_state_txt(wpa_s->wpa_state),
5092 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005093 wpabuf_free(wpa_s->pending_eapol_rx);
5094 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
5095 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005096 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005097 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
5098 ETH_ALEN);
Sunil8cd6f4d2022-06-28 18:40:46 +00005099 wpa_s->pending_eapol_encrypted = encrypted;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005100 }
5101 return;
5102 }
5103
Jouni Malinena05074c2012-12-21 21:35:35 +02005104 wpa_s->last_eapol_matches_bssid =
5105 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
5106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005107#ifdef CONFIG_AP
5108 if (wpa_s->ap_iface) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005109 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len,
5110 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005111 return;
5112 }
5113#endif /* CONFIG_AP */
5114
5115 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
5116 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
5117 "no key management is configured");
5118 return;
5119 }
5120
5121 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08005122 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005123 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
5124 wpa_s->wpa_state != WPA_COMPLETED) &&
5125 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005126 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005127 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005128 int timeout = 10;
5129
5130 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
5131 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
5132 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
5133 /* Use longer timeout for IEEE 802.1X/EAP */
5134 timeout = 70;
5135 }
5136
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005137#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005138 if (wpa_s->current_ssid && wpa_s->current_bss &&
5139 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
5140 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
5141 /*
5142 * Use shorter timeout if going through WPS AP iteration
5143 * for PIN config method with an AP that does not
5144 * advertise Selected Registrar.
5145 */
5146 struct wpabuf *wps_ie;
5147
5148 wps_ie = wpa_bss_get_vendor_ie_multi(
5149 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
5150 if (wps_ie &&
5151 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
5152 timeout = 10;
5153 wpabuf_free(wps_ie);
5154 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07005155#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005156
5157 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005158 }
5159 wpa_s->eapol_received++;
5160
5161 if (wpa_s->countermeasures) {
5162 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
5163 "EAPOL packet");
5164 return;
5165 }
5166
5167#ifdef CONFIG_IBSS_RSN
5168 if (wpa_s->current_ssid &&
5169 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005170 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len,
5171 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005172 return;
5173 }
5174#endif /* CONFIG_IBSS_RSN */
5175
5176 /* Source address of the incoming EAPOL frame could be compared to the
5177 * current BSSID. However, it is possible that a centralized
5178 * Authenticator could be using another MAC address than the BSSID of
5179 * an AP, so just allow any address to be used for now. The replies are
5180 * still sent to the current BSSID (if available), though. */
5181
5182 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
5183 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005184 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
5185 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Sunil8cd6f4d2022-06-28 18:40:46 +00005186 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len,
5187 encrypted) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005188 return;
5189 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08005190 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Sunil8cd6f4d2022-06-28 18:40:46 +00005191 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len, encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005192 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
5193 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07005194 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005195 * handshake processing which would normally set portValid. We
5196 * need this to allow the EAPOL state machines to be completed
5197 * without going through EAPOL-Key handshake.
5198 */
Hai Shalome21d4e82020-04-29 16:34:06 -07005199 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005200 }
5201}
5202
5203
Sunil8cd6f4d2022-06-28 18:40:46 +00005204static void wpa_supplicant_rx_eapol_cb(void *ctx, const u8 *src_addr,
5205 const u8 *buf, size_t len)
5206{
5207 wpa_supplicant_rx_eapol(ctx, src_addr, buf, len,
5208 FRAME_ENCRYPTION_UNKNOWN);
5209}
5210
5211
Hai Shalomb755a2a2020-04-23 21:49:02 -07005212static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
5213{
5214 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
5215 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
5216}
5217
5218
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005219int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005220{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005221 if ((!wpa_s->p2p_mgmt ||
5222 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5223 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005224 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005225 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
5226 wpa_drv_get_mac_addr(wpa_s),
5227 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005228 wpas_eapol_needs_l2_packet(wpa_s) ?
Sunil8cd6f4d2022-06-28 18:40:46 +00005229 wpa_supplicant_rx_eapol_cb : NULL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07005230 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005231 if (wpa_s->l2 == NULL)
5232 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005233
5234 if (l2_packet_set_packet_filter(wpa_s->l2,
5235 L2_PACKET_FILTER_PKTTYPE))
5236 wpa_dbg(wpa_s, MSG_DEBUG,
5237 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07005238
5239 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
5240 wpa_msg(wpa_s, MSG_ERROR,
5241 "Failed to get own L2 address");
5242 return -1;
5243 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005244 } else {
5245 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
5246 if (addr)
5247 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
5248 }
5249
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005250 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02005251 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005252
Hai Shalomc3565922019-10-28 11:58:20 -07005253#ifdef CONFIG_FST
5254 if (wpa_s->fst)
5255 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
5256#endif /* CONFIG_FST */
5257
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005258 return 0;
5259}
5260
5261
Dmitry Shmidt04949592012-07-19 12:16:46 -07005262static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
5263 const u8 *buf, size_t len)
5264{
5265 struct wpa_supplicant *wpa_s = ctx;
5266 const struct l2_ethhdr *eth;
5267
5268 if (len < sizeof(*eth))
5269 return;
5270 eth = (const struct l2_ethhdr *) buf;
5271
5272 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
5273 !(eth->h_dest[0] & 0x01)) {
5274 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5275 " (bridge - not for this interface - ignore)",
5276 MAC2STR(src_addr), MAC2STR(eth->h_dest));
5277 return;
5278 }
5279
5280 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
5281 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
5282 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
Sunil8cd6f4d2022-06-28 18:40:46 +00005283 len - sizeof(*eth), FRAME_ENCRYPTION_UNKNOWN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005284}
5285
5286
Hai Shalom899fcc72020-10-19 14:38:18 -07005287int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
5288 const char *bridge_ifname)
5289{
5290 if (wpa_s->wpa_state > WPA_SCANNING)
5291 return -EBUSY;
5292
5293 if (bridge_ifname &&
5294 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
5295 return -EINVAL;
5296
5297 if (!bridge_ifname)
5298 bridge_ifname = "";
5299
5300 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
5301 return 0;
5302
5303 if (wpa_s->l2_br) {
5304 l2_packet_deinit(wpa_s->l2_br);
5305 wpa_s->l2_br = NULL;
5306 }
5307
5308 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
5309 sizeof(wpa_s->bridge_ifname));
5310
5311 if (wpa_s->bridge_ifname[0]) {
5312 wpa_dbg(wpa_s, MSG_DEBUG,
5313 "Receiving packets from bridge interface '%s'",
5314 wpa_s->bridge_ifname);
5315 wpa_s->l2_br = l2_packet_init_bridge(
5316 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5317 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
5318 if (!wpa_s->l2_br) {
5319 wpa_msg(wpa_s, MSG_ERROR,
5320 "Failed to open l2_packet connection for the bridge interface '%s'",
5321 wpa_s->bridge_ifname);
5322 goto fail;
5323 }
5324 }
5325
5326#ifdef CONFIG_TDLS
5327 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5328 goto fail;
5329#endif /* CONFIG_TDLS */
5330
5331 return 0;
5332fail:
5333 wpa_s->bridge_ifname[0] = 0;
5334 if (wpa_s->l2_br) {
5335 l2_packet_deinit(wpa_s->l2_br);
5336 wpa_s->l2_br = NULL;
5337 }
5338#ifdef CONFIG_TDLS
5339 if (!wpa_s->p2p_mgmt)
5340 wpa_tdls_init(wpa_s->wpa);
5341#endif /* CONFIG_TDLS */
5342 return -EIO;
5343}
5344
5345
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005346/**
5347 * wpa_supplicant_driver_init - Initialize driver interface parameters
5348 * @wpa_s: Pointer to wpa_supplicant data
5349 * Returns: 0 on success, -1 on failure
5350 *
5351 * This function is called to initialize driver interface parameters.
5352 * wpa_drv_init() must have been called before this function to initialize the
5353 * driver interface.
5354 */
5355int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5356{
5357 static int interface_count = 0;
5358
5359 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5360 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005361
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005362 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5363 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005364 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005365 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5366
Hai Shalomb755a2a2020-04-23 21:49:02 -07005367 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005368 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5369 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005370 wpa_s->l2_br = l2_packet_init_bridge(
5371 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5372 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005373 if (wpa_s->l2_br == NULL) {
5374 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5375 "connection for the bridge interface '%s'",
5376 wpa_s->bridge_ifname);
5377 return -1;
5378 }
5379 }
5380
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005381 if (wpa_s->conf->ap_scan == 2 &&
5382 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5383 wpa_printf(MSG_INFO,
5384 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5385 }
5386
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005387 wpa_clear_keys(wpa_s, NULL);
5388
5389 /* Make sure that TKIP countermeasures are not left enabled (could
5390 * happen if wpa_supplicant is killed during countermeasures. */
5391 wpa_drv_set_countermeasures(wpa_s, 0);
5392
5393 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5394 wpa_drv_flush_pmkid(wpa_s);
5395
5396 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005397 wpa_s->prev_scan_wildcard = 0;
5398
Dmitry Shmidt04949592012-07-19 12:16:46 -07005399 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005400 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5401 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5402 interface_count = 0;
5403 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005404#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005405 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005406 wpa_supplicant_delayed_sched_scan(wpa_s,
5407 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005408 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005409 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005410 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005411#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005412 interface_count++;
5413 } else
5414 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5415
5416 return 0;
5417}
5418
5419
5420static int wpa_supplicant_daemon(const char *pid_file)
5421{
5422 wpa_printf(MSG_DEBUG, "Daemonize..");
5423 return os_daemonize(pid_file);
5424}
5425
5426
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005427static struct wpa_supplicant *
5428wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005429{
5430 struct wpa_supplicant *wpa_s;
5431
5432 wpa_s = os_zalloc(sizeof(*wpa_s));
5433 if (wpa_s == NULL)
5434 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005435 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005436 wpa_s->scan_interval = 5;
5437 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005438 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005439 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005440 wpa_s->sched_scanning = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005441 wpa_s->setband_mask = WPA_SETBAND_AUTO;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005442
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005443 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005444 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005445#ifdef CONFIG_TESTING_OPTIONS
5446 dl_list_init(&wpa_s->drv_signal_override);
5447#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc1a21442022-02-04 13:43:00 -08005448 dl_list_init(&wpa_s->active_scs_ids);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005449
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005450 return wpa_s;
5451}
5452
5453
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005454#ifdef CONFIG_HT_OVERRIDES
5455
5456static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5457 struct ieee80211_ht_capabilities *htcaps,
5458 struct ieee80211_ht_capabilities *htcaps_mask,
5459 const char *ht_mcs)
5460{
5461 /* parse ht_mcs into hex array */
5462 int i;
5463 const char *tmp = ht_mcs;
5464 char *end = NULL;
5465
5466 /* If ht_mcs is null, do not set anything */
5467 if (!ht_mcs)
5468 return 0;
5469
5470 /* This is what we are setting in the kernel */
5471 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5472
5473 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5474
5475 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005476 long v;
5477
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005478 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005479 v = strtol(tmp, &end, 16);
5480
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005481 if (errno == 0) {
5482 wpa_msg(wpa_s, MSG_DEBUG,
5483 "htcap value[%i]: %ld end: %p tmp: %p",
5484 i, v, end, tmp);
5485 if (end == tmp)
5486 break;
5487
5488 htcaps->supported_mcs_set[i] = v;
5489 tmp = end;
5490 } else {
5491 wpa_msg(wpa_s, MSG_ERROR,
5492 "Failed to parse ht-mcs: %s, error: %s\n",
5493 ht_mcs, strerror(errno));
5494 return -1;
5495 }
5496 }
5497
5498 /*
5499 * If we were able to parse any values, then set mask for the MCS set.
5500 */
5501 if (i) {
5502 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5503 IEEE80211_HT_MCS_MASK_LEN - 1);
5504 /* skip the 3 reserved bits */
5505 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5506 0x1f;
5507 }
5508
5509 return 0;
5510}
5511
5512
5513static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5514 struct ieee80211_ht_capabilities *htcaps,
5515 struct ieee80211_ht_capabilities *htcaps_mask,
5516 int disabled)
5517{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005518 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005519
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005520 if (disabled == -1)
5521 return 0;
5522
Hai Shalom74f70d42019-02-11 14:42:39 -08005523 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5524
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005525 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5526 htcaps_mask->ht_capabilities_info |= msk;
5527 if (disabled)
5528 htcaps->ht_capabilities_info &= msk;
5529 else
5530 htcaps->ht_capabilities_info |= msk;
5531
5532 return 0;
5533}
5534
5535
5536static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5537 struct ieee80211_ht_capabilities *htcaps,
5538 struct ieee80211_ht_capabilities *htcaps_mask,
5539 int factor)
5540{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005541 if (factor == -1)
5542 return 0;
5543
Hai Shalom74f70d42019-02-11 14:42:39 -08005544 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5545
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005546 if (factor < 0 || factor > 3) {
5547 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5548 "Must be 0-3 or -1", factor);
5549 return -EINVAL;
5550 }
5551
5552 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5553 htcaps->a_mpdu_params &= ~0x3;
5554 htcaps->a_mpdu_params |= factor & 0x3;
5555
5556 return 0;
5557}
5558
5559
5560static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5561 struct ieee80211_ht_capabilities *htcaps,
5562 struct ieee80211_ht_capabilities *htcaps_mask,
5563 int density)
5564{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005565 if (density == -1)
5566 return 0;
5567
Hai Shalom74f70d42019-02-11 14:42:39 -08005568 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5569
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005570 if (density < 0 || density > 7) {
5571 wpa_msg(wpa_s, MSG_ERROR,
5572 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5573 density);
5574 return -EINVAL;
5575 }
5576
5577 htcaps_mask->a_mpdu_params |= 0x1C;
5578 htcaps->a_mpdu_params &= ~(0x1C);
5579 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5580
5581 return 0;
5582}
5583
5584
5585static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5586 struct ieee80211_ht_capabilities *htcaps,
5587 struct ieee80211_ht_capabilities *htcaps_mask,
5588 int disabled)
5589{
Hai Shalom74f70d42019-02-11 14:42:39 -08005590 if (disabled)
5591 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005592
Paul Stewart092955c2017-02-06 09:13:09 -08005593 set_disable_ht40(htcaps, disabled);
5594 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005595
5596 return 0;
5597}
5598
5599
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005600static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5601 struct ieee80211_ht_capabilities *htcaps,
5602 struct ieee80211_ht_capabilities *htcaps_mask,
5603 int disabled)
5604{
5605 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005606 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5607 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005608
Hai Shalom74f70d42019-02-11 14:42:39 -08005609 if (disabled)
5610 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005611
5612 if (disabled)
5613 htcaps->ht_capabilities_info &= ~msk;
5614 else
5615 htcaps->ht_capabilities_info |= msk;
5616
5617 htcaps_mask->ht_capabilities_info |= msk;
5618
5619 return 0;
5620}
5621
5622
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005623static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5624 struct ieee80211_ht_capabilities *htcaps,
5625 struct ieee80211_ht_capabilities *htcaps_mask,
5626 int disabled)
5627{
5628 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005629 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005630
Hai Shalom74f70d42019-02-11 14:42:39 -08005631 if (disabled)
5632 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005633
5634 if (disabled)
5635 htcaps->ht_capabilities_info &= ~msk;
5636 else
5637 htcaps->ht_capabilities_info |= msk;
5638
5639 htcaps_mask->ht_capabilities_info |= msk;
5640
5641 return 0;
5642}
5643
5644
Hai Shalom74f70d42019-02-11 14:42:39 -08005645static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5646 struct ieee80211_ht_capabilities *htcaps,
5647 struct ieee80211_ht_capabilities *htcaps_mask,
5648 int tx_stbc)
5649{
5650 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5651
5652 if (tx_stbc == -1)
5653 return 0;
5654
5655 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5656
5657 if (tx_stbc < 0 || tx_stbc > 1) {
5658 wpa_msg(wpa_s, MSG_ERROR,
5659 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5660 return -EINVAL;
5661 }
5662
5663 htcaps_mask->ht_capabilities_info |= msk;
5664 htcaps->ht_capabilities_info &= ~msk;
5665 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5666
5667 return 0;
5668}
5669
5670
5671static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5672 struct ieee80211_ht_capabilities *htcaps,
5673 struct ieee80211_ht_capabilities *htcaps_mask,
5674 int rx_stbc)
5675{
5676 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5677
5678 if (rx_stbc == -1)
5679 return 0;
5680
5681 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5682
5683 if (rx_stbc < 0 || rx_stbc > 3) {
5684 wpa_msg(wpa_s, MSG_ERROR,
5685 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5686 return -EINVAL;
5687 }
5688
5689 htcaps_mask->ht_capabilities_info |= msk;
5690 htcaps->ht_capabilities_info &= ~msk;
5691 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5692
5693 return 0;
5694}
5695
5696
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005697void wpa_supplicant_apply_ht_overrides(
5698 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5699 struct wpa_driver_associate_params *params)
5700{
5701 struct ieee80211_ht_capabilities *htcaps;
5702 struct ieee80211_ht_capabilities *htcaps_mask;
5703
5704 if (!ssid)
5705 return;
5706
5707 params->disable_ht = ssid->disable_ht;
5708 if (!params->htcaps || !params->htcaps_mask)
5709 return;
5710
5711 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5712 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5713 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5714 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5715 ssid->disable_max_amsdu);
5716 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5717 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5718 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005719 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005720 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005721 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5722 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005723
5724 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005725 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005726 htcaps->ht_capabilities_info |= bit;
5727 htcaps_mask->ht_capabilities_info |= bit;
5728 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005729}
5730
5731#endif /* CONFIG_HT_OVERRIDES */
5732
5733
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005734#ifdef CONFIG_VHT_OVERRIDES
5735void wpa_supplicant_apply_vht_overrides(
5736 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5737 struct wpa_driver_associate_params *params)
5738{
5739 struct ieee80211_vht_capabilities *vhtcaps;
5740 struct ieee80211_vht_capabilities *vhtcaps_mask;
5741
5742 if (!ssid)
5743 return;
5744
5745 params->disable_vht = ssid->disable_vht;
5746
5747 vhtcaps = (void *) params->vhtcaps;
5748 vhtcaps_mask = (void *) params->vhtcaps_mask;
5749
5750 if (!vhtcaps || !vhtcaps_mask)
5751 return;
5752
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005753 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5754 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005755
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005756#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005757 if (ssid->disable_sgi) {
5758 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5759 VHT_CAP_SHORT_GI_160);
5760 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5761 VHT_CAP_SHORT_GI_160);
5762 wpa_msg(wpa_s, MSG_DEBUG,
5763 "disable-sgi override specified, vht-caps: 0x%x",
5764 vhtcaps->vht_capabilities_info);
5765 }
5766
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005767 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005768 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5769 int max_ampdu;
5770
5771 max_ampdu = (ssid->vht_capa &
5772 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5773 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005774
5775 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5776 wpa_set_ampdu_factor(wpa_s,
5777 (void *) params->htcaps,
5778 (void *) params->htcaps_mask,
5779 max_ampdu);
5780 }
5781#endif /* CONFIG_HT_OVERRIDES */
5782
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005783#define OVERRIDE_MCS(i) \
5784 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5785 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005786 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005787 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005788 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5789 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005790 } \
5791 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5792 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005793 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005794 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005795 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5796 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005797 }
5798
5799 OVERRIDE_MCS(1);
5800 OVERRIDE_MCS(2);
5801 OVERRIDE_MCS(3);
5802 OVERRIDE_MCS(4);
5803 OVERRIDE_MCS(5);
5804 OVERRIDE_MCS(6);
5805 OVERRIDE_MCS(7);
5806 OVERRIDE_MCS(8);
5807}
5808#endif /* CONFIG_VHT_OVERRIDES */
5809
5810
Hai Shalomfdcde762020-04-02 11:19:20 -07005811#ifdef CONFIG_HE_OVERRIDES
5812void wpa_supplicant_apply_he_overrides(
5813 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5814 struct wpa_driver_associate_params *params)
5815{
5816 if (!ssid)
5817 return;
5818
5819 params->disable_he = ssid->disable_he;
5820}
5821#endif /* CONFIG_HE_OVERRIDES */
5822
5823
Dmitry Shmidt04949592012-07-19 12:16:46 -07005824static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5825{
5826#ifdef PCSC_FUNCS
5827 size_t len;
5828
5829 if (!wpa_s->conf->pcsc_reader)
5830 return 0;
5831
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005832 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005833 if (!wpa_s->scard)
5834 return 1;
5835
5836 if (wpa_s->conf->pcsc_pin &&
5837 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5838 scard_deinit(wpa_s->scard);
5839 wpa_s->scard = NULL;
5840 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5841 return -1;
5842 }
5843
5844 len = sizeof(wpa_s->imsi) - 1;
5845 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5846 scard_deinit(wpa_s->scard);
5847 wpa_s->scard = NULL;
5848 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5849 return -1;
5850 }
5851 wpa_s->imsi[len] = '\0';
5852
5853 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5854
5855 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5856 wpa_s->imsi, wpa_s->mnc_len);
5857
5858 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5859 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5860#endif /* PCSC_FUNCS */
5861
5862 return 0;
5863}
5864
5865
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005866int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5867{
5868 char *val, *pos;
5869
5870 ext_password_deinit(wpa_s->ext_pw);
5871 wpa_s->ext_pw = NULL;
5872 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5873
5874 if (!wpa_s->conf->ext_password_backend)
5875 return 0;
5876
5877 val = os_strdup(wpa_s->conf->ext_password_backend);
5878 if (val == NULL)
5879 return -1;
5880 pos = os_strchr(val, ':');
5881 if (pos)
5882 *pos++ = '\0';
5883
5884 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5885
5886 wpa_s->ext_pw = ext_password_init(val, pos);
5887 os_free(val);
5888 if (wpa_s->ext_pw == NULL) {
5889 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5890 return -1;
5891 }
5892 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5893
5894 return 0;
5895}
5896
5897
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005898#ifdef CONFIG_FST
5899
5900static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5901{
5902 struct wpa_supplicant *wpa_s = ctx;
5903
5904 return (is_zero_ether_addr(wpa_s->bssid) ||
5905 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5906}
5907
5908
5909static void wpas_fst_get_channel_info_cb(void *ctx,
5910 enum hostapd_hw_mode *hw_mode,
5911 u8 *channel)
5912{
5913 struct wpa_supplicant *wpa_s = ctx;
5914
5915 if (wpa_s->current_bss) {
5916 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5917 channel);
5918 } else if (wpa_s->hw.num_modes) {
5919 *hw_mode = wpa_s->hw.modes[0].mode;
5920 } else {
5921 WPA_ASSERT(0);
5922 *hw_mode = 0;
5923 }
5924}
5925
5926
5927static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5928{
5929 struct wpa_supplicant *wpa_s = ctx;
5930
5931 *modes = wpa_s->hw.modes;
5932 return wpa_s->hw.num_modes;
5933}
5934
5935
5936static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5937{
5938 struct wpa_supplicant *wpa_s = ctx;
5939
5940 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5941 wpa_s->fst_ies = fst_ies;
5942}
5943
5944
5945static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5946{
5947 struct wpa_supplicant *wpa_s = ctx;
5948
Paul Stewart092955c2017-02-06 09:13:09 -08005949 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5950 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5951 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5952 return -1;
5953 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005954 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005955 wpa_s->own_addr, wpa_s->bssid,
5956 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005957 0);
5958}
5959
5960
5961static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5962{
5963 struct wpa_supplicant *wpa_s = ctx;
5964
5965 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5966 return wpa_s->received_mb_ies;
5967}
5968
5969
5970static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5971 const u8 *buf, size_t size)
5972{
5973 struct wpa_supplicant *wpa_s = ctx;
5974 struct mb_ies_info info;
5975
5976 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5977
5978 if (!mb_ies_info_by_ies(&info, buf, size)) {
5979 wpabuf_free(wpa_s->received_mb_ies);
5980 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5981 }
5982}
5983
5984
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005985static const u8 * wpas_fst_get_peer_first(void *ctx,
5986 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005987 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005988{
5989 struct wpa_supplicant *wpa_s = ctx;
5990
5991 *get_ctx = NULL;
5992 if (!is_zero_ether_addr(wpa_s->bssid))
5993 return (wpa_s->received_mb_ies || !mb_only) ?
5994 wpa_s->bssid : NULL;
5995 return NULL;
5996}
5997
5998
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005999static const u8 * wpas_fst_get_peer_next(void *ctx,
6000 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07006001 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006002{
6003 return NULL;
6004}
6005
6006void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
6007 struct fst_wpa_obj *iface_obj)
6008{
Sunil8cd6f4d2022-06-28 18:40:46 +00006009 os_memset(iface_obj, 0, sizeof(*iface_obj));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006010 iface_obj->ctx = wpa_s;
6011 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
6012 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
6013 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
6014 iface_obj->set_ies = wpas_fst_set_ies_cb;
6015 iface_obj->send_action = wpas_fst_send_action_cb;
6016 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
6017 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
6018 iface_obj->get_peer_first = wpas_fst_get_peer_first;
6019 iface_obj->get_peer_next = wpas_fst_get_peer_next;
6020}
6021#endif /* CONFIG_FST */
6022
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006023static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006024 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006025{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006026 struct wowlan_triggers *triggers;
6027 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006028
6029 if (!wpa_s->conf->wowlan_triggers)
6030 return 0;
6031
Dmitry Shmidt0207e232014-09-03 14:58:37 -07006032 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
6033 if (triggers) {
6034 ret = wpa_drv_wowlan(wpa_s, triggers);
6035 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006036 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006037 return ret;
6038}
6039
6040
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006041enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006042{
6043 if (freq < 3000)
6044 return BAND_2_4_GHZ;
6045 if (freq > 50000)
6046 return BAND_60_GHZ;
6047 return BAND_5_GHZ;
6048}
6049
6050
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006051unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006052{
6053 int i;
6054 unsigned int band = 0;
6055
6056 if (freqs) {
6057 /* freqs are specified for the radio work */
6058 for (i = 0; freqs[i]; i++)
6059 band |= wpas_freq_to_band(freqs[i]);
6060 } else {
6061 /*
6062 * freqs are not specified, implies all
6063 * the supported freqs by HW
6064 */
6065 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6066 if (wpa_s->hw.modes[i].num_channels != 0) {
6067 if (wpa_s->hw.modes[i].mode ==
6068 HOSTAPD_MODE_IEEE80211B ||
6069 wpa_s->hw.modes[i].mode ==
6070 HOSTAPD_MODE_IEEE80211G)
6071 band |= BAND_2_4_GHZ;
6072 else if (wpa_s->hw.modes[i].mode ==
6073 HOSTAPD_MODE_IEEE80211A)
6074 band |= BAND_5_GHZ;
6075 else if (wpa_s->hw.modes[i].mode ==
6076 HOSTAPD_MODE_IEEE80211AD)
6077 band |= BAND_60_GHZ;
6078 else if (wpa_s->hw.modes[i].mode ==
6079 HOSTAPD_MODE_IEEE80211ANY)
6080 band = BAND_2_4_GHZ | BAND_5_GHZ |
6081 BAND_60_GHZ;
6082 }
6083 }
6084 }
6085
6086 return band;
6087}
6088
6089
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006090static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
6091 const char *rn)
6092{
6093 struct wpa_supplicant *iface = wpa_s->global->ifaces;
6094 struct wpa_radio *radio;
6095
6096 while (rn && iface) {
6097 radio = iface->radio;
6098 if (radio && os_strcmp(rn, radio->name) == 0) {
6099 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
6100 wpa_s->ifname, rn);
6101 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6102 return radio;
6103 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08006104
6105 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006106 }
6107
6108 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
6109 wpa_s->ifname, rn ? rn : "N/A");
6110 radio = os_zalloc(sizeof(*radio));
6111 if (radio == NULL)
6112 return NULL;
6113
6114 if (rn)
6115 os_strlcpy(radio->name, rn, sizeof(radio->name));
6116 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006117 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006118 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
6119
6120 return radio;
6121}
6122
6123
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006124static void radio_work_free(struct wpa_radio_work *work)
6125{
6126 if (work->wpa_s->scan_work == work) {
6127 /* This should not really happen. */
6128 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
6129 work->type, work, work->started);
6130 work->wpa_s->scan_work = NULL;
6131 }
6132
6133#ifdef CONFIG_P2P
6134 if (work->wpa_s->p2p_scan_work == work) {
6135 /* This should not really happen. */
6136 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
6137 work->type, work, work->started);
6138 work->wpa_s->p2p_scan_work = NULL;
6139 }
6140#endif /* CONFIG_P2P */
6141
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006142 if (work->started) {
6143 work->wpa_s->radio->num_active_works--;
6144 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006145 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006146 work->type, work,
6147 work->wpa_s->radio->num_active_works);
6148 }
6149
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006150 dl_list_del(&work->list);
6151 os_free(work);
6152}
6153
6154
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006155static int radio_work_is_connect(struct wpa_radio_work *work)
6156{
6157 return os_strcmp(work->type, "sme-connect") == 0 ||
6158 os_strcmp(work->type, "connect") == 0;
6159}
6160
6161
6162static int radio_work_is_scan(struct wpa_radio_work *work)
6163{
6164 return os_strcmp(work->type, "scan") == 0 ||
6165 os_strcmp(work->type, "p2p-scan") == 0;
6166}
6167
6168
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006169static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
6170{
6171 struct wpa_radio_work *active_work = NULL;
6172 struct wpa_radio_work *tmp;
6173
6174 /* Get the active work to know the type and band. */
6175 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6176 if (tmp->started) {
6177 active_work = tmp;
6178 break;
6179 }
6180 }
6181
6182 if (!active_work) {
6183 /* No active work, start one */
6184 radio->num_active_works = 0;
6185 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
6186 list) {
6187 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006188 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006189 (((struct wpa_driver_scan_params *)
6190 tmp->ctx)->only_new_results ||
6191 tmp->wpa_s->clear_driver_scan_cache))
6192 continue;
6193 return tmp;
6194 }
6195 return NULL;
6196 }
6197
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006198 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006199 /*
6200 * If the active work is either connect or sme-connect,
6201 * do not parallelize them with other radio works.
6202 */
6203 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6204 "Do not parallelize radio work with %s",
6205 active_work->type);
6206 return NULL;
6207 }
6208
6209 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
6210 if (tmp->started)
6211 continue;
6212
6213 /*
6214 * If connect or sme-connect are enqueued, parallelize only
6215 * those operations ahead of them in the queue.
6216 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006217 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006218 break;
6219
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006220 /* Serialize parallel scan and p2p_scan operations on the same
6221 * interface since the driver_nl80211 mechanism for tracking
6222 * scan cookies does not yet have support for this. */
6223 if (active_work->wpa_s == tmp->wpa_s &&
6224 radio_work_is_scan(active_work) &&
6225 radio_work_is_scan(tmp)) {
6226 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6227 "Do not start work '%s' when another work '%s' is already scheduled",
6228 tmp->type, active_work->type);
6229 continue;
6230 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006231 /*
6232 * Check that the radio works are distinct and
6233 * on different bands.
6234 */
6235 if (os_strcmp(active_work->type, tmp->type) != 0 &&
6236 (active_work->bands != tmp->bands)) {
6237 /*
6238 * If a scan has to be scheduled through nl80211 scan
6239 * interface and if an external scan is already running,
6240 * do not schedule the scan since it is likely to get
6241 * rejected by kernel.
6242 */
6243 if (os_strcmp(tmp->type, "scan") == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08006244 external_scan_running(radio) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006245 (((struct wpa_driver_scan_params *)
6246 tmp->ctx)->only_new_results ||
6247 tmp->wpa_s->clear_driver_scan_cache))
6248 continue;
6249
6250 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
6251 "active_work:%s new_work:%s",
6252 active_work->type, tmp->type);
6253 return tmp;
6254 }
6255 }
6256
6257 /* Did not find a radio work to schedule in parallel. */
6258 return NULL;
6259}
6260
6261
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006262static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
6263{
6264 struct wpa_radio *radio = eloop_ctx;
6265 struct wpa_radio_work *work;
6266 struct os_reltime now, diff;
6267 struct wpa_supplicant *wpa_s;
6268
6269 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006270 if (work == NULL) {
6271 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006272 return;
6273 }
6274
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006275 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
6276 radio_list);
6277
6278 if (!(wpa_s &&
6279 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
6280 if (work->started)
6281 return; /* already started and still in progress */
6282
Hai Shalom60840252021-02-19 19:02:11 -08006283 if (wpa_s && external_scan_running(wpa_s->radio)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006284 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
6285 return;
6286 }
6287 } else {
6288 work = NULL;
6289 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
6290 /* get the work to schedule next */
6291 work = radio_work_get_next_work(radio);
6292 }
6293 if (!work)
6294 return;
6295 }
6296
6297 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006298 os_get_reltime(&now);
6299 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006300 wpa_dbg(wpa_s, MSG_DEBUG,
6301 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006302 work->type, work, diff.sec, diff.usec);
6303 work->started = 1;
6304 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006305 radio->num_active_works++;
6306
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006307 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006308
6309 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
6310 radio->num_active_works < MAX_ACTIVE_WORKS)
6311 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006312}
6313
6314
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006315/*
6316 * This function removes both started and pending radio works running on
6317 * the provided interface's radio.
6318 * Prior to the removal of the radio work, its callback (cb) is called with
6319 * deinit set to be 1. Each work's callback is responsible for clearing its
6320 * internal data and restoring to a correct state.
6321 * @wpa_s: wpa_supplicant data
6322 * @type: type of works to be removed
6323 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
6324 * this interface's works.
6325 */
6326void radio_remove_works(struct wpa_supplicant *wpa_s,
6327 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006328{
6329 struct wpa_radio_work *work, *tmp;
6330 struct wpa_radio *radio = wpa_s->radio;
6331
6332 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6333 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006334 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006335 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006336
6337 /* skip other ifaces' works */
6338 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006339 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006340
6341 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6342 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006343 work->cb(work, 1);
6344 radio_work_free(work);
6345 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006346
6347 /* in case we removed the started work */
6348 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006349}
6350
6351
Roshan Pius3a1667e2018-07-03 15:17:14 -07006352void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6353{
6354 struct wpa_radio_work *work;
6355 struct wpa_radio *radio = wpa_s->radio;
6356
6357 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6358 if (work->ctx != ctx)
6359 continue;
6360 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6361 work->type, work, work->started ? " (started)" : "");
6362 radio_work_free(work);
6363 break;
6364 }
6365}
6366
6367
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006368static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6369{
6370 struct wpa_radio *radio = wpa_s->radio;
6371
6372 if (!radio)
6373 return;
6374
6375 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6376 wpa_s->ifname, radio->name);
6377 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006378 radio_remove_works(wpa_s, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08006379 /* If the interface that triggered the external scan was removed, the
6380 * external scan is no longer running. */
6381 if (wpa_s == radio->external_scan_req_interface)
6382 radio->external_scan_req_interface = NULL;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006383 wpa_s->radio = NULL;
6384 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006385 return; /* Interfaces remain for this radio */
6386
6387 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006388 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006389 os_free(radio);
6390}
6391
6392
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006393void radio_work_check_next(struct wpa_supplicant *wpa_s)
6394{
6395 struct wpa_radio *radio = wpa_s->radio;
6396
6397 if (dl_list_empty(&radio->work))
6398 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006399 if (wpa_s->ext_work_in_progress) {
6400 wpa_printf(MSG_DEBUG,
6401 "External radio work in progress - delay start of pending item");
6402 return;
6403 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006404 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6405 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6406}
6407
6408
6409/**
6410 * radio_add_work - Add a radio work item
6411 * @wpa_s: Pointer to wpa_supplicant data
6412 * @freq: Frequency of the offchannel operation in MHz or 0
6413 * @type: Unique identifier for each type of work
6414 * @next: Force as the next work to be executed
6415 * @cb: Callback function for indicating when radio is available
6416 * @ctx: Context pointer for the work (work->ctx in cb())
6417 * Returns: 0 on success, -1 on failure
6418 *
6419 * This function is used to request time for an operation that requires
6420 * exclusive radio control. Once the radio is available, the registered callback
6421 * function will be called. radio_work_done() must be called once the exclusive
6422 * radio operation has been completed, so that the radio is freed for other
6423 * operations. The special case of deinit=1 is used to free the context data
6424 * during interface removal. That does not allow the callback function to start
6425 * the radio operation, i.e., it must free any resources allocated for the radio
6426 * work and return.
6427 *
6428 * The @freq parameter can be used to indicate a single channel on which the
6429 * offchannel operation will occur. This may allow multiple radio work
6430 * operations to be performed in parallel if they apply for the same channel.
6431 * Setting this to 0 indicates that the work item may use multiple channels or
6432 * requires exclusive control of the radio.
6433 */
6434int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6435 const char *type, int next,
6436 void (*cb)(struct wpa_radio_work *work, int deinit),
6437 void *ctx)
6438{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006439 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006440 struct wpa_radio_work *work;
6441 int was_empty;
6442
6443 work = os_zalloc(sizeof(*work));
6444 if (work == NULL)
6445 return -1;
6446 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6447 os_get_reltime(&work->time);
6448 work->freq = freq;
6449 work->type = type;
6450 work->wpa_s = wpa_s;
6451 work->cb = cb;
6452 work->ctx = ctx;
6453
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006454 if (freq)
6455 work->bands = wpas_freq_to_band(freq);
6456 else if (os_strcmp(type, "scan") == 0 ||
6457 os_strcmp(type, "p2p-scan") == 0)
6458 work->bands = wpas_get_bands(wpa_s,
6459 ((struct wpa_driver_scan_params *)
6460 ctx)->freqs);
6461 else
6462 work->bands = wpas_get_bands(wpa_s, NULL);
6463
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006464 was_empty = dl_list_empty(&wpa_s->radio->work);
6465 if (next)
6466 dl_list_add(&wpa_s->radio->work, &work->list);
6467 else
6468 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6469 if (was_empty) {
6470 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6471 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006472 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6473 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6474 wpa_dbg(wpa_s, MSG_DEBUG,
6475 "Try to schedule a radio work (num_active_works=%u)",
6476 radio->num_active_works);
6477 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006478 }
6479
6480 return 0;
6481}
6482
6483
6484/**
6485 * radio_work_done - Indicate that a radio work item has been completed
6486 * @work: Completed work
6487 *
6488 * This function is called once the callback function registered with
6489 * radio_add_work() has completed its work.
6490 */
6491void radio_work_done(struct wpa_radio_work *work)
6492{
6493 struct wpa_supplicant *wpa_s = work->wpa_s;
6494 struct os_reltime now, diff;
6495 unsigned int started = work->started;
6496
6497 os_get_reltime(&now);
6498 os_reltime_sub(&now, &work->time, &diff);
6499 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6500 work->type, work, started ? "done" : "canceled",
6501 diff.sec, diff.usec);
6502 radio_work_free(work);
6503 if (started)
6504 radio_work_check_next(wpa_s);
6505}
6506
6507
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006508struct wpa_radio_work *
6509radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006510{
6511 struct wpa_radio_work *work;
6512 struct wpa_radio *radio = wpa_s->radio;
6513
6514 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6515 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006516 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006517 }
6518
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006519 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006520}
6521
6522
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006523static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006524 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006525{
6526 const char *ifname, *driver, *rn;
6527
6528 driver = iface->driver;
6529next_driver:
6530 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6531 return -1;
6532
6533 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6534 if (wpa_s->drv_priv == NULL) {
6535 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006536 int level = MSG_ERROR;
6537
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006538 pos = driver ? os_strchr(driver, ',') : NULL;
6539 if (pos) {
6540 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6541 "driver interface - try next driver wrapper");
6542 driver = pos + 1;
6543 goto next_driver;
6544 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006545
6546#ifdef CONFIG_MATCH_IFACE
6547 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6548 level = MSG_DEBUG;
6549#endif /* CONFIG_MATCH_IFACE */
6550 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006551 return -1;
6552 }
6553 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6554 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6555 "driver_param '%s'", wpa_s->conf->driver_param);
6556 return -1;
6557 }
6558
6559 ifname = wpa_drv_get_ifname(wpa_s);
6560 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6561 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6562 "interface name with '%s'", ifname);
6563 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6564 }
6565
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006566 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006567 if (rn && rn[0] == '\0')
6568 rn = NULL;
6569
6570 wpa_s->radio = radio_add_interface(wpa_s, rn);
6571 if (wpa_s->radio == NULL)
6572 return -1;
6573
6574 return 0;
6575}
6576
6577
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006578#ifdef CONFIG_GAS_SERVER
6579
6580static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6581 unsigned int freq, const u8 *dst,
6582 const u8 *src, const u8 *bssid,
6583 const u8 *data, size_t data_len,
6584 enum offchannel_send_action_result result)
6585{
6586 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6587 " result=%s",
6588 freq, MAC2STR(dst),
6589 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6590 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6591 "FAILED"));
6592 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6593 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6594}
6595
6596
6597static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6598 struct wpabuf *buf, unsigned int wait_time)
6599{
6600 struct wpa_supplicant *wpa_s = ctx;
6601 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6602
6603 if (wait_time > wpa_s->max_remain_on_chan)
6604 wait_time = wpa_s->max_remain_on_chan;
6605
6606 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6607 wpabuf_head(buf), wpabuf_len(buf),
6608 wait_time, wpas_gas_server_tx_status, 0);
6609}
6610
6611#endif /* CONFIG_GAS_SERVER */
6612
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006613static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006614 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006615{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006616 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006617 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006618 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006619
6620 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6621 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6622 iface->confname ? iface->confname : "N/A",
6623 iface->driver ? iface->driver : "default",
6624 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6625 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6626
6627 if (iface->confname) {
6628#ifdef CONFIG_BACKEND_FILE
6629 wpa_s->confname = os_rel2abs_path(iface->confname);
6630 if (wpa_s->confname == NULL) {
6631 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6632 "for configuration file '%s'.",
6633 iface->confname);
6634 return -1;
6635 }
6636 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6637 iface->confname, wpa_s->confname);
6638#else /* CONFIG_BACKEND_FILE */
6639 wpa_s->confname = os_strdup(iface->confname);
6640#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006641 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006642 if (wpa_s->conf == NULL) {
6643 wpa_printf(MSG_ERROR, "Failed to read or parse "
6644 "configuration '%s'.", wpa_s->confname);
6645 return -1;
6646 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006647 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006648 if (wpa_s->confanother &&
6649 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6650 wpa_printf(MSG_ERROR,
6651 "Failed to read or parse configuration '%s'.",
6652 wpa_s->confanother);
6653 return -1;
6654 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006655
6656 /*
6657 * Override ctrl_interface and driver_param if set on command
6658 * line.
6659 */
6660 if (iface->ctrl_interface) {
6661 os_free(wpa_s->conf->ctrl_interface);
6662 wpa_s->conf->ctrl_interface =
6663 os_strdup(iface->ctrl_interface);
6664 }
6665
6666 if (iface->driver_param) {
6667 os_free(wpa_s->conf->driver_param);
6668 wpa_s->conf->driver_param =
6669 os_strdup(iface->driver_param);
6670 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006671
6672 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6673 os_free(wpa_s->conf->ctrl_interface);
6674 wpa_s->conf->ctrl_interface = NULL;
6675 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006676 } else
6677 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6678 iface->driver_param);
6679
6680 if (wpa_s->conf == NULL) {
6681 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6682 return -1;
6683 }
6684
6685 if (iface->ifname == NULL) {
6686 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6687 return -1;
6688 }
6689 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6690 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6691 iface->ifname);
6692 return -1;
6693 }
6694 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006695#ifdef CONFIG_MATCH_IFACE
6696 wpa_s->matched = iface->matched;
6697#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006698
6699 if (iface->bridge_ifname) {
6700 if (os_strlen(iface->bridge_ifname) >=
6701 sizeof(wpa_s->bridge_ifname)) {
6702 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6703 "name '%s'.", iface->bridge_ifname);
6704 return -1;
6705 }
6706 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6707 sizeof(wpa_s->bridge_ifname));
6708 }
6709
6710 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006711 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6712 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006713
6714 /* Initialize driver interface and register driver event handler before
6715 * L2 receive handler so that association events are processed before
6716 * EAPOL-Key packets if both become available for the same select()
6717 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006718 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006719 return -1;
6720
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006721 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6722 return -1;
6723
6724 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6725 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6726 NULL);
6727 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6728
6729 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6730 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6731 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6732 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6733 "dot11RSNAConfigPMKLifetime");
6734 return -1;
6735 }
6736
6737 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6738 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6739 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6740 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6741 "dot11RSNAConfigPMKReauthThreshold");
6742 return -1;
6743 }
6744
6745 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6746 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6747 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6748 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6749 "dot11RSNAConfigSATimeout");
6750 return -1;
6751 }
6752
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006753 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6754 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006755 &wpa_s->hw.flags,
6756 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006757 if (wpa_s->hw.modes) {
6758 u16 i;
6759
6760 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6761 if (wpa_s->hw.modes[i].vht_capab) {
6762 wpa_s->hw_capab = CAPAB_VHT;
6763 break;
6764 }
6765
6766 if (wpa_s->hw.modes[i].ht_capab &
6767 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6768 wpa_s->hw_capab = CAPAB_HT40;
6769 else if (wpa_s->hw.modes[i].ht_capab &&
6770 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6771 wpa_s->hw_capab = CAPAB_HT;
6772 }
6773 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006774
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006775 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6776 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006777 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006778 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006779 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006780 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006781 wpa_s->drv_rrm_flags = capa.rrm_flags;
Sunil Ravia04bd252022-05-02 22:54:18 -07006782 wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006783 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006784 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006785 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006786 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6787 wpa_s->max_sched_scan_plan_interval =
6788 capa.max_sched_scan_plan_interval;
6789 wpa_s->max_sched_scan_plan_iterations =
6790 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006791 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6792 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006793 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6794 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006795 wpa_s->extended_capa = capa.extended_capa;
6796 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6797 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006798 wpa_s->num_multichan_concurrent =
6799 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006800 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6801
6802 if (capa.mac_addr_rand_scan_supported)
6803 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6804 if (wpa_s->sched_scan_supported &&
6805 capa.mac_addr_rand_sched_scan_supported)
6806 wpa_s->mac_addr_rand_supported |=
6807 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006808
6809 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6810 if (wpa_s->extended_capa &&
6811 wpa_s->extended_capa_len >= 3 &&
6812 wpa_s->extended_capa[2] & 0x40)
6813 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006814 }
6815 if (wpa_s->max_remain_on_chan == 0)
6816 wpa_s->max_remain_on_chan = 1000;
6817
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006818 /*
6819 * Only take p2p_mgmt parameters when P2P Device is supported.
6820 * Doing it here as it determines whether l2_packet_init() will be done
6821 * during wpa_supplicant_driver_init().
6822 */
6823 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6824 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006825
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006826 if (wpa_s->num_multichan_concurrent == 0)
6827 wpa_s->num_multichan_concurrent = 1;
6828
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006829 if (wpa_supplicant_driver_init(wpa_s) < 0)
6830 return -1;
6831
6832#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006833 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006834 return -1;
6835#endif /* CONFIG_TDLS */
6836
6837 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6838 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6839 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6840 return -1;
6841 }
6842
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006843#ifdef CONFIG_FST
6844 if (wpa_s->conf->fst_group_id) {
6845 struct fst_iface_cfg cfg;
6846 struct fst_wpa_obj iface_obj;
6847
6848 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6849 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6850 sizeof(cfg.group_id));
6851 cfg.priority = wpa_s->conf->fst_priority;
6852 cfg.llt = wpa_s->conf->fst_llt;
6853
6854 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6855 &iface_obj, &cfg);
6856 if (!wpa_s->fst) {
6857 wpa_msg(wpa_s, MSG_ERROR,
6858 "FST: Cannot attach iface %s to group %s",
6859 wpa_s->ifname, cfg.group_id);
6860 return -1;
6861 }
6862 }
6863#endif /* CONFIG_FST */
6864
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006865 if (wpas_wps_init(wpa_s))
6866 return -1;
6867
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006868#ifdef CONFIG_GAS_SERVER
6869 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6870 if (!wpa_s->gas_server) {
6871 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6872 return -1;
6873 }
6874#endif /* CONFIG_GAS_SERVER */
6875
6876#ifdef CONFIG_DPP
6877 if (wpas_dpp_init(wpa_s) < 0)
6878 return -1;
6879#endif /* CONFIG_DPP */
6880
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006881 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6882 return -1;
6883 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6884
6885 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6886 if (wpa_s->ctrl_iface == NULL) {
6887 wpa_printf(MSG_ERROR,
6888 "Failed to initialize control interface '%s'.\n"
6889 "You may have another wpa_supplicant process "
6890 "already running or the file was\n"
6891 "left by an unclean termination of wpa_supplicant "
6892 "in which case you will need\n"
6893 "to manually remove this file before starting "
6894 "wpa_supplicant again.\n",
6895 wpa_s->conf->ctrl_interface);
6896 return -1;
6897 }
6898
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006899 wpa_s->gas = gas_query_init(wpa_s);
6900 if (wpa_s->gas == NULL) {
6901 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6902 return -1;
6903 }
6904
Roshan Pius3a1667e2018-07-03 15:17:14 -07006905 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6906 wpa_s->p2p_mgmt) &&
6907 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006908 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6909 return -1;
6910 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006911
6912 if (wpa_bss_init(wpa_s) < 0)
6913 return -1;
6914
Paul Stewart092955c2017-02-06 09:13:09 -08006915#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6916#ifdef CONFIG_MESH
6917 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6918#endif /* CONFIG_MESH */
6919#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6920
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006921 /*
6922 * Set Wake-on-WLAN triggers, if configured.
6923 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6924 * have effect anyway when the interface is down).
6925 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006926 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006927 return -1;
6928
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006929#ifdef CONFIG_EAP_PROXY
6930{
6931 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006932 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6933 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006934 if (wpa_s->mnc_len > 0) {
6935 wpa_s->imsi[len] = '\0';
6936 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6937 wpa_s->imsi, wpa_s->mnc_len);
6938 } else {
6939 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6940 }
6941}
6942#endif /* CONFIG_EAP_PROXY */
6943
Dmitry Shmidt04949592012-07-19 12:16:46 -07006944 if (pcsc_reader_init(wpa_s) < 0)
6945 return -1;
6946
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006947 if (wpas_init_ext_pw(wpa_s) < 0)
6948 return -1;
6949
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006950 wpas_rrm_reset(wpa_s);
6951
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006952 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6953
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006954#ifdef CONFIG_HS20
6955 hs20_init(wpa_s);
6956#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006957#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006958 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006959 if ((wpa_s->conf->oce & OCE_STA) &&
6960 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6961 wpa_s->enable_oce = OCE_STA;
6962 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6963 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6964 /* TODO: Need to add STA-CFON support */
6965 wpa_printf(MSG_ERROR,
6966 "OCE STA-CFON feature is not yet supported");
6967 }
6968 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006969 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6970#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006971
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006972 wpa_supplicant_set_default_scan_ies(wpa_s);
6973
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006974 return 0;
6975}
6976
6977
6978static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006979 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006980{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006981 struct wpa_global *global = wpa_s->global;
6982 struct wpa_supplicant *iface, *prev;
6983
Jimmy Chen0e73c002021-08-18 13:21:30 +08006984 if (wpa_s == wpa_s->parent || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006985 wpas_p2p_group_remove(wpa_s, "*");
6986
6987 iface = global->ifaces;
6988 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006989 if (iface->p2pdev == wpa_s)
6990 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006991 if (iface == wpa_s || iface->parent != wpa_s) {
6992 iface = iface->next;
6993 continue;
6994 }
6995 wpa_printf(MSG_DEBUG,
6996 "Remove remaining child interface %s from parent %s",
6997 iface->ifname, wpa_s->ifname);
6998 prev = iface;
6999 iface = iface->next;
7000 wpa_supplicant_remove_iface(global, prev, terminate);
7001 }
7002
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007003 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007004 if (wpa_s->drv_priv) {
Hai Shalom60840252021-02-19 19:02:11 -08007005 /*
7006 * Don't deauthenticate if WoWLAN is enable and not explicitly
7007 * been configured to disconnect.
7008 */
7009 if (!wpa_drv_get_wowlan(wpa_s) ||
7010 wpa_s->conf->wowlan_disconnect_on_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007011 wpa_supplicant_deauthenticate(
7012 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007013
Hai Shalomfdcde762020-04-02 11:19:20 -07007014 wpa_drv_set_countermeasures(wpa_s, 0);
7015 wpa_clear_keys(wpa_s, NULL);
7016 } else {
7017 wpa_msg(wpa_s, MSG_INFO,
7018 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
7019 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007020 }
7021
7022 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007023 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007024
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007025 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007026 radio_remove_interface(wpa_s);
7027
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007028#ifdef CONFIG_FST
7029 if (wpa_s->fst) {
7030 fst_detach(wpa_s->fst);
7031 wpa_s->fst = NULL;
7032 }
7033 if (wpa_s->received_mb_ies) {
7034 wpabuf_free(wpa_s->received_mb_ies);
7035 wpa_s->received_mb_ies = NULL;
7036 }
7037#endif /* CONFIG_FST */
7038
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007039 if (wpa_s->drv_priv)
7040 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007041
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007042 if (notify)
7043 wpas_notify_iface_removed(wpa_s);
7044
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007045 if (terminate)
7046 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007047
Jouni Malinenf3f8d3c2021-02-05 00:28:17 +02007048 wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
7049 wpa_s->ctrl_iface = NULL;
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007050
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007051#ifdef CONFIG_MESH
7052 if (wpa_s->ifmsh) {
Hai Shalom60840252021-02-19 19:02:11 -08007053 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007054 wpa_s->ifmsh = NULL;
7055 }
7056#endif /* CONFIG_MESH */
7057
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007058 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07007059 wpa_config_free(wpa_s->conf);
7060 wpa_s->conf = NULL;
7061 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007062
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007063 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07007064 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07007065
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007066 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007067}
7068
7069
Dmitry Shmidte4663042016-04-04 10:07:49 -07007070#ifdef CONFIG_MATCH_IFACE
7071
7072/**
7073 * wpa_supplicant_match_iface - Match an interface description to a name
7074 * @global: Pointer to global data from wpa_supplicant_init()
7075 * @ifname: Name of the interface to match
7076 * Returns: Pointer to the created interface description or %NULL on failure
7077 */
7078struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
7079 const char *ifname)
7080{
7081 int i;
7082 struct wpa_interface *iface, *miface;
7083
7084 for (i = 0; i < global->params.match_iface_count; i++) {
7085 miface = &global->params.match_ifaces[i];
7086 if (!miface->ifname ||
7087 fnmatch(miface->ifname, ifname, 0) == 0) {
7088 iface = os_zalloc(sizeof(*iface));
7089 if (!iface)
7090 return NULL;
7091 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07007092 if (!miface->ifname)
7093 iface->matched = WPA_IFACE_MATCHED_NULL;
7094 else
7095 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007096 iface->ifname = ifname;
7097 return iface;
7098 }
7099 }
7100
7101 return NULL;
7102}
7103
7104
7105/**
7106 * wpa_supplicant_match_existing - Match existing interfaces
7107 * @global: Pointer to global data from wpa_supplicant_init()
7108 * Returns: 0 on success, -1 on failure
7109 */
7110static int wpa_supplicant_match_existing(struct wpa_global *global)
7111{
7112 struct if_nameindex *ifi, *ifp;
7113 struct wpa_supplicant *wpa_s;
7114 struct wpa_interface *iface;
7115
7116 ifp = if_nameindex();
7117 if (!ifp) {
7118 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
7119 return -1;
7120 }
7121
7122 for (ifi = ifp; ifi->if_name; ifi++) {
7123 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
7124 if (wpa_s)
7125 continue;
7126 iface = wpa_supplicant_match_iface(global, ifi->if_name);
7127 if (iface) {
Hai Shalom60840252021-02-19 19:02:11 -08007128 wpa_supplicant_add_iface(global, iface, NULL);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007129 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007130 }
7131 }
7132
7133 if_freenameindex(ifp);
7134 return 0;
7135}
7136
7137#endif /* CONFIG_MATCH_IFACE */
7138
7139
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007140/**
7141 * wpa_supplicant_add_iface - Add a new network interface
7142 * @global: Pointer to global data from wpa_supplicant_init()
7143 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007144 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007145 * Returns: Pointer to the created interface or %NULL on failure
7146 *
7147 * This function is used to add new network interfaces for %wpa_supplicant.
7148 * This can be called before wpa_supplicant_run() to add interfaces before the
7149 * main event loop has been started. In addition, new interfaces can be added
7150 * dynamically while %wpa_supplicant is already running. This could happen,
7151 * e.g., when a hotplug network adapter is inserted.
7152 */
7153struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007154 struct wpa_interface *iface,
7155 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007156{
7157 struct wpa_supplicant *wpa_s;
7158 struct wpa_interface t_iface;
7159 struct wpa_ssid *ssid;
7160
7161 if (global == NULL || iface == NULL)
7162 return NULL;
7163
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007164 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007165 if (wpa_s == NULL)
7166 return NULL;
7167
7168 wpa_s->global = global;
7169
7170 t_iface = *iface;
7171 if (global->params.override_driver) {
7172 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
7173 "('%s' -> '%s')",
7174 iface->driver, global->params.override_driver);
7175 t_iface.driver = global->params.override_driver;
7176 }
7177 if (global->params.override_ctrl_interface) {
7178 wpa_printf(MSG_DEBUG, "Override interface parameter: "
7179 "ctrl_interface ('%s' -> '%s')",
7180 iface->ctrl_interface,
7181 global->params.override_ctrl_interface);
7182 t_iface.ctrl_interface =
7183 global->params.override_ctrl_interface;
7184 }
7185 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
7186 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
7187 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007188 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007189 return NULL;
7190 }
7191
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007192 /* Notify the control interfaces about new iface */
7193 if (wpas_notify_iface_added(wpa_s)) {
7194 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
7195 return NULL;
7196 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007197
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08007198 /* Notify the control interfaces about new networks for non p2p mgmt
7199 * ifaces. */
7200 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007201 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
7202 wpas_notify_network_added(wpa_s, ssid);
7203 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007204
7205 wpa_s->next = global->ifaces;
7206 global->ifaces = wpa_s;
7207
7208 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007209 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007210
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007211#ifdef CONFIG_P2P
7212 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07007213 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007214 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007215 wpas_p2p_add_p2pdev_interface(
7216 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007217 wpa_printf(MSG_INFO,
7218 "P2P: Failed to enable P2P Device interface");
7219 /* Try to continue without. P2P will be disabled. */
7220 }
7221#endif /* CONFIG_P2P */
7222
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007223 return wpa_s;
7224}
7225
7226
7227/**
7228 * wpa_supplicant_remove_iface - Remove a network interface
7229 * @global: Pointer to global data from wpa_supplicant_init()
7230 * @wpa_s: Pointer to the network interface to be removed
7231 * Returns: 0 if interface was removed, -1 if interface was not found
7232 *
7233 * This function can be used to dynamically remove network interfaces from
7234 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
7235 * addition, this function is used to remove all remaining interfaces when
7236 * %wpa_supplicant is terminated.
7237 */
7238int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007239 struct wpa_supplicant *wpa_s,
7240 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007241{
7242 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007243#ifdef CONFIG_MESH
7244 unsigned int mesh_if_created = wpa_s->mesh_if_created;
7245 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007246 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007247#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007248
7249 /* Remove interface from the global list of interfaces */
7250 prev = global->ifaces;
7251 if (prev == wpa_s) {
7252 global->ifaces = wpa_s->next;
7253 } else {
7254 while (prev && prev->next != wpa_s)
7255 prev = prev->next;
7256 if (prev == NULL)
7257 return -1;
7258 prev->next = wpa_s->next;
7259 }
7260
7261 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
7262
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007263#ifdef CONFIG_MESH
7264 if (mesh_if_created) {
7265 ifname = os_strdup(wpa_s->ifname);
7266 if (ifname == NULL) {
7267 wpa_dbg(wpa_s, MSG_ERROR,
7268 "mesh: Failed to malloc ifname");
7269 return -1;
7270 }
7271 }
7272#endif /* CONFIG_MESH */
7273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007274 if (global->p2p_group_formation == wpa_s)
7275 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007276 if (global->p2p_invite_group == wpa_s)
7277 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007278 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007279
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007280#ifdef CONFIG_MESH
7281 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007282 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007283 os_free(ifname);
7284 }
7285#endif /* CONFIG_MESH */
7286
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007287 return 0;
7288}
7289
7290
7291/**
7292 * wpa_supplicant_get_eap_mode - Get the current EAP mode
7293 * @wpa_s: Pointer to the network interface
7294 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
7295 */
7296const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
7297{
7298 const char *eapol_method;
7299
7300 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
7301 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
7302 return "NO-EAP";
7303 }
7304
7305 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
7306 if (eapol_method == NULL)
7307 return "UNKNOWN-EAP";
7308
7309 return eapol_method;
7310}
7311
7312
7313/**
7314 * wpa_supplicant_get_iface - Get a new network interface
7315 * @global: Pointer to global data from wpa_supplicant_init()
7316 * @ifname: Interface name
7317 * Returns: Pointer to the interface or %NULL if not found
7318 */
7319struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
7320 const char *ifname)
7321{
7322 struct wpa_supplicant *wpa_s;
7323
7324 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7325 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7326 return wpa_s;
7327 }
7328 return NULL;
7329}
7330
7331
7332#ifndef CONFIG_NO_WPA_MSG
7333static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7334{
7335 struct wpa_supplicant *wpa_s = ctx;
7336 if (wpa_s == NULL)
7337 return NULL;
7338 return wpa_s->ifname;
7339}
7340#endif /* CONFIG_NO_WPA_MSG */
7341
7342
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007343#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7344#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7345#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7346
7347/* Periodic cleanup tasks */
7348static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7349{
7350 struct wpa_global *global = eloop_ctx;
7351 struct wpa_supplicant *wpa_s;
7352
7353 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7354 wpas_periodic, global, NULL);
7355
7356#ifdef CONFIG_P2P
7357 if (global->p2p)
7358 p2p_expire_peers(global->p2p);
7359#endif /* CONFIG_P2P */
7360
7361 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7362 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7363#ifdef CONFIG_AP
7364 ap_periodic(wpa_s);
7365#endif /* CONFIG_AP */
7366 }
7367}
7368
7369
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007370/**
7371 * wpa_supplicant_init - Initialize %wpa_supplicant
7372 * @params: Parameters for %wpa_supplicant
7373 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7374 *
7375 * This function is used to initialize %wpa_supplicant. After successful
7376 * initialization, the returned data pointer can be used to add and remove
7377 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7378 */
7379struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7380{
7381 struct wpa_global *global;
7382 int ret, i;
7383
7384 if (params == NULL)
7385 return NULL;
7386
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007387#ifdef CONFIG_DRIVER_NDIS
7388 {
7389 void driver_ndis_init_ops(void);
7390 driver_ndis_init_ops();
7391 }
7392#endif /* CONFIG_DRIVER_NDIS */
7393
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007394#ifndef CONFIG_NO_WPA_MSG
7395 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7396#endif /* CONFIG_NO_WPA_MSG */
7397
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007398 if (params->wpa_debug_file_path)
7399 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007400 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007401 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007402 if (params->wpa_debug_syslog)
7403 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007404 if (params->wpa_debug_tracing) {
7405 ret = wpa_debug_open_linux_tracing();
7406 if (ret) {
7407 wpa_printf(MSG_ERROR,
7408 "Failed to enable trace logging");
7409 return NULL;
7410 }
7411 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007412
7413 ret = eap_register_methods();
7414 if (ret) {
7415 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7416 if (ret == -2)
7417 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7418 "the same EAP type.");
7419 return NULL;
7420 }
7421
7422 global = os_zalloc(sizeof(*global));
7423 if (global == NULL)
7424 return NULL;
7425 dl_list_init(&global->p2p_srv_bonjour);
7426 dl_list_init(&global->p2p_srv_upnp);
7427 global->params.daemonize = params->daemonize;
7428 global->params.wait_for_monitor = params->wait_for_monitor;
7429 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7430 if (params->pid_file)
7431 global->params.pid_file = os_strdup(params->pid_file);
7432 if (params->ctrl_interface)
7433 global->params.ctrl_interface =
7434 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007435 if (params->ctrl_interface_group)
7436 global->params.ctrl_interface_group =
7437 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007438 if (params->override_driver)
7439 global->params.override_driver =
7440 os_strdup(params->override_driver);
7441 if (params->override_ctrl_interface)
7442 global->params.override_ctrl_interface =
7443 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007444#ifdef CONFIG_MATCH_IFACE
7445 global->params.match_iface_count = params->match_iface_count;
7446 if (params->match_iface_count) {
7447 global->params.match_ifaces =
7448 os_calloc(params->match_iface_count,
7449 sizeof(struct wpa_interface));
7450 os_memcpy(global->params.match_ifaces,
7451 params->match_ifaces,
7452 params->match_iface_count *
7453 sizeof(struct wpa_interface));
7454 }
7455#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007456#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007457 if (params->conf_p2p_dev)
7458 global->params.conf_p2p_dev =
7459 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007460#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007461 wpa_debug_level = global->params.wpa_debug_level =
7462 params->wpa_debug_level;
7463 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7464 params->wpa_debug_show_keys;
7465 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7466 params->wpa_debug_timestamp;
7467
Hai Shalomfdcde762020-04-02 11:19:20 -07007468 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007469
7470 if (eloop_init()) {
7471 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7472 wpa_supplicant_deinit(global);
7473 return NULL;
7474 }
7475
Jouni Malinen75ecf522011-06-27 15:19:46 -07007476 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007477
7478 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7479 if (global->ctrl_iface == NULL) {
7480 wpa_supplicant_deinit(global);
7481 return NULL;
7482 }
7483
7484 if (wpas_notify_supplicant_initialized(global)) {
7485 wpa_supplicant_deinit(global);
7486 return NULL;
7487 }
7488
7489 for (i = 0; wpa_drivers[i]; i++)
7490 global->drv_count++;
7491 if (global->drv_count == 0) {
7492 wpa_printf(MSG_ERROR, "No drivers enabled");
7493 wpa_supplicant_deinit(global);
7494 return NULL;
7495 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007496 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007497 if (global->drv_priv == NULL) {
7498 wpa_supplicant_deinit(global);
7499 return NULL;
7500 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007501
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007502#ifdef CONFIG_WIFI_DISPLAY
7503 if (wifi_display_init(global) < 0) {
7504 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7505 wpa_supplicant_deinit(global);
7506 return NULL;
7507 }
7508#endif /* CONFIG_WIFI_DISPLAY */
7509
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007510 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7511 wpas_periodic, global, NULL);
7512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007513 return global;
7514}
7515
7516
7517/**
7518 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7519 * @global: Pointer to global data from wpa_supplicant_init()
7520 * Returns: 0 after successful event loop run, -1 on failure
7521 *
7522 * This function starts the main event loop and continues running as long as
7523 * there are any remaining events. In most cases, this function is running as
7524 * long as the %wpa_supplicant process in still in use.
7525 */
7526int wpa_supplicant_run(struct wpa_global *global)
7527{
7528 struct wpa_supplicant *wpa_s;
7529
7530 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007531 (wpa_supplicant_daemon(global->params.pid_file) ||
7532 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007533 return -1;
7534
Dmitry Shmidte4663042016-04-04 10:07:49 -07007535#ifdef CONFIG_MATCH_IFACE
7536 if (wpa_supplicant_match_existing(global))
7537 return -1;
7538#endif
7539
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007540 if (global->params.wait_for_monitor) {
7541 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007542 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007543 wpa_supplicant_ctrl_iface_wait(
7544 wpa_s->ctrl_iface);
7545 }
7546
7547 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7548 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7549
7550 eloop_run();
7551
7552 return 0;
7553}
7554
7555
7556/**
7557 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7558 * @global: Pointer to global data from wpa_supplicant_init()
7559 *
7560 * This function is called to deinitialize %wpa_supplicant and to free all
7561 * allocated resources. Remaining network interfaces will also be removed.
7562 */
7563void wpa_supplicant_deinit(struct wpa_global *global)
7564{
7565 int i;
7566
7567 if (global == NULL)
7568 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007569
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007570 eloop_cancel_timeout(wpas_periodic, global, NULL);
7571
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007572#ifdef CONFIG_WIFI_DISPLAY
7573 wifi_display_deinit(global);
7574#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007575
7576 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007577 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007578
7579 if (global->ctrl_iface)
7580 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7581
7582 wpas_notify_supplicant_deinitialized(global);
7583
7584 eap_peer_unregister_methods();
7585#ifdef CONFIG_AP
7586 eap_server_unregister_methods();
7587#endif /* CONFIG_AP */
7588
7589 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7590 if (!global->drv_priv[i])
7591 continue;
7592 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7593 }
7594 os_free(global->drv_priv);
7595
7596 random_deinit();
7597
7598 eloop_destroy();
7599
7600 if (global->params.pid_file) {
7601 os_daemonize_terminate(global->params.pid_file);
7602 os_free(global->params.pid_file);
7603 }
7604 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007605 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007606 os_free(global->params.override_driver);
7607 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007608#ifdef CONFIG_MATCH_IFACE
7609 os_free(global->params.match_ifaces);
7610#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007611#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007612 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007613#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007614
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007615 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007616 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007617 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007618
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007619 os_free(global);
7620 wpa_debug_close_syslog();
7621 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007622 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007623}
7624
7625
7626void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7627{
7628 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7629 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7630 char country[3];
7631 country[0] = wpa_s->conf->country[0];
7632 country[1] = wpa_s->conf->country[1];
7633 country[2] = '\0';
7634 if (wpa_drv_set_country(wpa_s, country) < 0) {
7635 wpa_printf(MSG_ERROR, "Failed to set country code "
7636 "'%s'", country);
7637 }
7638 }
7639
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007640 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7641 wpas_init_ext_pw(wpa_s);
7642
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007643 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7644 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7645
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007646 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7647 struct wpa_driver_capa capa;
7648 int res = wpa_drv_get_capa(wpa_s, &capa);
7649
7650 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7651 wpa_printf(MSG_ERROR,
7652 "Failed to update wowlan_triggers to '%s'",
7653 wpa_s->conf->wowlan_triggers);
7654 }
7655
Hai Shalom81f62d82019-07-22 12:10:00 -07007656 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7657 wpa_supplicant_set_default_scan_ies(wpa_s);
7658
Hai Shalom899fcc72020-10-19 14:38:18 -07007659#ifdef CONFIG_BGSCAN
7660 /*
7661 * We default to global bgscan parameters only when per-network bgscan
7662 * parameters aren't set. Only bother resetting bgscan parameters if
7663 * this is the case.
7664 */
7665 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7666 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7667 wpa_s->wpa_state == WPA_COMPLETED)
7668 wpa_supplicant_reset_bgscan(wpa_s);
7669#endif /* CONFIG_BGSCAN */
7670
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007671#ifdef CONFIG_WPS
7672 wpas_wps_update_config(wpa_s);
7673#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007674 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007675 wpa_s->conf->changed_parameters = 0;
7676}
7677
7678
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007679void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007680{
7681 int i;
7682
7683 for (i = 0; i < *num_freqs; i++) {
7684 if (freqs[i] == freq)
7685 return;
7686 }
7687
7688 freqs[*num_freqs] = freq;
7689 (*num_freqs)++;
7690}
7691
7692
7693static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7694{
7695 struct wpa_bss *bss, *cbss;
7696 const int max_freqs = 10;
7697 int *freqs;
7698 int num_freqs = 0;
7699
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007700 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007701 if (freqs == NULL)
7702 return NULL;
7703
7704 cbss = wpa_s->current_bss;
7705
7706 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7707 if (bss == cbss)
7708 continue;
7709 if (bss->ssid_len == cbss->ssid_len &&
7710 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom60840252021-02-19 19:02:11 -08007711 !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007712 add_freq(freqs, &num_freqs, bss->freq);
7713 if (num_freqs == max_freqs)
7714 break;
7715 }
7716 }
7717
7718 if (num_freqs == 0) {
7719 os_free(freqs);
7720 freqs = NULL;
7721 }
7722
7723 return freqs;
7724}
7725
7726
7727void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7728{
7729 int timeout;
7730 int count;
7731 int *freqs = NULL;
7732
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007733 wpas_connect_work_done(wpa_s);
7734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007735 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007736 * Remove possible authentication timeout since the connection failed.
7737 */
7738 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7739
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007740 /*
Hai Shalom60840252021-02-19 19:02:11 -08007741 * There is no point in ignoring the AP temporarily if this event is
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007742 * generated based on local request to disconnect.
7743 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007744 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007745 wpa_s->own_disconnect_req = 0;
7746 wpa_dbg(wpa_s, MSG_DEBUG,
7747 "Ignore connection failure due to local request to disconnect");
7748 return;
7749 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007750 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007751 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7752 "indication since interface has been put into "
7753 "disconnected state");
7754 return;
7755 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007756 if (wpa_s->auto_reconnect_disabled) {
7757 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7758 "indication since auto connect is disabled");
7759 return;
7760 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007761
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007762 /*
Hai Shalom60840252021-02-19 19:02:11 -08007763 * Add the failed BSSID into the ignore list and speed up next scan
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007764 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007765 */
Hai Shalom60840252021-02-19 19:02:11 -08007766 count = wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007767 if (count == 1 && wpa_s->current_bss) {
7768 /*
Hai Shalom60840252021-02-19 19:02:11 -08007769 * This BSS was not in the ignore list before. If there is
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007770 * another BSS available for the same ESS, we should try that
7771 * next. Otherwise, we may as well try this one once more
7772 * before allowing other, likely worse, ESSes to be considered.
7773 */
7774 freqs = get_bss_freqs_in_ess(wpa_s);
7775 if (freqs) {
7776 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7777 "has been seen; try it next");
Hai Shalom60840252021-02-19 19:02:11 -08007778 wpa_bssid_ignore_add(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007779 /*
7780 * On the next scan, go through only the known channels
7781 * used in this ESS based on previous scans to speed up
7782 * common load balancing use case.
7783 */
7784 os_free(wpa_s->next_scan_freqs);
7785 wpa_s->next_scan_freqs = freqs;
7786 }
7787 }
7788
Hai Shalom899fcc72020-10-19 14:38:18 -07007789 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007790
Hai Shalom899fcc72020-10-19 14:38:18 -07007791 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007792 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7793 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007794 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007795 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007796 /*
7797 * Multiple consecutive connection failures mean that other APs are
7798 * either not available or have already been tried, so we can start
7799 * increasing the delay here to avoid constant scanning.
7800 */
7801 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007802 case 1:
7803 timeout = 100;
7804 break;
7805 case 2:
7806 timeout = 500;
7807 break;
7808 case 3:
7809 timeout = 1000;
7810 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007811 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007812 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007813 break;
7814 default:
7815 timeout = 10000;
7816 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007817 }
7818
Hai Shalom899fcc72020-10-19 14:38:18 -07007819 wpa_dbg(wpa_s, MSG_DEBUG,
7820 "Consecutive connection failures: %d --> request scan in %d ms",
7821 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007822
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007823 /*
7824 * TODO: if more than one possible AP is available in scan results,
7825 * could try the other ones before requesting a new scan.
7826 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007827
7828 /* speed up the connection attempt with normal scan */
7829 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007830 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7831 1000 * (timeout % 1000));
7832}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007833
7834
Hai Shalomce48b4a2018-09-05 11:41:35 -07007835#ifdef CONFIG_FILS
Hai Shalomc1a21442022-02-04 13:43:00 -08007836
7837void fils_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
7838{
7839 struct wpa_ssid *ssid = wpa_s->current_ssid;
7840 const u8 *realm, *username, *rrk;
7841 size_t realm_len, username_len, rrk_len;
7842 u16 next_seq_num;
7843
7844 /* Clear the PMKSA cache entry if FILS authentication was rejected.
7845 * Check for ERP keys existing to limit when this can be done since
7846 * the rejection response is not protected and such triggers should
7847 * really not allow internal state to be modified unless required to
7848 * avoid significant issues in functionality. In addition, drop
7849 * externally configure PMKSA entries even without ERP keys since it
7850 * is possible for an external component to add PMKSA entries for FILS
7851 * authentication without restoring previously generated ERP keys.
7852 *
7853 * In this case, this is needed to allow recovery from cases where the
7854 * AP or authentication server has dropped PMKSAs and ERP keys. */
7855 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt))
7856 return;
7857
7858 if (eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7859 &username, &username_len,
7860 &realm, &realm_len, &next_seq_num,
7861 &rrk, &rrk_len) != 0 ||
7862 !realm) {
7863 wpa_dbg(wpa_s, MSG_DEBUG,
7864 "FILS: Drop external PMKSA cache entry");
7865 wpa_sm_aborted_external_cached(wpa_s->wpa);
7866 wpa_sm_external_pmksa_cache_flush(wpa_s->wpa, ssid);
7867 return;
7868 }
7869
7870 wpa_dbg(wpa_s, MSG_DEBUG, "FILS: Drop PMKSA cache entry");
7871 wpa_sm_aborted_cached(wpa_s->wpa);
7872 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
7873}
7874
7875
Hai Shalomce48b4a2018-09-05 11:41:35 -07007876void fils_connection_failure(struct wpa_supplicant *wpa_s)
7877{
7878 struct wpa_ssid *ssid = wpa_s->current_ssid;
7879 const u8 *realm, *username, *rrk;
7880 size_t realm_len, username_len, rrk_len;
7881 u16 next_seq_num;
7882
7883 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7884 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7885 &username, &username_len,
7886 &realm, &realm_len, &next_seq_num,
7887 &rrk, &rrk_len) != 0 ||
7888 !realm)
7889 return;
7890
7891 wpa_hexdump_ascii(MSG_DEBUG,
7892 "FILS: Store last connection failure realm",
7893 realm, realm_len);
7894 os_free(wpa_s->last_con_fail_realm);
7895 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7896 if (wpa_s->last_con_fail_realm) {
7897 wpa_s->last_con_fail_realm_len = realm_len;
7898 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7899 }
7900}
7901#endif /* CONFIG_FILS */
7902
7903
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007904int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7905{
7906 return wpa_s->conf->ap_scan == 2 ||
7907 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7908}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007909
Dmitry Shmidt04949592012-07-19 12:16:46 -07007910
Gabriel Biren57ededa2021-09-03 16:08:50 +00007911#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_AIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007912int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7913 struct wpa_ssid *ssid,
7914 const char *field,
7915 const char *value)
7916{
7917#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007918 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007919
7920 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7921 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7922 (const u8 *) value, os_strlen(value));
7923
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007924 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007925 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007926#else /* IEEE8021X_EAPOL */
7927 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7928 return -1;
7929#endif /* IEEE8021X_EAPOL */
7930}
7931
7932int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7933 struct wpa_ssid *ssid,
7934 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007935 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007936{
7937#ifdef IEEE8021X_EAPOL
7938 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007939 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007940
7941 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007942 case WPA_CTRL_REQ_EAP_IDENTITY:
7943 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007944 os_free(eap->imsi_identity);
7945 if (value == NULL)
7946 return -1;
7947 identity = os_strchr(value, ':');
7948 if (identity == NULL) {
7949 /* plain identity */
7950 eap->identity = (u8 *)os_strdup(value);
7951 eap->identity_len = os_strlen(value);
7952 } else {
7953 /* have both plain identity and encrypted identity */
7954 imsi_identity = value;
7955 *identity++ = '\0';
7956 /* plain identity */
7957 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7958 eap->imsi_identity_len = strlen(imsi_identity);
7959 /* encrypted identity */
7960 eap->identity = (u8 *)dup_binstr(identity,
7961 value_len - strlen(imsi_identity) - 1);
7962 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7963 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007964 eap->pending_req_identity = 0;
7965 if (ssid == wpa_s->current_ssid)
7966 wpa_s->reassociate = 1;
7967 break;
7968 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007969 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007970 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007971 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007972 eap->pending_req_password = 0;
7973 if (ssid == wpa_s->current_ssid)
7974 wpa_s->reassociate = 1;
7975 break;
7976 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007977 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007978 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007979 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007980 eap->pending_req_new_password = 0;
7981 if (ssid == wpa_s->current_ssid)
7982 wpa_s->reassociate = 1;
7983 break;
7984 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007985 str_clear_free(eap->cert.pin);
7986 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007987 eap->pending_req_pin = 0;
7988 if (ssid == wpa_s->current_ssid)
7989 wpa_s->reassociate = 1;
7990 break;
7991 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007992 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007993 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007994 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007995 os_free(eap->pending_req_otp);
7996 eap->pending_req_otp = NULL;
7997 eap->pending_req_otp_len = 0;
7998 break;
7999 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07008000 str_clear_free(eap->cert.private_key_passwd);
8001 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008002 eap->pending_req_passphrase = 0;
8003 if (ssid == wpa_s->current_ssid)
8004 wpa_s->reassociate = 1;
8005 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008006 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07008007 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07008008 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08008009 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07008010 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008011 case WPA_CTRL_REQ_PSK_PASSPHRASE:
8012 if (wpa_config_set(ssid, "psk", value, 0) < 0)
8013 return -1;
8014 ssid->mem_only_psk = 1;
8015 if (ssid->passphrase)
8016 wpa_config_update_psk(ssid);
8017 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
8018 wpa_supplicant_req_scan(wpa_s, 0, 0);
8019 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008020 case WPA_CTRL_REQ_EXT_CERT_CHECK:
8021 if (eap->pending_ext_cert_check != PENDING_CHECK)
8022 return -1;
8023 if (os_strcmp(value, "good") == 0)
8024 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
8025 else if (os_strcmp(value, "bad") == 0)
8026 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
8027 else
8028 return -1;
8029 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008030 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07008031 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008032 return -1;
8033 }
8034
8035 return 0;
8036#else /* IEEE8021X_EAPOL */
8037 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
8038 return -1;
8039#endif /* IEEE8021X_EAPOL */
8040}
Gabriel Biren57ededa2021-09-03 16:08:50 +00008041#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_AIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008042
8043
8044int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8045{
Hai Shalomfdcde762020-04-02 11:19:20 -07008046#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07008047 int i;
8048 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07008049#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008050
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008051 if (wpa_s->p2p_mgmt)
8052 return 1; /* no normal network profiles on p2p_mgmt interface */
8053
Dmitry Shmidt04949592012-07-19 12:16:46 -07008054 if (ssid == NULL)
8055 return 1;
8056
8057 if (ssid->disabled)
8058 return 1;
8059
Hai Shalomfdcde762020-04-02 11:19:20 -07008060#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08008061 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008062 drv_enc = wpa_s->drv_enc;
8063 else
8064 drv_enc = (unsigned int) -1;
8065
8066 for (i = 0; i < NUM_WEP_KEYS; i++) {
8067 size_t len = ssid->wep_key_len[i];
8068 if (len == 0)
8069 continue;
8070 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
8071 continue;
8072 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
8073 continue;
8074 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
8075 continue;
8076 return 1; /* invalid WEP key */
8077 }
Hai Shalomfdcde762020-04-02 11:19:20 -07008078#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07008079
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008080 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008081 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008082 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07008083 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008084 return 1;
8085
Sunil8cd6f4d2022-06-28 18:40:46 +00008086#ifdef CRYPTO_RSA_OAEP_SHA256
8087 if (ssid->eap.imsi_privacy_cert) {
8088 struct crypto_rsa_key *key;
8089 bool failed = false;
8090
8091 key = crypto_rsa_key_read(ssid->eap.imsi_privacy_cert, false);
8092 if (!key)
8093 failed = true;
8094 crypto_rsa_key_free(key);
8095 if (failed) {
8096 wpa_printf(MSG_DEBUG,
8097 "Invalid imsi_privacy_cert (%s) - disable network",
8098 ssid->eap.imsi_privacy_cert);
8099 return 1;
8100 }
8101 }
8102#endif /* CRYPTO_RSA_OAEP_SHA256 */
8103
Dmitry Shmidt04949592012-07-19 12:16:46 -07008104 return 0;
8105}
8106
8107
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008108int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
8109{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008110 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
8111 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
8112 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
8113 /*
8114 * Driver does not support BIP -- ignore pmf=1 default
8115 * since the connection with PMF would fail and the
8116 * configuration does not require PMF to be enabled.
8117 */
8118 return NO_MGMT_FRAME_PROTECTION;
8119 }
8120
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008121 if (ssid &&
8122 (ssid->key_mgmt &
8123 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
8124 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
8125 /*
8126 * Do not use the default PMF value for non-RSN networks
8127 * since PMF is available only with RSN and pmf=2
8128 * configuration would otherwise prevent connections to
8129 * all open networks.
8130 */
8131 return NO_MGMT_FRAME_PROTECTION;
8132 }
8133
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008134 return wpa_s->conf->pmf;
8135 }
8136
8137 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08008138}
8139
8140
Hai Shalomc1a21442022-02-04 13:43:00 -08008141int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr)
8142{
8143 if (wpa_s->current_ssid == NULL ||
8144 wpa_s->wpa_state < WPA_4WAY_HANDSHAKE ||
8145 os_memcmp(addr, wpa_s->bssid, ETH_ALEN) != 0)
8146 return 0;
8147 return wpa_sm_pmf_enabled(wpa_s->wpa);
8148}
8149
8150
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008151int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008152{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008153 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008154 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07008155 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008156 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07008157 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008158}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008159
8160
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008161void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008162{
8163 struct wpa_ssid *ssid = wpa_s->current_ssid;
8164 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008165 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008166
8167 if (ssid == NULL) {
8168 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
8169 "SSID block");
8170 return;
8171 }
8172
8173 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
8174 return;
8175
8176 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07008177
8178#ifdef CONFIG_P2P
8179 if (ssid->p2p_group &&
8180 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
8181 /*
8182 * Skip the wait time since there is a short timeout on the
8183 * connection to a P2P group.
8184 */
8185 return;
8186 }
8187#endif /* CONFIG_P2P */
8188
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008189 if (ssid->auth_failures > 50)
8190 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008191 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008192 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008193 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008194 dur = 90;
8195 else if (ssid->auth_failures > 3)
8196 dur = 60;
8197 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008198 dur = 30;
8199 else if (ssid->auth_failures > 1)
8200 dur = 20;
8201 else
8202 dur = 10;
8203
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008204 if (ssid->auth_failures > 1 &&
8205 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
8206 dur += os_random() % (ssid->auth_failures * 10);
8207
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008208 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008209 if (now.sec + dur <= ssid->disabled_until.sec)
8210 return;
8211
8212 ssid->disabled_until.sec = now.sec + dur;
8213
8214 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008215 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008216 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07008217 ssid->auth_failures, dur, reason);
Gabriel Biren3a2ec2c2022-03-07 17:59:41 +00008218
8219 char *format_str = "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s";
8220 int msg_len = snprintf(NULL, 0, format_str,
8221 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8222 ssid->auth_failures, dur, reason) + 1;
8223 char *msg = os_malloc(msg_len);
8224 snprintf(msg, msg_len, format_str,
8225 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
8226 ssid->auth_failures, dur, reason);
8227 wpas_notify_ssid_temp_disabled(wpa_s, msg);
8228 os_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008229}
8230
8231
8232void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
8233 struct wpa_ssid *ssid, int clear_failures)
8234{
8235 if (ssid == NULL)
8236 return;
8237
8238 if (ssid->disabled_until.sec) {
8239 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
8240 "id=%d ssid=\"%s\"",
8241 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
8242 }
8243 ssid->disabled_until.sec = 0;
8244 ssid->disabled_until.usec = 0;
8245 if (clear_failures)
8246 ssid->auth_failures = 0;
8247}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008248
8249
8250int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
8251{
8252 size_t i;
8253
8254 if (wpa_s->disallow_aps_bssid == NULL)
8255 return 0;
8256
8257 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
8258 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
8259 bssid, ETH_ALEN) == 0)
8260 return 1;
8261 }
8262
8263 return 0;
8264}
8265
8266
8267int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
8268 size_t ssid_len)
8269{
8270 size_t i;
8271
8272 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
8273 return 0;
8274
8275 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
8276 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
8277 if (ssid_len == s->ssid_len &&
8278 os_memcmp(ssid, s->ssid, ssid_len) == 0)
8279 return 1;
8280 }
8281
8282 return 0;
8283}
8284
8285
8286/**
8287 * wpas_request_connection - Request a new connection
8288 * @wpa_s: Pointer to the network interface
8289 *
8290 * This function is used to request a new connection to be found. It will mark
8291 * the interface to allow reassociation and request a new scan to find a
8292 * suitable network to connect to.
8293 */
8294void wpas_request_connection(struct wpa_supplicant *wpa_s)
8295{
8296 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008297 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008298 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008299 wpa_s->disconnected = 0;
8300 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07008301 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08008302
8303 if (wpa_supplicant_fast_associate(wpa_s) != 1)
8304 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08008305 else
8306 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008307}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008308
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008309
Roshan Pius02242d72016-08-09 15:31:48 -07008310/**
8311 * wpas_request_disconnection - Request disconnection
8312 * @wpa_s: Pointer to the network interface
8313 *
8314 * This function is used to request disconnection from the currently connected
8315 * network. This will stop any ongoing scans and initiate deauthentication.
8316 */
8317void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
8318{
8319#ifdef CONFIG_SME
8320 wpa_s->sme.prev_bssid_set = 0;
8321#endif /* CONFIG_SME */
8322 wpa_s->reassociate = 0;
8323 wpa_s->disconnected = 1;
8324 wpa_supplicant_cancel_sched_scan(wpa_s);
8325 wpa_supplicant_cancel_scan(wpa_s);
8326 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
8327 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07008328 radio_remove_works(wpa_s, "connect", 0);
8329 radio_remove_works(wpa_s, "sme-connect", 0);
Hai Shalomc1a21442022-02-04 13:43:00 -08008330 wpa_s->roam_in_progress = false;
8331#ifdef CONFIG_WNM
8332 wpa_s->bss_trans_mgmt_in_progress = false;
8333#endif /* CONFIG_WNM */
Roshan Pius02242d72016-08-09 15:31:48 -07008334}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008335
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07008336
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008337void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
8338 struct wpa_used_freq_data *freqs_data,
8339 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008340{
8341 unsigned int i;
8342
8343 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
8344 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008345 for (i = 0; i < len; i++) {
8346 struct wpa_used_freq_data *cur = &freqs_data[i];
8347 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
8348 i, cur->freq, cur->flags);
8349 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008350}
8351
8352
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008353/*
8354 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008355 * are using the same radio as the current interface, and in addition, get
8356 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008357 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008358int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
8359 struct wpa_used_freq_data *freqs_data,
8360 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008361{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008362 struct wpa_supplicant *ifs;
8363 u8 bssid[ETH_ALEN];
8364 int freq;
8365 unsigned int idx = 0, i;
8366
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008367 wpa_dbg(wpa_s, MSG_DEBUG,
8368 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008369 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008370
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008371 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8372 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008373 if (idx == len)
8374 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008375
8376 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
8377 continue;
8378
8379 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008380 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
8381 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008382 freq = ifs->current_ssid->frequency;
8383 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
8384 freq = ifs->assoc_freq;
8385 else
8386 continue;
8387
8388 /* Hold only distinct freqs */
8389 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008390 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008391 break;
8392
8393 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008394 freqs_data[idx++].freq = freq;
8395
8396 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008397 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008398 WPA_FREQ_USED_BY_P2P_CLIENT :
8399 WPA_FREQ_USED_BY_INFRA_STATION;
8400 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008401 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08008402
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008403 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07008404 return idx;
8405}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008406
8407
8408/*
8409 * Find the operating frequencies of any of the virtual interfaces that
8410 * are using the same radio as the current interface.
8411 */
8412int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
8413 int *freq_array, unsigned int len)
8414{
8415 struct wpa_used_freq_data *freqs_data;
8416 int num, i;
8417
8418 os_memset(freq_array, 0, sizeof(int) * len);
8419
8420 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8421 if (!freqs_data)
8422 return -1;
8423
8424 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8425 for (i = 0; i < num; i++)
8426 freq_array[i] = freqs_data[i].freq;
8427
8428 os_free(freqs_data);
8429
8430 return num;
8431}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008432
8433
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008434struct wpa_supplicant *
8435wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8436{
8437 switch (frame) {
8438#ifdef CONFIG_P2P
8439 case VENDOR_ELEM_PROBE_REQ_P2P:
8440 case VENDOR_ELEM_PROBE_RESP_P2P:
8441 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8442 case VENDOR_ELEM_BEACON_P2P_GO:
8443 case VENDOR_ELEM_P2P_PD_REQ:
8444 case VENDOR_ELEM_P2P_PD_RESP:
8445 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8446 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8447 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8448 case VENDOR_ELEM_P2P_INV_REQ:
8449 case VENDOR_ELEM_P2P_INV_RESP:
8450 case VENDOR_ELEM_P2P_ASSOC_REQ:
8451 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008452 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008453#endif /* CONFIG_P2P */
8454 default:
8455 return wpa_s;
8456 }
8457}
8458
8459
8460void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8461{
8462 unsigned int i;
8463 char buf[30];
8464
8465 wpa_printf(MSG_DEBUG, "Update vendor elements");
8466
8467 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8468 if (wpa_s->vendor_elem[i]) {
8469 int res;
8470
8471 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8472 if (!os_snprintf_error(sizeof(buf), res)) {
8473 wpa_hexdump_buf(MSG_DEBUG, buf,
8474 wpa_s->vendor_elem[i]);
8475 }
8476 }
8477 }
8478
8479#ifdef CONFIG_P2P
Jimmy Chen48b484b2022-01-25 00:17:50 +08008480 if ((wpa_s->parent == wpa_s || (wpa_s == wpa_s->p2pdev && wpa_s->p2p_mgmt)) &&
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008481 wpa_s->global->p2p &&
8482 !wpa_s->global->p2p_disabled)
8483 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8484#endif /* CONFIG_P2P */
8485}
8486
8487
8488int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8489 const u8 *elem, size_t len)
8490{
8491 u8 *ie, *end;
8492
8493 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8494 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8495
8496 for (; ie + 1 < end; ie += 2 + ie[1]) {
8497 if (ie + len > end)
8498 break;
8499 if (os_memcmp(ie, elem, len) != 0)
8500 continue;
8501
8502 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8503 wpabuf_free(wpa_s->vendor_elem[frame]);
8504 wpa_s->vendor_elem[frame] = NULL;
8505 } else {
8506 os_memmove(ie, ie + len, end - (ie + len));
8507 wpa_s->vendor_elem[frame]->used -= len;
8508 }
8509 wpas_vendor_elem_update(wpa_s);
8510 return 0;
8511 }
8512
8513 return -1;
8514}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008515
8516
8517struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008518 u16 num_modes, enum hostapd_hw_mode mode,
Hai Shalom60840252021-02-19 19:02:11 -08008519 bool is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008520{
8521 u16 i;
8522
Hai Shalomc1a21442022-02-04 13:43:00 -08008523 if (!modes)
8524 return NULL;
8525
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008526 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008527 if (modes[i].mode != mode ||
8528 !modes[i].num_channels || !modes[i].channels)
8529 continue;
8530 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8531 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008532 return &modes[i];
8533 }
8534
8535 return NULL;
8536}
8537
8538
Hai Shalomc1a21442022-02-04 13:43:00 -08008539struct hostapd_hw_modes * get_mode_with_freq(struct hostapd_hw_modes *modes,
8540 u16 num_modes, int freq)
8541{
8542 int i, j;
8543
8544 for (i = 0; i < num_modes; i++) {
8545 for (j = 0; j < modes[i].num_channels; j++) {
8546 if (freq == modes[i].channels[j].freq)
8547 return &modes[i];
8548 }
8549 }
8550
8551 return NULL;
8552}
8553
8554
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008555static struct
8556wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8557 const u8 *bssid)
8558{
8559 struct wpa_bss_tmp_disallowed *bss;
8560
8561 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8562 struct wpa_bss_tmp_disallowed, list) {
8563 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8564 return bss;
8565 }
8566
8567 return NULL;
8568}
8569
8570
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008571static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8572{
8573 struct wpa_bss_tmp_disallowed *tmp;
8574 unsigned int num_bssid = 0;
8575 u8 *bssids;
8576 int ret;
8577
8578 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8579 if (!bssids)
8580 return -1;
8581 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8582 struct wpa_bss_tmp_disallowed, list) {
8583 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8584 ETH_ALEN);
8585 num_bssid++;
8586 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008587 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008588 os_free(bssids);
8589 return ret;
8590}
8591
8592
8593static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8594{
8595 struct wpa_supplicant *wpa_s = eloop_ctx;
8596 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8597
8598 /* Make sure the bss is not already freed */
8599 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8600 struct wpa_bss_tmp_disallowed, list) {
8601 if (bss == tmp) {
Hai Shalomc1a21442022-02-04 13:43:00 -08008602 remove_bss_tmp_disallowed_entry(wpa_s, tmp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008603 wpa_set_driver_tmp_disallow_list(wpa_s);
8604 break;
8605 }
8606 }
8607}
8608
8609
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008610void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008611 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008612{
8613 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008614
8615 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8616 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008617 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008618 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008619 }
8620
8621 bss = os_malloc(sizeof(*bss));
8622 if (!bss) {
8623 wpa_printf(MSG_DEBUG,
8624 "Failed to allocate memory for temp disallow BSS");
8625 return;
8626 }
8627
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008628 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8629 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008630 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008631
8632finish:
8633 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008634 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8635 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008636}
8637
8638
Hai Shalom74f70d42019-02-11 14:42:39 -08008639int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8640 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008641{
Hai Shalom74f70d42019-02-11 14:42:39 -08008642 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008643
8644 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8645 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008646 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8647 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008648 break;
8649 }
8650 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008651 if (!disallowed)
8652 return 0;
8653
8654 if (disallowed->rssi_threshold != 0 &&
Hai Shalomc1a21442022-02-04 13:43:00 -08008655 bss->level > disallowed->rssi_threshold) {
8656 remove_bss_tmp_disallowed_entry(wpa_s, disallowed);
8657 wpa_set_driver_tmp_disallow_list(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008658 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08008659 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008660
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008661 return 1;
8662}
Hai Shalom81f62d82019-07-22 12:10:00 -07008663
8664
8665int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8666 unsigned int type, const u8 *addr,
8667 const u8 *mask)
8668{
8669 if ((addr && !mask) || (!addr && mask)) {
8670 wpa_printf(MSG_INFO,
8671 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8672 return -1;
8673 }
8674
8675 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8676 wpa_printf(MSG_INFO,
8677 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8678 return -1;
8679 }
8680
8681 if (type & MAC_ADDR_RAND_SCAN) {
8682 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8683 addr, mask))
8684 return -1;
8685 }
8686
8687 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8688 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8689 addr, mask))
8690 return -1;
8691
8692 if (wpa_s->sched_scanning && !wpa_s->pno)
8693 wpas_scan_restart_sched_scan(wpa_s);
8694 }
8695
8696 if (type & MAC_ADDR_RAND_PNO) {
8697 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8698 addr, mask))
8699 return -1;
8700
8701 if (wpa_s->pno) {
8702 wpas_stop_pno(wpa_s);
8703 wpas_start_pno(wpa_s);
8704 }
8705 }
8706
8707 return 0;
8708}
8709
8710
8711int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8712 unsigned int type)
8713{
8714 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8715 if (wpa_s->pno) {
8716 if (type & MAC_ADDR_RAND_PNO) {
8717 wpas_stop_pno(wpa_s);
8718 wpas_start_pno(wpa_s);
8719 }
8720 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8721 wpas_scan_restart_sched_scan(wpa_s);
8722 }
8723
8724 return 0;
8725}
Hai Shalomfdcde762020-04-02 11:19:20 -07008726
8727
8728int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8729 struct wpa_signal_info *si)
8730{
8731 int res;
8732
8733 if (!wpa_s->driver->signal_poll)
8734 return -1;
8735
8736 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8737
8738#ifdef CONFIG_TESTING_OPTIONS
8739 if (res == 0) {
8740 struct driver_signal_override *dso;
8741
8742 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8743 struct driver_signal_override, list) {
8744 if (os_memcmp(wpa_s->bssid, dso->bssid,
8745 ETH_ALEN) != 0)
8746 continue;
8747 wpa_printf(MSG_DEBUG,
8748 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8749 si->current_signal,
8750 dso->si_current_signal,
8751 si->avg_signal,
8752 dso->si_avg_signal,
8753 si->avg_beacon_signal,
8754 dso->si_avg_beacon_signal,
8755 si->current_noise,
8756 dso->si_current_noise);
8757 si->current_signal = dso->si_current_signal;
8758 si->avg_signal = dso->si_avg_signal;
8759 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8760 si->current_noise = dso->si_current_noise;
8761 break;
8762 }
8763 }
8764#endif /* CONFIG_TESTING_OPTIONS */
8765
8766 return res;
8767}
8768
8769
8770struct wpa_scan_results *
8771wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8772{
8773 struct wpa_scan_results *scan_res;
8774#ifdef CONFIG_TESTING_OPTIONS
8775 size_t idx;
8776#endif /* CONFIG_TESTING_OPTIONS */
8777
8778 if (!wpa_s->driver->get_scan_results2)
8779 return NULL;
8780
8781 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8782
8783#ifdef CONFIG_TESTING_OPTIONS
8784 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8785 struct driver_signal_override *dso;
8786 struct wpa_scan_res *res = scan_res->res[idx];
8787
8788 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8789 struct driver_signal_override, list) {
8790 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8791 continue;
8792 wpa_printf(MSG_DEBUG,
8793 "Override driver scan signal level %d->%d for "
8794 MACSTR,
8795 res->level, dso->scan_level,
8796 MAC2STR(res->bssid));
8797 res->flags |= WPA_SCAN_QUAL_INVALID;
8798 if (dso->scan_level < 0)
8799 res->flags |= WPA_SCAN_LEVEL_DBM;
8800 else
8801 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8802 res->level = dso->scan_level;
8803 break;
8804 }
8805 }
8806#endif /* CONFIG_TESTING_OPTIONS */
8807
8808 return scan_res;
8809}