blob: 6ab5485adb4e322564ba76f429d5f06fb1864a40 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalom74f70d42019-02-11 14:42:39 -08003 * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
20#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "eapol_supp/eapol_supp_sm.h"
23#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070024#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "eap_server/eap_methods.h"
26#include "rsn_supp/wpa.h"
27#include "eloop.h"
28#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070029#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "l2_packet/l2_packet.h"
31#include "wpa_supplicant_i.h"
32#include "driver_i.h"
33#include "ctrl_iface.h"
34#include "pcsc_funcs.h"
35#include "common/version.h"
36#include "rsn_supp/preauth.h"
37#include "rsn_supp/pmksa_cache.h"
38#include "common/wpa_ctrl.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070039#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080041#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070042#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070043#include "common/dpp.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070044#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080045#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "blacklist.h"
47#include "wpas_glue.h"
48#include "wps_supplicant.h"
49#include "ibss_rsn.h"
50#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080051#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070052#include "ap.h"
53#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070054#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070055#include "notify.h"
56#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070057#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070058#include "bss.h"
59#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080060#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070061#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070062#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070063#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080064#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070065#include "dpp_supplicant.h"
66#ifdef CONFIG_MESH
67#include "ap/ap_config.h"
68#include "ap/hostapd.h"
69#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070071const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072"wpa_supplicant v" VERSION_STR "\n"
Hai Shalom74f70d42019-02-11 14:42:39 -080073"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070075const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080076"This software may be distributed under the terms of the BSD license.\n"
77"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070078#ifdef EAP_TLS_OPENSSL
79"\nThis product includes software developed by the OpenSSL Project\n"
80"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
81#endif /* EAP_TLS_OPENSSL */
82;
83
84#ifndef CONFIG_NO_STDOUT_DEBUG
85/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070086const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080087"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070088const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080089"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070090"\n"
91"Redistribution and use in source and binary forms, with or without\n"
92"modification, are permitted provided that the following conditions are\n"
93"met:\n"
94"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070095const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096"1. Redistributions of source code must retain the above copyright\n"
97" notice, this list of conditions and the following disclaimer.\n"
98"\n"
99"2. Redistributions in binary form must reproduce the above copyright\n"
100" notice, this list of conditions and the following disclaimer in the\n"
101" documentation and/or other materials provided with the distribution.\n"
102"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700103const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700104"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
105" names of its contributors may be used to endorse or promote products\n"
106" derived from this software without specific prior written permission.\n"
107"\n"
108"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
109"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
110"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
111"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700112const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700113"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
114"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
115"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
116"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
117"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
118"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
119"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
120"\n";
121#endif /* CONFIG_NO_STDOUT_DEBUG */
122
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700123
124static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
125#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
126static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
127#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700128#ifdef CONFIG_OWE
129static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
130#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700131
132
Hai Shalomfdcde762020-04-02 11:19:20 -0700133#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700134/* Configure default/group WEP keys for static WEP */
135int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
136{
137 int i, set = 0;
138
139 for (i = 0; i < NUM_WEP_KEYS; i++) {
140 if (ssid->wep_key_len[i] == 0)
141 continue;
142
143 set = 1;
144 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
145 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700146 ssid->wep_key[i], ssid->wep_key_len[i],
147 i == ssid->wep_tx_keyidx ?
148 KEY_FLAG_GROUP_RX_TX_DEFAULT :
149 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700150 }
151
152 return set;
153}
Hai Shalomfdcde762020-04-02 11:19:20 -0700154#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700155
156
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700157int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
158 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700159{
160 u8 key[32];
161 size_t keylen;
162 enum wpa_alg alg;
163 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800164 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700165
166 /* IBSS/WPA-None uses only one key (Group) for both receiving and
167 * sending unicast and multicast packets. */
168
169 if (ssid->mode != WPAS_MODE_IBSS) {
170 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
171 "IBSS/ad-hoc) for WPA-None", ssid->mode);
172 return -1;
173 }
174
175 if (!ssid->psk_set) {
176 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
177 "WPA-None");
178 return -1;
179 }
180
181 switch (wpa_s->group_cipher) {
182 case WPA_CIPHER_CCMP:
183 os_memcpy(key, ssid->psk, 16);
184 keylen = 16;
185 alg = WPA_ALG_CCMP;
186 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700187 case WPA_CIPHER_GCMP:
188 os_memcpy(key, ssid->psk, 16);
189 keylen = 16;
190 alg = WPA_ALG_GCMP;
191 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700192 case WPA_CIPHER_TKIP:
193 /* WPA-None uses the same Michael MIC key for both TX and RX */
194 os_memcpy(key, ssid->psk, 16 + 8);
195 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
196 keylen = 32;
197 alg = WPA_ALG_TKIP;
198 break;
199 default:
200 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
201 "WPA-None", wpa_s->group_cipher);
202 return -1;
203 }
204
205 /* TODO: should actually remember the previously used seq#, both for TX
206 * and RX from each STA.. */
207
Hai Shalomfdcde762020-04-02 11:19:20 -0700208 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen,
209 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800210 os_memset(key, 0, sizeof(key));
211 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700212}
213
214
215static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
216{
217 struct wpa_supplicant *wpa_s = eloop_ctx;
218 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700219 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
220 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
221 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700222 bssid = wpa_s->pending_bssid;
223 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
224 MAC2STR(bssid));
225 wpa_blacklist_add(wpa_s, bssid);
Roshan Pius92cbe442020-10-08 16:15:13 -0700226 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700227 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800228 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700229 wpa_s->reassociate = 1;
230
231 /*
232 * If we timed out, the AP or the local radio may be busy.
233 * So, wait a second until scanning again.
234 */
235 wpa_supplicant_req_scan(wpa_s, 1, 0);
236}
237
238
239/**
240 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
241 * @wpa_s: Pointer to wpa_supplicant data
242 * @sec: Number of seconds after which to time out authentication
243 * @usec: Number of microseconds after which to time out authentication
244 *
245 * This function is used to schedule a timeout for the current authentication
246 * attempt.
247 */
248void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
249 int sec, int usec)
250{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700251 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700252 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
253 return;
254
255 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
256 "%d usec", sec, usec);
257 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700258 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700259 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
260}
261
262
Roshan Pius3a1667e2018-07-03 15:17:14 -0700263/*
264 * wpas_auth_timeout_restart - Restart and change timeout for authentication
265 * @wpa_s: Pointer to wpa_supplicant data
266 * @sec_diff: difference in seconds applied to original timeout value
267 */
268void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
269{
270 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
271
272 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
273 wpa_dbg(wpa_s, MSG_DEBUG,
274 "Authentication timeout restart: %d sec", new_sec);
275 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
276 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
277 wpa_s, NULL);
278 }
279}
280
281
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700282/**
283 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
284 * @wpa_s: Pointer to wpa_supplicant data
285 *
286 * This function is used to cancel authentication timeout scheduled with
287 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
288 * been completed.
289 */
290void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
291{
292 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
293 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
294 wpa_blacklist_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700295 os_free(wpa_s->last_con_fail_realm);
296 wpa_s->last_con_fail_realm = NULL;
297 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700298}
299
300
301/**
302 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
303 * @wpa_s: Pointer to wpa_supplicant data
304 *
305 * This function is used to configure EAPOL state machine based on the selected
306 * authentication mode.
307 */
308void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
309{
310#ifdef IEEE8021X_EAPOL
311 struct eapol_config eapol_conf;
312 struct wpa_ssid *ssid = wpa_s->current_ssid;
313
314#ifdef CONFIG_IBSS_RSN
315 if (ssid->mode == WPAS_MODE_IBSS &&
316 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
317 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
318 /*
319 * RSN IBSS authentication is per-STA and we can disable the
320 * per-BSSID EAPOL authentication.
321 */
322 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
Hai Shalome21d4e82020-04-29 16:34:06 -0700323 eapol_sm_notify_eap_success(wpa_s->eapol, true);
324 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700325 return;
326 }
327#endif /* CONFIG_IBSS_RSN */
328
Hai Shalome21d4e82020-04-29 16:34:06 -0700329 eapol_sm_notify_eap_success(wpa_s->eapol, false);
330 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700331
332 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
333 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
334 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
335 else
336 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
337
338 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
339 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
340 eapol_conf.accept_802_1x_keys = 1;
341 eapol_conf.required_keys = 0;
342 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
343 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
344 }
345 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
346 eapol_conf.required_keys |=
347 EAPOL_REQUIRE_KEY_BROADCAST;
348 }
349
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700350 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700351 eapol_conf.required_keys = 0;
352 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700353 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354 eapol_conf.workaround = ssid->eap_workaround;
355 eapol_conf.eap_disabled =
356 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
357 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
358 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700359 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800360
361#ifdef CONFIG_WPS
362 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
363 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
364 if (wpa_s->current_bss) {
365 struct wpabuf *ie;
366 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
367 WPS_IE_VENDOR_TYPE);
368 if (ie) {
369 if (wps_is_20(ie))
370 eapol_conf.wps |=
371 EAPOL_PEER_IS_WPS20_AP;
372 wpabuf_free(ie);
373 }
374 }
375 }
376#endif /* CONFIG_WPS */
377
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700378 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700379
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800380#ifdef CONFIG_MACSEC
381 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
382 ieee802_1x_create_preshared_mka(wpa_s, ssid);
383 else
384 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
385#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800386#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700387}
388
389
390/**
391 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
392 * @wpa_s: Pointer to wpa_supplicant data
393 * @ssid: Configuration data for the network
394 *
395 * This function is used to configure WPA state machine and related parameters
396 * to a mode where WPA is not enabled. This is called as part of the
397 * authentication configuration when the selected network does not use WPA.
398 */
399void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
400 struct wpa_ssid *ssid)
401{
Hai Shalomfdcde762020-04-02 11:19:20 -0700402#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700403 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700404#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700405
406 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
407 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
408 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
409 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
410 else
411 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
412 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
413 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700414 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700416 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
417 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
419 wpa_s->group_cipher = WPA_CIPHER_NONE;
420 wpa_s->mgmt_group_cipher = 0;
421
Hai Shalomfdcde762020-04-02 11:19:20 -0700422#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700423 for (i = 0; i < NUM_WEP_KEYS; i++) {
424 if (ssid->wep_key_len[i] > 5) {
425 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
426 wpa_s->group_cipher = WPA_CIPHER_WEP104;
427 break;
428 } else if (ssid->wep_key_len[i] > 0) {
429 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
430 wpa_s->group_cipher = WPA_CIPHER_WEP40;
431 break;
432 }
433 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700434#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700435
436 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
437 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
438 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
439 wpa_s->pairwise_cipher);
440 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
442 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443
444 pmksa_cache_clear_current(wpa_s->wpa);
445}
446
447
Dmitry Shmidt04949592012-07-19 12:16:46 -0700448void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800449{
450 int i;
451 if (wpa_s->hw.modes == NULL)
452 return;
453
454 for (i = 0; i < wpa_s->hw.num_modes; i++) {
455 os_free(wpa_s->hw.modes[i].channels);
456 os_free(wpa_s->hw.modes[i].rates);
457 }
458
459 os_free(wpa_s->hw.modes);
460 wpa_s->hw.modes = NULL;
461}
462
463
Hai Shalom74f70d42019-02-11 14:42:39 -0800464void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800465{
466 struct wpa_bss_tmp_disallowed *bss, *prev;
467
468 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
469 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700470 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800471 dl_list_del(&bss->list);
472 os_free(bss);
473 }
474}
475
476
Paul Stewart092955c2017-02-06 09:13:09 -0800477void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
478{
479 struct fils_hlp_req *req;
480
481 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
482 list)) != NULL) {
483 dl_list_del(&req->list);
484 wpabuf_free(req->pkt);
485 os_free(req);
486 }
487}
488
489
Hai Shalomfdcde762020-04-02 11:19:20 -0700490void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
491{
492 struct wpa_supplicant *wpa_s = eloop_ctx;
493
494 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
495 return;
496 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
497 wpa_bss_flush(wpa_s);
498}
499
500
501#ifdef CONFIG_TESTING_OPTIONS
502void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
503{
504 struct driver_signal_override *dso;
505
506 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
507 struct driver_signal_override, list))) {
508 dl_list_del(&dso->list);
509 os_free(dso);
510 }
511}
512#endif /* CONFIG_TESTING_OPTIONS */
513
514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
516{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700517 int i;
518
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700519 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700520 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700521 scard_deinit(wpa_s->scard);
522 wpa_s->scard = NULL;
523 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
524 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
525 l2_packet_deinit(wpa_s->l2);
526 wpa_s->l2 = NULL;
527 if (wpa_s->l2_br) {
528 l2_packet_deinit(wpa_s->l2_br);
529 wpa_s->l2_br = NULL;
530 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800531#ifdef CONFIG_TESTING_OPTIONS
532 l2_packet_deinit(wpa_s->l2_test);
533 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800534 os_free(wpa_s->get_pref_freq_list_override);
535 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700536 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
537 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800538 os_free(wpa_s->extra_sae_rejected_groups);
539 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700540 wpabuf_free(wpa_s->rsne_override_eapol);
541 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800542 wpabuf_free(wpa_s->rsnxe_override_assoc);
543 wpa_s->rsnxe_override_assoc = NULL;
544 wpabuf_free(wpa_s->rsnxe_override_eapol);
545 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700546 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800547#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549 if (wpa_s->conf != NULL) {
550 struct wpa_ssid *ssid;
551 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
552 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700553 }
554
555 os_free(wpa_s->confname);
556 wpa_s->confname = NULL;
557
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700558 os_free(wpa_s->confanother);
559 wpa_s->confanother = NULL;
560
Hai Shalomce48b4a2018-09-05 11:41:35 -0700561 os_free(wpa_s->last_con_fail_realm);
562 wpa_s->last_con_fail_realm = NULL;
563 wpa_s->last_con_fail_realm_len = 0;
564
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700565 wpa_sm_set_eapol(wpa_s->wpa, NULL);
566 eapol_sm_deinit(wpa_s->eapol);
567 wpa_s->eapol = NULL;
568
569 rsn_preauth_deinit(wpa_s->wpa);
570
571#ifdef CONFIG_TDLS
572 wpa_tdls_deinit(wpa_s->wpa);
573#endif /* CONFIG_TDLS */
574
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800575 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700576 pmksa_candidate_free(wpa_s->wpa);
577 wpa_sm_deinit(wpa_s->wpa);
578 wpa_s->wpa = NULL;
579 wpa_blacklist_clear(wpa_s);
580
581 wpa_bss_deinit(wpa_s);
582
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700583 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700584 wpa_supplicant_cancel_scan(wpa_s);
585 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800586 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
587#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
588 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
589 wpa_s, NULL);
590#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700592 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700593 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700594
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700595 wpas_wps_deinit(wpa_s);
596
597 wpabuf_free(wpa_s->pending_eapol_rx);
598 wpa_s->pending_eapol_rx = NULL;
599
600#ifdef CONFIG_IBSS_RSN
601 ibss_rsn_deinit(wpa_s->ibss_rsn);
602 wpa_s->ibss_rsn = NULL;
603#endif /* CONFIG_IBSS_RSN */
604
605 sme_deinit(wpa_s);
606
607#ifdef CONFIG_AP
608 wpa_supplicant_ap_deinit(wpa_s);
609#endif /* CONFIG_AP */
610
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700611 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700612
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800613#ifdef CONFIG_OFFCHANNEL
614 offchannel_deinit(wpa_s);
615#endif /* CONFIG_OFFCHANNEL */
616
617 wpa_supplicant_cancel_sched_scan(wpa_s);
618
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700619 os_free(wpa_s->next_scan_freqs);
620 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800621
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800622 os_free(wpa_s->manual_scan_freqs);
623 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700624 os_free(wpa_s->select_network_scan_freqs);
625 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800626
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700627 os_free(wpa_s->manual_sched_scan_freqs);
628 wpa_s->manual_sched_scan_freqs = NULL;
629
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800630 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
631
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700632 /*
633 * Need to remove any pending gas-query radio work before the
634 * gas_query_deinit() call because gas_query::work has not yet been set
635 * for works that have not been started. gas_query_free() will be unable
636 * to cancel such pending radio works and once the pending gas-query
637 * radio work eventually gets removed, the deinit notification call to
638 * gas_query_start_cb() would result in dereferencing freed memory.
639 */
640 if (wpa_s->radio)
641 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800642 gas_query_deinit(wpa_s->gas);
643 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700644 gas_server_deinit(wpa_s->gas_server);
645 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800646
647 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700648
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700649 ieee802_1x_dealloc_kay_sm(wpa_s);
650
Dmitry Shmidt04949592012-07-19 12:16:46 -0700651 os_free(wpa_s->bssid_filter);
652 wpa_s->bssid_filter = NULL;
653
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800654 os_free(wpa_s->disallow_aps_bssid);
655 wpa_s->disallow_aps_bssid = NULL;
656 os_free(wpa_s->disallow_aps_ssid);
657 wpa_s->disallow_aps_ssid = NULL;
658
Dmitry Shmidt04949592012-07-19 12:16:46 -0700659 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700660#ifdef CONFIG_WNM
661 wnm_deallocate_memory(wpa_s);
662#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700663
664 ext_password_deinit(wpa_s->ext_pw);
665 wpa_s->ext_pw = NULL;
666
667 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800668 wpa_s->last_gas_resp = NULL;
669 wpabuf_free(wpa_s->prev_gas_resp);
670 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700671
672 os_free(wpa_s->last_scan_res);
673 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800674
675#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700676 if (wpa_s->drv_priv)
677 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700678 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800679#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700680
681 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
682 wpabuf_free(wpa_s->vendor_elem[i]);
683 wpa_s->vendor_elem[i] = NULL;
684 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800685
686 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800687
688 wpa_s->sched_scan_plans_num = 0;
689 os_free(wpa_s->sched_scan_plans);
690 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800691
692#ifdef CONFIG_MBO
693 wpa_s->non_pref_chan_num = 0;
694 os_free(wpa_s->non_pref_chan);
695 wpa_s->non_pref_chan = NULL;
696#endif /* CONFIG_MBO */
697
698 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700699
700 wpabuf_free(wpa_s->lci);
701 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800702 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800703
704#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
705#ifdef CONFIG_MESH
706 {
707 struct external_pmksa_cache *entry;
708
709 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
710 struct external_pmksa_cache,
711 list)) != NULL) {
712 dl_list_del(&entry->list);
713 os_free(entry->pmksa_cache);
714 os_free(entry);
715 }
716 }
717#endif /* CONFIG_MESH */
718#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
719
720 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800721
722 wpabuf_free(wpa_s->ric_ies);
723 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700724
725#ifdef CONFIG_DPP
726 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700727 dpp_global_deinit(wpa_s->dpp);
728 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700729#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730}
731
732
733/**
734 * wpa_clear_keys - Clear keys configured for the driver
735 * @wpa_s: Pointer to wpa_supplicant data
736 * @addr: Previously used BSSID or %NULL if not available
737 *
738 * This function clears the encryption keys that has been previously configured
739 * for the driver.
740 */
741void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
742{
Hai Shalomc3565922019-10-28 11:58:20 -0700743 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744
745 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800746 for (i = 0; i < max; i++) {
747 if (wpa_s->keys_cleared & BIT(i))
748 continue;
749 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700750 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800751 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700752 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
753 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800754 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700755 if (!(wpa_s->keys_cleared & BIT(0)))
756 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
757 0, NULL, 0, KEY_FLAG_PAIRWISE);
758 if (!(wpa_s->keys_cleared & BIT(15)))
759 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
760 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700761 /* MLME-SETPROTECTION.request(None) */
762 wpa_drv_mlme_setprotection(
763 wpa_s, addr,
764 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
765 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
766 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800767 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700768}
769
770
771/**
772 * wpa_supplicant_state_txt - Get the connection state name as a text string
773 * @state: State (wpa_state; WPA_*)
774 * Returns: The state name as a printable text string
775 */
776const char * wpa_supplicant_state_txt(enum wpa_states state)
777{
778 switch (state) {
779 case WPA_DISCONNECTED:
780 return "DISCONNECTED";
781 case WPA_INACTIVE:
782 return "INACTIVE";
783 case WPA_INTERFACE_DISABLED:
784 return "INTERFACE_DISABLED";
785 case WPA_SCANNING:
786 return "SCANNING";
787 case WPA_AUTHENTICATING:
788 return "AUTHENTICATING";
789 case WPA_ASSOCIATING:
790 return "ASSOCIATING";
791 case WPA_ASSOCIATED:
792 return "ASSOCIATED";
793 case WPA_4WAY_HANDSHAKE:
794 return "4WAY_HANDSHAKE";
795 case WPA_GROUP_HANDSHAKE:
796 return "GROUP_HANDSHAKE";
797 case WPA_COMPLETED:
798 return "COMPLETED";
799 default:
800 return "UNKNOWN";
801 }
802}
803
804
805#ifdef CONFIG_BGSCAN
806
Hai Shalom899fcc72020-10-19 14:38:18 -0700807static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
808{
809 if (wpa_s->bgscan_ssid) {
810 bgscan_deinit(wpa_s);
811 wpa_s->bgscan_ssid = NULL;
812 }
813}
814
815
816/**
817 * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID.
818 * @wpa_s: Pointer to the wpa_supplicant data
819 *
820 * Stop, start, or reconfigure the scan parameters depending on the method.
821 */
822void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700823{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800824 const char *name;
825
826 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
827 name = wpa_s->current_ssid->bgscan;
828 else
829 name = wpa_s->conf->bgscan;
Hai Shalom899fcc72020-10-19 14:38:18 -0700830 if (!name || name[0] == '\0') {
831 wpa_supplicant_stop_bgscan(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800832 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700833 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800834 if (wpas_driver_bss_selection(wpa_s))
835 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800836#ifdef CONFIG_P2P
837 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
838 return;
839#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700840
841 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800842 if (wpa_s->current_ssid) {
843 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700844 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
845 "bgscan");
846 /*
847 * Live without bgscan; it is only used as a roaming
848 * optimization, so the initial connection is not
849 * affected.
850 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700851 } else {
852 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700853 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700854 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
855 0);
856 if (scan_res) {
857 bgscan_notify_scan(wpa_s, scan_res);
858 wpa_scan_results_free(scan_res);
859 }
860 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700861 } else
862 wpa_s->bgscan_ssid = NULL;
863}
864
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700865#endif /* CONFIG_BGSCAN */
866
867
Dmitry Shmidt04949592012-07-19 12:16:46 -0700868static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
869{
870 if (autoscan_init(wpa_s, 0))
871 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
872}
873
874
875static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
876{
877 autoscan_deinit(wpa_s);
878}
879
880
881void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
882{
883 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
884 wpa_s->wpa_state == WPA_SCANNING) {
885 autoscan_deinit(wpa_s);
886 wpa_supplicant_start_autoscan(wpa_s);
887 }
888}
889
890
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700891/**
892 * wpa_supplicant_set_state - Set current connection state
893 * @wpa_s: Pointer to wpa_supplicant data
894 * @state: The new connection state
895 *
896 * This function is called whenever the connection state changes, e.g.,
897 * association is completed for WPA/WPA2 4-Way Handshake is started.
898 */
899void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
900 enum wpa_states state)
901{
902 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700903#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700904 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700905#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700906
907 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
908 wpa_supplicant_state_txt(wpa_s->wpa_state),
909 wpa_supplicant_state_txt(state));
910
Hai Shalom74f70d42019-02-11 14:42:39 -0800911 if (state == WPA_COMPLETED &&
912 os_reltime_initialized(&wpa_s->roam_start)) {
913 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
914 wpa_s->roam_start.sec = 0;
915 wpa_s->roam_start.usec = 0;
916 wpas_notify_auth_changed(wpa_s);
917 wpas_notify_roam_time(wpa_s);
918 wpas_notify_roam_complete(wpa_s);
919 } else if (state == WPA_DISCONNECTED &&
920 os_reltime_initialized(&wpa_s->roam_start)) {
921 wpa_s->roam_start.sec = 0;
922 wpa_s->roam_start.usec = 0;
923 wpa_s->roam_time.sec = 0;
924 wpa_s->roam_time.usec = 0;
925 wpas_notify_roam_complete(wpa_s);
926 }
927
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800928 if (state == WPA_INTERFACE_DISABLED) {
929 /* Assure normal scan when interface is restored */
930 wpa_s->normal_scans = 0;
931 }
932
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700933 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800934 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700935 /* Reinitialize normal_scan counter */
936 wpa_s->normal_scans = 0;
937 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800938
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700939#ifdef CONFIG_P2P
940 /*
941 * P2PS client has to reply to Probe Request frames received on the
942 * group operating channel. Enable Probe Request frame reporting for
943 * P2P connected client in case p2p_cli_probe configuration property is
944 * set to 1.
945 */
946 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
947 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
948 wpa_s->current_ssid->p2p_group) {
949 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
950 wpa_dbg(wpa_s, MSG_DEBUG,
951 "P2P: Enable CLI Probe Request RX reporting");
952 wpa_s->p2p_cli_probe =
953 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
954 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
955 wpa_dbg(wpa_s, MSG_DEBUG,
956 "P2P: Disable CLI Probe Request RX reporting");
957 wpa_s->p2p_cli_probe = 0;
958 wpa_drv_probe_req_report(wpa_s, 0);
959 }
960 }
961#endif /* CONFIG_P2P */
962
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700963 if (state != WPA_SCANNING)
964 wpa_supplicant_notify_scanning(wpa_s, 0);
965
966 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700967 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700968 int fils_hlp_sent = 0;
969
970#ifdef CONFIG_SME
971 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
972 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
973 fils_hlp_sent = 1;
974#endif /* CONFIG_SME */
975 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
976 wpa_auth_alg_fils(wpa_s->auth_alg))
977 fils_hlp_sent = 1;
978
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700979#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700981 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800982 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700983 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700984 ssid && ssid->id_str ? ssid->id_str : "",
985 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700986#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700987 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Hai Shalom899fcc72020-10-19 14:38:18 -0700988 wpa_s->consecutive_conn_failures = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700990 wpa_drv_set_operstate(wpa_s, 1);
991#ifndef IEEE8021X_EAPOL
992 wpa_drv_set_supp_port(wpa_s, 1);
993#endif /* IEEE8021X_EAPOL */
994 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700995 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700997
998 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700999
1000#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1001 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -07001002 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001003#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -07001004#ifdef CONFIG_OWE
1005 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1006 wpas_update_owe_connect_params(wpa_s);
1007#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1009 state == WPA_ASSOCIATED) {
1010 wpa_s->new_connection = 1;
1011 wpa_drv_set_operstate(wpa_s, 0);
1012#ifndef IEEE8021X_EAPOL
1013 wpa_drv_set_supp_port(wpa_s, 0);
1014#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001015 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 }
1017 wpa_s->wpa_state = state;
1018
1019#ifdef CONFIG_BGSCAN
Hai Shalom899fcc72020-10-19 14:38:18 -07001020 if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
1021 wpa_supplicant_reset_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001022 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001023 wpa_supplicant_stop_bgscan(wpa_s);
1024#endif /* CONFIG_BGSCAN */
1025
Hai Shalom5f92bc92019-04-18 11:54:11 -07001026 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001027 wpa_supplicant_stop_autoscan(wpa_s);
1028
1029 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1030 wpa_supplicant_start_autoscan(wpa_s);
1031
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001032 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1033 wmm_ac_notify_disassoc(wpa_s);
1034
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001035 if (wpa_s->wpa_state != old_state) {
1036 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1037
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001038 /*
1039 * Notify the P2P Device interface about a state change in one
1040 * of the interfaces.
1041 */
1042 wpas_p2p_indicate_state_change(wpa_s);
1043
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001044 if (wpa_s->wpa_state == WPA_COMPLETED ||
1045 old_state == WPA_COMPLETED)
1046 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001047#ifdef CONFIG_DPP2
1048 if (wpa_s->wpa_state == WPA_COMPLETED)
1049 wpas_dpp_connected(wpa_s);
1050#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001051 }
Hai Shalomc3565922019-10-28 11:58:20 -07001052#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1053 if (update_fils_connect_params)
1054 wpas_update_fils_connect_params(wpa_s);
1055#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001056}
1057
1058
1059void wpa_supplicant_terminate_proc(struct wpa_global *global)
1060{
1061 int pending = 0;
1062#ifdef CONFIG_WPS
1063 struct wpa_supplicant *wpa_s = global->ifaces;
1064 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001065 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001066 if (wpas_wps_terminate_pending(wpa_s) == 1)
1067 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001068#ifdef CONFIG_P2P
1069 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1070 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1071 wpas_p2p_disconnect(wpa_s);
1072#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001073 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074 }
1075#endif /* CONFIG_WPS */
1076 if (pending)
1077 return;
1078 eloop_terminate();
1079}
1080
1081
1082static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1083{
1084 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085 wpa_supplicant_terminate_proc(global);
1086}
1087
1088
1089void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1090{
1091 enum wpa_states old_state = wpa_s->wpa_state;
1092
1093 wpa_s->pairwise_cipher = 0;
1094 wpa_s->group_cipher = 0;
1095 wpa_s->mgmt_group_cipher = 0;
1096 wpa_s->key_mgmt = 0;
1097 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001098 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099
1100 if (wpa_s->wpa_state != old_state)
1101 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1102}
1103
1104
1105/**
1106 * wpa_supplicant_reload_configuration - Reload configuration data
1107 * @wpa_s: Pointer to wpa_supplicant data
1108 * Returns: 0 on success or -1 if configuration parsing failed
1109 *
1110 * This function can be used to request that the configuration data is reloaded
1111 * (e.g., after configuration file change). This function is reloading
1112 * configuration only for one interface, so this may need to be called multiple
1113 * times if %wpa_supplicant is controlling multiple interfaces and all
1114 * interfaces need reconfiguration.
1115 */
1116int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1117{
1118 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119 int reconf_ctrl;
1120 int old_ap_scan;
1121
1122 if (wpa_s->confname == NULL)
1123 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001124 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125 if (conf == NULL) {
1126 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1127 "file '%s' - exiting", wpa_s->confname);
1128 return -1;
1129 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001130 if (wpa_s->confanother &&
1131 !wpa_config_read(wpa_s->confanother, conf)) {
1132 wpa_msg(wpa_s, MSG_ERROR,
1133 "Failed to parse the configuration file '%s' - exiting",
1134 wpa_s->confanother);
1135 return -1;
1136 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001137
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 conf->changed_parameters = (unsigned int) -1;
1139
1140 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1141 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1142 os_strcmp(conf->ctrl_interface,
1143 wpa_s->conf->ctrl_interface) != 0);
1144
1145 if (reconf_ctrl && wpa_s->ctrl_iface) {
1146 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1147 wpa_s->ctrl_iface = NULL;
1148 }
1149
1150 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001151 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001152 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1153 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001154 wpa_supplicant_deauthenticate(wpa_s,
1155 WLAN_REASON_DEAUTH_LEAVING);
1156 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001157
1158 /*
1159 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001160 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001161 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001162 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1163 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1164 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 /*
1166 * Clear forced success to clear EAP state for next
1167 * authentication.
1168 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001169 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001170 }
1171 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1172 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001173 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001174 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1175 rsn_preauth_deinit(wpa_s->wpa);
1176
1177 old_ap_scan = wpa_s->conf->ap_scan;
1178 wpa_config_free(wpa_s->conf);
1179 wpa_s->conf = conf;
1180 if (old_ap_scan != wpa_s->conf->ap_scan)
1181 wpas_notify_ap_scan_changed(wpa_s);
1182
1183 if (reconf_ctrl)
1184 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1185
1186 wpa_supplicant_update_config(wpa_s);
1187
1188 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001189 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190 wpa_s->reassociate = 1;
1191 wpa_supplicant_req_scan(wpa_s, 0, 0);
1192 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001193 wpa_blacklist_clear(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1195 return 0;
1196}
1197
1198
1199static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1200{
1201 struct wpa_global *global = signal_ctx;
1202 struct wpa_supplicant *wpa_s;
1203 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1204 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1205 sig);
1206 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1207 wpa_supplicant_terminate_proc(global);
1208 }
1209 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001210
1211 if (wpa_debug_reopen_file() < 0) {
1212 /* Ignore errors since we cannot really do much to fix this */
1213 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1214 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001215}
1216
1217
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001218static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1219 struct wpa_ssid *ssid,
1220 struct wpa_ie_data *ie)
1221{
1222 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1223 if (ret) {
1224 if (ret == -2) {
1225 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1226 "from association info");
1227 }
1228 return -1;
1229 }
1230
1231 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1232 "cipher suites");
1233 if (!(ie->group_cipher & ssid->group_cipher)) {
1234 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1235 "cipher 0x%x (mask 0x%x) - reject",
1236 ie->group_cipher, ssid->group_cipher);
1237 return -1;
1238 }
1239 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1240 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1241 "cipher 0x%x (mask 0x%x) - reject",
1242 ie->pairwise_cipher, ssid->pairwise_cipher);
1243 return -1;
1244 }
1245 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1246 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1247 "management 0x%x (mask 0x%x) - reject",
1248 ie->key_mgmt, ssid->key_mgmt);
1249 return -1;
1250 }
1251
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001252 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001253 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001254 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1255 "that does not support management frame protection - "
1256 "reject");
1257 return -1;
1258 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001259
1260 return 0;
1261}
1262
1263
Hai Shalom021b0b52019-04-10 11:17:58 -07001264static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1265 int freq)
1266{
1267 if (!ie->has_group)
1268 ie->group_cipher = wpa_default_rsn_cipher(freq);
1269 if (!ie->has_pairwise)
1270 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1271 return (ie->group_cipher & ssid->group_cipher) &&
1272 (ie->pairwise_cipher & ssid->pairwise_cipher);
1273}
1274
1275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001276/**
1277 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1278 * @wpa_s: Pointer to wpa_supplicant data
1279 * @bss: Scan results for the selected BSS, or %NULL if not available
1280 * @ssid: Configuration data for the selected network
1281 * @wpa_ie: Buffer for the WPA/RSN IE
1282 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1283 * used buffer length in case the functions returns success.
1284 * Returns: 0 on success or -1 on failure
1285 *
1286 * This function is used to configure authentication and encryption parameters
1287 * based on the network configuration and scan result for the selected BSS (if
1288 * available).
1289 */
1290int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1291 struct wpa_bss *bss, struct wpa_ssid *ssid,
1292 u8 *wpa_ie, size_t *wpa_ie_len)
1293{
1294 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001295 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001296 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001297
1298 if (bss) {
1299 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1300 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001301 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001302 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001303 } else {
1304 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1305 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001306
1307 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1308 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001309 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001310 (ie.key_mgmt & ssid->key_mgmt)) {
1311 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1312 proto = WPA_PROTO_RSN;
1313 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001314 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315 (ie.group_cipher & ssid->group_cipher) &&
1316 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1317 (ie.key_mgmt & ssid->key_mgmt)) {
1318 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1319 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001320#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001321 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1322 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1323 (ie.group_cipher & ssid->group_cipher) &&
1324 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1325 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001326 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001327 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001328 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1329 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1330 (ie.group_cipher & ssid->group_cipher) &&
1331 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1332 (ie.key_mgmt & ssid->key_mgmt)) {
1333 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1334 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001335#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001336 } else if (bss) {
1337 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001338 wpa_dbg(wpa_s, MSG_DEBUG,
1339 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1340 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1341 ssid->key_mgmt);
1342 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1343 MAC2STR(bss->bssid),
1344 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1345 bss_wpa ? " WPA" : "",
1346 bss_rsn ? " RSN" : "",
1347 bss_osen ? " OSEN" : "");
1348 if (bss_rsn) {
1349 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1350 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1351 wpa_dbg(wpa_s, MSG_DEBUG,
1352 "Could not parse RSN element");
1353 } else {
1354 wpa_dbg(wpa_s, MSG_DEBUG,
1355 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1356 ie.pairwise_cipher, ie.group_cipher,
1357 ie.key_mgmt);
1358 }
1359 }
1360 if (bss_wpa) {
1361 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1362 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1363 wpa_dbg(wpa_s, MSG_DEBUG,
1364 "Could not parse WPA element");
1365 } else {
1366 wpa_dbg(wpa_s, MSG_DEBUG,
1367 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1368 ie.pairwise_cipher, ie.group_cipher,
1369 ie.key_mgmt);
1370 }
1371 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001372 return -1;
1373 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001374 if (ssid->proto & WPA_PROTO_OSEN)
1375 proto = WPA_PROTO_OSEN;
1376 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001377 proto = WPA_PROTO_RSN;
1378 else
1379 proto = WPA_PROTO_WPA;
1380 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1381 os_memset(&ie, 0, sizeof(ie));
1382 ie.group_cipher = ssid->group_cipher;
1383 ie.pairwise_cipher = ssid->pairwise_cipher;
1384 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001385 ie.mgmt_group_cipher = 0;
1386 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1387 if (ssid->group_mgmt_cipher &
1388 WPA_CIPHER_BIP_GMAC_256)
1389 ie.mgmt_group_cipher =
1390 WPA_CIPHER_BIP_GMAC_256;
1391 else if (ssid->group_mgmt_cipher &
1392 WPA_CIPHER_BIP_CMAC_256)
1393 ie.mgmt_group_cipher =
1394 WPA_CIPHER_BIP_CMAC_256;
1395 else if (ssid->group_mgmt_cipher &
1396 WPA_CIPHER_BIP_GMAC_128)
1397 ie.mgmt_group_cipher =
1398 WPA_CIPHER_BIP_GMAC_128;
1399 else
1400 ie.mgmt_group_cipher =
1401 WPA_CIPHER_AES_128_CMAC;
1402 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001403#ifdef CONFIG_OWE
1404 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1405 !ssid->owe_only &&
1406 !bss_wpa && !bss_rsn && !bss_osen) {
1407 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1408 wpa_s->wpa_proto = 0;
1409 *wpa_ie_len = 0;
1410 return 0;
1411 }
1412#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001413 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1414 "based on configuration");
1415 } else
1416 proto = ie.proto;
1417 }
1418
1419 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1420 "pairwise %d key_mgmt %d proto %d",
1421 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001422 if (ssid->ieee80211w) {
1423 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1424 ie.mgmt_group_cipher);
1425 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001426
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001427 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001428 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1429 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001430 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001431
1432 if (bss || !wpa_s->ap_ies_from_associnfo) {
1433 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1434 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1435 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001436 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1437 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1438 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001439 return -1;
1440 }
1441
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001442#ifdef CONFIG_NO_WPA
1443 wpa_s->group_cipher = WPA_CIPHER_NONE;
1444 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1445#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001447 wpa_dbg(wpa_s, MSG_DEBUG,
1448 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1449 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001450 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1451 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001452 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1453 "cipher");
1454 return -1;
1455 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001456 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1457 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001458
1459 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001460 wpa_dbg(wpa_s, MSG_DEBUG,
1461 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1462 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001463 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1464 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001465 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1466 "cipher");
1467 return -1;
1468 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001469 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1470 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001471#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001472
1473 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001474#ifdef CONFIG_SAE
1475 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1476 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1477#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001478#ifdef CONFIG_IEEE80211R
1479 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1480 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1481 sel &= ~WPA_KEY_MGMT_FT;
1482#endif /* CONFIG_IEEE80211R */
1483 wpa_dbg(wpa_s, MSG_DEBUG,
1484 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1485 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001486 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001487#ifdef CONFIG_IEEE80211R
1488#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001489 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1490 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001491 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1492 wpa_dbg(wpa_s, MSG_DEBUG,
1493 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001494 if (!ssid->ft_eap_pmksa_caching &&
1495 pmksa_cache_get_current(wpa_s->wpa)) {
1496 /* PMKSA caching with FT may have interoperability
1497 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001498 wpa_dbg(wpa_s, MSG_DEBUG,
1499 "WPA: Disable PMKSA caching for FT/802.1X connection");
1500 pmksa_cache_clear_current(wpa_s->wpa);
1501 }
1502#endif /* CONFIG_SHA384 */
1503#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001504#ifdef CONFIG_SUITEB192
1505 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1506 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1507 wpa_dbg(wpa_s, MSG_DEBUG,
1508 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1509#endif /* CONFIG_SUITEB192 */
1510#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001511 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1512 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1513 wpa_dbg(wpa_s, MSG_DEBUG,
1514 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001515#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001516#ifdef CONFIG_FILS
1517#ifdef CONFIG_IEEE80211R
1518 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1519 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1520 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1521 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1522 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1523 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1524#endif /* CONFIG_IEEE80211R */
1525 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1526 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1527 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1528 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1529 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1530 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1531#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001532#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001533 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1534 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001535 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1536 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001537 if (!ssid->ft_eap_pmksa_caching &&
1538 pmksa_cache_get_current(wpa_s->wpa)) {
1539 /* PMKSA caching with FT may have interoperability
1540 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001541 wpa_dbg(wpa_s, MSG_DEBUG,
1542 "WPA: Disable PMKSA caching for FT/802.1X connection");
1543 pmksa_cache_clear_current(wpa_s->wpa);
1544 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001545#endif /* CONFIG_IEEE80211R */
1546#ifdef CONFIG_DPP
1547 } else if (sel & WPA_KEY_MGMT_DPP) {
1548 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1549 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1550#endif /* CONFIG_DPP */
1551#ifdef CONFIG_SAE
1552 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1553 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1554 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1555 } else if (sel & WPA_KEY_MGMT_SAE) {
1556 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1557 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1558#endif /* CONFIG_SAE */
1559#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001560 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1561 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1562 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1563#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001564 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1565 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1566 wpa_dbg(wpa_s, MSG_DEBUG,
1567 "WPA: using KEY_MGMT 802.1X with SHA256");
1568 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1569 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1570 wpa_dbg(wpa_s, MSG_DEBUG,
1571 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001572 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1573 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1574 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1575 } else if (sel & WPA_KEY_MGMT_PSK) {
1576 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1577 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1578 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1579 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1580 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001581#ifdef CONFIG_HS20
1582 } else if (sel & WPA_KEY_MGMT_OSEN) {
1583 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1584 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1585#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001586#ifdef CONFIG_OWE
1587 } else if (sel & WPA_KEY_MGMT_OWE) {
1588 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1589 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1590#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001591 } else {
1592 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1593 "authenticated key management type");
1594 return -1;
1595 }
1596
1597 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1598 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1599 wpa_s->pairwise_cipher);
1600 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1601
Hai Shalomc3565922019-10-28 11:58:20 -07001602 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1603 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1604 wpa_msg(wpa_s, MSG_INFO,
1605 "RSN: Management frame protection required but the selected AP does not enable it");
1606 return -1;
1607 }
1608
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001609 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001610 if (ssid->group_mgmt_cipher)
1611 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001612 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001613 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1614 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001615 wpa_dbg(wpa_s, MSG_DEBUG,
1616 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1617 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001618 if (sel & WPA_CIPHER_AES_128_CMAC) {
1619 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1620 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1621 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001622 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1623 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1624 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1625 "BIP-GMAC-128");
1626 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1627 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1628 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1629 "BIP-GMAC-256");
1630 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1631 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1632 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1633 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001634 } else {
1635 wpa_s->mgmt_group_cipher = 0;
1636 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1637 }
1638 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1639 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001640 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001641 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001642#ifdef CONFIG_OCV
1643 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
1644#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001645 sae_pwe = wpa_s->conf->sae_pwe;
1646 if (ssid->sae_password_id && sae_pwe != 3)
1647 sae_pwe = 1;
1648 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalom899fcc72020-10-19 14:38:18 -07001649#ifdef CONFIG_SAE_PK
1650 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
1651 wpa_key_mgmt_sae(ssid->key_mgmt) &&
1652 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
1653 ((ssid->sae_password &&
1654 sae_pk_valid_password(ssid->sae_password)) ||
1655 (!ssid->sae_password && ssid->passphrase &&
1656 sae_pk_valid_password(ssid->passphrase))));
1657#endif /* CONFIG_SAE_PK */
Hai Shalomb755a2a2020-04-23 21:49:02 -07001658#ifdef CONFIG_TESTING_OPTIONS
1659 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1660 wpa_s->ft_rsnxe_used);
Hai Shalom899fcc72020-10-19 14:38:18 -07001661 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL,
1662 wpa_s->oci_freq_override_eapol);
1663 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2,
1664 wpa_s->oci_freq_override_eapol_g2);
1665 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC,
1666 wpa_s->oci_freq_override_ft_assoc);
1667 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC,
1668 wpa_s->oci_freq_override_fils_assoc);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001669#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001670
1671 /* Extended Key ID is only supported in infrastructure BSS so far */
1672 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1673 (ssid->proto & WPA_PROTO_RSN) &&
1674 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1675 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1676 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1677 int use_ext_key_id = 0;
1678
1679 wpa_msg(wpa_s, MSG_DEBUG,
1680 "WPA: Enable Extended Key ID support");
1681 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1682 wpa_s->conf->extended_key_id);
1683 if (bss_rsn &&
1684 wpa_s->conf->extended_key_id &&
1685 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1686 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1687 use_ext_key_id = 1;
1688 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1689 use_ext_key_id);
1690 } else {
1691 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1692 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1693 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001694
1695 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1696 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1697 return -1;
1698 }
1699
Hai Shalomc3565922019-10-28 11:58:20 -07001700 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1701 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1702 &wpa_s->rsnxe_len)) {
1703 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1704 return -1;
1705 }
1706
Hai Shalom021b0b52019-04-10 11:17:58 -07001707 if (0) {
1708#ifdef CONFIG_DPP
1709 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1710 /* Use PMK from DPP network introduction (PMKSA entry) */
1711 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001712#ifdef CONFIG_DPP2
1713 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1714#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001715#endif /* CONFIG_DPP */
1716 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001717 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001718 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001719
Roshan Pius3a1667e2018-07-03 15:17:14 -07001720 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1721 WPA_KEY_MGMT_FT_PSK |
1722 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1723
1724 if (ssid->psk_set && !sae_only) {
1725 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1726 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001727 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1728 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001729 psk_set = 1;
1730 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001731
Roshan Pius3a1667e2018-07-03 15:17:14 -07001732 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1733 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001734 psk_set = 1;
1735
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001736#ifndef CONFIG_NO_PBKDF2
1737 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001738 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001739 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001740 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1741 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001742 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1743 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001744 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001745 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001746 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001747 }
1748#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001749#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001750 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001751 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1752 ssid->ext_psk);
1753 char pw_str[64 + 1];
1754 u8 psk[PMK_LEN];
1755
1756 if (pw == NULL) {
1757 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1758 "found from external storage");
1759 return -1;
1760 }
1761
1762 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1763 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1764 "PSK length %d in external storage",
1765 (int) wpabuf_len(pw));
1766 ext_password_free(pw);
1767 return -1;
1768 }
1769
1770 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1771 pw_str[wpabuf_len(pw)] = '\0';
1772
1773#ifndef CONFIG_NO_PBKDF2
1774 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1775 {
1776 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1777 4096, psk, PMK_LEN);
1778 os_memset(pw_str, 0, sizeof(pw_str));
1779 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1780 "external passphrase)",
1781 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001782 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1783 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001784 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001785 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001786 } else
1787#endif /* CONFIG_NO_PBKDF2 */
1788 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1789 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1790 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1791 "Invalid PSK hex string");
1792 os_memset(pw_str, 0, sizeof(pw_str));
1793 ext_password_free(pw);
1794 return -1;
1795 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001796 wpa_hexdump_key(MSG_MSGDUMP,
1797 "PSK (from external PSK)",
1798 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001799 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1800 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001801 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001802 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001803 } else {
1804 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1805 "PSK available");
1806 os_memset(pw_str, 0, sizeof(pw_str));
1807 ext_password_free(pw);
1808 return -1;
1809 }
1810
1811 os_memset(pw_str, 0, sizeof(pw_str));
1812 ext_password_free(pw);
1813 }
1814#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001815
1816 if (!psk_set) {
1817 wpa_msg(wpa_s, MSG_INFO,
1818 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001819 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001820 return -1;
1821 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001822#ifdef CONFIG_OWE
1823 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1824 /* OWE Diffie-Hellman exchange in (Re)Association
1825 * Request/Response frames set the PMK, so do not override it
1826 * here. */
1827#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001828 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001829 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1830
Hai Shalomfdcde762020-04-02 11:19:20 -07001831 if (ssid->mode != WPAS_MODE_IBSS &&
1832 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1833 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1834 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1835 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1836 wpa_msg(wpa_s, MSG_INFO,
1837 "Disable PTK0 rekey support - replaced with reconnect");
1838 wpa_s->deny_ptk0_rekey = 1;
1839 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1840 } else {
1841 wpa_s->deny_ptk0_rekey = 0;
1842 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1843 }
1844
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001845 return 0;
1846}
1847
1848
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001849static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1850{
1851 *pos = 0x00;
1852
1853 switch (idx) {
1854 case 0: /* Bits 0-7 */
1855 break;
1856 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001857 if (wpa_s->conf->coloc_intf_reporting) {
1858 /* Bit 13 - Collocated Interference Reporting */
1859 *pos |= 0x20;
1860 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001861 break;
1862 case 2: /* Bits 16-23 */
1863#ifdef CONFIG_WNM
1864 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001865 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001866 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001867#endif /* CONFIG_WNM */
1868 break;
1869 case 3: /* Bits 24-31 */
1870#ifdef CONFIG_WNM
1871 *pos |= 0x02; /* Bit 25 - SSID List */
1872#endif /* CONFIG_WNM */
1873#ifdef CONFIG_INTERWORKING
1874 if (wpa_s->conf->interworking)
1875 *pos |= 0x80; /* Bit 31 - Interworking */
1876#endif /* CONFIG_INTERWORKING */
1877 break;
1878 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001879#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001880 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001881 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001882#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001883 break;
1884 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001885#ifdef CONFIG_HS20
1886 if (wpa_s->conf->hs20)
1887 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1888#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001889#ifdef CONFIG_MBO
1890 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1891#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001892 break;
1893 case 6: /* Bits 48-55 */
1894 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001895 case 7: /* Bits 56-63 */
1896 break;
1897 case 8: /* Bits 64-71 */
1898 if (wpa_s->conf->ftm_responder)
1899 *pos |= 0x40; /* Bit 70 - FTM responder */
1900 if (wpa_s->conf->ftm_initiator)
1901 *pos |= 0x80; /* Bit 71 - FTM initiator */
1902 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001903 case 9: /* Bits 72-79 */
1904#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001905 if (!wpa_s->disable_fils)
1906 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001907#endif /* CONFIG_FILS */
1908 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07001909 case 10: /* Bits 80-87 */
1910 *pos |= 0x20; /* Bit 85 - Mirrored SCS */
1911 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001912 }
1913}
1914
1915
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001916int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001917{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001918 u8 *pos = buf;
Hai Shalom899fcc72020-10-19 14:38:18 -07001919 u8 len = 11, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001920
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001921 if (len < wpa_s->extended_capa_len)
1922 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001923 if (buflen < (size_t) len + 2) {
1924 wpa_printf(MSG_INFO,
1925 "Not enough room for building extended capabilities element");
1926 return -1;
1927 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001928
1929 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001930 *pos++ = len;
1931 for (i = 0; i < len; i++, pos++) {
1932 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001933
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001934 if (i < wpa_s->extended_capa_len) {
1935 *pos &= ~wpa_s->extended_capa_mask[i];
1936 *pos |= wpa_s->extended_capa[i];
1937 }
1938 }
1939
1940 while (len > 0 && buf[1 + len] == 0) {
1941 len--;
1942 buf[1] = len;
1943 }
1944 if (len == 0)
1945 return 0;
1946
1947 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001948}
1949
1950
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001951static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1952 struct wpa_bss *test_bss)
1953{
1954 struct wpa_bss *bss;
1955
1956 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1957 if (bss == test_bss)
1958 return 1;
1959 }
1960
1961 return 0;
1962}
1963
1964
1965static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1966 struct wpa_ssid *test_ssid)
1967{
1968 struct wpa_ssid *ssid;
1969
1970 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1971 if (ssid == test_ssid)
1972 return 1;
1973 }
1974
1975 return 0;
1976}
1977
1978
1979int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1980 struct wpa_ssid *test_ssid)
1981{
1982 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1983 return 0;
1984
1985 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1986}
1987
1988
1989void wpas_connect_work_free(struct wpa_connect_work *cwork)
1990{
1991 if (cwork == NULL)
1992 return;
1993 os_free(cwork);
1994}
1995
1996
1997void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1998{
1999 struct wpa_connect_work *cwork;
2000 struct wpa_radio_work *work = wpa_s->connect_work;
2001
2002 if (!work)
2003 return;
2004
2005 wpa_s->connect_work = NULL;
2006 cwork = work->ctx;
2007 work->ctx = NULL;
2008 wpas_connect_work_free(cwork);
2009 radio_work_done(work);
2010}
2011
2012
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002013int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
2014{
2015 struct os_reltime now;
2016 u8 addr[ETH_ALEN];
2017
2018 os_get_reltime(&now);
2019 if (wpa_s->last_mac_addr_style == style &&
2020 wpa_s->last_mac_addr_change.sec != 0 &&
2021 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
2022 wpa_s->conf->rand_addr_lifetime)) {
2023 wpa_msg(wpa_s, MSG_DEBUG,
2024 "Previously selected random MAC address has not yet expired");
2025 return 0;
2026 }
2027
2028 switch (style) {
2029 case 1:
2030 if (random_mac_addr(addr) < 0)
2031 return -1;
2032 break;
2033 case 2:
2034 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2035 if (random_mac_addr_keep_oui(addr) < 0)
2036 return -1;
2037 break;
2038 default:
2039 return -1;
2040 }
2041
2042 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2043 wpa_msg(wpa_s, MSG_INFO,
2044 "Failed to set random MAC address");
2045 return -1;
2046 }
2047
2048 os_get_reltime(&wpa_s->last_mac_addr_change);
2049 wpa_s->mac_addr_changed = 1;
2050 wpa_s->last_mac_addr_style = style;
2051
2052 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2053 wpa_msg(wpa_s, MSG_INFO,
2054 "Could not update MAC address information");
2055 return -1;
2056 }
2057
2058 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2059 MAC2STR(addr));
2060
2061 return 0;
2062}
2063
2064
2065int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2066{
2067 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2068 !wpa_s->conf->preassoc_mac_addr)
2069 return 0;
2070
2071 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2072}
2073
2074
Hai Shalomc3565922019-10-28 11:58:20 -07002075static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2076{
2077#ifdef CONFIG_SAE
2078 int *groups = conf->sae_groups;
2079 int default_groups[] = { 19, 20, 21, 0 };
2080 const char *password;
2081
2082 if (!groups || groups[0] <= 0)
2083 groups = default_groups;
2084
2085 password = ssid->sae_password;
2086 if (!password)
2087 password = ssid->passphrase;
2088
Hai Shalom899fcc72020-10-19 14:38:18 -07002089 if (!password ||
2090 (conf->sae_pwe == 0 && !ssid->sae_password_id &&
2091 !sae_pk_valid_password(password)) ||
Hai Shalomfdcde762020-04-02 11:19:20 -07002092 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002093 /* PT derivation not needed */
2094 sae_deinit_pt(ssid->pt);
2095 ssid->pt = NULL;
2096 return;
2097 }
2098
2099 if (ssid->pt)
2100 return; /* PT already derived */
2101 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2102 (const u8 *) password, os_strlen(password),
2103 ssid->sae_password_id);
2104#endif /* CONFIG_SAE */
2105}
2106
2107
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002108static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2109{
2110#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2111 os_free(wpa_s->sme.sae_rejected_groups);
2112 wpa_s->sme.sae_rejected_groups = NULL;
2113#ifdef CONFIG_TESTING_OPTIONS
2114 if (wpa_s->extra_sae_rejected_groups) {
2115 int i, *groups = wpa_s->extra_sae_rejected_groups;
2116
2117 for (i = 0; groups[i]; i++) {
2118 wpa_printf(MSG_DEBUG,
2119 "TESTING: Indicate rejection of an extra SAE group %d",
2120 groups[i]);
2121 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2122 groups[i]);
2123 }
2124 }
2125#endif /* CONFIG_TESTING_OPTIONS */
2126#endif /* CONFIG_SAE && CONFIG_SME */
2127}
2128
2129
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002130static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2131
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002132/**
2133 * wpa_supplicant_associate - Request association
2134 * @wpa_s: Pointer to wpa_supplicant data
2135 * @bss: Scan results for the selected BSS, or %NULL if not available
2136 * @ssid: Configuration data for the selected network
2137 *
2138 * This function is used to request %wpa_supplicant to associate with a BSS.
2139 */
2140void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2141 struct wpa_bss *bss, struct wpa_ssid *ssid)
2142{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002143 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002144 int rand_style;
2145
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002146 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002147 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002148
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002149 /*
2150 * If we are starting a new connection, any previously pending EAPOL
2151 * RX cannot be valid anymore.
2152 */
2153 wpabuf_free(wpa_s->pending_eapol_rx);
2154 wpa_s->pending_eapol_rx = NULL;
2155
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002156 if (ssid->mac_addr == -1)
2157 rand_style = wpa_s->conf->mac_addr;
2158 else
2159 rand_style = ssid->mac_addr;
2160
Hai Shalomfdcde762020-04-02 11:19:20 -07002161 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002162 wmm_ac_clear_saved_tspecs(wpa_s);
2163 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002164 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002165#ifdef CONFIG_TESTING_OPTIONS
2166 wpa_s->testing_resend_assoc = 0;
2167#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002168
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002169 if (wpa_s->last_ssid == ssid) {
2170 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002171 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002172 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2173 wmm_ac_save_tspecs(wpa_s);
2174 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002175 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2176 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002177 }
Hai Shalomc3565922019-10-28 11:58:20 -07002178 } else {
2179#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002180 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002181 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2182#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002183 }
2184
2185 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002186 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2187 return;
2188 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002189 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002190 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2191 wpa_msg(wpa_s, MSG_INFO,
2192 "Could not restore permanent MAC address");
2193 return;
2194 }
2195 wpa_s->mac_addr_changed = 0;
2196 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2197 wpa_msg(wpa_s, MSG_INFO,
2198 "Could not update MAC address information");
2199 return;
2200 }
2201 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2202 }
2203 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002204
2205#ifdef CONFIG_IBSS_RSN
2206 ibss_rsn_deinit(wpa_s->ibss_rsn);
2207 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002208#else /* CONFIG_IBSS_RSN */
2209 if (ssid->mode == WPAS_MODE_IBSS &&
2210 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2211 wpa_msg(wpa_s, MSG_INFO,
2212 "IBSS RSN not supported in the build");
2213 return;
2214 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002215#endif /* CONFIG_IBSS_RSN */
2216
2217 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2218 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2219#ifdef CONFIG_AP
2220 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2221 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2222 "mode");
2223 return;
2224 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002225 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2226 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002227 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2228 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002229 return;
2230 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231 wpa_s->current_bss = bss;
2232#else /* CONFIG_AP */
2233 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2234 "the build");
2235#endif /* CONFIG_AP */
2236 return;
2237 }
2238
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002239 if (ssid->mode == WPAS_MODE_MESH) {
2240#ifdef CONFIG_MESH
2241 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2242 wpa_msg(wpa_s, MSG_INFO,
2243 "Driver does not support mesh mode");
2244 return;
2245 }
2246 if (bss)
2247 ssid->frequency = bss->freq;
2248 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2249 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2250 return;
2251 }
2252 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002253 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
2254 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
2255 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002256 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002257#else /* CONFIG_MESH */
2258 wpa_msg(wpa_s, MSG_ERROR,
2259 "mesh mode support not included in the build");
2260#endif /* CONFIG_MESH */
2261 return;
2262 }
2263
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002264 /*
2265 * Set WPA state machine configuration to match the selected network now
2266 * so that the information is available before wpas_start_assoc_cb()
2267 * gets called. This is needed at least for RSN pre-authentication where
2268 * candidate APs are added to a list based on scan result processing
2269 * before completion of the first association.
2270 */
2271 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2272
2273#ifdef CONFIG_DPP
2274 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2275 return;
2276#endif /* CONFIG_DPP */
2277
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002278#ifdef CONFIG_TDLS
2279 if (bss)
2280 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2281 bss->ie_len);
2282#endif /* CONFIG_TDLS */
2283
Hai Shalomc3565922019-10-28 11:58:20 -07002284#ifdef CONFIG_MBO
2285 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2286#endif /* CONFIG_MBO */
2287
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002288 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002289 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002290 sme_authenticate(wpa_s, bss, ssid);
2291 return;
2292 }
2293
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002294 if (wpa_s->connect_work) {
2295 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2296 return;
2297 }
2298
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002299 if (radio_work_pending(wpa_s, "connect")) {
2300 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2301 return;
2302 }
2303
Dmitry Shmidt29333592017-01-09 12:27:11 -08002304#ifdef CONFIG_SME
2305 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2306 /* Clear possibly set auth_alg, if any, from last attempt. */
2307 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2308 }
2309#endif /* CONFIG_SME */
2310
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002311 wpas_abort_ongoing_scan(wpa_s);
2312
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002313 cwork = os_zalloc(sizeof(*cwork));
2314 if (cwork == NULL)
2315 return;
2316
2317 cwork->bss = bss;
2318 cwork->ssid = ssid;
2319
2320 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2321 wpas_start_assoc_cb, cwork) < 0) {
2322 os_free(cwork);
2323 }
2324}
2325
2326
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002327static int bss_is_ibss(struct wpa_bss *bss)
2328{
2329 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2330 IEEE80211_CAP_IBSS;
2331}
2332
2333
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002334static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2335 const struct wpa_ssid *ssid)
2336{
2337 enum hostapd_hw_mode hw_mode;
2338 struct hostapd_hw_modes *mode = NULL;
2339 u8 channel;
2340 int i;
2341
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002342 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2343 if (hw_mode == NUM_HOSTAPD_MODES)
2344 return 0;
2345 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2346 if (wpa_s->hw.modes[i].mode == hw_mode) {
2347 mode = &wpa_s->hw.modes[i];
2348 break;
2349 }
2350 }
2351
2352 if (!mode)
2353 return 0;
2354
2355 return mode->vht_capab != 0;
2356}
2357
2358
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002359void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2360 const struct wpa_ssid *ssid,
2361 struct hostapd_freq_params *freq)
2362{
Hai Shalom81f62d82019-07-22 12:10:00 -07002363 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002364 enum hostapd_hw_mode hw_mode;
2365 struct hostapd_hw_modes *mode = NULL;
2366 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2367 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002368 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002369 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2370 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002371 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002372 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002373 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002374 int chwidth, seg0, seg1;
2375 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002376 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002377
2378 freq->freq = ssid->frequency;
2379
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002380 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2381 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2382
2383 if (ssid->mode != WPAS_MODE_IBSS)
2384 break;
2385
2386 /* Don't adjust control freq in case of fixed_freq */
2387 if (ssid->fixed_freq)
2388 break;
2389
2390 if (!bss_is_ibss(bss))
2391 continue;
2392
2393 if (ssid->ssid_len == bss->ssid_len &&
2394 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2395 wpa_printf(MSG_DEBUG,
2396 "IBSS already found in scan results, adjust control freq: %d",
2397 bss->freq);
2398 freq->freq = bss->freq;
2399 obss_scan = 0;
2400 break;
2401 }
2402 }
2403
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002404 /* For IBSS check HT_IBSS flag */
2405 if (ssid->mode == WPAS_MODE_IBSS &&
2406 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2407 return;
2408
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002409 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2410 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2411 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2412 wpa_printf(MSG_DEBUG,
2413 "IBSS: WEP/TKIP detected, do not try to enable HT");
2414 return;
2415 }
2416
2417 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002418 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2419 if (wpa_s->hw.modes[i].mode == hw_mode) {
2420 mode = &wpa_s->hw.modes[i];
2421 break;
2422 }
2423 }
2424
2425 if (!mode)
2426 return;
2427
Hai Shalomc3565922019-10-28 11:58:20 -07002428 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2429 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002430
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002431#ifdef CONFIG_HT_OVERRIDES
2432 if (ssid->disable_ht) {
2433 freq->ht_enabled = 0;
2434 return;
2435 }
2436#endif /* CONFIG_HT_OVERRIDES */
2437
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002438 freq->ht_enabled = ht_supported(mode);
2439 if (!freq->ht_enabled)
2440 return;
2441
Hai Shalomc3565922019-10-28 11:58:20 -07002442 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2443 if (is_24ghz)
2444 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002445#ifdef CONFIG_HE_OVERRIDES
2446 if (is_24ghz && ssid->disable_he)
2447 freq->he_enabled = 0;
2448#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002449
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002450 /* Setup higher BW only for 5 GHz */
2451 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2452 return;
2453
2454 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2455 pri_chan = &mode->channels[chan_idx];
2456 if (pri_chan->chan == channel)
2457 break;
2458 pri_chan = NULL;
2459 }
2460 if (!pri_chan)
2461 return;
2462
2463 /* Check primary channel flags */
2464 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2465 return;
2466
Hai Shalom74f70d42019-02-11 14:42:39 -08002467 freq->channel = pri_chan->chan;
2468
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002469#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002470 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002471#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002472 if (ssid->disable_vht)
2473 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002474#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002475 goto skip_ht40;
2476 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002477#endif /* CONFIG_HT_OVERRIDES */
2478
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002479 /* Check/setup HT40+/HT40- */
2480 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2481 if (ht40plus[j] == channel) {
2482 ht40 = 1;
2483 break;
2484 }
2485 }
2486
2487 /* Find secondary channel */
2488 for (i = 0; i < mode->num_channels; i++) {
2489 sec_chan = &mode->channels[i];
2490 if (sec_chan->chan == channel + ht40 * 4)
2491 break;
2492 sec_chan = NULL;
2493 }
2494 if (!sec_chan)
2495 return;
2496
2497 /* Check secondary channel flags */
2498 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2499 return;
2500
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002501 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002502 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2503 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002504 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002505 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2506 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002507 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002508 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002509
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002510 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002511 struct wpa_scan_results *scan_res;
2512
2513 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2514 if (scan_res == NULL) {
2515 /* Back to HT20 */
2516 freq->sec_channel_offset = 0;
2517 return;
2518 }
2519
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002520 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002521 switch (res) {
2522 case 0:
2523 /* Back to HT20 */
2524 freq->sec_channel_offset = 0;
2525 break;
2526 case 1:
2527 /* Configuration allowed */
2528 break;
2529 case 2:
2530 /* Switch pri/sec channels */
2531 freq->freq = hw_get_freq(mode, sec_chan->chan);
2532 freq->sec_channel_offset = -freq->sec_channel_offset;
2533 freq->channel = sec_chan->chan;
2534 break;
2535 default:
2536 freq->sec_channel_offset = 0;
2537 break;
2538 }
2539
2540 wpa_scan_results_free(scan_res);
2541 }
2542
Hai Shalom74f70d42019-02-11 14:42:39 -08002543#ifdef CONFIG_HT_OVERRIDES
2544skip_ht40:
2545#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002546 wpa_printf(MSG_DEBUG,
2547 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2548 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002549
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002550 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002551 return;
2552
2553 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002554 if (ssid->mode == WPAS_MODE_IBSS &&
2555 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002556 return;
2557
2558 vht_freq = *freq;
2559
Paul Stewart092955c2017-02-06 09:13:09 -08002560#ifdef CONFIG_VHT_OVERRIDES
2561 if (ssid->disable_vht) {
2562 freq->vht_enabled = 0;
2563 return;
2564 }
2565#endif /* CONFIG_VHT_OVERRIDES */
2566
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002567 vht_freq.vht_enabled = vht_supported(mode);
2568 if (!vht_freq.vht_enabled)
2569 return;
2570
Hai Shalomfdcde762020-04-02 11:19:20 -07002571 /* Enable HE with VHT for 5 GHz */
2572 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002573
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002574 /* setup center_freq1, bandwidth */
2575 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2576 if (freq->channel >= vht80[j] &&
2577 freq->channel < vht80[j] + 16)
2578 break;
2579 }
2580
2581 if (j == ARRAY_SIZE(vht80))
2582 return;
2583
2584 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2585 struct hostapd_channel_data *chan;
2586
2587 chan = hw_get_channel_chan(mode, i, NULL);
2588 if (!chan)
2589 return;
2590
2591 /* Back to HT configuration if channel not usable */
2592 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2593 return;
2594 }
2595
Hai Shalom81f62d82019-07-22 12:10:00 -07002596 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002597 seg0 = vht80[j] + 6;
2598 seg1 = 0;
2599
Hai Shalom81f62d82019-07-22 12:10:00 -07002600 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002601 /* setup center_freq2, bandwidth */
2602 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2603 /* Only accept 80 MHz segments separated by a gap */
2604 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2605 continue;
2606 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2607 struct hostapd_channel_data *chan;
2608
2609 chan = hw_get_channel_chan(mode, i, NULL);
2610 if (!chan)
2611 continue;
2612
2613 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2614 HOSTAPD_CHAN_NO_IR |
2615 HOSTAPD_CHAN_RADAR))
2616 continue;
2617
2618 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002619 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002620 vht_caps |=
2621 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2622 seg1 = vht80[k] + 6;
2623 }
2624
Hai Shalom81f62d82019-07-22 12:10:00 -07002625 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002626 break;
2627 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002628 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002629 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002630 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002631 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2632 seg0 = 50;
2633 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002634 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002635 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2636 seg0 = 114;
2637 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002638 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2639 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002640 seg0 = vht80[j] + 2;
2641#ifdef CONFIG_HT_OVERRIDES
2642 if (ssid->disable_ht40)
2643 seg0 = 0;
2644#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002645 }
2646
Hai Shalomfdcde762020-04-02 11:19:20 -07002647#ifdef CONFIG_HE_OVERRIDES
2648 if (ssid->disable_he) {
2649 vht_freq.he_enabled = 0;
2650 freq->he_enabled = 0;
2651 }
2652#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002653 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002654 freq->channel, ssid->enable_edmg,
2655 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002656 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002657 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002658 chwidth, seg0, seg1, vht_caps,
2659 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002660 return;
2661
2662 *freq = vht_freq;
2663
2664 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2665 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002666}
2667
2668
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002669#ifdef CONFIG_FILS
2670static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2671 size_t ie_buf_len)
2672{
2673 struct fils_hlp_req *req;
2674 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2675 const u8 *pos;
2676 u8 *buf = ie_buf;
2677
2678 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2679 list) {
2680 rem_len = ie_buf_len - ie_len;
2681 pos = wpabuf_head(req->pkt);
2682 hdr_len = 1 + 2 * ETH_ALEN + 6;
2683 hlp_len = wpabuf_len(req->pkt);
2684
2685 if (rem_len < 2 + hdr_len + hlp_len) {
2686 wpa_printf(MSG_ERROR,
2687 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2688 (unsigned long) rem_len,
2689 (unsigned long) (2 + hdr_len + hlp_len));
2690 break;
2691 }
2692
2693 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2694 /* Element ID */
2695 *buf++ = WLAN_EID_EXTENSION;
2696 /* Length */
2697 *buf++ = len;
2698 /* Element ID Extension */
2699 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2700 /* Destination MAC address */
2701 os_memcpy(buf, req->dst, ETH_ALEN);
2702 buf += ETH_ALEN;
2703 /* Source MAC address */
2704 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2705 buf += ETH_ALEN;
2706 /* LLC/SNAP Header */
2707 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2708 buf += 6;
2709 /* HLP Packet */
2710 os_memcpy(buf, pos, len - hdr_len);
2711 buf += len - hdr_len;
2712 pos += len - hdr_len;
2713
2714 hlp_len -= len - hdr_len;
2715 ie_len += 2 + len;
2716 rem_len -= 2 + len;
2717
2718 while (hlp_len) {
2719 len = (hlp_len > 255) ? 255 : hlp_len;
2720 if (rem_len < 2 + len)
2721 break;
2722 *buf++ = WLAN_EID_FRAGMENT;
2723 *buf++ = len;
2724 os_memcpy(buf, pos, len);
2725 buf += len;
2726 pos += len;
2727
2728 hlp_len -= len;
2729 ie_len += 2 + len;
2730 rem_len -= 2 + len;
2731 }
2732 }
2733
2734 return ie_len;
2735}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002736
2737
2738int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2739{
2740 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2741 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2742 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2743 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2744}
2745
2746
2747int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2748{
2749#ifdef CONFIG_FILS_SK_PFS
2750 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2751 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2752#else /* CONFIG_FILS_SK_PFS */
2753 return 0;
2754#endif /* CONFIG_FILS_SK_PFS */
2755}
2756
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002757#endif /* CONFIG_FILS */
2758
2759
2760static u8 * wpas_populate_assoc_ies(
2761 struct wpa_supplicant *wpa_s,
2762 struct wpa_bss *bss, struct wpa_ssid *ssid,
2763 struct wpa_driver_associate_params *params,
2764 enum wpa_drv_update_connect_params_mask *mask)
2765{
2766 u8 *wpa_ie;
2767 size_t max_wpa_ie_len = 500;
2768 size_t wpa_ie_len;
2769 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002770#ifdef CONFIG_MBO
2771 const u8 *mbo_ie;
2772#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302773#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2774 int pmksa_cached = 0;
2775#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002776#ifdef CONFIG_FILS
2777 const u8 *realm, *username, *rrk;
2778 size_t realm_len, username_len, rrk_len;
2779 u16 next_seq_num;
2780 struct fils_hlp_req *req;
2781
2782 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2783 list) {
2784 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2785 2 + 2 * wpabuf_len(req->pkt) / 255;
2786 }
2787#endif /* CONFIG_FILS */
2788
2789 wpa_ie = os_malloc(max_wpa_ie_len);
2790 if (!wpa_ie) {
2791 wpa_printf(MSG_ERROR,
2792 "Failed to allocate connect IE buffer for %lu bytes",
2793 (unsigned long) max_wpa_ie_len);
2794 return NULL;
2795 }
2796
2797 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2798 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2799 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2800 int try_opportunistic;
2801 const u8 *cache_id = NULL;
2802
2803 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2804 wpa_s->conf->okc :
2805 ssid->proactive_key_caching) &&
2806 (ssid->proto & WPA_PROTO_RSN);
2807#ifdef CONFIG_FILS
2808 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2809 cache_id = wpa_bss_get_fils_cache_id(bss);
2810#endif /* CONFIG_FILS */
2811 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2812 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002813 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002814 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302815#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2816 pmksa_cached = 1;
2817#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002818 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002819 wpa_ie_len = max_wpa_ie_len;
2820 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2821 wpa_ie, &wpa_ie_len)) {
2822 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2823 "key management and encryption suites");
2824 os_free(wpa_ie);
2825 return NULL;
2826 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002827#ifdef CONFIG_HS20
2828 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2829 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2830 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2831 wpa_ie_len = max_wpa_ie_len;
2832 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2833 wpa_ie, &wpa_ie_len)) {
2834 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2835 "key management and encryption suites");
2836 os_free(wpa_ie);
2837 return NULL;
2838 }
2839#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002840 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2841 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2842 /*
2843 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2844 * use non-WPA since the scan results did not indicate that the
2845 * AP is using WPA or WPA2.
2846 */
2847 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2848 wpa_ie_len = 0;
2849 wpa_s->wpa_proto = 0;
2850 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2851 wpa_ie_len = max_wpa_ie_len;
2852 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2853 wpa_ie, &wpa_ie_len)) {
2854 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2855 "key management and encryption suites (no "
2856 "scan results)");
2857 os_free(wpa_ie);
2858 return NULL;
2859 }
2860#ifdef CONFIG_WPS
2861 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2862 struct wpabuf *wps_ie;
2863 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2864 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2865 wpa_ie_len = wpabuf_len(wps_ie);
2866 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2867 } else
2868 wpa_ie_len = 0;
2869 wpabuf_free(wps_ie);
2870 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2871 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2872 params->wps = WPS_MODE_PRIVACY;
2873 else
2874 params->wps = WPS_MODE_OPEN;
2875 wpa_s->wpa_proto = 0;
2876#endif /* CONFIG_WPS */
2877 } else {
2878 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2879 wpa_ie_len = 0;
2880 wpa_s->wpa_proto = 0;
2881 }
2882
2883#ifdef IEEE8021X_EAPOL
2884 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2885 if (ssid->leap) {
2886 if (ssid->non_leap == 0)
2887 algs = WPA_AUTH_ALG_LEAP;
2888 else
2889 algs |= WPA_AUTH_ALG_LEAP;
2890 }
2891 }
2892
2893#ifdef CONFIG_FILS
2894 /* Clear FILS association */
2895 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2896
2897 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2898 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2899 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2900 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002901 &next_seq_num, &rrk, &rrk_len) == 0 &&
2902 (!wpa_s->last_con_fail_realm ||
2903 wpa_s->last_con_fail_realm_len != realm_len ||
2904 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002905 algs = WPA_AUTH_ALG_FILS;
2906 params->fils_erp_username = username;
2907 params->fils_erp_username_len = username_len;
2908 params->fils_erp_realm = realm;
2909 params->fils_erp_realm_len = realm_len;
2910 params->fils_erp_next_seq_num = next_seq_num;
2911 params->fils_erp_rrk = rrk;
2912 params->fils_erp_rrk_len = rrk_len;
2913
2914 if (mask)
2915 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302916 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2917 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2918 pmksa_cached) {
2919 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002920 }
2921#endif /* CONFIG_FILS */
2922#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002923#ifdef CONFIG_SAE
2924 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2925 algs = WPA_AUTH_ALG_SAE;
2926#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002927
2928 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2929 if (ssid->auth_alg) {
2930 algs = ssid->auth_alg;
2931 wpa_dbg(wpa_s, MSG_DEBUG,
2932 "Overriding auth_alg selection: 0x%x", algs);
2933 }
2934
Hai Shalom5f92bc92019-04-18 11:54:11 -07002935#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302936 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07002937 wpa_dbg(wpa_s, MSG_DEBUG,
2938 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2939 algs = WPA_AUTH_ALG_OPEN;
2940 }
2941#endif /* CONFIG_SAE */
2942
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002943#ifdef CONFIG_P2P
2944 if (wpa_s->global->p2p) {
2945 u8 *pos;
2946 size_t len;
2947 int res;
2948 pos = wpa_ie + wpa_ie_len;
2949 len = max_wpa_ie_len - wpa_ie_len;
2950 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2951 ssid->p2p_group);
2952 if (res >= 0)
2953 wpa_ie_len += res;
2954 }
2955
2956 wpa_s->cross_connect_disallowed = 0;
2957 if (bss) {
2958 struct wpabuf *p2p;
2959 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2960 if (p2p) {
2961 wpa_s->cross_connect_disallowed =
2962 p2p_get_cross_connect_disallowed(p2p);
2963 wpabuf_free(p2p);
2964 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2965 "connection",
2966 wpa_s->cross_connect_disallowed ?
2967 "disallows" : "allows");
2968 }
2969 }
2970
2971 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2972#endif /* CONFIG_P2P */
2973
2974 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002975 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002976 wpa_ie + wpa_ie_len,
2977 max_wpa_ie_len -
2978 wpa_ie_len);
2979 }
2980
2981 /*
2982 * Workaround: Add Extended Capabilities element only if the AP
2983 * included this element in Beacon/Probe Response frames. Some older
2984 * APs seem to have interoperability issues if this element is
2985 * included, so while the standard may require us to include the
2986 * element in all cases, it is justifiable to skip it to avoid
2987 * interoperability issues.
2988 */
2989 if (ssid->p2p_group)
2990 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2991 else
2992 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2993
2994 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2995 u8 ext_capab[18];
2996 int ext_capab_len;
2997 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2998 sizeof(ext_capab));
2999 if (ext_capab_len > 0 &&
3000 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
3001 u8 *pos = wpa_ie;
3002 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
3003 pos += 2 + pos[1];
3004 os_memmove(pos + ext_capab_len, pos,
3005 wpa_ie_len - (pos - wpa_ie));
3006 wpa_ie_len += ext_capab_len;
3007 os_memcpy(pos, ext_capab, ext_capab_len);
3008 }
3009 }
3010
3011#ifdef CONFIG_HS20
3012 if (is_hs20_network(wpa_s, ssid, bss)) {
3013 struct wpabuf *hs20;
3014
Roshan Pius3a1667e2018-07-03 15:17:14 -07003015 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003016 if (hs20) {
3017 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
3018 size_t len;
3019
Hai Shalom74f70d42019-02-11 14:42:39 -08003020 wpas_hs20_add_indication(hs20, pps_mo_id,
3021 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07003022 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003023 len = max_wpa_ie_len - wpa_ie_len;
3024 if (wpabuf_len(hs20) <= len) {
3025 os_memcpy(wpa_ie + wpa_ie_len,
3026 wpabuf_head(hs20), wpabuf_len(hs20));
3027 wpa_ie_len += wpabuf_len(hs20);
3028 }
3029 wpabuf_free(hs20);
3030
3031 hs20_configure_frame_filters(wpa_s);
3032 }
3033 }
3034#endif /* CONFIG_HS20 */
3035
3036 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3037 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3038 size_t len;
3039
3040 len = max_wpa_ie_len - wpa_ie_len;
3041 if (wpabuf_len(buf) <= len) {
3042 os_memcpy(wpa_ie + wpa_ie_len,
3043 wpabuf_head(buf), wpabuf_len(buf));
3044 wpa_ie_len += wpabuf_len(buf);
3045 }
3046 }
3047
3048#ifdef CONFIG_FST
3049 if (wpa_s->fst_ies) {
3050 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3051
3052 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3053 os_memcpy(wpa_ie + wpa_ie_len,
3054 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3055 wpa_ie_len += fst_ies_len;
3056 }
3057 }
3058#endif /* CONFIG_FST */
3059
3060#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003061 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003062 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003063 int len;
3064
3065 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003066 max_wpa_ie_len - wpa_ie_len,
3067 !!mbo_attr_from_mbo_ie(mbo_ie,
3068 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003069 if (len >= 0)
3070 wpa_ie_len += len;
3071 }
3072#endif /* CONFIG_MBO */
3073
3074#ifdef CONFIG_FILS
3075 if (algs == WPA_AUTH_ALG_FILS) {
3076 size_t len;
3077
3078 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3079 max_wpa_ie_len - wpa_ie_len);
3080 wpa_ie_len += len;
3081 }
3082#endif /* CONFIG_FILS */
3083
3084#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003085#ifdef CONFIG_TESTING_OPTIONS
3086 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3087 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3088 } else
3089#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003090 if (algs == WPA_AUTH_ALG_OPEN &&
3091 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3092 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003093 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003094
Roshan Pius3a1667e2018-07-03 15:17:14 -07003095 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003096 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003097 } else if (wpa_s->assoc_status_code ==
3098 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003099 if (wpa_s->last_owe_group == 19)
3100 group = 20;
3101 else if (wpa_s->last_owe_group == 20)
3102 group = 21;
3103 else
3104 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003105 } else {
3106 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003107 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003108
Roshan Pius3a1667e2018-07-03 15:17:14 -07003109 wpa_s->last_owe_group = group;
3110 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003111 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3112 if (owe_ie &&
3113 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3114 os_memcpy(wpa_ie + wpa_ie_len,
3115 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3116 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003117 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003118 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003119 }
3120#endif /* CONFIG_OWE */
3121
Hai Shalom021b0b52019-04-10 11:17:58 -07003122#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003123 if (DPP_VERSION > 1 &&
3124 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003125 ssid->dpp_netaccesskey &&
3126 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003127 struct rsn_pmksa_cache_entry *pmksa;
3128
3129 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3130 if (!pmksa || !pmksa->dpp_pfs)
3131 goto pfs_fail;
3132
Hai Shalom021b0b52019-04-10 11:17:58 -07003133 dpp_pfs_free(wpa_s->dpp_pfs);
3134 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3135 ssid->dpp_netaccesskey_len);
3136 if (!wpa_s->dpp_pfs) {
3137 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3138 /* Try to continue without PFS */
3139 goto pfs_fail;
3140 }
3141 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3142 max_wpa_ie_len - wpa_ie_len) {
3143 os_memcpy(wpa_ie + wpa_ie_len,
3144 wpabuf_head(wpa_s->dpp_pfs->ie),
3145 wpabuf_len(wpa_s->dpp_pfs->ie));
3146 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3147 }
3148 }
3149pfs_fail:
3150#endif /* CONFIG_DPP2 */
3151
Roshan Pius3a1667e2018-07-03 15:17:14 -07003152#ifdef CONFIG_IEEE80211R
3153 /*
3154 * Add MDIE under these conditions: the network profile allows FT,
3155 * the AP supports FT, and the mobility domain ID matches.
3156 */
3157 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3158 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3159
3160 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3161 size_t len = 0;
3162 const u8 *md = mdie + 2;
3163 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3164
3165 if (os_memcmp(md, wpa_md,
3166 MOBILITY_DOMAIN_ID_LEN) == 0) {
3167 /* Add mobility domain IE */
3168 len = wpa_ft_add_mdie(
3169 wpa_s->wpa, wpa_ie + wpa_ie_len,
3170 max_wpa_ie_len - wpa_ie_len, mdie);
3171 wpa_ie_len += len;
3172 }
3173#ifdef CONFIG_SME
3174 if (len > 0 && wpa_s->sme.ft_used &&
3175 wpa_sm_has_ptk(wpa_s->wpa)) {
3176 wpa_dbg(wpa_s, MSG_DEBUG,
3177 "SME: Trying to use FT over-the-air");
3178 algs |= WPA_AUTH_ALG_FT;
3179 }
3180#endif /* CONFIG_SME */
3181 }
3182 }
3183#endif /* CONFIG_IEEE80211R */
3184
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003185#ifdef CONFIG_TESTING_OPTIONS
3186 if (wpa_s->rsnxe_override_assoc &&
3187 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3188 max_wpa_ie_len - wpa_ie_len) {
3189 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3190 os_memcpy(wpa_ie + wpa_ie_len,
3191 wpabuf_head(wpa_s->rsnxe_override_assoc),
3192 wpabuf_len(wpa_s->rsnxe_override_assoc));
3193 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3194 } else
3195#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003196 if (wpa_s->rsnxe_len > 0 &&
3197 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3198 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3199 wpa_ie_len += wpa_s->rsnxe_len;
3200 }
3201
Hai Shalom899fcc72020-10-19 14:38:18 -07003202 if (bss && wpa_s->robust_av.valid_config) {
3203 struct wpabuf *mscs_ie;
3204 size_t mscs_ie_len, buf_len;
3205
3206 if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS))
3207 goto mscs_fail;
3208
3209 buf_len = 3 + /* MSCS descriptor IE header */
3210 1 + /* Request type */
3211 2 + /* User priority control */
3212 4 + /* Stream timeout */
3213 3 + /* TCLAS Mask IE header */
3214 wpa_s->robust_av.frame_classifier_len;
3215 mscs_ie = wpabuf_alloc(buf_len);
3216 if (!mscs_ie) {
3217 wpa_printf(MSG_INFO,
3218 "MSCS: Failed to allocate MSCS IE");
3219 goto mscs_fail;
3220 }
3221
3222 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
3223 if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) {
3224 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
3225 mscs_ie_len = wpabuf_len(mscs_ie);
3226 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie),
3227 mscs_ie_len);
3228 wpa_ie_len += mscs_ie_len;
3229 }
3230
3231 wpabuf_free(mscs_ie);
3232 }
3233mscs_fail:
3234
Hai Shalom74f70d42019-02-11 14:42:39 -08003235 if (ssid->multi_ap_backhaul_sta) {
3236 size_t multi_ap_ie_len;
3237
3238 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3239 max_wpa_ie_len - wpa_ie_len,
3240 MULTI_AP_BACKHAUL_STA);
3241 if (multi_ap_ie_len == 0) {
3242 wpa_printf(MSG_ERROR,
3243 "Multi-AP: Failed to build Multi-AP IE");
3244 os_free(wpa_ie);
3245 return NULL;
3246 }
3247 wpa_ie_len += multi_ap_ie_len;
3248 }
3249
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003250 params->wpa_ie = wpa_ie;
3251 params->wpa_ie_len = wpa_ie_len;
3252 params->auth_alg = algs;
3253 if (mask)
3254 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3255
3256 return wpa_ie;
3257}
3258
3259
Hai Shalomc3565922019-10-28 11:58:20 -07003260#ifdef CONFIG_OWE
3261static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3262{
3263 struct wpa_driver_associate_params params;
3264 u8 *wpa_ie;
3265
3266 os_memset(&params, 0, sizeof(params));
3267 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3268 wpa_s->current_ssid, &params, NULL);
3269 if (!wpa_ie)
3270 return;
3271
3272 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3273 os_free(wpa_ie);
3274}
3275#endif /* CONFIG_OWE */
3276
3277
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003278#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3279static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3280{
3281 struct wpa_driver_associate_params params;
3282 enum wpa_drv_update_connect_params_mask mask = 0;
3283 u8 *wpa_ie;
3284
3285 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3286 return; /* nothing to do */
3287
3288 os_memset(&params, 0, sizeof(params));
3289 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3290 wpa_s->current_ssid, &params, &mask);
3291 if (!wpa_ie)
3292 return;
3293
3294 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3295 os_free(wpa_ie);
3296 return;
3297 }
3298
3299 wpa_s->auth_alg = params.auth_alg;
3300 wpa_drv_update_connect_params(wpa_s, &params, mask);
3301 os_free(wpa_ie);
3302}
3303#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3304
3305
Hai Shalomc3565922019-10-28 11:58:20 -07003306static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3307{
3308 if (!edmg_ie || edmg_ie[1] < 6)
3309 return 0;
3310 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3311}
3312
3313
3314static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3315{
3316 if (!edmg_ie || edmg_ie[1] < 6)
3317 return 0;
3318 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3319}
3320
3321
3322/* Returns the intersection of two EDMG configurations.
3323 * Note: The current implementation is limited to CB2 only (CB1 included),
3324 * i.e., the implementation supports up to 2 contiguous channels.
3325 * For supporting non-contiguous (aggregated) channels and for supporting
3326 * CB3 and above, this function will need to be extended.
3327 */
3328static struct ieee80211_edmg_config
3329get_edmg_intersection(struct ieee80211_edmg_config a,
3330 struct ieee80211_edmg_config b,
3331 u8 primary_channel)
3332{
3333 struct ieee80211_edmg_config result;
3334 int i, contiguous = 0;
3335 int max_contiguous = 0;
3336
3337 result.channels = b.channels & a.channels;
3338 if (!result.channels) {
3339 wpa_printf(MSG_DEBUG,
3340 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3341 a.channels, b.channels);
3342 goto fail;
3343 }
3344
3345 if (!(result.channels & BIT(primary_channel - 1))) {
3346 wpa_printf(MSG_DEBUG,
3347 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3348 primary_channel, result.channels);
3349 goto fail;
3350 }
3351
3352 /* Find max contiguous channels */
3353 for (i = 0; i < 6; i++) {
3354 if (result.channels & BIT(i))
3355 contiguous++;
3356 else
3357 contiguous = 0;
3358
3359 if (contiguous > max_contiguous)
3360 max_contiguous = contiguous;
3361 }
3362
3363 /* Assuming AP and STA supports ONLY contiguous channels,
3364 * bw configuration can have value between 4-7.
3365 */
3366 if ((b.bw_config < a.bw_config))
3367 result.bw_config = b.bw_config;
3368 else
3369 result.bw_config = a.bw_config;
3370
3371 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3372 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3373 wpa_printf(MSG_DEBUG,
3374 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3375 max_contiguous);
3376 goto fail;
3377 }
3378
3379 return result;
3380
3381fail:
3382 result.channels = 0;
3383 result.bw_config = 0;
3384 return result;
3385}
3386
3387
3388static struct ieee80211_edmg_config
3389get_supported_edmg(struct wpa_supplicant *wpa_s,
3390 struct hostapd_freq_params *freq,
3391 struct ieee80211_edmg_config request_edmg)
3392{
3393 enum hostapd_hw_mode hw_mode;
3394 struct hostapd_hw_modes *mode = NULL;
3395 u8 primary_channel;
3396
3397 if (!wpa_s->hw.modes)
3398 goto fail;
3399
3400 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3401 if (hw_mode == NUM_HOSTAPD_MODES)
3402 goto fail;
3403
Hai Shalomfdcde762020-04-02 11:19:20 -07003404 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003405 if (!mode)
3406 goto fail;
3407
3408 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3409
3410fail:
3411 request_edmg.channels = 0;
3412 request_edmg.bw_config = 0;
3413 return request_edmg;
3414}
3415
3416
Hai Shalom021b0b52019-04-10 11:17:58 -07003417#ifdef CONFIG_MBO
3418void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3419{
3420 struct wpa_driver_associate_params params;
3421 u8 *wpa_ie;
3422
3423 /*
3424 * Update MBO connect params only in case of change of MBO attributes
3425 * when connected, if the AP support MBO.
3426 */
3427
3428 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3429 !wpa_s->current_bss ||
3430 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3431 return;
3432
3433 os_memset(&params, 0, sizeof(params));
3434 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3435 wpa_s->current_ssid, &params, NULL);
3436 if (!wpa_ie)
3437 return;
3438
3439 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3440 os_free(wpa_ie);
3441}
3442#endif /* CONFIG_MBO */
3443
3444
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003445static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3446{
3447 struct wpa_connect_work *cwork = work->ctx;
3448 struct wpa_bss *bss = cwork->bss;
3449 struct wpa_ssid *ssid = cwork->ssid;
3450 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003451 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003452 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003453 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003454 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003455 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003456#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003457 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003458#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003459 int assoc_failed = 0;
3460 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003461 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003462#ifdef CONFIG_HT_OVERRIDES
3463 struct ieee80211_ht_capabilities htcaps;
3464 struct ieee80211_ht_capabilities htcaps_mask;
3465#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003466#ifdef CONFIG_VHT_OVERRIDES
3467 struct ieee80211_vht_capabilities vhtcaps;
3468 struct ieee80211_vht_capabilities vhtcaps_mask;
3469#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003470
3471 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003472 if (work->started) {
3473 wpa_s->connect_work = NULL;
3474
3475 /* cancel possible auth. timeout */
3476 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3477 NULL);
3478 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003479 wpas_connect_work_free(cwork);
3480 return;
3481 }
3482
3483 wpa_s->connect_work = work;
3484
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003485 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3486 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003487 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3488 wpas_connect_work_done(wpa_s);
3489 return;
3490 }
3491
Dmitry Shmidte4663042016-04-04 10:07:49 -07003492 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003493 os_memset(&params, 0, sizeof(params));
3494 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003495 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003496 if (bss &&
3497 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003498#ifdef CONFIG_IEEE80211R
3499 const u8 *ie, *md = NULL;
3500#endif /* CONFIG_IEEE80211R */
3501 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3502 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3503 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3504 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3505 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3506 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3507 if (bssid_changed)
3508 wpas_notify_bssid_changed(wpa_s);
3509#ifdef CONFIG_IEEE80211R
3510 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3511 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3512 md = ie + 2;
3513 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3514 if (md) {
3515 /* Prepare for the next transition */
3516 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3517 }
3518#endif /* CONFIG_IEEE80211R */
3519#ifdef CONFIG_WPS
3520 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3521 wpa_s->conf->ap_scan == 2 &&
3522 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3523 /* Use ap_scan==1 style network selection to find the network
3524 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003525 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003526 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527 wpa_s->reassociate = 1;
3528 wpa_supplicant_req_scan(wpa_s, 0, 0);
3529 return;
3530#endif /* CONFIG_WPS */
3531 } else {
3532 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3533 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003534 if (bss)
3535 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3536 else
3537 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003538 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003539 if (!wpa_s->pno)
3540 wpa_supplicant_cancel_sched_scan(wpa_s);
3541
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003542 wpa_supplicant_cancel_scan(wpa_s);
3543
3544 /* Starting new association, so clear the possibly used WPA IE from the
3545 * previous association. */
3546 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003547 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3548 wpa_s->rsnxe_len = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -07003549 wpa_s->mscs_setup_done = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003550
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003551 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3552 if (!wpa_ie) {
3553 wpas_connect_work_done(wpa_s);
3554 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003555 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003557 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3558 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003559 cipher_pairwise = wpa_s->pairwise_cipher;
3560 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003561 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003562 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3563 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3564 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3565 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003566#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003567 if (wpa_set_wep_keys(wpa_s, ssid)) {
3568 use_crypt = 1;
3569 wep_keys_set = 1;
3570 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003571#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003572 }
3573 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3574 use_crypt = 0;
3575
3576#ifdef IEEE8021X_EAPOL
3577 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3578 if ((ssid->eapol_flags &
3579 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3580 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3581 !wep_keys_set) {
3582 use_crypt = 0;
3583 } else {
3584 /* Assume that dynamic WEP-104 keys will be used and
3585 * set cipher suites in order for drivers to expect
3586 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003587 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003588 }
3589 }
3590#endif /* IEEE8021X_EAPOL */
3591
3592 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3593 /* Set the key before (and later after) association */
3594 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3595 }
3596
3597 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3598 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003599 params.ssid = bss->ssid;
3600 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003601 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3602 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003603 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3604 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003605 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003606 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003607 ssid->bssid_set,
3608 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003609 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003610 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003611 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003612 params.bssid_hint = bss->bssid;
3613 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003614 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003615 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003616 if (ssid->bssid_hint_set)
3617 params.bssid_hint = ssid->bssid_hint;
3618
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003619 params.ssid = ssid->ssid;
3620 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003621 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003622 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003623
3624 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3625 wpa_s->conf->ap_scan == 2) {
3626 params.bssid = ssid->bssid;
3627 params.fixed_bssid = 1;
3628 }
3629
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003630 /* Initial frequency for IBSS/mesh */
3631 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003632 ssid->frequency > 0 && params.freq.freq == 0)
3633 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003634
3635 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003636 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003637 if (ssid->beacon_int)
3638 params.beacon_int = ssid->beacon_int;
3639 else
3640 params.beacon_int = wpa_s->conf->beacon_int;
3641 }
3642
Hai Shalomc3565922019-10-28 11:58:20 -07003643 if (bss && ssid->enable_edmg)
3644 edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len,
3645 WLAN_EID_EXT_EDMG_OPERATION);
3646 else
3647 edmg_ie_oper = NULL;
3648
3649 if (edmg_ie_oper) {
3650 params.freq.edmg.channels =
3651 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3652 params.freq.edmg.bw_config =
3653 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3654 wpa_printf(MSG_DEBUG,
3655 "AP supports EDMG channels 0x%x, bw_config %d",
3656 params.freq.edmg.channels,
3657 params.freq.edmg.bw_config);
3658
3659 /* User may ask for specific EDMG channel for EDMG connection
3660 * (must be supported by AP)
3661 */
3662 if (ssid->edmg_channel) {
3663 struct ieee80211_edmg_config configured_edmg;
3664 enum hostapd_hw_mode hw_mode;
3665 u8 primary_channel;
3666
3667 hw_mode = ieee80211_freq_to_chan(bss->freq,
3668 &primary_channel);
3669 if (hw_mode == NUM_HOSTAPD_MODES)
3670 goto edmg_fail;
3671
3672 hostapd_encode_edmg_chan(ssid->enable_edmg,
3673 ssid->edmg_channel,
3674 primary_channel,
3675 &configured_edmg);
3676
3677 if (ieee802_edmg_is_allowed(params.freq.edmg,
3678 configured_edmg)) {
3679 params.freq.edmg = configured_edmg;
3680 wpa_printf(MSG_DEBUG,
3681 "Use EDMG channel %d for connection",
3682 ssid->edmg_channel);
3683 } else {
3684 edmg_fail:
3685 params.freq.edmg.channels = 0;
3686 params.freq.edmg.bw_config = 0;
3687 wpa_printf(MSG_WARNING,
3688 "EDMG channel %d not supported by AP, fallback to DMG",
3689 ssid->edmg_channel);
3690 }
3691 }
3692
3693 if (params.freq.edmg.channels) {
3694 wpa_printf(MSG_DEBUG,
3695 "EDMG before: channels 0x%x, bw_config %d",
3696 params.freq.edmg.channels,
3697 params.freq.edmg.bw_config);
3698 params.freq.edmg = get_supported_edmg(wpa_s,
3699 &params.freq,
3700 params.freq.edmg);
3701 wpa_printf(MSG_DEBUG,
3702 "EDMG after: channels 0x%x, bw_config %d",
3703 params.freq.edmg.channels,
3704 params.freq.edmg.bw_config);
3705 }
3706 }
3707
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708 params.pairwise_suite = cipher_pairwise;
3709 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003710 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003711 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003712 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003713 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003714 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003715 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003716#ifdef CONFIG_WEP
3717 {
3718 int i;
3719
3720 for (i = 0; i < NUM_WEP_KEYS; i++) {
3721 if (ssid->wep_key_len[i])
3722 params.wep_key[i] = ssid->wep_key[i];
3723 params.wep_key_len[i] = ssid->wep_key_len[i];
3724 }
3725 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003726 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003727#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003728
Hai Shalom74f70d42019-02-11 14:42:39 -08003729 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003730 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3731 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003732 params.passphrase = ssid->passphrase;
3733 if (ssid->psk_set)
3734 params.psk = ssid->psk;
3735 }
3736
Hai Shalom74f70d42019-02-11 14:42:39 -08003737 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3738 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3739 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3740 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3741 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003742 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003743
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003744 if (wpa_s->conf->key_mgmt_offload) {
3745 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3746 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003747 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3748 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003749 params.req_key_mgmt_offload =
3750 ssid->proactive_key_caching < 0 ?
3751 wpa_s->conf->okc : ssid->proactive_key_caching;
3752 else
3753 params.req_key_mgmt_offload = 1;
3754
3755 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3756 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3757 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3758 ssid->psk_set)
3759 params.psk = ssid->psk;
3760 }
3761
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003762 params.drop_unencrypted = use_crypt;
3763
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003764 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003765 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003766 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3767 struct wpa_ie_data ie;
3768 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3769 ie.capabilities &
3770 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3771 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3772 "MFP: require MFP");
3773 params.mgmt_frame_protection =
3774 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003775#ifdef CONFIG_OWE
3776 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3777 !ssid->owe_only) {
3778 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3779#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003780 }
3781 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003782
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003783 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003784
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003785 if (wpa_s->p2pdev->set_sta_uapsd)
3786 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003787 else
3788 params.uapsd = -1;
3789
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003790#ifdef CONFIG_HT_OVERRIDES
3791 os_memset(&htcaps, 0, sizeof(htcaps));
3792 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3793 params.htcaps = (u8 *) &htcaps;
3794 params.htcaps_mask = (u8 *) &htcaps_mask;
3795 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3796#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003797#ifdef CONFIG_VHT_OVERRIDES
3798 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3799 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3800 params.vhtcaps = &vhtcaps;
3801 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003802 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003803#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003804#ifdef CONFIG_HE_OVERRIDES
3805 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3806#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003807
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003808#ifdef CONFIG_P2P
3809 /*
3810 * If multi-channel concurrency is not supported, check for any
3811 * frequency conflict. In case of any frequency conflict, remove the
3812 * least prioritized connection.
3813 */
3814 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003815 int freq, num;
3816 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003817 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003818 wpa_printf(MSG_DEBUG,
3819 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003820 freq, params.freq.freq);
3821 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003822 wpa_s, params.freq.freq, ssid) < 0) {
3823 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003824 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003825 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003826 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003827 }
3828 }
3829#endif /* CONFIG_P2P */
3830
Dmitry Shmidte4663042016-04-04 10:07:49 -07003831 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3832 wpa_s->current_ssid)
3833 params.prev_bssid = prev_bssid;
3834
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003835 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003836 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003837 if (ret < 0) {
3838 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3839 "failed");
3840 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3841 /*
3842 * The driver is known to mean what is saying, so we
3843 * can stop right here; the association will not
3844 * succeed.
3845 */
3846 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Roger Wang4c09cc92020-11-05 18:57:12 +08003847 wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
3848 wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003849 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003850 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3851 return;
3852 }
3853 /* try to continue anyway; new association will be tried again
3854 * after timeout */
3855 assoc_failed = 1;
3856 }
3857
3858 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3859 /* Set the key after the association just in case association
3860 * cleared the previously configured key. */
3861 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3862 /* No need to timeout authentication since there is no key
3863 * management. */
3864 wpa_supplicant_cancel_auth_timeout(wpa_s);
3865 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3866#ifdef CONFIG_IBSS_RSN
3867 } else if (ssid->mode == WPAS_MODE_IBSS &&
3868 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3869 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3870 /*
3871 * RSN IBSS authentication is per-STA and we can disable the
3872 * per-BSSID authentication.
3873 */
3874 wpa_supplicant_cancel_auth_timeout(wpa_s);
3875#endif /* CONFIG_IBSS_RSN */
3876 } else {
3877 /* Timeout for IEEE 802.11 authentication and association */
3878 int timeout = 60;
3879
3880 if (assoc_failed) {
3881 /* give IBSS a bit more time */
3882 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3883 } else if (wpa_s->conf->ap_scan == 1) {
3884 /* give IBSS a bit more time */
3885 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3886 }
3887 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3888 }
3889
Hai Shalomfdcde762020-04-02 11:19:20 -07003890#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003891 if (wep_keys_set &&
3892 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003893 /* Set static WEP keys again */
3894 wpa_set_wep_keys(wpa_s, ssid);
3895 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003896#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003897
3898 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3899 /*
3900 * Do not allow EAP session resumption between different
3901 * network configurations.
3902 */
3903 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3904 }
3905 old_ssid = wpa_s->current_ssid;
3906 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003907
3908 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003909 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003910#ifdef CONFIG_HS20
3911 hs20_configure_frame_filters(wpa_s);
3912#endif /* CONFIG_HS20 */
3913 }
3914
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003915 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3916 wpa_supplicant_initiate_eapol(wpa_s);
3917 if (old_ssid != wpa_s->current_ssid)
3918 wpas_notify_network_changed(wpa_s);
3919}
3920
3921
3922static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3923 const u8 *addr)
3924{
3925 struct wpa_ssid *old_ssid;
3926
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003927 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003928 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003930 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003931 wpa_sm_set_config(wpa_s->wpa, NULL);
3932 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3933 if (old_ssid != wpa_s->current_ssid)
3934 wpas_notify_network_changed(wpa_s);
3935 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3936}
3937
3938
3939/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003940 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3941 * @wpa_s: Pointer to wpa_supplicant data
3942 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3943 *
3944 * This function is used to request %wpa_supplicant to deauthenticate from the
3945 * current AP.
3946 */
3947void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003948 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003949{
3950 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003951 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003952 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003953
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003954 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003955 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003956 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003957 reason_code, reason2str(reason_code),
3958 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003959
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003960 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3961 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3962 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003963 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003964 else if (!is_zero_ether_addr(wpa_s->bssid))
3965 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003966 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3967 /*
3968 * When using driver-based BSS selection, we may not know the
3969 * BSSID with which we are currently trying to associate. We
3970 * need to notify the driver of this disconnection even in such
3971 * a case, so use the all zeros address here.
3972 */
3973 addr = wpa_s->bssid;
3974 zero_addr = 1;
3975 }
3976
Hai Shalom74f70d42019-02-11 14:42:39 -08003977 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3978 wpa_s->enabled_4addr_mode = 0;
3979
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003980#ifdef CONFIG_TDLS
3981 wpa_tdls_teardown_peers(wpa_s->wpa);
3982#endif /* CONFIG_TDLS */
3983
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003984#ifdef CONFIG_MESH
3985 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003986 struct mesh_conf *mconf;
3987
3988 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003989 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3990 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003991 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3992 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003993 wpa_supplicant_leave_mesh(wpa_s);
3994 }
3995#endif /* CONFIG_MESH */
3996
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003997 if (addr) {
3998 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003999 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07004000 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004001 event.deauth_info.locally_generated = 1;
4002 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004003 if (zero_addr)
4004 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004005 }
4006
4007 wpa_supplicant_clear_connection(wpa_s, addr);
4008}
4009
Hai Shalomfdcde762020-04-02 11:19:20 -07004010
4011void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4012{
4013 wpa_s->own_reconnect_req = 1;
4014 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4015
4016}
4017
4018
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004019static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4020 struct wpa_ssid *ssid)
4021{
4022 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4023 return;
4024
4025 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004026 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004027 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4028 wpas_notify_network_enabled_changed(wpa_s, ssid);
4029
4030 /*
4031 * Try to reassociate since there is no current configuration and a new
4032 * network was made available.
4033 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004034 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004035 wpa_s->reassociate = 1;
4036}
4037
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004038
Roshan Pius950bec92016-07-19 09:49:24 -07004039/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004040 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004041 * @wpa_s: wpa_supplicant structure for a network interface
4042 * Returns: The new network configuration or %NULL if operation failed
4043 *
4044 * This function performs the following operations:
4045 * 1. Adds a new network.
4046 * 2. Send network addition notification.
4047 * 3. Marks the network disabled.
4048 * 4. Set network default parameters.
4049 */
4050struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4051{
4052 struct wpa_ssid *ssid;
4053
4054 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004055 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004056 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004057 wpas_notify_network_added(wpa_s, ssid);
4058 ssid->disabled = 1;
4059 wpa_config_set_network_defaults(ssid);
4060
4061 return ssid;
4062}
4063
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004064
Roshan Pius950bec92016-07-19 09:49:24 -07004065/**
4066 * wpa_supplicant_remove_network - Remove a configured network based on id
4067 * @wpa_s: wpa_supplicant structure for a network interface
4068 * @id: Unique network id to search for
4069 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4070 * could not be removed
4071 *
4072 * This function performs the following operations:
4073 * 1. Removes the network.
4074 * 2. Send network removal notification.
4075 * 3. Update internal state machines.
4076 * 4. Stop any running sched scans.
4077 */
4078int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4079{
4080 struct wpa_ssid *ssid;
4081 int was_disabled;
4082
4083 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004084 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004085 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004086 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004087
4088 if (wpa_s->last_ssid == ssid)
4089 wpa_s->last_ssid = NULL;
4090
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004091 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004092#ifdef CONFIG_SME
4093 wpa_s->sme.prev_bssid_set = 0;
4094#endif /* CONFIG_SME */
4095 /*
4096 * Invalidate the EAP session cache if the current or
4097 * previously used network is removed.
4098 */
4099 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4100 }
4101
4102 if (ssid == wpa_s->current_ssid) {
4103 wpa_sm_set_config(wpa_s->wpa, NULL);
4104 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4105
4106 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4107 wpa_s->own_disconnect_req = 1;
4108 wpa_supplicant_deauthenticate(wpa_s,
4109 WLAN_REASON_DEAUTH_LEAVING);
4110 }
4111
4112 was_disabled = ssid->disabled;
4113
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004114 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004115 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004116
4117 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004118 wpa_printf(MSG_DEBUG,
4119 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004120 wpa_supplicant_cancel_sched_scan(wpa_s);
4121 wpa_supplicant_req_scan(wpa_s, 0, 0);
4122 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004123
Roshan Pius950bec92016-07-19 09:49:24 -07004124 return 0;
4125}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004127
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004128/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004129 * wpa_supplicant_remove_all_networks - Remove all configured networks
4130 * @wpa_s: wpa_supplicant structure for a network interface
4131 * Returns: 0 on success (errors are currently ignored)
4132 *
4133 * This function performs the following operations:
4134 * 1. Remove all networks.
4135 * 2. Send network removal notifications.
4136 * 3. Update internal state machines.
4137 * 4. Stop any running sched scans.
4138 */
4139int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4140{
4141 struct wpa_ssid *ssid;
4142
4143 if (wpa_s->sched_scanning)
4144 wpa_supplicant_cancel_sched_scan(wpa_s);
4145
4146 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4147 if (wpa_s->current_ssid) {
4148#ifdef CONFIG_SME
4149 wpa_s->sme.prev_bssid_set = 0;
4150#endif /* CONFIG_SME */
4151 wpa_sm_set_config(wpa_s->wpa, NULL);
4152 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4153 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4154 wpa_s->own_disconnect_req = 1;
4155 wpa_supplicant_deauthenticate(
4156 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4157 }
4158 ssid = wpa_s->conf->ssid;
4159 while (ssid) {
4160 struct wpa_ssid *remove_ssid = ssid;
4161 int id;
4162
4163 id = ssid->id;
4164 ssid = ssid->next;
4165 if (wpa_s->last_ssid == remove_ssid)
4166 wpa_s->last_ssid = NULL;
4167 wpas_notify_network_removed(wpa_s, remove_ssid);
4168 wpa_config_remove_network(wpa_s->conf, id);
4169 }
4170 return 0;
4171}
4172
4173
4174/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004175 * wpa_supplicant_enable_network - Mark a configured network as enabled
4176 * @wpa_s: wpa_supplicant structure for a network interface
4177 * @ssid: wpa_ssid structure for a configured network or %NULL
4178 *
4179 * Enables the specified network or all networks if no network specified.
4180 */
4181void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4182 struct wpa_ssid *ssid)
4183{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004184 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004185 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4186 wpa_supplicant_enable_one_network(wpa_s, ssid);
4187 } else
4188 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004189
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004190 if (wpa_s->reassociate && !wpa_s->disconnected &&
4191 (!wpa_s->current_ssid ||
4192 wpa_s->wpa_state == WPA_DISCONNECTED ||
4193 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004194 if (wpa_s->sched_scanning) {
4195 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4196 "new network to scan filters");
4197 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004198 }
4199
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004200 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4201 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004202 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004203 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004204 }
4205}
4206
4207
4208/**
4209 * wpa_supplicant_disable_network - Mark a configured network as disabled
4210 * @wpa_s: wpa_supplicant structure for a network interface
4211 * @ssid: wpa_ssid structure for a configured network or %NULL
4212 *
4213 * Disables the specified network or all networks if no network specified.
4214 */
4215void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4216 struct wpa_ssid *ssid)
4217{
4218 struct wpa_ssid *other_ssid;
4219 int was_disabled;
4220
4221 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004222 if (wpa_s->sched_scanning)
4223 wpa_supplicant_cancel_sched_scan(wpa_s);
4224
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004225 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4226 other_ssid = other_ssid->next) {
4227 was_disabled = other_ssid->disabled;
4228 if (was_disabled == 2)
4229 continue; /* do not change persistent P2P group
4230 * data */
4231
4232 other_ssid->disabled = 1;
4233
4234 if (was_disabled != other_ssid->disabled)
4235 wpas_notify_network_enabled_changed(
4236 wpa_s, other_ssid);
4237 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004238 if (wpa_s->current_ssid) {
4239 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4240 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004241 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004242 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004243 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004244 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004245 if (ssid == wpa_s->current_ssid) {
4246 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4247 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004248 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004249 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004250 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004251
4252 was_disabled = ssid->disabled;
4253
4254 ssid->disabled = 1;
4255
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004256 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004257 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004258 if (wpa_s->sched_scanning) {
4259 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4260 "to remove network from filters");
4261 wpa_supplicant_cancel_sched_scan(wpa_s);
4262 wpa_supplicant_req_scan(wpa_s, 0, 0);
4263 }
4264 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004265 }
4266}
4267
4268
4269/**
4270 * wpa_supplicant_select_network - Attempt association with a network
4271 * @wpa_s: wpa_supplicant structure for a network interface
4272 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4273 */
4274void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4275 struct wpa_ssid *ssid)
4276{
4277
4278 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004279 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004280
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004281 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004282 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4283 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004284 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004286 disconnected = 1;
4287 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004288
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004289 if (ssid)
4290 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4291
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004292 /*
4293 * Mark all other networks disabled or mark all networks enabled if no
4294 * network specified.
4295 */
4296 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4297 other_ssid = other_ssid->next) {
4298 int was_disabled = other_ssid->disabled;
4299 if (was_disabled == 2)
4300 continue; /* do not change persistent P2P group data */
4301
4302 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004303 if (was_disabled && !other_ssid->disabled)
4304 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004305
4306 if (was_disabled != other_ssid->disabled)
4307 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4308 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004309
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004310 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4311 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004312 /* We are already associated with the selected network */
4313 wpa_printf(MSG_DEBUG, "Already associated with the "
4314 "selected network - do nothing");
4315 return;
4316 }
4317
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004318 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004319 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004320 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004321 wpa_s->connect_without_scan =
4322 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004323
4324 /*
4325 * Don't optimize next scan freqs since a new ESS has been
4326 * selected.
4327 */
4328 os_free(wpa_s->next_scan_freqs);
4329 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004330 } else {
4331 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004332 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004333
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004334 wpa_s->disconnected = 0;
4335 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004336 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004337 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004338 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004339 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004340 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4341 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004342
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004343 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004344 wpa_supplicant_fast_associate(wpa_s) != 1) {
4345 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004346 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004347 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004348 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349
4350 if (ssid)
4351 wpas_notify_network_selected(wpa_s, ssid);
4352}
4353
4354
4355/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004356 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4357 * @wpa_s: wpa_supplicant structure for a network interface
4358 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4359 * @pkcs11_module_path: PKCS #11 module path or NULL
4360 * Returns: 0 on success; -1 on failure
4361 *
4362 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4363 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4364 * module path fails the paths will be reset to the default value (NULL).
4365 */
4366int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4367 const char *pkcs11_engine_path,
4368 const char *pkcs11_module_path)
4369{
4370 char *pkcs11_engine_path_copy = NULL;
4371 char *pkcs11_module_path_copy = NULL;
4372
4373 if (pkcs11_engine_path != NULL) {
4374 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4375 if (pkcs11_engine_path_copy == NULL)
4376 return -1;
4377 }
4378 if (pkcs11_module_path != NULL) {
4379 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004380 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004381 os_free(pkcs11_engine_path_copy);
4382 return -1;
4383 }
4384 }
4385
4386 os_free(wpa_s->conf->pkcs11_engine_path);
4387 os_free(wpa_s->conf->pkcs11_module_path);
4388 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4389 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4390
4391 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4392 eapol_sm_deinit(wpa_s->eapol);
4393 wpa_s->eapol = NULL;
4394 if (wpa_supplicant_init_eapol(wpa_s)) {
4395 /* Error -> Reset paths to the default value (NULL) once. */
4396 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4397 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4398 NULL);
4399
4400 return -1;
4401 }
4402 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4403
4404 return 0;
4405}
4406
4407
4408/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004409 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4410 * @wpa_s: wpa_supplicant structure for a network interface
4411 * @ap_scan: AP scan mode
4412 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4413 *
4414 */
4415int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4416{
4417
4418 int old_ap_scan;
4419
4420 if (ap_scan < 0 || ap_scan > 2)
4421 return -1;
4422
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004423 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4424 wpa_printf(MSG_INFO,
4425 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4426 }
4427
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004428#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004429 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4430 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4431 wpa_s->wpa_state < WPA_COMPLETED) {
4432 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4433 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004434 return 0;
4435 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004436#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004437
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004438 old_ap_scan = wpa_s->conf->ap_scan;
4439 wpa_s->conf->ap_scan = ap_scan;
4440
4441 if (old_ap_scan != wpa_s->conf->ap_scan)
4442 wpas_notify_ap_scan_changed(wpa_s);
4443
4444 return 0;
4445}
4446
4447
4448/**
4449 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4450 * @wpa_s: wpa_supplicant structure for a network interface
4451 * @expire_age: Expiration age in seconds
4452 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4453 *
4454 */
4455int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4456 unsigned int bss_expire_age)
4457{
4458 if (bss_expire_age < 10) {
4459 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4460 bss_expire_age);
4461 return -1;
4462 }
4463 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4464 bss_expire_age);
4465 wpa_s->conf->bss_expiration_age = bss_expire_age;
4466
4467 return 0;
4468}
4469
4470
4471/**
4472 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4473 * @wpa_s: wpa_supplicant structure for a network interface
4474 * @expire_count: number of scans after which an unseen BSS is reclaimed
4475 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4476 *
4477 */
4478int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4479 unsigned int bss_expire_count)
4480{
4481 if (bss_expire_count < 1) {
4482 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4483 bss_expire_count);
4484 return -1;
4485 }
4486 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4487 bss_expire_count);
4488 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4489
4490 return 0;
4491}
4492
4493
4494/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004495 * wpa_supplicant_set_scan_interval - Set scan interval
4496 * @wpa_s: wpa_supplicant structure for a network interface
4497 * @scan_interval: scan interval in seconds
4498 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4499 *
4500 */
4501int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4502 int scan_interval)
4503{
4504 if (scan_interval < 0) {
4505 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4506 scan_interval);
4507 return -1;
4508 }
4509 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4510 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004511 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004512
4513 return 0;
4514}
4515
4516
4517/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004518 * wpa_supplicant_set_debug_params - Set global debug params
4519 * @global: wpa_global structure
4520 * @debug_level: debug level
4521 * @debug_timestamp: determines if show timestamp in debug data
4522 * @debug_show_keys: determines if show keys in debug data
4523 * Returns: 0 if succeed or -1 if debug_level has wrong value
4524 */
4525int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4526 int debug_timestamp, int debug_show_keys)
4527{
4528
4529 int old_level, old_timestamp, old_show_keys;
4530
4531 /* check for allowed debuglevels */
4532 if (debug_level != MSG_EXCESSIVE &&
4533 debug_level != MSG_MSGDUMP &&
4534 debug_level != MSG_DEBUG &&
4535 debug_level != MSG_INFO &&
4536 debug_level != MSG_WARNING &&
4537 debug_level != MSG_ERROR)
4538 return -1;
4539
4540 old_level = wpa_debug_level;
4541 old_timestamp = wpa_debug_timestamp;
4542 old_show_keys = wpa_debug_show_keys;
4543
4544 wpa_debug_level = debug_level;
4545 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4546 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4547
4548 if (wpa_debug_level != old_level)
4549 wpas_notify_debug_level_changed(global);
4550 if (wpa_debug_timestamp != old_timestamp)
4551 wpas_notify_debug_timestamp_changed(global);
4552 if (wpa_debug_show_keys != old_show_keys)
4553 wpas_notify_debug_show_keys_changed(global);
4554
4555 return 0;
4556}
4557
4558
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004559#ifdef CONFIG_OWE
4560static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4561 const u8 *entry_ssid, size_t entry_ssid_len)
4562{
4563 const u8 *owe, *pos, *end;
4564 u8 ssid_len;
4565 struct wpa_bss *bss;
4566
4567 /* Check network profile SSID aganst the SSID in the
4568 * OWE Transition Mode element. */
4569
4570 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4571 if (!bss)
4572 return 0;
4573
4574 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4575 if (!owe)
4576 return 0;
4577
4578 pos = owe + 6;
4579 end = owe + 2 + owe[1];
4580
4581 if (end - pos < ETH_ALEN + 1)
4582 return 0;
4583 pos += ETH_ALEN;
4584 ssid_len = *pos++;
4585 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4586 return 0;
4587
4588 return entry_ssid_len == ssid_len &&
4589 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4590}
4591#endif /* CONFIG_OWE */
4592
4593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004594/**
4595 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4596 * @wpa_s: Pointer to wpa_supplicant data
4597 * Returns: A pointer to the current network structure or %NULL on failure
4598 */
4599struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4600{
4601 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004602 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004603 int res;
4604 size_t ssid_len;
4605 u8 bssid[ETH_ALEN];
4606 int wired;
4607
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004608 res = wpa_drv_get_ssid(wpa_s, ssid);
4609 if (res < 0) {
4610 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4611 "driver");
4612 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004613 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004614 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004615
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004616 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004617 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4618 "driver");
4619 return NULL;
4620 }
4621
4622 wired = wpa_s->conf->ap_scan == 0 &&
4623 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4624
4625 entry = wpa_s->conf->ssid;
4626 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004627 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004628 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004629 (!entry->ssid ||
4630 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4631 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004632 (!entry->bssid_set ||
4633 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4634 return entry;
4635#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004636 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004637 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4638 (entry->ssid == NULL || entry->ssid_len == 0) &&
4639 (!entry->bssid_set ||
4640 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4641 return entry;
4642#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004643
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004644#ifdef CONFIG_OWE
4645 if (!wpas_network_disabled(wpa_s, entry) &&
4646 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4647 entry->ssid_len) &&
4648 (!entry->bssid_set ||
4649 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4650 return entry;
4651#endif /* CONFIG_OWE */
4652
Dmitry Shmidt04949592012-07-19 12:16:46 -07004653 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004654 entry->ssid_len == 0 &&
4655 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4656 return entry;
4657
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004658 entry = entry->next;
4659 }
4660
4661 return NULL;
4662}
4663
4664
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004665static int select_driver(struct wpa_supplicant *wpa_s, int i)
4666{
4667 struct wpa_global *global = wpa_s->global;
4668
4669 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004670 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004671 if (global->drv_priv[i] == NULL) {
4672 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4673 "'%s'", wpa_drivers[i]->name);
4674 return -1;
4675 }
4676 }
4677
4678 wpa_s->driver = wpa_drivers[i];
4679 wpa_s->global_drv_priv = global->drv_priv[i];
4680
4681 return 0;
4682}
4683
4684
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004685static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4686 const char *name)
4687{
4688 int i;
4689 size_t len;
4690 const char *pos, *driver = name;
4691
4692 if (wpa_s == NULL)
4693 return -1;
4694
4695 if (wpa_drivers[0] == NULL) {
4696 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4697 "wpa_supplicant");
4698 return -1;
4699 }
4700
4701 if (name == NULL) {
4702 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004703 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004704 }
4705
4706 do {
4707 pos = os_strchr(driver, ',');
4708 if (pos)
4709 len = pos - driver;
4710 else
4711 len = os_strlen(driver);
4712
4713 for (i = 0; wpa_drivers[i]; i++) {
4714 if (os_strlen(wpa_drivers[i]->name) == len &&
4715 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004716 0) {
4717 /* First driver that succeeds wins */
4718 if (select_driver(wpa_s, i) == 0)
4719 return 0;
4720 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004721 }
4722
4723 driver = pos + 1;
4724 } while (pos);
4725
4726 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4727 return -1;
4728}
4729
4730
4731/**
4732 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4733 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4734 * with struct wpa_driver_ops::init()
4735 * @src_addr: Source address of the EAPOL frame
4736 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4737 * @len: Length of the EAPOL data
4738 *
4739 * This function is called for each received EAPOL frame. Most driver
4740 * interfaces rely on more generic OS mechanism for receiving frames through
4741 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4742 * take care of received EAPOL frames and deliver them to the core supplicant
4743 * code by calling this function.
4744 */
4745void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4746 const u8 *buf, size_t len)
4747{
4748 struct wpa_supplicant *wpa_s = ctx;
4749
4750 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4751 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4752
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004753#ifdef CONFIG_TESTING_OPTIONS
4754 if (wpa_s->ignore_auth_resp) {
4755 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4756 return;
4757 }
4758#endif /* CONFIG_TESTING_OPTIONS */
4759
Jouni Malinena05074c2012-12-21 21:35:35 +02004760 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4761 (wpa_s->last_eapol_matches_bssid &&
4762#ifdef CONFIG_AP
4763 !wpa_s->ap_iface &&
4764#endif /* CONFIG_AP */
4765 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004766 /*
4767 * There is possible race condition between receiving the
4768 * association event and the EAPOL frame since they are coming
4769 * through different paths from the driver. In order to avoid
4770 * issues in trying to process the EAPOL frame before receiving
4771 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004772 * the association event is received. This may also be needed in
4773 * driver-based roaming case, so also use src_addr != BSSID as a
4774 * trigger if we have previously confirmed that the
4775 * Authenticator uses BSSID as the src_addr (which is not the
4776 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004777 */
4778 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004779 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4780 wpa_supplicant_state_txt(wpa_s->wpa_state),
4781 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004782 wpabuf_free(wpa_s->pending_eapol_rx);
4783 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4784 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004785 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004786 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4787 ETH_ALEN);
4788 }
4789 return;
4790 }
4791
Jouni Malinena05074c2012-12-21 21:35:35 +02004792 wpa_s->last_eapol_matches_bssid =
4793 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4794
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004795#ifdef CONFIG_AP
4796 if (wpa_s->ap_iface) {
4797 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4798 return;
4799 }
4800#endif /* CONFIG_AP */
4801
4802 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4803 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4804 "no key management is configured");
4805 return;
4806 }
4807
4808 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004809 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004810 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4811 wpa_s->wpa_state != WPA_COMPLETED) &&
4812 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004813 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004814 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004815 int timeout = 10;
4816
4817 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4818 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4819 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4820 /* Use longer timeout for IEEE 802.1X/EAP */
4821 timeout = 70;
4822 }
4823
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004824#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004825 if (wpa_s->current_ssid && wpa_s->current_bss &&
4826 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4827 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4828 /*
4829 * Use shorter timeout if going through WPS AP iteration
4830 * for PIN config method with an AP that does not
4831 * advertise Selected Registrar.
4832 */
4833 struct wpabuf *wps_ie;
4834
4835 wps_ie = wpa_bss_get_vendor_ie_multi(
4836 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4837 if (wps_ie &&
4838 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4839 timeout = 10;
4840 wpabuf_free(wps_ie);
4841 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004842#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004843
4844 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004845 }
4846 wpa_s->eapol_received++;
4847
4848 if (wpa_s->countermeasures) {
4849 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4850 "EAPOL packet");
4851 return;
4852 }
4853
4854#ifdef CONFIG_IBSS_RSN
4855 if (wpa_s->current_ssid &&
4856 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4857 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4858 return;
4859 }
4860#endif /* CONFIG_IBSS_RSN */
4861
4862 /* Source address of the incoming EAPOL frame could be compared to the
4863 * current BSSID. However, it is possible that a centralized
4864 * Authenticator could be using another MAC address than the BSSID of
4865 * an AP, so just allow any address to be used for now. The replies are
4866 * still sent to the current BSSID (if available), though. */
4867
4868 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4869 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004870 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4871 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004872 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4873 return;
4874 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004875 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004876 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4877 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4878 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07004879 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004880 * handshake processing which would normally set portValid. We
4881 * need this to allow the EAPOL state machines to be completed
4882 * without going through EAPOL-Key handshake.
4883 */
Hai Shalome21d4e82020-04-29 16:34:06 -07004884 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004885 }
4886}
4887
4888
Hai Shalomb755a2a2020-04-23 21:49:02 -07004889static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
4890{
4891 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
4892 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
4893}
4894
4895
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004896int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004897{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004898 if ((!wpa_s->p2p_mgmt ||
4899 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4900 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004901 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004902 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4903 wpa_drv_get_mac_addr(wpa_s),
4904 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07004905 wpas_eapol_needs_l2_packet(wpa_s) ?
4906 wpa_supplicant_rx_eapol : NULL,
4907 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004908 if (wpa_s->l2 == NULL)
4909 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004910
4911 if (l2_packet_set_packet_filter(wpa_s->l2,
4912 L2_PACKET_FILTER_PKTTYPE))
4913 wpa_dbg(wpa_s, MSG_DEBUG,
4914 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07004915
4916 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4917 wpa_msg(wpa_s, MSG_ERROR,
4918 "Failed to get own L2 address");
4919 return -1;
4920 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004921 } else {
4922 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4923 if (addr)
4924 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4925 }
4926
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004927 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004928 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004929
Hai Shalomc3565922019-10-28 11:58:20 -07004930#ifdef CONFIG_FST
4931 if (wpa_s->fst)
4932 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4933#endif /* CONFIG_FST */
4934
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004935 return 0;
4936}
4937
4938
Dmitry Shmidt04949592012-07-19 12:16:46 -07004939static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4940 const u8 *buf, size_t len)
4941{
4942 struct wpa_supplicant *wpa_s = ctx;
4943 const struct l2_ethhdr *eth;
4944
4945 if (len < sizeof(*eth))
4946 return;
4947 eth = (const struct l2_ethhdr *) buf;
4948
4949 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4950 !(eth->h_dest[0] & 0x01)) {
4951 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4952 " (bridge - not for this interface - ignore)",
4953 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4954 return;
4955 }
4956
4957 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4958 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4959 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4960 len - sizeof(*eth));
4961}
4962
4963
Hai Shalom899fcc72020-10-19 14:38:18 -07004964int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
4965 const char *bridge_ifname)
4966{
4967 if (wpa_s->wpa_state > WPA_SCANNING)
4968 return -EBUSY;
4969
4970 if (bridge_ifname &&
4971 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
4972 return -EINVAL;
4973
4974 if (!bridge_ifname)
4975 bridge_ifname = "";
4976
4977 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
4978 return 0;
4979
4980 if (wpa_s->l2_br) {
4981 l2_packet_deinit(wpa_s->l2_br);
4982 wpa_s->l2_br = NULL;
4983 }
4984
4985 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
4986 sizeof(wpa_s->bridge_ifname));
4987
4988 if (wpa_s->bridge_ifname[0]) {
4989 wpa_dbg(wpa_s, MSG_DEBUG,
4990 "Receiving packets from bridge interface '%s'",
4991 wpa_s->bridge_ifname);
4992 wpa_s->l2_br = l2_packet_init_bridge(
4993 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4994 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
4995 if (!wpa_s->l2_br) {
4996 wpa_msg(wpa_s, MSG_ERROR,
4997 "Failed to open l2_packet connection for the bridge interface '%s'",
4998 wpa_s->bridge_ifname);
4999 goto fail;
5000 }
5001 }
5002
5003#ifdef CONFIG_TDLS
5004 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5005 goto fail;
5006#endif /* CONFIG_TDLS */
5007
5008 return 0;
5009fail:
5010 wpa_s->bridge_ifname[0] = 0;
5011 if (wpa_s->l2_br) {
5012 l2_packet_deinit(wpa_s->l2_br);
5013 wpa_s->l2_br = NULL;
5014 }
5015#ifdef CONFIG_TDLS
5016 if (!wpa_s->p2p_mgmt)
5017 wpa_tdls_init(wpa_s->wpa);
5018#endif /* CONFIG_TDLS */
5019 return -EIO;
5020}
5021
5022
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005023/**
5024 * wpa_supplicant_driver_init - Initialize driver interface parameters
5025 * @wpa_s: Pointer to wpa_supplicant data
5026 * Returns: 0 on success, -1 on failure
5027 *
5028 * This function is called to initialize driver interface parameters.
5029 * wpa_drv_init() must have been called before this function to initialize the
5030 * driver interface.
5031 */
5032int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5033{
5034 static int interface_count = 0;
5035
5036 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5037 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005038
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005039 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5040 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005041 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005042 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5043
Hai Shalomb755a2a2020-04-23 21:49:02 -07005044 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005045 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5046 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005047 wpa_s->l2_br = l2_packet_init_bridge(
5048 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5049 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005050 if (wpa_s->l2_br == NULL) {
5051 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5052 "connection for the bridge interface '%s'",
5053 wpa_s->bridge_ifname);
5054 return -1;
5055 }
5056 }
5057
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005058 if (wpa_s->conf->ap_scan == 2 &&
5059 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5060 wpa_printf(MSG_INFO,
5061 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5062 }
5063
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005064 wpa_clear_keys(wpa_s, NULL);
5065
5066 /* Make sure that TKIP countermeasures are not left enabled (could
5067 * happen if wpa_supplicant is killed during countermeasures. */
5068 wpa_drv_set_countermeasures(wpa_s, 0);
5069
5070 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5071 wpa_drv_flush_pmkid(wpa_s);
5072
5073 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005074 wpa_s->prev_scan_wildcard = 0;
5075
Dmitry Shmidt04949592012-07-19 12:16:46 -07005076 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005077 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5078 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5079 interface_count = 0;
5080 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005081#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005082 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005083 wpa_supplicant_delayed_sched_scan(wpa_s,
5084 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005085 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005086 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005087 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005088#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005089 interface_count++;
5090 } else
5091 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5092
5093 return 0;
5094}
5095
5096
5097static int wpa_supplicant_daemon(const char *pid_file)
5098{
5099 wpa_printf(MSG_DEBUG, "Daemonize..");
5100 return os_daemonize(pid_file);
5101}
5102
5103
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005104static struct wpa_supplicant *
5105wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005106{
5107 struct wpa_supplicant *wpa_s;
5108
5109 wpa_s = os_zalloc(sizeof(*wpa_s));
5110 if (wpa_s == NULL)
5111 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005112 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005113 wpa_s->scan_interval = 5;
5114 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005115 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005116 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005117 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005118
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005119 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005120 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005121#ifdef CONFIG_TESTING_OPTIONS
5122 dl_list_init(&wpa_s->drv_signal_override);
5123#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005124
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005125 return wpa_s;
5126}
5127
5128
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005129#ifdef CONFIG_HT_OVERRIDES
5130
5131static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5132 struct ieee80211_ht_capabilities *htcaps,
5133 struct ieee80211_ht_capabilities *htcaps_mask,
5134 const char *ht_mcs)
5135{
5136 /* parse ht_mcs into hex array */
5137 int i;
5138 const char *tmp = ht_mcs;
5139 char *end = NULL;
5140
5141 /* If ht_mcs is null, do not set anything */
5142 if (!ht_mcs)
5143 return 0;
5144
5145 /* This is what we are setting in the kernel */
5146 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5147
5148 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5149
5150 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005151 long v;
5152
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005153 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005154 v = strtol(tmp, &end, 16);
5155
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005156 if (errno == 0) {
5157 wpa_msg(wpa_s, MSG_DEBUG,
5158 "htcap value[%i]: %ld end: %p tmp: %p",
5159 i, v, end, tmp);
5160 if (end == tmp)
5161 break;
5162
5163 htcaps->supported_mcs_set[i] = v;
5164 tmp = end;
5165 } else {
5166 wpa_msg(wpa_s, MSG_ERROR,
5167 "Failed to parse ht-mcs: %s, error: %s\n",
5168 ht_mcs, strerror(errno));
5169 return -1;
5170 }
5171 }
5172
5173 /*
5174 * If we were able to parse any values, then set mask for the MCS set.
5175 */
5176 if (i) {
5177 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5178 IEEE80211_HT_MCS_MASK_LEN - 1);
5179 /* skip the 3 reserved bits */
5180 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5181 0x1f;
5182 }
5183
5184 return 0;
5185}
5186
5187
5188static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5189 struct ieee80211_ht_capabilities *htcaps,
5190 struct ieee80211_ht_capabilities *htcaps_mask,
5191 int disabled)
5192{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005193 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005194
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005195 if (disabled == -1)
5196 return 0;
5197
Hai Shalom74f70d42019-02-11 14:42:39 -08005198 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5199
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005200 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5201 htcaps_mask->ht_capabilities_info |= msk;
5202 if (disabled)
5203 htcaps->ht_capabilities_info &= msk;
5204 else
5205 htcaps->ht_capabilities_info |= msk;
5206
5207 return 0;
5208}
5209
5210
5211static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5212 struct ieee80211_ht_capabilities *htcaps,
5213 struct ieee80211_ht_capabilities *htcaps_mask,
5214 int factor)
5215{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005216 if (factor == -1)
5217 return 0;
5218
Hai Shalom74f70d42019-02-11 14:42:39 -08005219 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5220
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005221 if (factor < 0 || factor > 3) {
5222 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5223 "Must be 0-3 or -1", factor);
5224 return -EINVAL;
5225 }
5226
5227 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5228 htcaps->a_mpdu_params &= ~0x3;
5229 htcaps->a_mpdu_params |= factor & 0x3;
5230
5231 return 0;
5232}
5233
5234
5235static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5236 struct ieee80211_ht_capabilities *htcaps,
5237 struct ieee80211_ht_capabilities *htcaps_mask,
5238 int density)
5239{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005240 if (density == -1)
5241 return 0;
5242
Hai Shalom74f70d42019-02-11 14:42:39 -08005243 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5244
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005245 if (density < 0 || density > 7) {
5246 wpa_msg(wpa_s, MSG_ERROR,
5247 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5248 density);
5249 return -EINVAL;
5250 }
5251
5252 htcaps_mask->a_mpdu_params |= 0x1C;
5253 htcaps->a_mpdu_params &= ~(0x1C);
5254 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5255
5256 return 0;
5257}
5258
5259
5260static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5261 struct ieee80211_ht_capabilities *htcaps,
5262 struct ieee80211_ht_capabilities *htcaps_mask,
5263 int disabled)
5264{
Hai Shalom74f70d42019-02-11 14:42:39 -08005265 if (disabled)
5266 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005267
Paul Stewart092955c2017-02-06 09:13:09 -08005268 set_disable_ht40(htcaps, disabled);
5269 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005270
5271 return 0;
5272}
5273
5274
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005275static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5276 struct ieee80211_ht_capabilities *htcaps,
5277 struct ieee80211_ht_capabilities *htcaps_mask,
5278 int disabled)
5279{
5280 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005281 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5282 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005283
Hai Shalom74f70d42019-02-11 14:42:39 -08005284 if (disabled)
5285 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005286
5287 if (disabled)
5288 htcaps->ht_capabilities_info &= ~msk;
5289 else
5290 htcaps->ht_capabilities_info |= msk;
5291
5292 htcaps_mask->ht_capabilities_info |= msk;
5293
5294 return 0;
5295}
5296
5297
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005298static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5299 struct ieee80211_ht_capabilities *htcaps,
5300 struct ieee80211_ht_capabilities *htcaps_mask,
5301 int disabled)
5302{
5303 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005304 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005305
Hai Shalom74f70d42019-02-11 14:42:39 -08005306 if (disabled)
5307 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005308
5309 if (disabled)
5310 htcaps->ht_capabilities_info &= ~msk;
5311 else
5312 htcaps->ht_capabilities_info |= msk;
5313
5314 htcaps_mask->ht_capabilities_info |= msk;
5315
5316 return 0;
5317}
5318
5319
Hai Shalom74f70d42019-02-11 14:42:39 -08005320static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5321 struct ieee80211_ht_capabilities *htcaps,
5322 struct ieee80211_ht_capabilities *htcaps_mask,
5323 int tx_stbc)
5324{
5325 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5326
5327 if (tx_stbc == -1)
5328 return 0;
5329
5330 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5331
5332 if (tx_stbc < 0 || tx_stbc > 1) {
5333 wpa_msg(wpa_s, MSG_ERROR,
5334 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5335 return -EINVAL;
5336 }
5337
5338 htcaps_mask->ht_capabilities_info |= msk;
5339 htcaps->ht_capabilities_info &= ~msk;
5340 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5341
5342 return 0;
5343}
5344
5345
5346static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5347 struct ieee80211_ht_capabilities *htcaps,
5348 struct ieee80211_ht_capabilities *htcaps_mask,
5349 int rx_stbc)
5350{
5351 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5352
5353 if (rx_stbc == -1)
5354 return 0;
5355
5356 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5357
5358 if (rx_stbc < 0 || rx_stbc > 3) {
5359 wpa_msg(wpa_s, MSG_ERROR,
5360 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5361 return -EINVAL;
5362 }
5363
5364 htcaps_mask->ht_capabilities_info |= msk;
5365 htcaps->ht_capabilities_info &= ~msk;
5366 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5367
5368 return 0;
5369}
5370
5371
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005372void wpa_supplicant_apply_ht_overrides(
5373 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5374 struct wpa_driver_associate_params *params)
5375{
5376 struct ieee80211_ht_capabilities *htcaps;
5377 struct ieee80211_ht_capabilities *htcaps_mask;
5378
5379 if (!ssid)
5380 return;
5381
5382 params->disable_ht = ssid->disable_ht;
5383 if (!params->htcaps || !params->htcaps_mask)
5384 return;
5385
5386 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5387 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5388 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5389 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5390 ssid->disable_max_amsdu);
5391 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5392 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5393 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005394 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005395 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005396 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5397 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005398
5399 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005400 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005401 htcaps->ht_capabilities_info |= bit;
5402 htcaps_mask->ht_capabilities_info |= bit;
5403 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005404}
5405
5406#endif /* CONFIG_HT_OVERRIDES */
5407
5408
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005409#ifdef CONFIG_VHT_OVERRIDES
5410void wpa_supplicant_apply_vht_overrides(
5411 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5412 struct wpa_driver_associate_params *params)
5413{
5414 struct ieee80211_vht_capabilities *vhtcaps;
5415 struct ieee80211_vht_capabilities *vhtcaps_mask;
5416
5417 if (!ssid)
5418 return;
5419
5420 params->disable_vht = ssid->disable_vht;
5421
5422 vhtcaps = (void *) params->vhtcaps;
5423 vhtcaps_mask = (void *) params->vhtcaps_mask;
5424
5425 if (!vhtcaps || !vhtcaps_mask)
5426 return;
5427
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005428 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5429 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005430
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005431#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005432 if (ssid->disable_sgi) {
5433 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5434 VHT_CAP_SHORT_GI_160);
5435 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5436 VHT_CAP_SHORT_GI_160);
5437 wpa_msg(wpa_s, MSG_DEBUG,
5438 "disable-sgi override specified, vht-caps: 0x%x",
5439 vhtcaps->vht_capabilities_info);
5440 }
5441
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005442 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005443 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5444 int max_ampdu;
5445
5446 max_ampdu = (ssid->vht_capa &
5447 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5448 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005449
5450 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5451 wpa_set_ampdu_factor(wpa_s,
5452 (void *) params->htcaps,
5453 (void *) params->htcaps_mask,
5454 max_ampdu);
5455 }
5456#endif /* CONFIG_HT_OVERRIDES */
5457
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005458#define OVERRIDE_MCS(i) \
5459 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5460 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005461 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005462 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005463 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5464 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005465 } \
5466 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5467 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005468 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005469 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005470 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5471 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005472 }
5473
5474 OVERRIDE_MCS(1);
5475 OVERRIDE_MCS(2);
5476 OVERRIDE_MCS(3);
5477 OVERRIDE_MCS(4);
5478 OVERRIDE_MCS(5);
5479 OVERRIDE_MCS(6);
5480 OVERRIDE_MCS(7);
5481 OVERRIDE_MCS(8);
5482}
5483#endif /* CONFIG_VHT_OVERRIDES */
5484
5485
Hai Shalomfdcde762020-04-02 11:19:20 -07005486#ifdef CONFIG_HE_OVERRIDES
5487void wpa_supplicant_apply_he_overrides(
5488 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5489 struct wpa_driver_associate_params *params)
5490{
5491 if (!ssid)
5492 return;
5493
5494 params->disable_he = ssid->disable_he;
5495}
5496#endif /* CONFIG_HE_OVERRIDES */
5497
5498
Dmitry Shmidt04949592012-07-19 12:16:46 -07005499static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5500{
5501#ifdef PCSC_FUNCS
5502 size_t len;
5503
5504 if (!wpa_s->conf->pcsc_reader)
5505 return 0;
5506
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005507 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005508 if (!wpa_s->scard)
5509 return 1;
5510
5511 if (wpa_s->conf->pcsc_pin &&
5512 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5513 scard_deinit(wpa_s->scard);
5514 wpa_s->scard = NULL;
5515 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5516 return -1;
5517 }
5518
5519 len = sizeof(wpa_s->imsi) - 1;
5520 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5521 scard_deinit(wpa_s->scard);
5522 wpa_s->scard = NULL;
5523 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5524 return -1;
5525 }
5526 wpa_s->imsi[len] = '\0';
5527
5528 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5529
5530 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5531 wpa_s->imsi, wpa_s->mnc_len);
5532
5533 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5534 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5535#endif /* PCSC_FUNCS */
5536
5537 return 0;
5538}
5539
5540
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005541int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5542{
5543 char *val, *pos;
5544
5545 ext_password_deinit(wpa_s->ext_pw);
5546 wpa_s->ext_pw = NULL;
5547 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5548
5549 if (!wpa_s->conf->ext_password_backend)
5550 return 0;
5551
5552 val = os_strdup(wpa_s->conf->ext_password_backend);
5553 if (val == NULL)
5554 return -1;
5555 pos = os_strchr(val, ':');
5556 if (pos)
5557 *pos++ = '\0';
5558
5559 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5560
5561 wpa_s->ext_pw = ext_password_init(val, pos);
5562 os_free(val);
5563 if (wpa_s->ext_pw == NULL) {
5564 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5565 return -1;
5566 }
5567 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5568
5569 return 0;
5570}
5571
5572
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005573#ifdef CONFIG_FST
5574
5575static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5576{
5577 struct wpa_supplicant *wpa_s = ctx;
5578
5579 return (is_zero_ether_addr(wpa_s->bssid) ||
5580 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5581}
5582
5583
5584static void wpas_fst_get_channel_info_cb(void *ctx,
5585 enum hostapd_hw_mode *hw_mode,
5586 u8 *channel)
5587{
5588 struct wpa_supplicant *wpa_s = ctx;
5589
5590 if (wpa_s->current_bss) {
5591 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5592 channel);
5593 } else if (wpa_s->hw.num_modes) {
5594 *hw_mode = wpa_s->hw.modes[0].mode;
5595 } else {
5596 WPA_ASSERT(0);
5597 *hw_mode = 0;
5598 }
5599}
5600
5601
5602static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5603{
5604 struct wpa_supplicant *wpa_s = ctx;
5605
5606 *modes = wpa_s->hw.modes;
5607 return wpa_s->hw.num_modes;
5608}
5609
5610
5611static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5612{
5613 struct wpa_supplicant *wpa_s = ctx;
5614
5615 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5616 wpa_s->fst_ies = fst_ies;
5617}
5618
5619
5620static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5621{
5622 struct wpa_supplicant *wpa_s = ctx;
5623
Paul Stewart092955c2017-02-06 09:13:09 -08005624 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5625 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5626 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5627 return -1;
5628 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005629 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005630 wpa_s->own_addr, wpa_s->bssid,
5631 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005632 0);
5633}
5634
5635
5636static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5637{
5638 struct wpa_supplicant *wpa_s = ctx;
5639
5640 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5641 return wpa_s->received_mb_ies;
5642}
5643
5644
5645static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5646 const u8 *buf, size_t size)
5647{
5648 struct wpa_supplicant *wpa_s = ctx;
5649 struct mb_ies_info info;
5650
5651 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5652
5653 if (!mb_ies_info_by_ies(&info, buf, size)) {
5654 wpabuf_free(wpa_s->received_mb_ies);
5655 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5656 }
5657}
5658
5659
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005660static const u8 * wpas_fst_get_peer_first(void *ctx,
5661 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005662 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005663{
5664 struct wpa_supplicant *wpa_s = ctx;
5665
5666 *get_ctx = NULL;
5667 if (!is_zero_ether_addr(wpa_s->bssid))
5668 return (wpa_s->received_mb_ies || !mb_only) ?
5669 wpa_s->bssid : NULL;
5670 return NULL;
5671}
5672
5673
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005674static const u8 * wpas_fst_get_peer_next(void *ctx,
5675 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005676 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005677{
5678 return NULL;
5679}
5680
5681void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5682 struct fst_wpa_obj *iface_obj)
5683{
5684 iface_obj->ctx = wpa_s;
5685 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5686 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5687 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5688 iface_obj->set_ies = wpas_fst_set_ies_cb;
5689 iface_obj->send_action = wpas_fst_send_action_cb;
5690 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5691 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5692 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5693 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5694}
5695#endif /* CONFIG_FST */
5696
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005697static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005698 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005699{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005700 struct wowlan_triggers *triggers;
5701 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005702
5703 if (!wpa_s->conf->wowlan_triggers)
5704 return 0;
5705
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005706 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5707 if (triggers) {
5708 ret = wpa_drv_wowlan(wpa_s, triggers);
5709 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005710 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005711 return ret;
5712}
5713
5714
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005715enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005716{
5717 if (freq < 3000)
5718 return BAND_2_4_GHZ;
5719 if (freq > 50000)
5720 return BAND_60_GHZ;
5721 return BAND_5_GHZ;
5722}
5723
5724
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005725unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005726{
5727 int i;
5728 unsigned int band = 0;
5729
5730 if (freqs) {
5731 /* freqs are specified for the radio work */
5732 for (i = 0; freqs[i]; i++)
5733 band |= wpas_freq_to_band(freqs[i]);
5734 } else {
5735 /*
5736 * freqs are not specified, implies all
5737 * the supported freqs by HW
5738 */
5739 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5740 if (wpa_s->hw.modes[i].num_channels != 0) {
5741 if (wpa_s->hw.modes[i].mode ==
5742 HOSTAPD_MODE_IEEE80211B ||
5743 wpa_s->hw.modes[i].mode ==
5744 HOSTAPD_MODE_IEEE80211G)
5745 band |= BAND_2_4_GHZ;
5746 else if (wpa_s->hw.modes[i].mode ==
5747 HOSTAPD_MODE_IEEE80211A)
5748 band |= BAND_5_GHZ;
5749 else if (wpa_s->hw.modes[i].mode ==
5750 HOSTAPD_MODE_IEEE80211AD)
5751 band |= BAND_60_GHZ;
5752 else if (wpa_s->hw.modes[i].mode ==
5753 HOSTAPD_MODE_IEEE80211ANY)
5754 band = BAND_2_4_GHZ | BAND_5_GHZ |
5755 BAND_60_GHZ;
5756 }
5757 }
5758 }
5759
5760 return band;
5761}
5762
5763
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005764static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5765 const char *rn)
5766{
5767 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5768 struct wpa_radio *radio;
5769
5770 while (rn && iface) {
5771 radio = iface->radio;
5772 if (radio && os_strcmp(rn, radio->name) == 0) {
5773 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5774 wpa_s->ifname, rn);
5775 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5776 return radio;
5777 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005778
5779 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005780 }
5781
5782 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5783 wpa_s->ifname, rn ? rn : "N/A");
5784 radio = os_zalloc(sizeof(*radio));
5785 if (radio == NULL)
5786 return NULL;
5787
5788 if (rn)
5789 os_strlcpy(radio->name, rn, sizeof(radio->name));
5790 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005791 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005792 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5793
5794 return radio;
5795}
5796
5797
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005798static void radio_work_free(struct wpa_radio_work *work)
5799{
5800 if (work->wpa_s->scan_work == work) {
5801 /* This should not really happen. */
5802 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5803 work->type, work, work->started);
5804 work->wpa_s->scan_work = NULL;
5805 }
5806
5807#ifdef CONFIG_P2P
5808 if (work->wpa_s->p2p_scan_work == work) {
5809 /* This should not really happen. */
5810 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5811 work->type, work, work->started);
5812 work->wpa_s->p2p_scan_work = NULL;
5813 }
5814#endif /* CONFIG_P2P */
5815
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005816 if (work->started) {
5817 work->wpa_s->radio->num_active_works--;
5818 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005819 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005820 work->type, work,
5821 work->wpa_s->radio->num_active_works);
5822 }
5823
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005824 dl_list_del(&work->list);
5825 os_free(work);
5826}
5827
5828
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005829static int radio_work_is_connect(struct wpa_radio_work *work)
5830{
5831 return os_strcmp(work->type, "sme-connect") == 0 ||
5832 os_strcmp(work->type, "connect") == 0;
5833}
5834
5835
5836static int radio_work_is_scan(struct wpa_radio_work *work)
5837{
5838 return os_strcmp(work->type, "scan") == 0 ||
5839 os_strcmp(work->type, "p2p-scan") == 0;
5840}
5841
5842
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005843static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5844{
5845 struct wpa_radio_work *active_work = NULL;
5846 struct wpa_radio_work *tmp;
5847
5848 /* Get the active work to know the type and band. */
5849 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5850 if (tmp->started) {
5851 active_work = tmp;
5852 break;
5853 }
5854 }
5855
5856 if (!active_work) {
5857 /* No active work, start one */
5858 radio->num_active_works = 0;
5859 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5860 list) {
5861 if (os_strcmp(tmp->type, "scan") == 0 &&
5862 radio->external_scan_running &&
5863 (((struct wpa_driver_scan_params *)
5864 tmp->ctx)->only_new_results ||
5865 tmp->wpa_s->clear_driver_scan_cache))
5866 continue;
5867 return tmp;
5868 }
5869 return NULL;
5870 }
5871
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005872 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005873 /*
5874 * If the active work is either connect or sme-connect,
5875 * do not parallelize them with other radio works.
5876 */
5877 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5878 "Do not parallelize radio work with %s",
5879 active_work->type);
5880 return NULL;
5881 }
5882
5883 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5884 if (tmp->started)
5885 continue;
5886
5887 /*
5888 * If connect or sme-connect are enqueued, parallelize only
5889 * those operations ahead of them in the queue.
5890 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005891 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005892 break;
5893
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005894 /* Serialize parallel scan and p2p_scan operations on the same
5895 * interface since the driver_nl80211 mechanism for tracking
5896 * scan cookies does not yet have support for this. */
5897 if (active_work->wpa_s == tmp->wpa_s &&
5898 radio_work_is_scan(active_work) &&
5899 radio_work_is_scan(tmp)) {
5900 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5901 "Do not start work '%s' when another work '%s' is already scheduled",
5902 tmp->type, active_work->type);
5903 continue;
5904 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005905 /*
5906 * Check that the radio works are distinct and
5907 * on different bands.
5908 */
5909 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5910 (active_work->bands != tmp->bands)) {
5911 /*
5912 * If a scan has to be scheduled through nl80211 scan
5913 * interface and if an external scan is already running,
5914 * do not schedule the scan since it is likely to get
5915 * rejected by kernel.
5916 */
5917 if (os_strcmp(tmp->type, "scan") == 0 &&
5918 radio->external_scan_running &&
5919 (((struct wpa_driver_scan_params *)
5920 tmp->ctx)->only_new_results ||
5921 tmp->wpa_s->clear_driver_scan_cache))
5922 continue;
5923
5924 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5925 "active_work:%s new_work:%s",
5926 active_work->type, tmp->type);
5927 return tmp;
5928 }
5929 }
5930
5931 /* Did not find a radio work to schedule in parallel. */
5932 return NULL;
5933}
5934
5935
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005936static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5937{
5938 struct wpa_radio *radio = eloop_ctx;
5939 struct wpa_radio_work *work;
5940 struct os_reltime now, diff;
5941 struct wpa_supplicant *wpa_s;
5942
5943 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005944 if (work == NULL) {
5945 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005946 return;
5947 }
5948
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005949 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5950 radio_list);
5951
5952 if (!(wpa_s &&
5953 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5954 if (work->started)
5955 return; /* already started and still in progress */
5956
5957 if (wpa_s && wpa_s->radio->external_scan_running) {
5958 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5959 return;
5960 }
5961 } else {
5962 work = NULL;
5963 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5964 /* get the work to schedule next */
5965 work = radio_work_get_next_work(radio);
5966 }
5967 if (!work)
5968 return;
5969 }
5970
5971 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005972 os_get_reltime(&now);
5973 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005974 wpa_dbg(wpa_s, MSG_DEBUG,
5975 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005976 work->type, work, diff.sec, diff.usec);
5977 work->started = 1;
5978 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005979 radio->num_active_works++;
5980
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005981 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005982
5983 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5984 radio->num_active_works < MAX_ACTIVE_WORKS)
5985 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005986}
5987
5988
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005989/*
5990 * This function removes both started and pending radio works running on
5991 * the provided interface's radio.
5992 * Prior to the removal of the radio work, its callback (cb) is called with
5993 * deinit set to be 1. Each work's callback is responsible for clearing its
5994 * internal data and restoring to a correct state.
5995 * @wpa_s: wpa_supplicant data
5996 * @type: type of works to be removed
5997 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5998 * this interface's works.
5999 */
6000void radio_remove_works(struct wpa_supplicant *wpa_s,
6001 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006002{
6003 struct wpa_radio_work *work, *tmp;
6004 struct wpa_radio *radio = wpa_s->radio;
6005
6006 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6007 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006008 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006009 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006010
6011 /* skip other ifaces' works */
6012 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006013 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006014
6015 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6016 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006017 work->cb(work, 1);
6018 radio_work_free(work);
6019 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006020
6021 /* in case we removed the started work */
6022 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006023}
6024
6025
Roshan Pius3a1667e2018-07-03 15:17:14 -07006026void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6027{
6028 struct wpa_radio_work *work;
6029 struct wpa_radio *radio = wpa_s->radio;
6030
6031 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6032 if (work->ctx != ctx)
6033 continue;
6034 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6035 work->type, work, work->started ? " (started)" : "");
6036 radio_work_free(work);
6037 break;
6038 }
6039}
6040
6041
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006042static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6043{
6044 struct wpa_radio *radio = wpa_s->radio;
6045
6046 if (!radio)
6047 return;
6048
6049 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6050 wpa_s->ifname, radio->name);
6051 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006052 radio_remove_works(wpa_s, NULL, 0);
6053 wpa_s->radio = NULL;
6054 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006055 return; /* Interfaces remain for this radio */
6056
6057 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006058 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006059 os_free(radio);
6060}
6061
6062
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006063void radio_work_check_next(struct wpa_supplicant *wpa_s)
6064{
6065 struct wpa_radio *radio = wpa_s->radio;
6066
6067 if (dl_list_empty(&radio->work))
6068 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006069 if (wpa_s->ext_work_in_progress) {
6070 wpa_printf(MSG_DEBUG,
6071 "External radio work in progress - delay start of pending item");
6072 return;
6073 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006074 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6075 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6076}
6077
6078
6079/**
6080 * radio_add_work - Add a radio work item
6081 * @wpa_s: Pointer to wpa_supplicant data
6082 * @freq: Frequency of the offchannel operation in MHz or 0
6083 * @type: Unique identifier for each type of work
6084 * @next: Force as the next work to be executed
6085 * @cb: Callback function for indicating when radio is available
6086 * @ctx: Context pointer for the work (work->ctx in cb())
6087 * Returns: 0 on success, -1 on failure
6088 *
6089 * This function is used to request time for an operation that requires
6090 * exclusive radio control. Once the radio is available, the registered callback
6091 * function will be called. radio_work_done() must be called once the exclusive
6092 * radio operation has been completed, so that the radio is freed for other
6093 * operations. The special case of deinit=1 is used to free the context data
6094 * during interface removal. That does not allow the callback function to start
6095 * the radio operation, i.e., it must free any resources allocated for the radio
6096 * work and return.
6097 *
6098 * The @freq parameter can be used to indicate a single channel on which the
6099 * offchannel operation will occur. This may allow multiple radio work
6100 * operations to be performed in parallel if they apply for the same channel.
6101 * Setting this to 0 indicates that the work item may use multiple channels or
6102 * requires exclusive control of the radio.
6103 */
6104int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6105 const char *type, int next,
6106 void (*cb)(struct wpa_radio_work *work, int deinit),
6107 void *ctx)
6108{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006109 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006110 struct wpa_radio_work *work;
6111 int was_empty;
6112
6113 work = os_zalloc(sizeof(*work));
6114 if (work == NULL)
6115 return -1;
6116 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6117 os_get_reltime(&work->time);
6118 work->freq = freq;
6119 work->type = type;
6120 work->wpa_s = wpa_s;
6121 work->cb = cb;
6122 work->ctx = ctx;
6123
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006124 if (freq)
6125 work->bands = wpas_freq_to_band(freq);
6126 else if (os_strcmp(type, "scan") == 0 ||
6127 os_strcmp(type, "p2p-scan") == 0)
6128 work->bands = wpas_get_bands(wpa_s,
6129 ((struct wpa_driver_scan_params *)
6130 ctx)->freqs);
6131 else
6132 work->bands = wpas_get_bands(wpa_s, NULL);
6133
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006134 was_empty = dl_list_empty(&wpa_s->radio->work);
6135 if (next)
6136 dl_list_add(&wpa_s->radio->work, &work->list);
6137 else
6138 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6139 if (was_empty) {
6140 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6141 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006142 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6143 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6144 wpa_dbg(wpa_s, MSG_DEBUG,
6145 "Try to schedule a radio work (num_active_works=%u)",
6146 radio->num_active_works);
6147 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006148 }
6149
6150 return 0;
6151}
6152
6153
6154/**
6155 * radio_work_done - Indicate that a radio work item has been completed
6156 * @work: Completed work
6157 *
6158 * This function is called once the callback function registered with
6159 * radio_add_work() has completed its work.
6160 */
6161void radio_work_done(struct wpa_radio_work *work)
6162{
6163 struct wpa_supplicant *wpa_s = work->wpa_s;
6164 struct os_reltime now, diff;
6165 unsigned int started = work->started;
6166
6167 os_get_reltime(&now);
6168 os_reltime_sub(&now, &work->time, &diff);
6169 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6170 work->type, work, started ? "done" : "canceled",
6171 diff.sec, diff.usec);
6172 radio_work_free(work);
6173 if (started)
6174 radio_work_check_next(wpa_s);
6175}
6176
6177
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006178struct wpa_radio_work *
6179radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006180{
6181 struct wpa_radio_work *work;
6182 struct wpa_radio *radio = wpa_s->radio;
6183
6184 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6185 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006186 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006187 }
6188
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006189 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006190}
6191
6192
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006193static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006194 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006195{
6196 const char *ifname, *driver, *rn;
6197
6198 driver = iface->driver;
6199next_driver:
6200 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6201 return -1;
6202
6203 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6204 if (wpa_s->drv_priv == NULL) {
6205 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006206 int level = MSG_ERROR;
6207
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006208 pos = driver ? os_strchr(driver, ',') : NULL;
6209 if (pos) {
6210 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6211 "driver interface - try next driver wrapper");
6212 driver = pos + 1;
6213 goto next_driver;
6214 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006215
6216#ifdef CONFIG_MATCH_IFACE
6217 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6218 level = MSG_DEBUG;
6219#endif /* CONFIG_MATCH_IFACE */
6220 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006221 return -1;
6222 }
6223 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6224 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6225 "driver_param '%s'", wpa_s->conf->driver_param);
6226 return -1;
6227 }
6228
6229 ifname = wpa_drv_get_ifname(wpa_s);
6230 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6231 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6232 "interface name with '%s'", ifname);
6233 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6234 }
6235
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006236 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006237 if (rn && rn[0] == '\0')
6238 rn = NULL;
6239
6240 wpa_s->radio = radio_add_interface(wpa_s, rn);
6241 if (wpa_s->radio == NULL)
6242 return -1;
6243
6244 return 0;
6245}
6246
6247
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006248#ifdef CONFIG_GAS_SERVER
6249
6250static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6251 unsigned int freq, const u8 *dst,
6252 const u8 *src, const u8 *bssid,
6253 const u8 *data, size_t data_len,
6254 enum offchannel_send_action_result result)
6255{
6256 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6257 " result=%s",
6258 freq, MAC2STR(dst),
6259 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6260 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6261 "FAILED"));
6262 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6263 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6264}
6265
6266
6267static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6268 struct wpabuf *buf, unsigned int wait_time)
6269{
6270 struct wpa_supplicant *wpa_s = ctx;
6271 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6272
6273 if (wait_time > wpa_s->max_remain_on_chan)
6274 wait_time = wpa_s->max_remain_on_chan;
6275
6276 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6277 wpabuf_head(buf), wpabuf_len(buf),
6278 wait_time, wpas_gas_server_tx_status, 0);
6279}
6280
6281#endif /* CONFIG_GAS_SERVER */
6282
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006283static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006284 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006285{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006286 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006287 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006288 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006289
6290 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6291 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6292 iface->confname ? iface->confname : "N/A",
6293 iface->driver ? iface->driver : "default",
6294 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6295 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6296
6297 if (iface->confname) {
6298#ifdef CONFIG_BACKEND_FILE
6299 wpa_s->confname = os_rel2abs_path(iface->confname);
6300 if (wpa_s->confname == NULL) {
6301 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6302 "for configuration file '%s'.",
6303 iface->confname);
6304 return -1;
6305 }
6306 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6307 iface->confname, wpa_s->confname);
6308#else /* CONFIG_BACKEND_FILE */
6309 wpa_s->confname = os_strdup(iface->confname);
6310#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006311 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006312 if (wpa_s->conf == NULL) {
6313 wpa_printf(MSG_ERROR, "Failed to read or parse "
6314 "configuration '%s'.", wpa_s->confname);
6315 return -1;
6316 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006317 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006318 if (wpa_s->confanother &&
6319 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6320 wpa_printf(MSG_ERROR,
6321 "Failed to read or parse configuration '%s'.",
6322 wpa_s->confanother);
6323 return -1;
6324 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006325
6326 /*
6327 * Override ctrl_interface and driver_param if set on command
6328 * line.
6329 */
6330 if (iface->ctrl_interface) {
6331 os_free(wpa_s->conf->ctrl_interface);
6332 wpa_s->conf->ctrl_interface =
6333 os_strdup(iface->ctrl_interface);
6334 }
6335
6336 if (iface->driver_param) {
6337 os_free(wpa_s->conf->driver_param);
6338 wpa_s->conf->driver_param =
6339 os_strdup(iface->driver_param);
6340 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006341
6342 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6343 os_free(wpa_s->conf->ctrl_interface);
6344 wpa_s->conf->ctrl_interface = NULL;
6345 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006346 } else
6347 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6348 iface->driver_param);
6349
6350 if (wpa_s->conf == NULL) {
6351 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6352 return -1;
6353 }
6354
6355 if (iface->ifname == NULL) {
6356 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6357 return -1;
6358 }
6359 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6360 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6361 iface->ifname);
6362 return -1;
6363 }
6364 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006365#ifdef CONFIG_MATCH_IFACE
6366 wpa_s->matched = iface->matched;
6367#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006368
6369 if (iface->bridge_ifname) {
6370 if (os_strlen(iface->bridge_ifname) >=
6371 sizeof(wpa_s->bridge_ifname)) {
6372 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6373 "name '%s'.", iface->bridge_ifname);
6374 return -1;
6375 }
6376 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6377 sizeof(wpa_s->bridge_ifname));
6378 }
6379
6380 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006381 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6382 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006383
6384 /* Initialize driver interface and register driver event handler before
6385 * L2 receive handler so that association events are processed before
6386 * EAPOL-Key packets if both become available for the same select()
6387 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006388 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006389 return -1;
6390
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006391 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6392 return -1;
6393
6394 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6395 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6396 NULL);
6397 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6398
6399 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6400 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6401 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6402 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6403 "dot11RSNAConfigPMKLifetime");
6404 return -1;
6405 }
6406
6407 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6408 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6409 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6410 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6411 "dot11RSNAConfigPMKReauthThreshold");
6412 return -1;
6413 }
6414
6415 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6416 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6417 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6418 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6419 "dot11RSNAConfigSATimeout");
6420 return -1;
6421 }
6422
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006423 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6424 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006425 &wpa_s->hw.flags,
6426 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006427 if (wpa_s->hw.modes) {
6428 u16 i;
6429
6430 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6431 if (wpa_s->hw.modes[i].vht_capab) {
6432 wpa_s->hw_capab = CAPAB_VHT;
6433 break;
6434 }
6435
6436 if (wpa_s->hw.modes[i].ht_capab &
6437 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6438 wpa_s->hw_capab = CAPAB_HT40;
6439 else if (wpa_s->hw.modes[i].ht_capab &&
6440 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6441 wpa_s->hw_capab = CAPAB_HT;
6442 }
6443 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006444
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006445 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6446 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006447 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006448 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006449 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006450 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006451 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006452 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006453 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006454 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006455 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6456 wpa_s->max_sched_scan_plan_interval =
6457 capa.max_sched_scan_plan_interval;
6458 wpa_s->max_sched_scan_plan_iterations =
6459 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006460 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6461 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006462 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6463 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006464 wpa_s->extended_capa = capa.extended_capa;
6465 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6466 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006467 wpa_s->num_multichan_concurrent =
6468 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006469 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6470
6471 if (capa.mac_addr_rand_scan_supported)
6472 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6473 if (wpa_s->sched_scan_supported &&
6474 capa.mac_addr_rand_sched_scan_supported)
6475 wpa_s->mac_addr_rand_supported |=
6476 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006477
6478 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6479 if (wpa_s->extended_capa &&
6480 wpa_s->extended_capa_len >= 3 &&
6481 wpa_s->extended_capa[2] & 0x40)
6482 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006483 }
6484 if (wpa_s->max_remain_on_chan == 0)
6485 wpa_s->max_remain_on_chan = 1000;
6486
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006487 /*
6488 * Only take p2p_mgmt parameters when P2P Device is supported.
6489 * Doing it here as it determines whether l2_packet_init() will be done
6490 * during wpa_supplicant_driver_init().
6491 */
6492 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6493 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006494
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006495 if (wpa_s->num_multichan_concurrent == 0)
6496 wpa_s->num_multichan_concurrent = 1;
6497
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006498 if (wpa_supplicant_driver_init(wpa_s) < 0)
6499 return -1;
6500
6501#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006502 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006503 return -1;
6504#endif /* CONFIG_TDLS */
6505
6506 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6507 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6508 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6509 return -1;
6510 }
6511
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006512#ifdef CONFIG_FST
6513 if (wpa_s->conf->fst_group_id) {
6514 struct fst_iface_cfg cfg;
6515 struct fst_wpa_obj iface_obj;
6516
6517 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6518 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6519 sizeof(cfg.group_id));
6520 cfg.priority = wpa_s->conf->fst_priority;
6521 cfg.llt = wpa_s->conf->fst_llt;
6522
6523 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6524 &iface_obj, &cfg);
6525 if (!wpa_s->fst) {
6526 wpa_msg(wpa_s, MSG_ERROR,
6527 "FST: Cannot attach iface %s to group %s",
6528 wpa_s->ifname, cfg.group_id);
6529 return -1;
6530 }
6531 }
6532#endif /* CONFIG_FST */
6533
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006534 if (wpas_wps_init(wpa_s))
6535 return -1;
6536
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006537#ifdef CONFIG_GAS_SERVER
6538 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6539 if (!wpa_s->gas_server) {
6540 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6541 return -1;
6542 }
6543#endif /* CONFIG_GAS_SERVER */
6544
6545#ifdef CONFIG_DPP
6546 if (wpas_dpp_init(wpa_s) < 0)
6547 return -1;
6548#endif /* CONFIG_DPP */
6549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006550 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6551 return -1;
6552 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6553
6554 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6555 if (wpa_s->ctrl_iface == NULL) {
6556 wpa_printf(MSG_ERROR,
6557 "Failed to initialize control interface '%s'.\n"
6558 "You may have another wpa_supplicant process "
6559 "already running or the file was\n"
6560 "left by an unclean termination of wpa_supplicant "
6561 "in which case you will need\n"
6562 "to manually remove this file before starting "
6563 "wpa_supplicant again.\n",
6564 wpa_s->conf->ctrl_interface);
6565 return -1;
6566 }
6567
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006568 wpa_s->gas = gas_query_init(wpa_s);
6569 if (wpa_s->gas == NULL) {
6570 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6571 return -1;
6572 }
6573
Roshan Pius3a1667e2018-07-03 15:17:14 -07006574 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6575 wpa_s->p2p_mgmt) &&
6576 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006577 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6578 return -1;
6579 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006580
6581 if (wpa_bss_init(wpa_s) < 0)
6582 return -1;
6583
Paul Stewart092955c2017-02-06 09:13:09 -08006584#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6585#ifdef CONFIG_MESH
6586 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6587#endif /* CONFIG_MESH */
6588#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6589
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006590 /*
6591 * Set Wake-on-WLAN triggers, if configured.
6592 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6593 * have effect anyway when the interface is down).
6594 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006595 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006596 return -1;
6597
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006598#ifdef CONFIG_EAP_PROXY
6599{
6600 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006601 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6602 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006603 if (wpa_s->mnc_len > 0) {
6604 wpa_s->imsi[len] = '\0';
6605 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6606 wpa_s->imsi, wpa_s->mnc_len);
6607 } else {
6608 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6609 }
6610}
6611#endif /* CONFIG_EAP_PROXY */
6612
Dmitry Shmidt04949592012-07-19 12:16:46 -07006613 if (pcsc_reader_init(wpa_s) < 0)
6614 return -1;
6615
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006616 if (wpas_init_ext_pw(wpa_s) < 0)
6617 return -1;
6618
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006619 wpas_rrm_reset(wpa_s);
6620
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006621 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6622
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006623#ifdef CONFIG_HS20
6624 hs20_init(wpa_s);
6625#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006626#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006627 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006628 if ((wpa_s->conf->oce & OCE_STA) &&
6629 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6630 wpa_s->enable_oce = OCE_STA;
6631 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6632 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6633 /* TODO: Need to add STA-CFON support */
6634 wpa_printf(MSG_ERROR,
6635 "OCE STA-CFON feature is not yet supported");
6636 }
6637 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006638 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6639#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006640
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006641 wpa_supplicant_set_default_scan_ies(wpa_s);
6642
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006643 return 0;
6644}
6645
6646
6647static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006648 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006649{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006650 struct wpa_global *global = wpa_s->global;
6651 struct wpa_supplicant *iface, *prev;
6652
6653 if (wpa_s == wpa_s->parent)
6654 wpas_p2p_group_remove(wpa_s, "*");
6655
6656 iface = global->ifaces;
6657 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006658 if (iface->p2pdev == wpa_s)
6659 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006660 if (iface == wpa_s || iface->parent != wpa_s) {
6661 iface = iface->next;
6662 continue;
6663 }
6664 wpa_printf(MSG_DEBUG,
6665 "Remove remaining child interface %s from parent %s",
6666 iface->ifname, wpa_s->ifname);
6667 prev = iface;
6668 iface = iface->next;
6669 wpa_supplicant_remove_iface(global, prev, terminate);
6670 }
6671
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006672 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006673 if (wpa_s->drv_priv) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006674 /* Don't deauthenticate if WoWLAN is enabled */
6675 if (!wpa_drv_get_wowlan(wpa_s)) {
6676 wpa_supplicant_deauthenticate(
6677 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006678
Hai Shalomfdcde762020-04-02 11:19:20 -07006679 wpa_drv_set_countermeasures(wpa_s, 0);
6680 wpa_clear_keys(wpa_s, NULL);
6681 } else {
6682 wpa_msg(wpa_s, MSG_INFO,
6683 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6684 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006685 }
6686
6687 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006688 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006689
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006690 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006691 radio_remove_interface(wpa_s);
6692
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006693#ifdef CONFIG_FST
6694 if (wpa_s->fst) {
6695 fst_detach(wpa_s->fst);
6696 wpa_s->fst = NULL;
6697 }
6698 if (wpa_s->received_mb_ies) {
6699 wpabuf_free(wpa_s->received_mb_ies);
6700 wpa_s->received_mb_ies = NULL;
6701 }
6702#endif /* CONFIG_FST */
6703
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006704 if (wpa_s->drv_priv)
6705 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006706
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006707 if (notify)
6708 wpas_notify_iface_removed(wpa_s);
6709
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006710 if (terminate)
6711 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006712
6713 if (wpa_s->ctrl_iface) {
6714 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6715 wpa_s->ctrl_iface = NULL;
6716 }
6717
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006718#ifdef CONFIG_MESH
6719 if (wpa_s->ifmsh) {
6720 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6721 wpa_s->ifmsh = NULL;
6722 }
6723#endif /* CONFIG_MESH */
6724
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006725 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006726 wpa_config_free(wpa_s->conf);
6727 wpa_s->conf = NULL;
6728 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006729
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006730 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006731 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006732
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006733 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006734}
6735
6736
Dmitry Shmidte4663042016-04-04 10:07:49 -07006737#ifdef CONFIG_MATCH_IFACE
6738
6739/**
6740 * wpa_supplicant_match_iface - Match an interface description to a name
6741 * @global: Pointer to global data from wpa_supplicant_init()
6742 * @ifname: Name of the interface to match
6743 * Returns: Pointer to the created interface description or %NULL on failure
6744 */
6745struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6746 const char *ifname)
6747{
6748 int i;
6749 struct wpa_interface *iface, *miface;
6750
6751 for (i = 0; i < global->params.match_iface_count; i++) {
6752 miface = &global->params.match_ifaces[i];
6753 if (!miface->ifname ||
6754 fnmatch(miface->ifname, ifname, 0) == 0) {
6755 iface = os_zalloc(sizeof(*iface));
6756 if (!iface)
6757 return NULL;
6758 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07006759 if (!miface->ifname)
6760 iface->matched = WPA_IFACE_MATCHED_NULL;
6761 else
6762 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07006763 iface->ifname = ifname;
6764 return iface;
6765 }
6766 }
6767
6768 return NULL;
6769}
6770
6771
6772/**
6773 * wpa_supplicant_match_existing - Match existing interfaces
6774 * @global: Pointer to global data from wpa_supplicant_init()
6775 * Returns: 0 on success, -1 on failure
6776 */
6777static int wpa_supplicant_match_existing(struct wpa_global *global)
6778{
6779 struct if_nameindex *ifi, *ifp;
6780 struct wpa_supplicant *wpa_s;
6781 struct wpa_interface *iface;
6782
6783 ifp = if_nameindex();
6784 if (!ifp) {
6785 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6786 return -1;
6787 }
6788
6789 for (ifi = ifp; ifi->if_name; ifi++) {
6790 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6791 if (wpa_s)
6792 continue;
6793 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6794 if (iface) {
6795 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6796 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006797 }
6798 }
6799
6800 if_freenameindex(ifp);
6801 return 0;
6802}
6803
6804#endif /* CONFIG_MATCH_IFACE */
6805
6806
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006807/**
6808 * wpa_supplicant_add_iface - Add a new network interface
6809 * @global: Pointer to global data from wpa_supplicant_init()
6810 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006811 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006812 * Returns: Pointer to the created interface or %NULL on failure
6813 *
6814 * This function is used to add new network interfaces for %wpa_supplicant.
6815 * This can be called before wpa_supplicant_run() to add interfaces before the
6816 * main event loop has been started. In addition, new interfaces can be added
6817 * dynamically while %wpa_supplicant is already running. This could happen,
6818 * e.g., when a hotplug network adapter is inserted.
6819 */
6820struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006821 struct wpa_interface *iface,
6822 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006823{
6824 struct wpa_supplicant *wpa_s;
6825 struct wpa_interface t_iface;
6826 struct wpa_ssid *ssid;
6827
6828 if (global == NULL || iface == NULL)
6829 return NULL;
6830
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006831 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006832 if (wpa_s == NULL)
6833 return NULL;
6834
6835 wpa_s->global = global;
6836
6837 t_iface = *iface;
6838 if (global->params.override_driver) {
6839 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6840 "('%s' -> '%s')",
6841 iface->driver, global->params.override_driver);
6842 t_iface.driver = global->params.override_driver;
6843 }
6844 if (global->params.override_ctrl_interface) {
6845 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6846 "ctrl_interface ('%s' -> '%s')",
6847 iface->ctrl_interface,
6848 global->params.override_ctrl_interface);
6849 t_iface.ctrl_interface =
6850 global->params.override_ctrl_interface;
6851 }
6852 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6853 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6854 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006855 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006856 return NULL;
6857 }
6858
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006859 /* Notify the control interfaces about new iface */
6860 if (wpas_notify_iface_added(wpa_s)) {
6861 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6862 return NULL;
6863 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006864
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006865 /* Notify the control interfaces about new networks for non p2p mgmt
6866 * ifaces. */
6867 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006868 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6869 wpas_notify_network_added(wpa_s, ssid);
6870 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006871
6872 wpa_s->next = global->ifaces;
6873 global->ifaces = wpa_s;
6874
6875 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006876 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006877
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006878#ifdef CONFIG_P2P
6879 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006880 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006881 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006882 wpas_p2p_add_p2pdev_interface(
6883 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006884 wpa_printf(MSG_INFO,
6885 "P2P: Failed to enable P2P Device interface");
6886 /* Try to continue without. P2P will be disabled. */
6887 }
6888#endif /* CONFIG_P2P */
6889
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006890 return wpa_s;
6891}
6892
6893
6894/**
6895 * wpa_supplicant_remove_iface - Remove a network interface
6896 * @global: Pointer to global data from wpa_supplicant_init()
6897 * @wpa_s: Pointer to the network interface to be removed
6898 * Returns: 0 if interface was removed, -1 if interface was not found
6899 *
6900 * This function can be used to dynamically remove network interfaces from
6901 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6902 * addition, this function is used to remove all remaining interfaces when
6903 * %wpa_supplicant is terminated.
6904 */
6905int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006906 struct wpa_supplicant *wpa_s,
6907 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006908{
6909 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006910#ifdef CONFIG_MESH
6911 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6912 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006913 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006914#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006915
6916 /* Remove interface from the global list of interfaces */
6917 prev = global->ifaces;
6918 if (prev == wpa_s) {
6919 global->ifaces = wpa_s->next;
6920 } else {
6921 while (prev && prev->next != wpa_s)
6922 prev = prev->next;
6923 if (prev == NULL)
6924 return -1;
6925 prev->next = wpa_s->next;
6926 }
6927
6928 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6929
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006930#ifdef CONFIG_MESH
6931 if (mesh_if_created) {
6932 ifname = os_strdup(wpa_s->ifname);
6933 if (ifname == NULL) {
6934 wpa_dbg(wpa_s, MSG_ERROR,
6935 "mesh: Failed to malloc ifname");
6936 return -1;
6937 }
6938 }
6939#endif /* CONFIG_MESH */
6940
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006941 if (global->p2p_group_formation == wpa_s)
6942 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006943 if (global->p2p_invite_group == wpa_s)
6944 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006945 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006946
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006947#ifdef CONFIG_MESH
6948 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006949 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006950 os_free(ifname);
6951 }
6952#endif /* CONFIG_MESH */
6953
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006954 return 0;
6955}
6956
6957
6958/**
6959 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6960 * @wpa_s: Pointer to the network interface
6961 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6962 */
6963const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6964{
6965 const char *eapol_method;
6966
6967 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6968 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6969 return "NO-EAP";
6970 }
6971
6972 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6973 if (eapol_method == NULL)
6974 return "UNKNOWN-EAP";
6975
6976 return eapol_method;
6977}
6978
6979
6980/**
6981 * wpa_supplicant_get_iface - Get a new network interface
6982 * @global: Pointer to global data from wpa_supplicant_init()
6983 * @ifname: Interface name
6984 * Returns: Pointer to the interface or %NULL if not found
6985 */
6986struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6987 const char *ifname)
6988{
6989 struct wpa_supplicant *wpa_s;
6990
6991 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6992 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6993 return wpa_s;
6994 }
6995 return NULL;
6996}
6997
6998
6999#ifndef CONFIG_NO_WPA_MSG
7000static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
7001{
7002 struct wpa_supplicant *wpa_s = ctx;
7003 if (wpa_s == NULL)
7004 return NULL;
7005 return wpa_s->ifname;
7006}
7007#endif /* CONFIG_NO_WPA_MSG */
7008
7009
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007010#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7011#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7012#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7013
7014/* Periodic cleanup tasks */
7015static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7016{
7017 struct wpa_global *global = eloop_ctx;
7018 struct wpa_supplicant *wpa_s;
7019
7020 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7021 wpas_periodic, global, NULL);
7022
7023#ifdef CONFIG_P2P
7024 if (global->p2p)
7025 p2p_expire_peers(global->p2p);
7026#endif /* CONFIG_P2P */
7027
7028 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7029 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7030#ifdef CONFIG_AP
7031 ap_periodic(wpa_s);
7032#endif /* CONFIG_AP */
7033 }
7034}
7035
7036
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007037/**
7038 * wpa_supplicant_init - Initialize %wpa_supplicant
7039 * @params: Parameters for %wpa_supplicant
7040 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7041 *
7042 * This function is used to initialize %wpa_supplicant. After successful
7043 * initialization, the returned data pointer can be used to add and remove
7044 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7045 */
7046struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7047{
7048 struct wpa_global *global;
7049 int ret, i;
7050
7051 if (params == NULL)
7052 return NULL;
7053
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007054#ifdef CONFIG_DRIVER_NDIS
7055 {
7056 void driver_ndis_init_ops(void);
7057 driver_ndis_init_ops();
7058 }
7059#endif /* CONFIG_DRIVER_NDIS */
7060
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007061#ifndef CONFIG_NO_WPA_MSG
7062 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7063#endif /* CONFIG_NO_WPA_MSG */
7064
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007065 if (params->wpa_debug_file_path)
7066 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007067 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007068 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007069 if (params->wpa_debug_syslog)
7070 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007071 if (params->wpa_debug_tracing) {
7072 ret = wpa_debug_open_linux_tracing();
7073 if (ret) {
7074 wpa_printf(MSG_ERROR,
7075 "Failed to enable trace logging");
7076 return NULL;
7077 }
7078 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007079
7080 ret = eap_register_methods();
7081 if (ret) {
7082 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7083 if (ret == -2)
7084 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7085 "the same EAP type.");
7086 return NULL;
7087 }
7088
7089 global = os_zalloc(sizeof(*global));
7090 if (global == NULL)
7091 return NULL;
7092 dl_list_init(&global->p2p_srv_bonjour);
7093 dl_list_init(&global->p2p_srv_upnp);
7094 global->params.daemonize = params->daemonize;
7095 global->params.wait_for_monitor = params->wait_for_monitor;
7096 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7097 if (params->pid_file)
7098 global->params.pid_file = os_strdup(params->pid_file);
7099 if (params->ctrl_interface)
7100 global->params.ctrl_interface =
7101 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007102 if (params->ctrl_interface_group)
7103 global->params.ctrl_interface_group =
7104 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007105 if (params->override_driver)
7106 global->params.override_driver =
7107 os_strdup(params->override_driver);
7108 if (params->override_ctrl_interface)
7109 global->params.override_ctrl_interface =
7110 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007111#ifdef CONFIG_MATCH_IFACE
7112 global->params.match_iface_count = params->match_iface_count;
7113 if (params->match_iface_count) {
7114 global->params.match_ifaces =
7115 os_calloc(params->match_iface_count,
7116 sizeof(struct wpa_interface));
7117 os_memcpy(global->params.match_ifaces,
7118 params->match_ifaces,
7119 params->match_iface_count *
7120 sizeof(struct wpa_interface));
7121 }
7122#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007123#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007124 if (params->conf_p2p_dev)
7125 global->params.conf_p2p_dev =
7126 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007127#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007128 wpa_debug_level = global->params.wpa_debug_level =
7129 params->wpa_debug_level;
7130 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7131 params->wpa_debug_show_keys;
7132 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7133 params->wpa_debug_timestamp;
7134
Hai Shalomfdcde762020-04-02 11:19:20 -07007135 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007136
7137 if (eloop_init()) {
7138 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7139 wpa_supplicant_deinit(global);
7140 return NULL;
7141 }
7142
Jouni Malinen75ecf522011-06-27 15:19:46 -07007143 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007144
7145 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7146 if (global->ctrl_iface == NULL) {
7147 wpa_supplicant_deinit(global);
7148 return NULL;
7149 }
7150
7151 if (wpas_notify_supplicant_initialized(global)) {
7152 wpa_supplicant_deinit(global);
7153 return NULL;
7154 }
7155
7156 for (i = 0; wpa_drivers[i]; i++)
7157 global->drv_count++;
7158 if (global->drv_count == 0) {
7159 wpa_printf(MSG_ERROR, "No drivers enabled");
7160 wpa_supplicant_deinit(global);
7161 return NULL;
7162 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007163 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007164 if (global->drv_priv == NULL) {
7165 wpa_supplicant_deinit(global);
7166 return NULL;
7167 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007168
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007169#ifdef CONFIG_WIFI_DISPLAY
7170 if (wifi_display_init(global) < 0) {
7171 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7172 wpa_supplicant_deinit(global);
7173 return NULL;
7174 }
7175#endif /* CONFIG_WIFI_DISPLAY */
7176
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007177 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7178 wpas_periodic, global, NULL);
7179
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007180 return global;
7181}
7182
7183
7184/**
7185 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7186 * @global: Pointer to global data from wpa_supplicant_init()
7187 * Returns: 0 after successful event loop run, -1 on failure
7188 *
7189 * This function starts the main event loop and continues running as long as
7190 * there are any remaining events. In most cases, this function is running as
7191 * long as the %wpa_supplicant process in still in use.
7192 */
7193int wpa_supplicant_run(struct wpa_global *global)
7194{
7195 struct wpa_supplicant *wpa_s;
7196
7197 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007198 (wpa_supplicant_daemon(global->params.pid_file) ||
7199 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007200 return -1;
7201
Dmitry Shmidte4663042016-04-04 10:07:49 -07007202#ifdef CONFIG_MATCH_IFACE
7203 if (wpa_supplicant_match_existing(global))
7204 return -1;
7205#endif
7206
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007207 if (global->params.wait_for_monitor) {
7208 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007209 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007210 wpa_supplicant_ctrl_iface_wait(
7211 wpa_s->ctrl_iface);
7212 }
7213
7214 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7215 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7216
7217 eloop_run();
7218
7219 return 0;
7220}
7221
7222
7223/**
7224 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7225 * @global: Pointer to global data from wpa_supplicant_init()
7226 *
7227 * This function is called to deinitialize %wpa_supplicant and to free all
7228 * allocated resources. Remaining network interfaces will also be removed.
7229 */
7230void wpa_supplicant_deinit(struct wpa_global *global)
7231{
7232 int i;
7233
7234 if (global == NULL)
7235 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007236
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007237 eloop_cancel_timeout(wpas_periodic, global, NULL);
7238
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007239#ifdef CONFIG_WIFI_DISPLAY
7240 wifi_display_deinit(global);
7241#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007242
7243 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007244 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007245
7246 if (global->ctrl_iface)
7247 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7248
7249 wpas_notify_supplicant_deinitialized(global);
7250
7251 eap_peer_unregister_methods();
7252#ifdef CONFIG_AP
7253 eap_server_unregister_methods();
7254#endif /* CONFIG_AP */
7255
7256 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7257 if (!global->drv_priv[i])
7258 continue;
7259 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7260 }
7261 os_free(global->drv_priv);
7262
7263 random_deinit();
7264
7265 eloop_destroy();
7266
7267 if (global->params.pid_file) {
7268 os_daemonize_terminate(global->params.pid_file);
7269 os_free(global->params.pid_file);
7270 }
7271 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007272 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007273 os_free(global->params.override_driver);
7274 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007275#ifdef CONFIG_MATCH_IFACE
7276 os_free(global->params.match_ifaces);
7277#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007278#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007279 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007280#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007281
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007282 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007283 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007284 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007285
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007286 os_free(global);
7287 wpa_debug_close_syslog();
7288 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007289 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007290}
7291
7292
7293void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7294{
7295 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7296 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7297 char country[3];
7298 country[0] = wpa_s->conf->country[0];
7299 country[1] = wpa_s->conf->country[1];
7300 country[2] = '\0';
7301 if (wpa_drv_set_country(wpa_s, country) < 0) {
7302 wpa_printf(MSG_ERROR, "Failed to set country code "
7303 "'%s'", country);
7304 }
7305 }
7306
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007307 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7308 wpas_init_ext_pw(wpa_s);
7309
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007310 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7311 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7312
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007313 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7314 struct wpa_driver_capa capa;
7315 int res = wpa_drv_get_capa(wpa_s, &capa);
7316
7317 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7318 wpa_printf(MSG_ERROR,
7319 "Failed to update wowlan_triggers to '%s'",
7320 wpa_s->conf->wowlan_triggers);
7321 }
7322
Hai Shalom81f62d82019-07-22 12:10:00 -07007323 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7324 wpa_supplicant_set_default_scan_ies(wpa_s);
7325
Hai Shalom899fcc72020-10-19 14:38:18 -07007326#ifdef CONFIG_BGSCAN
7327 /*
7328 * We default to global bgscan parameters only when per-network bgscan
7329 * parameters aren't set. Only bother resetting bgscan parameters if
7330 * this is the case.
7331 */
7332 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7333 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7334 wpa_s->wpa_state == WPA_COMPLETED)
7335 wpa_supplicant_reset_bgscan(wpa_s);
7336#endif /* CONFIG_BGSCAN */
7337
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007338#ifdef CONFIG_WPS
7339 wpas_wps_update_config(wpa_s);
7340#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007341 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007342 wpa_s->conf->changed_parameters = 0;
7343}
7344
7345
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007346void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007347{
7348 int i;
7349
7350 for (i = 0; i < *num_freqs; i++) {
7351 if (freqs[i] == freq)
7352 return;
7353 }
7354
7355 freqs[*num_freqs] = freq;
7356 (*num_freqs)++;
7357}
7358
7359
7360static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7361{
7362 struct wpa_bss *bss, *cbss;
7363 const int max_freqs = 10;
7364 int *freqs;
7365 int num_freqs = 0;
7366
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007367 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007368 if (freqs == NULL)
7369 return NULL;
7370
7371 cbss = wpa_s->current_bss;
7372
7373 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7374 if (bss == cbss)
7375 continue;
7376 if (bss->ssid_len == cbss->ssid_len &&
7377 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom899fcc72020-10-19 14:38:18 -07007378 !wpa_blacklist_is_blacklisted(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007379 add_freq(freqs, &num_freqs, bss->freq);
7380 if (num_freqs == max_freqs)
7381 break;
7382 }
7383 }
7384
7385 if (num_freqs == 0) {
7386 os_free(freqs);
7387 freqs = NULL;
7388 }
7389
7390 return freqs;
7391}
7392
7393
7394void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7395{
7396 int timeout;
7397 int count;
7398 int *freqs = NULL;
7399
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007400 wpas_connect_work_done(wpa_s);
7401
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007402 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007403 * Remove possible authentication timeout since the connection failed.
7404 */
7405 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7406
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007407 /*
7408 * There is no point in blacklisting the AP if this event is
7409 * generated based on local request to disconnect.
7410 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007411 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007412 wpa_s->own_disconnect_req = 0;
7413 wpa_dbg(wpa_s, MSG_DEBUG,
7414 "Ignore connection failure due to local request to disconnect");
7415 return;
7416 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007417 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007418 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7419 "indication since interface has been put into "
7420 "disconnected state");
7421 return;
7422 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007423 if (wpa_s->auto_reconnect_disabled) {
7424 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7425 "indication since auto connect is disabled");
7426 return;
7427 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007428
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007429 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007430 * Add the failed BSSID into the blacklist and speed up next scan
7431 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007432 */
7433 count = wpa_blacklist_add(wpa_s, bssid);
7434 if (count == 1 && wpa_s->current_bss) {
7435 /*
7436 * This BSS was not in the blacklist before. If there is
7437 * another BSS available for the same ESS, we should try that
7438 * next. Otherwise, we may as well try this one once more
7439 * before allowing other, likely worse, ESSes to be considered.
7440 */
7441 freqs = get_bss_freqs_in_ess(wpa_s);
7442 if (freqs) {
7443 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7444 "has been seen; try it next");
7445 wpa_blacklist_add(wpa_s, bssid);
7446 /*
7447 * On the next scan, go through only the known channels
7448 * used in this ESS based on previous scans to speed up
7449 * common load balancing use case.
7450 */
7451 os_free(wpa_s->next_scan_freqs);
7452 wpa_s->next_scan_freqs = freqs;
7453 }
7454 }
7455
Hai Shalom899fcc72020-10-19 14:38:18 -07007456 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007457
Hai Shalom899fcc72020-10-19 14:38:18 -07007458 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007459 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7460 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007461 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007462 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007463 /*
7464 * Multiple consecutive connection failures mean that other APs are
7465 * either not available or have already been tried, so we can start
7466 * increasing the delay here to avoid constant scanning.
7467 */
7468 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007469 case 1:
7470 timeout = 100;
7471 break;
7472 case 2:
7473 timeout = 500;
7474 break;
7475 case 3:
7476 timeout = 1000;
7477 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007478 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007479 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007480 break;
7481 default:
7482 timeout = 10000;
7483 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007484 }
7485
Hai Shalom899fcc72020-10-19 14:38:18 -07007486 wpa_dbg(wpa_s, MSG_DEBUG,
7487 "Consecutive connection failures: %d --> request scan in %d ms",
7488 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007489
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007490 /*
7491 * TODO: if more than one possible AP is available in scan results,
7492 * could try the other ones before requesting a new scan.
7493 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007494
7495 /* speed up the connection attempt with normal scan */
7496 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007497 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7498 1000 * (timeout % 1000));
7499}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007500
7501
Hai Shalomce48b4a2018-09-05 11:41:35 -07007502#ifdef CONFIG_FILS
7503void fils_connection_failure(struct wpa_supplicant *wpa_s)
7504{
7505 struct wpa_ssid *ssid = wpa_s->current_ssid;
7506 const u8 *realm, *username, *rrk;
7507 size_t realm_len, username_len, rrk_len;
7508 u16 next_seq_num;
7509
7510 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7511 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7512 &username, &username_len,
7513 &realm, &realm_len, &next_seq_num,
7514 &rrk, &rrk_len) != 0 ||
7515 !realm)
7516 return;
7517
7518 wpa_hexdump_ascii(MSG_DEBUG,
7519 "FILS: Store last connection failure realm",
7520 realm, realm_len);
7521 os_free(wpa_s->last_con_fail_realm);
7522 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7523 if (wpa_s->last_con_fail_realm) {
7524 wpa_s->last_con_fail_realm_len = realm_len;
7525 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7526 }
7527}
7528#endif /* CONFIG_FILS */
7529
7530
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007531int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7532{
7533 return wpa_s->conf->ap_scan == 2 ||
7534 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7535}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007536
Dmitry Shmidt04949592012-07-19 12:16:46 -07007537
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007538#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007539int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7540 struct wpa_ssid *ssid,
7541 const char *field,
7542 const char *value)
7543{
7544#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007545 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007546
7547 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7548 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7549 (const u8 *) value, os_strlen(value));
7550
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007551 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007552 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007553#else /* IEEE8021X_EAPOL */
7554 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7555 return -1;
7556#endif /* IEEE8021X_EAPOL */
7557}
7558
7559int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7560 struct wpa_ssid *ssid,
7561 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007562 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007563{
7564#ifdef IEEE8021X_EAPOL
7565 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007566 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007567
7568 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007569 case WPA_CTRL_REQ_EAP_IDENTITY:
7570 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007571 os_free(eap->imsi_identity);
7572 if (value == NULL)
7573 return -1;
7574 identity = os_strchr(value, ':');
7575 if (identity == NULL) {
7576 /* plain identity */
7577 eap->identity = (u8 *)os_strdup(value);
7578 eap->identity_len = os_strlen(value);
7579 } else {
7580 /* have both plain identity and encrypted identity */
7581 imsi_identity = value;
7582 *identity++ = '\0';
7583 /* plain identity */
7584 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7585 eap->imsi_identity_len = strlen(imsi_identity);
7586 /* encrypted identity */
7587 eap->identity = (u8 *)dup_binstr(identity,
7588 value_len - strlen(imsi_identity) - 1);
7589 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7590 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007591 eap->pending_req_identity = 0;
7592 if (ssid == wpa_s->current_ssid)
7593 wpa_s->reassociate = 1;
7594 break;
7595 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007596 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007597 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007598 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007599 eap->pending_req_password = 0;
7600 if (ssid == wpa_s->current_ssid)
7601 wpa_s->reassociate = 1;
7602 break;
7603 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007604 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007605 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007606 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007607 eap->pending_req_new_password = 0;
7608 if (ssid == wpa_s->current_ssid)
7609 wpa_s->reassociate = 1;
7610 break;
7611 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007612 str_clear_free(eap->cert.pin);
7613 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007614 eap->pending_req_pin = 0;
7615 if (ssid == wpa_s->current_ssid)
7616 wpa_s->reassociate = 1;
7617 break;
7618 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007619 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007620 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007621 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007622 os_free(eap->pending_req_otp);
7623 eap->pending_req_otp = NULL;
7624 eap->pending_req_otp_len = 0;
7625 break;
7626 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007627 str_clear_free(eap->cert.private_key_passwd);
7628 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007629 eap->pending_req_passphrase = 0;
7630 if (ssid == wpa_s->current_ssid)
7631 wpa_s->reassociate = 1;
7632 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007633 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007634 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007635 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007636 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007637 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007638 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7639 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7640 return -1;
7641 ssid->mem_only_psk = 1;
7642 if (ssid->passphrase)
7643 wpa_config_update_psk(ssid);
7644 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7645 wpa_supplicant_req_scan(wpa_s, 0, 0);
7646 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007647 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7648 if (eap->pending_ext_cert_check != PENDING_CHECK)
7649 return -1;
7650 if (os_strcmp(value, "good") == 0)
7651 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7652 else if (os_strcmp(value, "bad") == 0)
7653 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7654 else
7655 return -1;
7656 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007657 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007658 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007659 return -1;
7660 }
7661
7662 return 0;
7663#else /* IEEE8021X_EAPOL */
7664 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7665 return -1;
7666#endif /* IEEE8021X_EAPOL */
7667}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007668#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007669
7670
7671int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7672{
Hai Shalomfdcde762020-04-02 11:19:20 -07007673#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007674 int i;
7675 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007676#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007677
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007678 if (wpa_s->p2p_mgmt)
7679 return 1; /* no normal network profiles on p2p_mgmt interface */
7680
Dmitry Shmidt04949592012-07-19 12:16:46 -07007681 if (ssid == NULL)
7682 return 1;
7683
7684 if (ssid->disabled)
7685 return 1;
7686
Hai Shalomfdcde762020-04-02 11:19:20 -07007687#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007688 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007689 drv_enc = wpa_s->drv_enc;
7690 else
7691 drv_enc = (unsigned int) -1;
7692
7693 for (i = 0; i < NUM_WEP_KEYS; i++) {
7694 size_t len = ssid->wep_key_len[i];
7695 if (len == 0)
7696 continue;
7697 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7698 continue;
7699 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7700 continue;
7701 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7702 continue;
7703 return 1; /* invalid WEP key */
7704 }
Hai Shalomfdcde762020-04-02 11:19:20 -07007705#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007706
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007707 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007708 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007709 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007710 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007711 return 1;
7712
Dmitry Shmidt04949592012-07-19 12:16:46 -07007713 return 0;
7714}
7715
7716
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007717int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7718{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007719 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7720 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7721 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7722 /*
7723 * Driver does not support BIP -- ignore pmf=1 default
7724 * since the connection with PMF would fail and the
7725 * configuration does not require PMF to be enabled.
7726 */
7727 return NO_MGMT_FRAME_PROTECTION;
7728 }
7729
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007730 if (ssid &&
7731 (ssid->key_mgmt &
7732 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7733 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7734 /*
7735 * Do not use the default PMF value for non-RSN networks
7736 * since PMF is available only with RSN and pmf=2
7737 * configuration would otherwise prevent connections to
7738 * all open networks.
7739 */
7740 return NO_MGMT_FRAME_PROTECTION;
7741 }
7742
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007743 return wpa_s->conf->pmf;
7744 }
7745
7746 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007747}
7748
7749
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007750int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007751{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007752 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007753 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007754 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007755 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007756 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007757}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007758
7759
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007760void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007761{
7762 struct wpa_ssid *ssid = wpa_s->current_ssid;
7763 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007764 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007765
7766 if (ssid == NULL) {
7767 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7768 "SSID block");
7769 return;
7770 }
7771
7772 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7773 return;
7774
7775 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007776
7777#ifdef CONFIG_P2P
7778 if (ssid->p2p_group &&
7779 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7780 /*
7781 * Skip the wait time since there is a short timeout on the
7782 * connection to a P2P group.
7783 */
7784 return;
7785 }
7786#endif /* CONFIG_P2P */
7787
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007788 if (ssid->auth_failures > 50)
7789 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007790 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007791 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007792 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007793 dur = 90;
7794 else if (ssid->auth_failures > 3)
7795 dur = 60;
7796 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007797 dur = 30;
7798 else if (ssid->auth_failures > 1)
7799 dur = 20;
7800 else
7801 dur = 10;
7802
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007803 if (ssid->auth_failures > 1 &&
7804 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7805 dur += os_random() % (ssid->auth_failures * 10);
7806
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007807 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007808 if (now.sec + dur <= ssid->disabled_until.sec)
7809 return;
7810
7811 ssid->disabled_until.sec = now.sec + dur;
7812
7813 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007814 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007815 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007816 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007817}
7818
7819
7820void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7821 struct wpa_ssid *ssid, int clear_failures)
7822{
7823 if (ssid == NULL)
7824 return;
7825
7826 if (ssid->disabled_until.sec) {
7827 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7828 "id=%d ssid=\"%s\"",
7829 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7830 }
7831 ssid->disabled_until.sec = 0;
7832 ssid->disabled_until.usec = 0;
7833 if (clear_failures)
7834 ssid->auth_failures = 0;
7835}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007836
7837
7838int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7839{
7840 size_t i;
7841
7842 if (wpa_s->disallow_aps_bssid == NULL)
7843 return 0;
7844
7845 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7846 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7847 bssid, ETH_ALEN) == 0)
7848 return 1;
7849 }
7850
7851 return 0;
7852}
7853
7854
7855int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7856 size_t ssid_len)
7857{
7858 size_t i;
7859
7860 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7861 return 0;
7862
7863 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7864 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7865 if (ssid_len == s->ssid_len &&
7866 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7867 return 1;
7868 }
7869
7870 return 0;
7871}
7872
7873
7874/**
7875 * wpas_request_connection - Request a new connection
7876 * @wpa_s: Pointer to the network interface
7877 *
7878 * This function is used to request a new connection to be found. It will mark
7879 * the interface to allow reassociation and request a new scan to find a
7880 * suitable network to connect to.
7881 */
7882void wpas_request_connection(struct wpa_supplicant *wpa_s)
7883{
7884 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007885 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007886 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007887 wpa_s->disconnected = 0;
7888 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007889 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007890
7891 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7892 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007893 else
7894 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007895}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007896
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007897
Roshan Pius02242d72016-08-09 15:31:48 -07007898/**
7899 * wpas_request_disconnection - Request disconnection
7900 * @wpa_s: Pointer to the network interface
7901 *
7902 * This function is used to request disconnection from the currently connected
7903 * network. This will stop any ongoing scans and initiate deauthentication.
7904 */
7905void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7906{
7907#ifdef CONFIG_SME
7908 wpa_s->sme.prev_bssid_set = 0;
7909#endif /* CONFIG_SME */
7910 wpa_s->reassociate = 0;
7911 wpa_s->disconnected = 1;
7912 wpa_supplicant_cancel_sched_scan(wpa_s);
7913 wpa_supplicant_cancel_scan(wpa_s);
7914 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7915 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007916 radio_remove_works(wpa_s, "connect", 0);
7917 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007918}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007919
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007920
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007921void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7922 struct wpa_used_freq_data *freqs_data,
7923 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007924{
7925 unsigned int i;
7926
7927 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7928 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007929 for (i = 0; i < len; i++) {
7930 struct wpa_used_freq_data *cur = &freqs_data[i];
7931 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7932 i, cur->freq, cur->flags);
7933 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007934}
7935
7936
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007937/*
7938 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007939 * are using the same radio as the current interface, and in addition, get
7940 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007941 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007942int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7943 struct wpa_used_freq_data *freqs_data,
7944 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007945{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007946 struct wpa_supplicant *ifs;
7947 u8 bssid[ETH_ALEN];
7948 int freq;
7949 unsigned int idx = 0, i;
7950
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007951 wpa_dbg(wpa_s, MSG_DEBUG,
7952 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007953 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007954
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007955 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7956 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007957 if (idx == len)
7958 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007959
7960 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7961 continue;
7962
7963 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007964 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7965 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007966 freq = ifs->current_ssid->frequency;
7967 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7968 freq = ifs->assoc_freq;
7969 else
7970 continue;
7971
7972 /* Hold only distinct freqs */
7973 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007974 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007975 break;
7976
7977 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007978 freqs_data[idx++].freq = freq;
7979
7980 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007981 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007982 WPA_FREQ_USED_BY_P2P_CLIENT :
7983 WPA_FREQ_USED_BY_INFRA_STATION;
7984 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007985 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007986
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007987 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007988 return idx;
7989}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007990
7991
7992/*
7993 * Find the operating frequencies of any of the virtual interfaces that
7994 * are using the same radio as the current interface.
7995 */
7996int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7997 int *freq_array, unsigned int len)
7998{
7999 struct wpa_used_freq_data *freqs_data;
8000 int num, i;
8001
8002 os_memset(freq_array, 0, sizeof(int) * len);
8003
8004 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8005 if (!freqs_data)
8006 return -1;
8007
8008 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8009 for (i = 0; i < num; i++)
8010 freq_array[i] = freqs_data[i].freq;
8011
8012 os_free(freqs_data);
8013
8014 return num;
8015}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008016
8017
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008018struct wpa_supplicant *
8019wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8020{
8021 switch (frame) {
8022#ifdef CONFIG_P2P
8023 case VENDOR_ELEM_PROBE_REQ_P2P:
8024 case VENDOR_ELEM_PROBE_RESP_P2P:
8025 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8026 case VENDOR_ELEM_BEACON_P2P_GO:
8027 case VENDOR_ELEM_P2P_PD_REQ:
8028 case VENDOR_ELEM_P2P_PD_RESP:
8029 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8030 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8031 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8032 case VENDOR_ELEM_P2P_INV_REQ:
8033 case VENDOR_ELEM_P2P_INV_RESP:
8034 case VENDOR_ELEM_P2P_ASSOC_REQ:
8035 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008036 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008037#endif /* CONFIG_P2P */
8038 default:
8039 return wpa_s;
8040 }
8041}
8042
8043
8044void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8045{
8046 unsigned int i;
8047 char buf[30];
8048
8049 wpa_printf(MSG_DEBUG, "Update vendor elements");
8050
8051 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8052 if (wpa_s->vendor_elem[i]) {
8053 int res;
8054
8055 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8056 if (!os_snprintf_error(sizeof(buf), res)) {
8057 wpa_hexdump_buf(MSG_DEBUG, buf,
8058 wpa_s->vendor_elem[i]);
8059 }
8060 }
8061 }
8062
8063#ifdef CONFIG_P2P
8064 if (wpa_s->parent == wpa_s &&
8065 wpa_s->global->p2p &&
8066 !wpa_s->global->p2p_disabled)
8067 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8068#endif /* CONFIG_P2P */
8069}
8070
8071
8072int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8073 const u8 *elem, size_t len)
8074{
8075 u8 *ie, *end;
8076
8077 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8078 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8079
8080 for (; ie + 1 < end; ie += 2 + ie[1]) {
8081 if (ie + len > end)
8082 break;
8083 if (os_memcmp(ie, elem, len) != 0)
8084 continue;
8085
8086 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8087 wpabuf_free(wpa_s->vendor_elem[frame]);
8088 wpa_s->vendor_elem[frame] = NULL;
8089 } else {
8090 os_memmove(ie, ie + len, end - (ie + len));
8091 wpa_s->vendor_elem[frame]->used -= len;
8092 }
8093 wpas_vendor_elem_update(wpa_s);
8094 return 0;
8095 }
8096
8097 return -1;
8098}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008099
8100
8101struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008102 u16 num_modes, enum hostapd_hw_mode mode,
8103 int is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008104{
8105 u16 i;
8106
8107 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008108 if (modes[i].mode != mode ||
8109 !modes[i].num_channels || !modes[i].channels)
8110 continue;
8111 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8112 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008113 return &modes[i];
8114 }
8115
8116 return NULL;
8117}
8118
8119
8120static struct
8121wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8122 const u8 *bssid)
8123{
8124 struct wpa_bss_tmp_disallowed *bss;
8125
8126 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8127 struct wpa_bss_tmp_disallowed, list) {
8128 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8129 return bss;
8130 }
8131
8132 return NULL;
8133}
8134
8135
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008136static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8137{
8138 struct wpa_bss_tmp_disallowed *tmp;
8139 unsigned int num_bssid = 0;
8140 u8 *bssids;
8141 int ret;
8142
8143 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8144 if (!bssids)
8145 return -1;
8146 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8147 struct wpa_bss_tmp_disallowed, list) {
8148 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8149 ETH_ALEN);
8150 num_bssid++;
8151 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008152 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008153 os_free(bssids);
8154 return ret;
8155}
8156
8157
8158static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8159{
8160 struct wpa_supplicant *wpa_s = eloop_ctx;
8161 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8162
8163 /* Make sure the bss is not already freed */
8164 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8165 struct wpa_bss_tmp_disallowed, list) {
8166 if (bss == tmp) {
8167 dl_list_del(&tmp->list);
8168 os_free(tmp);
8169 wpa_set_driver_tmp_disallow_list(wpa_s);
8170 break;
8171 }
8172 }
8173}
8174
8175
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008176void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008177 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008178{
8179 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008180
8181 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8182 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008183 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008184 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008185 }
8186
8187 bss = os_malloc(sizeof(*bss));
8188 if (!bss) {
8189 wpa_printf(MSG_DEBUG,
8190 "Failed to allocate memory for temp disallow BSS");
8191 return;
8192 }
8193
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008194 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8195 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008196 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008197
8198finish:
8199 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008200 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8201 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008202}
8203
8204
Hai Shalom74f70d42019-02-11 14:42:39 -08008205int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8206 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008207{
Hai Shalom74f70d42019-02-11 14:42:39 -08008208 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008209
8210 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8211 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008212 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8213 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008214 break;
8215 }
8216 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008217 if (!disallowed)
8218 return 0;
8219
8220 if (disallowed->rssi_threshold != 0 &&
8221 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008222 return 0;
8223
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008224 return 1;
8225}
Hai Shalom81f62d82019-07-22 12:10:00 -07008226
8227
8228int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8229 unsigned int type, const u8 *addr,
8230 const u8 *mask)
8231{
8232 if ((addr && !mask) || (!addr && mask)) {
8233 wpa_printf(MSG_INFO,
8234 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8235 return -1;
8236 }
8237
8238 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8239 wpa_printf(MSG_INFO,
8240 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8241 return -1;
8242 }
8243
8244 if (type & MAC_ADDR_RAND_SCAN) {
8245 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8246 addr, mask))
8247 return -1;
8248 }
8249
8250 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8251 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8252 addr, mask))
8253 return -1;
8254
8255 if (wpa_s->sched_scanning && !wpa_s->pno)
8256 wpas_scan_restart_sched_scan(wpa_s);
8257 }
8258
8259 if (type & MAC_ADDR_RAND_PNO) {
8260 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8261 addr, mask))
8262 return -1;
8263
8264 if (wpa_s->pno) {
8265 wpas_stop_pno(wpa_s);
8266 wpas_start_pno(wpa_s);
8267 }
8268 }
8269
8270 return 0;
8271}
8272
8273
8274int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8275 unsigned int type)
8276{
8277 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8278 if (wpa_s->pno) {
8279 if (type & MAC_ADDR_RAND_PNO) {
8280 wpas_stop_pno(wpa_s);
8281 wpas_start_pno(wpa_s);
8282 }
8283 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8284 wpas_scan_restart_sched_scan(wpa_s);
8285 }
8286
8287 return 0;
8288}
Hai Shalomfdcde762020-04-02 11:19:20 -07008289
8290
8291int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8292 struct wpa_signal_info *si)
8293{
8294 int res;
8295
8296 if (!wpa_s->driver->signal_poll)
8297 return -1;
8298
8299 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8300
8301#ifdef CONFIG_TESTING_OPTIONS
8302 if (res == 0) {
8303 struct driver_signal_override *dso;
8304
8305 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8306 struct driver_signal_override, list) {
8307 if (os_memcmp(wpa_s->bssid, dso->bssid,
8308 ETH_ALEN) != 0)
8309 continue;
8310 wpa_printf(MSG_DEBUG,
8311 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8312 si->current_signal,
8313 dso->si_current_signal,
8314 si->avg_signal,
8315 dso->si_avg_signal,
8316 si->avg_beacon_signal,
8317 dso->si_avg_beacon_signal,
8318 si->current_noise,
8319 dso->si_current_noise);
8320 si->current_signal = dso->si_current_signal;
8321 si->avg_signal = dso->si_avg_signal;
8322 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8323 si->current_noise = dso->si_current_noise;
8324 break;
8325 }
8326 }
8327#endif /* CONFIG_TESTING_OPTIONS */
8328
8329 return res;
8330}
8331
8332
8333struct wpa_scan_results *
8334wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8335{
8336 struct wpa_scan_results *scan_res;
8337#ifdef CONFIG_TESTING_OPTIONS
8338 size_t idx;
8339#endif /* CONFIG_TESTING_OPTIONS */
8340
8341 if (!wpa_s->driver->get_scan_results2)
8342 return NULL;
8343
8344 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8345
8346#ifdef CONFIG_TESTING_OPTIONS
8347 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8348 struct driver_signal_override *dso;
8349 struct wpa_scan_res *res = scan_res->res[idx];
8350
8351 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8352 struct driver_signal_override, list) {
8353 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8354 continue;
8355 wpa_printf(MSG_DEBUG,
8356 "Override driver scan signal level %d->%d for "
8357 MACSTR,
8358 res->level, dso->scan_level,
8359 MAC2STR(res->bssid));
8360 res->flags |= WPA_SCAN_QUAL_INVALID;
8361 if (dso->scan_level < 0)
8362 res->flags |= WPA_SCAN_LEVEL_DBM;
8363 else
8364 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8365 res->level = dso->scan_level;
8366 break;
8367 }
8368 }
8369#endif /* CONFIG_TESTING_OPTIONS */
8370
8371 return scan_res;
8372}