blob: 67fb42669239b0968c9feba713dd2b807b7a3232 [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);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003847 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003848 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3849 return;
3850 }
3851 /* try to continue anyway; new association will be tried again
3852 * after timeout */
3853 assoc_failed = 1;
3854 }
3855
3856 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3857 /* Set the key after the association just in case association
3858 * cleared the previously configured key. */
3859 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3860 /* No need to timeout authentication since there is no key
3861 * management. */
3862 wpa_supplicant_cancel_auth_timeout(wpa_s);
3863 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3864#ifdef CONFIG_IBSS_RSN
3865 } else if (ssid->mode == WPAS_MODE_IBSS &&
3866 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3867 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3868 /*
3869 * RSN IBSS authentication is per-STA and we can disable the
3870 * per-BSSID authentication.
3871 */
3872 wpa_supplicant_cancel_auth_timeout(wpa_s);
3873#endif /* CONFIG_IBSS_RSN */
3874 } else {
3875 /* Timeout for IEEE 802.11 authentication and association */
3876 int timeout = 60;
3877
3878 if (assoc_failed) {
3879 /* give IBSS a bit more time */
3880 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3881 } else if (wpa_s->conf->ap_scan == 1) {
3882 /* give IBSS a bit more time */
3883 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3884 }
3885 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3886 }
3887
Hai Shalomfdcde762020-04-02 11:19:20 -07003888#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003889 if (wep_keys_set &&
3890 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003891 /* Set static WEP keys again */
3892 wpa_set_wep_keys(wpa_s, ssid);
3893 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003894#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003895
3896 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3897 /*
3898 * Do not allow EAP session resumption between different
3899 * network configurations.
3900 */
3901 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3902 }
3903 old_ssid = wpa_s->current_ssid;
3904 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003905
3906 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003907 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003908#ifdef CONFIG_HS20
3909 hs20_configure_frame_filters(wpa_s);
3910#endif /* CONFIG_HS20 */
3911 }
3912
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003913 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3914 wpa_supplicant_initiate_eapol(wpa_s);
3915 if (old_ssid != wpa_s->current_ssid)
3916 wpas_notify_network_changed(wpa_s);
3917}
3918
3919
3920static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3921 const u8 *addr)
3922{
3923 struct wpa_ssid *old_ssid;
3924
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003925 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003926 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003927 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003928 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929 wpa_sm_set_config(wpa_s->wpa, NULL);
3930 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3931 if (old_ssid != wpa_s->current_ssid)
3932 wpas_notify_network_changed(wpa_s);
3933 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3934}
3935
3936
3937/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003938 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3939 * @wpa_s: Pointer to wpa_supplicant data
3940 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3941 *
3942 * This function is used to request %wpa_supplicant to deauthenticate from the
3943 * current AP.
3944 */
3945void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003946 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003947{
3948 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003949 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003950 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003951
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003952 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003953 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003954 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003955 reason_code, reason2str(reason_code),
3956 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003957
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003958 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3959 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3960 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003961 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003962 else if (!is_zero_ether_addr(wpa_s->bssid))
3963 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003964 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3965 /*
3966 * When using driver-based BSS selection, we may not know the
3967 * BSSID with which we are currently trying to associate. We
3968 * need to notify the driver of this disconnection even in such
3969 * a case, so use the all zeros address here.
3970 */
3971 addr = wpa_s->bssid;
3972 zero_addr = 1;
3973 }
3974
Hai Shalom74f70d42019-02-11 14:42:39 -08003975 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3976 wpa_s->enabled_4addr_mode = 0;
3977
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003978#ifdef CONFIG_TDLS
3979 wpa_tdls_teardown_peers(wpa_s->wpa);
3980#endif /* CONFIG_TDLS */
3981
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003982#ifdef CONFIG_MESH
3983 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003984 struct mesh_conf *mconf;
3985
3986 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003987 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3988 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003989 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3990 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003991 wpa_supplicant_leave_mesh(wpa_s);
3992 }
3993#endif /* CONFIG_MESH */
3994
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003995 if (addr) {
3996 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003997 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07003998 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003999 event.deauth_info.locally_generated = 1;
4000 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004001 if (zero_addr)
4002 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004003 }
4004
4005 wpa_supplicant_clear_connection(wpa_s, addr);
4006}
4007
Hai Shalomfdcde762020-04-02 11:19:20 -07004008
4009void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
4010{
4011 wpa_s->own_reconnect_req = 1;
4012 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
4013
4014}
4015
4016
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004017static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
4018 struct wpa_ssid *ssid)
4019{
4020 if (!ssid || !ssid->disabled || ssid->disabled == 2)
4021 return;
4022
4023 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004024 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004025 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4026 wpas_notify_network_enabled_changed(wpa_s, ssid);
4027
4028 /*
4029 * Try to reassociate since there is no current configuration and a new
4030 * network was made available.
4031 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004032 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004033 wpa_s->reassociate = 1;
4034}
4035
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004036
Roshan Pius950bec92016-07-19 09:49:24 -07004037/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004038 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07004039 * @wpa_s: wpa_supplicant structure for a network interface
4040 * Returns: The new network configuration or %NULL if operation failed
4041 *
4042 * This function performs the following operations:
4043 * 1. Adds a new network.
4044 * 2. Send network addition notification.
4045 * 3. Marks the network disabled.
4046 * 4. Set network default parameters.
4047 */
4048struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
4049{
4050 struct wpa_ssid *ssid;
4051
4052 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004053 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004054 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07004055 wpas_notify_network_added(wpa_s, ssid);
4056 ssid->disabled = 1;
4057 wpa_config_set_network_defaults(ssid);
4058
4059 return ssid;
4060}
4061
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004062
Roshan Pius950bec92016-07-19 09:49:24 -07004063/**
4064 * wpa_supplicant_remove_network - Remove a configured network based on id
4065 * @wpa_s: wpa_supplicant structure for a network interface
4066 * @id: Unique network id to search for
4067 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4068 * could not be removed
4069 *
4070 * This function performs the following operations:
4071 * 1. Removes the network.
4072 * 2. Send network removal notification.
4073 * 3. Update internal state machines.
4074 * 4. Stop any running sched scans.
4075 */
4076int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4077{
4078 struct wpa_ssid *ssid;
4079 int was_disabled;
4080
4081 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004082 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004083 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004084 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004085
4086 if (wpa_s->last_ssid == ssid)
4087 wpa_s->last_ssid = NULL;
4088
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004089 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004090#ifdef CONFIG_SME
4091 wpa_s->sme.prev_bssid_set = 0;
4092#endif /* CONFIG_SME */
4093 /*
4094 * Invalidate the EAP session cache if the current or
4095 * previously used network is removed.
4096 */
4097 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4098 }
4099
4100 if (ssid == wpa_s->current_ssid) {
4101 wpa_sm_set_config(wpa_s->wpa, NULL);
4102 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4103
4104 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4105 wpa_s->own_disconnect_req = 1;
4106 wpa_supplicant_deauthenticate(wpa_s,
4107 WLAN_REASON_DEAUTH_LEAVING);
4108 }
4109
4110 was_disabled = ssid->disabled;
4111
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004112 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004113 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004114
4115 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004116 wpa_printf(MSG_DEBUG,
4117 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004118 wpa_supplicant_cancel_sched_scan(wpa_s);
4119 wpa_supplicant_req_scan(wpa_s, 0, 0);
4120 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004121
Roshan Pius950bec92016-07-19 09:49:24 -07004122 return 0;
4123}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004124
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004125
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126/**
Hai Shalom899fcc72020-10-19 14:38:18 -07004127 * wpa_supplicant_remove_all_networks - Remove all configured networks
4128 * @wpa_s: wpa_supplicant structure for a network interface
4129 * Returns: 0 on success (errors are currently ignored)
4130 *
4131 * This function performs the following operations:
4132 * 1. Remove all networks.
4133 * 2. Send network removal notifications.
4134 * 3. Update internal state machines.
4135 * 4. Stop any running sched scans.
4136 */
4137int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s)
4138{
4139 struct wpa_ssid *ssid;
4140
4141 if (wpa_s->sched_scanning)
4142 wpa_supplicant_cancel_sched_scan(wpa_s);
4143
4144 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4145 if (wpa_s->current_ssid) {
4146#ifdef CONFIG_SME
4147 wpa_s->sme.prev_bssid_set = 0;
4148#endif /* CONFIG_SME */
4149 wpa_sm_set_config(wpa_s->wpa, NULL);
4150 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4151 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4152 wpa_s->own_disconnect_req = 1;
4153 wpa_supplicant_deauthenticate(
4154 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4155 }
4156 ssid = wpa_s->conf->ssid;
4157 while (ssid) {
4158 struct wpa_ssid *remove_ssid = ssid;
4159 int id;
4160
4161 id = ssid->id;
4162 ssid = ssid->next;
4163 if (wpa_s->last_ssid == remove_ssid)
4164 wpa_s->last_ssid = NULL;
4165 wpas_notify_network_removed(wpa_s, remove_ssid);
4166 wpa_config_remove_network(wpa_s->conf, id);
4167 }
4168 return 0;
4169}
4170
4171
4172/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004173 * wpa_supplicant_enable_network - Mark a configured network as enabled
4174 * @wpa_s: wpa_supplicant structure for a network interface
4175 * @ssid: wpa_ssid structure for a configured network or %NULL
4176 *
4177 * Enables the specified network or all networks if no network specified.
4178 */
4179void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4180 struct wpa_ssid *ssid)
4181{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004182 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004183 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4184 wpa_supplicant_enable_one_network(wpa_s, ssid);
4185 } else
4186 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004187
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004188 if (wpa_s->reassociate && !wpa_s->disconnected &&
4189 (!wpa_s->current_ssid ||
4190 wpa_s->wpa_state == WPA_DISCONNECTED ||
4191 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004192 if (wpa_s->sched_scanning) {
4193 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4194 "new network to scan filters");
4195 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004196 }
4197
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004198 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4199 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004200 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004201 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004202 }
4203}
4204
4205
4206/**
4207 * wpa_supplicant_disable_network - Mark a configured network as disabled
4208 * @wpa_s: wpa_supplicant structure for a network interface
4209 * @ssid: wpa_ssid structure for a configured network or %NULL
4210 *
4211 * Disables the specified network or all networks if no network specified.
4212 */
4213void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4214 struct wpa_ssid *ssid)
4215{
4216 struct wpa_ssid *other_ssid;
4217 int was_disabled;
4218
4219 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004220 if (wpa_s->sched_scanning)
4221 wpa_supplicant_cancel_sched_scan(wpa_s);
4222
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004223 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4224 other_ssid = other_ssid->next) {
4225 was_disabled = other_ssid->disabled;
4226 if (was_disabled == 2)
4227 continue; /* do not change persistent P2P group
4228 * data */
4229
4230 other_ssid->disabled = 1;
4231
4232 if (was_disabled != other_ssid->disabled)
4233 wpas_notify_network_enabled_changed(
4234 wpa_s, other_ssid);
4235 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004236 if (wpa_s->current_ssid) {
4237 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4238 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004239 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004240 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004241 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004242 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004243 if (ssid == wpa_s->current_ssid) {
4244 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4245 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004246 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004247 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004248 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004249
4250 was_disabled = ssid->disabled;
4251
4252 ssid->disabled = 1;
4253
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004254 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004255 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004256 if (wpa_s->sched_scanning) {
4257 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4258 "to remove network from filters");
4259 wpa_supplicant_cancel_sched_scan(wpa_s);
4260 wpa_supplicant_req_scan(wpa_s, 0, 0);
4261 }
4262 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004263 }
4264}
4265
4266
4267/**
4268 * wpa_supplicant_select_network - Attempt association with a network
4269 * @wpa_s: wpa_supplicant structure for a network interface
4270 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4271 */
4272void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4273 struct wpa_ssid *ssid)
4274{
4275
4276 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004277 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004278
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004279 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004280 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4281 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004282 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004283 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004284 disconnected = 1;
4285 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004286
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004287 if (ssid)
4288 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4289
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004290 /*
4291 * Mark all other networks disabled or mark all networks enabled if no
4292 * network specified.
4293 */
4294 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4295 other_ssid = other_ssid->next) {
4296 int was_disabled = other_ssid->disabled;
4297 if (was_disabled == 2)
4298 continue; /* do not change persistent P2P group data */
4299
4300 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004301 if (was_disabled && !other_ssid->disabled)
4302 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004303
4304 if (was_disabled != other_ssid->disabled)
4305 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4306 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004307
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004308 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4309 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004310 /* We are already associated with the selected network */
4311 wpa_printf(MSG_DEBUG, "Already associated with the "
4312 "selected network - do nothing");
4313 return;
4314 }
4315
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004316 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004317 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004318 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004319 wpa_s->connect_without_scan =
4320 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004321
4322 /*
4323 * Don't optimize next scan freqs since a new ESS has been
4324 * selected.
4325 */
4326 os_free(wpa_s->next_scan_freqs);
4327 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004328 } else {
4329 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004330 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004331
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004332 wpa_s->disconnected = 0;
4333 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004334 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004335 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004336 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004337 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004338 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4339 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004340
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004341 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004342 wpa_supplicant_fast_associate(wpa_s) != 1) {
4343 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004344 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004345 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004346 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347
4348 if (ssid)
4349 wpas_notify_network_selected(wpa_s, ssid);
4350}
4351
4352
4353/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004354 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4355 * @wpa_s: wpa_supplicant structure for a network interface
4356 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4357 * @pkcs11_module_path: PKCS #11 module path or NULL
4358 * Returns: 0 on success; -1 on failure
4359 *
4360 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4361 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4362 * module path fails the paths will be reset to the default value (NULL).
4363 */
4364int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4365 const char *pkcs11_engine_path,
4366 const char *pkcs11_module_path)
4367{
4368 char *pkcs11_engine_path_copy = NULL;
4369 char *pkcs11_module_path_copy = NULL;
4370
4371 if (pkcs11_engine_path != NULL) {
4372 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4373 if (pkcs11_engine_path_copy == NULL)
4374 return -1;
4375 }
4376 if (pkcs11_module_path != NULL) {
4377 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004378 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004379 os_free(pkcs11_engine_path_copy);
4380 return -1;
4381 }
4382 }
4383
4384 os_free(wpa_s->conf->pkcs11_engine_path);
4385 os_free(wpa_s->conf->pkcs11_module_path);
4386 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4387 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4388
4389 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4390 eapol_sm_deinit(wpa_s->eapol);
4391 wpa_s->eapol = NULL;
4392 if (wpa_supplicant_init_eapol(wpa_s)) {
4393 /* Error -> Reset paths to the default value (NULL) once. */
4394 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4395 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4396 NULL);
4397
4398 return -1;
4399 }
4400 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4401
4402 return 0;
4403}
4404
4405
4406/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004407 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4408 * @wpa_s: wpa_supplicant structure for a network interface
4409 * @ap_scan: AP scan mode
4410 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4411 *
4412 */
4413int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4414{
4415
4416 int old_ap_scan;
4417
4418 if (ap_scan < 0 || ap_scan > 2)
4419 return -1;
4420
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004421 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4422 wpa_printf(MSG_INFO,
4423 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4424 }
4425
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004426#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004427 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4428 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4429 wpa_s->wpa_state < WPA_COMPLETED) {
4430 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4431 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004432 return 0;
4433 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004434#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004436 old_ap_scan = wpa_s->conf->ap_scan;
4437 wpa_s->conf->ap_scan = ap_scan;
4438
4439 if (old_ap_scan != wpa_s->conf->ap_scan)
4440 wpas_notify_ap_scan_changed(wpa_s);
4441
4442 return 0;
4443}
4444
4445
4446/**
4447 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4448 * @wpa_s: wpa_supplicant structure for a network interface
4449 * @expire_age: Expiration age in seconds
4450 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4451 *
4452 */
4453int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4454 unsigned int bss_expire_age)
4455{
4456 if (bss_expire_age < 10) {
4457 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4458 bss_expire_age);
4459 return -1;
4460 }
4461 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4462 bss_expire_age);
4463 wpa_s->conf->bss_expiration_age = bss_expire_age;
4464
4465 return 0;
4466}
4467
4468
4469/**
4470 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4471 * @wpa_s: wpa_supplicant structure for a network interface
4472 * @expire_count: number of scans after which an unseen BSS is reclaimed
4473 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4474 *
4475 */
4476int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4477 unsigned int bss_expire_count)
4478{
4479 if (bss_expire_count < 1) {
4480 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4481 bss_expire_count);
4482 return -1;
4483 }
4484 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4485 bss_expire_count);
4486 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4487
4488 return 0;
4489}
4490
4491
4492/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004493 * wpa_supplicant_set_scan_interval - Set scan interval
4494 * @wpa_s: wpa_supplicant structure for a network interface
4495 * @scan_interval: scan interval in seconds
4496 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4497 *
4498 */
4499int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4500 int scan_interval)
4501{
4502 if (scan_interval < 0) {
4503 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4504 scan_interval);
4505 return -1;
4506 }
4507 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4508 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004509 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004510
4511 return 0;
4512}
4513
4514
4515/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004516 * wpa_supplicant_set_debug_params - Set global debug params
4517 * @global: wpa_global structure
4518 * @debug_level: debug level
4519 * @debug_timestamp: determines if show timestamp in debug data
4520 * @debug_show_keys: determines if show keys in debug data
4521 * Returns: 0 if succeed or -1 if debug_level has wrong value
4522 */
4523int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4524 int debug_timestamp, int debug_show_keys)
4525{
4526
4527 int old_level, old_timestamp, old_show_keys;
4528
4529 /* check for allowed debuglevels */
4530 if (debug_level != MSG_EXCESSIVE &&
4531 debug_level != MSG_MSGDUMP &&
4532 debug_level != MSG_DEBUG &&
4533 debug_level != MSG_INFO &&
4534 debug_level != MSG_WARNING &&
4535 debug_level != MSG_ERROR)
4536 return -1;
4537
4538 old_level = wpa_debug_level;
4539 old_timestamp = wpa_debug_timestamp;
4540 old_show_keys = wpa_debug_show_keys;
4541
4542 wpa_debug_level = debug_level;
4543 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4544 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4545
4546 if (wpa_debug_level != old_level)
4547 wpas_notify_debug_level_changed(global);
4548 if (wpa_debug_timestamp != old_timestamp)
4549 wpas_notify_debug_timestamp_changed(global);
4550 if (wpa_debug_show_keys != old_show_keys)
4551 wpas_notify_debug_show_keys_changed(global);
4552
4553 return 0;
4554}
4555
4556
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004557#ifdef CONFIG_OWE
4558static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4559 const u8 *entry_ssid, size_t entry_ssid_len)
4560{
4561 const u8 *owe, *pos, *end;
4562 u8 ssid_len;
4563 struct wpa_bss *bss;
4564
4565 /* Check network profile SSID aganst the SSID in the
4566 * OWE Transition Mode element. */
4567
4568 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4569 if (!bss)
4570 return 0;
4571
4572 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4573 if (!owe)
4574 return 0;
4575
4576 pos = owe + 6;
4577 end = owe + 2 + owe[1];
4578
4579 if (end - pos < ETH_ALEN + 1)
4580 return 0;
4581 pos += ETH_ALEN;
4582 ssid_len = *pos++;
4583 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4584 return 0;
4585
4586 return entry_ssid_len == ssid_len &&
4587 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4588}
4589#endif /* CONFIG_OWE */
4590
4591
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004592/**
4593 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4594 * @wpa_s: Pointer to wpa_supplicant data
4595 * Returns: A pointer to the current network structure or %NULL on failure
4596 */
4597struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4598{
4599 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004600 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004601 int res;
4602 size_t ssid_len;
4603 u8 bssid[ETH_ALEN];
4604 int wired;
4605
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004606 res = wpa_drv_get_ssid(wpa_s, ssid);
4607 if (res < 0) {
4608 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4609 "driver");
4610 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004611 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004612 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004613
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004614 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004615 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4616 "driver");
4617 return NULL;
4618 }
4619
4620 wired = wpa_s->conf->ap_scan == 0 &&
4621 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4622
4623 entry = wpa_s->conf->ssid;
4624 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004625 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004626 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004627 (!entry->ssid ||
4628 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4629 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004630 (!entry->bssid_set ||
4631 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4632 return entry;
4633#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004634 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004635 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4636 (entry->ssid == NULL || entry->ssid_len == 0) &&
4637 (!entry->bssid_set ||
4638 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4639 return entry;
4640#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004641
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004642#ifdef CONFIG_OWE
4643 if (!wpas_network_disabled(wpa_s, entry) &&
4644 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4645 entry->ssid_len) &&
4646 (!entry->bssid_set ||
4647 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4648 return entry;
4649#endif /* CONFIG_OWE */
4650
Dmitry Shmidt04949592012-07-19 12:16:46 -07004651 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004652 entry->ssid_len == 0 &&
4653 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4654 return entry;
4655
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004656 entry = entry->next;
4657 }
4658
4659 return NULL;
4660}
4661
4662
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004663static int select_driver(struct wpa_supplicant *wpa_s, int i)
4664{
4665 struct wpa_global *global = wpa_s->global;
4666
4667 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004668 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004669 if (global->drv_priv[i] == NULL) {
4670 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4671 "'%s'", wpa_drivers[i]->name);
4672 return -1;
4673 }
4674 }
4675
4676 wpa_s->driver = wpa_drivers[i];
4677 wpa_s->global_drv_priv = global->drv_priv[i];
4678
4679 return 0;
4680}
4681
4682
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004683static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4684 const char *name)
4685{
4686 int i;
4687 size_t len;
4688 const char *pos, *driver = name;
4689
4690 if (wpa_s == NULL)
4691 return -1;
4692
4693 if (wpa_drivers[0] == NULL) {
4694 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4695 "wpa_supplicant");
4696 return -1;
4697 }
4698
4699 if (name == NULL) {
4700 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004701 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004702 }
4703
4704 do {
4705 pos = os_strchr(driver, ',');
4706 if (pos)
4707 len = pos - driver;
4708 else
4709 len = os_strlen(driver);
4710
4711 for (i = 0; wpa_drivers[i]; i++) {
4712 if (os_strlen(wpa_drivers[i]->name) == len &&
4713 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004714 0) {
4715 /* First driver that succeeds wins */
4716 if (select_driver(wpa_s, i) == 0)
4717 return 0;
4718 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004719 }
4720
4721 driver = pos + 1;
4722 } while (pos);
4723
4724 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4725 return -1;
4726}
4727
4728
4729/**
4730 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4731 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4732 * with struct wpa_driver_ops::init()
4733 * @src_addr: Source address of the EAPOL frame
4734 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4735 * @len: Length of the EAPOL data
4736 *
4737 * This function is called for each received EAPOL frame. Most driver
4738 * interfaces rely on more generic OS mechanism for receiving frames through
4739 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4740 * take care of received EAPOL frames and deliver them to the core supplicant
4741 * code by calling this function.
4742 */
4743void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4744 const u8 *buf, size_t len)
4745{
4746 struct wpa_supplicant *wpa_s = ctx;
4747
4748 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4749 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4750
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004751#ifdef CONFIG_TESTING_OPTIONS
4752 if (wpa_s->ignore_auth_resp) {
4753 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4754 return;
4755 }
4756#endif /* CONFIG_TESTING_OPTIONS */
4757
Jouni Malinena05074c2012-12-21 21:35:35 +02004758 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4759 (wpa_s->last_eapol_matches_bssid &&
4760#ifdef CONFIG_AP
4761 !wpa_s->ap_iface &&
4762#endif /* CONFIG_AP */
4763 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004764 /*
4765 * There is possible race condition between receiving the
4766 * association event and the EAPOL frame since they are coming
4767 * through different paths from the driver. In order to avoid
4768 * issues in trying to process the EAPOL frame before receiving
4769 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004770 * the association event is received. This may also be needed in
4771 * driver-based roaming case, so also use src_addr != BSSID as a
4772 * trigger if we have previously confirmed that the
4773 * Authenticator uses BSSID as the src_addr (which is not the
4774 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004775 */
4776 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004777 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4778 wpa_supplicant_state_txt(wpa_s->wpa_state),
4779 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004780 wpabuf_free(wpa_s->pending_eapol_rx);
4781 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4782 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004783 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004784 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4785 ETH_ALEN);
4786 }
4787 return;
4788 }
4789
Jouni Malinena05074c2012-12-21 21:35:35 +02004790 wpa_s->last_eapol_matches_bssid =
4791 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4792
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004793#ifdef CONFIG_AP
4794 if (wpa_s->ap_iface) {
4795 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4796 return;
4797 }
4798#endif /* CONFIG_AP */
4799
4800 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4801 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4802 "no key management is configured");
4803 return;
4804 }
4805
4806 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004807 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004808 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4809 wpa_s->wpa_state != WPA_COMPLETED) &&
4810 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004811 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004812 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004813 int timeout = 10;
4814
4815 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4816 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4817 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4818 /* Use longer timeout for IEEE 802.1X/EAP */
4819 timeout = 70;
4820 }
4821
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004822#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004823 if (wpa_s->current_ssid && wpa_s->current_bss &&
4824 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4825 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4826 /*
4827 * Use shorter timeout if going through WPS AP iteration
4828 * for PIN config method with an AP that does not
4829 * advertise Selected Registrar.
4830 */
4831 struct wpabuf *wps_ie;
4832
4833 wps_ie = wpa_bss_get_vendor_ie_multi(
4834 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4835 if (wps_ie &&
4836 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4837 timeout = 10;
4838 wpabuf_free(wps_ie);
4839 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004840#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004841
4842 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004843 }
4844 wpa_s->eapol_received++;
4845
4846 if (wpa_s->countermeasures) {
4847 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4848 "EAPOL packet");
4849 return;
4850 }
4851
4852#ifdef CONFIG_IBSS_RSN
4853 if (wpa_s->current_ssid &&
4854 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4855 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4856 return;
4857 }
4858#endif /* CONFIG_IBSS_RSN */
4859
4860 /* Source address of the incoming EAPOL frame could be compared to the
4861 * current BSSID. However, it is possible that a centralized
4862 * Authenticator could be using another MAC address than the BSSID of
4863 * an AP, so just allow any address to be used for now. The replies are
4864 * still sent to the current BSSID (if available), though. */
4865
4866 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4867 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004868 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4869 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004870 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4871 return;
4872 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004873 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004874 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4875 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4876 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07004877 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004878 * handshake processing which would normally set portValid. We
4879 * need this to allow the EAPOL state machines to be completed
4880 * without going through EAPOL-Key handshake.
4881 */
Hai Shalome21d4e82020-04-29 16:34:06 -07004882 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004883 }
4884}
4885
4886
Hai Shalomb755a2a2020-04-23 21:49:02 -07004887static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
4888{
4889 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
4890 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
4891}
4892
4893
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004894int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004895{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004896 if ((!wpa_s->p2p_mgmt ||
4897 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4898 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004899 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004900 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4901 wpa_drv_get_mac_addr(wpa_s),
4902 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07004903 wpas_eapol_needs_l2_packet(wpa_s) ?
4904 wpa_supplicant_rx_eapol : NULL,
4905 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004906 if (wpa_s->l2 == NULL)
4907 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004908
4909 if (l2_packet_set_packet_filter(wpa_s->l2,
4910 L2_PACKET_FILTER_PKTTYPE))
4911 wpa_dbg(wpa_s, MSG_DEBUG,
4912 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07004913
4914 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4915 wpa_msg(wpa_s, MSG_ERROR,
4916 "Failed to get own L2 address");
4917 return -1;
4918 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004919 } else {
4920 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4921 if (addr)
4922 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4923 }
4924
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004925 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004926 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004927
Hai Shalomc3565922019-10-28 11:58:20 -07004928#ifdef CONFIG_FST
4929 if (wpa_s->fst)
4930 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4931#endif /* CONFIG_FST */
4932
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004933 return 0;
4934}
4935
4936
Dmitry Shmidt04949592012-07-19 12:16:46 -07004937static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4938 const u8 *buf, size_t len)
4939{
4940 struct wpa_supplicant *wpa_s = ctx;
4941 const struct l2_ethhdr *eth;
4942
4943 if (len < sizeof(*eth))
4944 return;
4945 eth = (const struct l2_ethhdr *) buf;
4946
4947 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4948 !(eth->h_dest[0] & 0x01)) {
4949 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4950 " (bridge - not for this interface - ignore)",
4951 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4952 return;
4953 }
4954
4955 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4956 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4957 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4958 len - sizeof(*eth));
4959}
4960
4961
Hai Shalom899fcc72020-10-19 14:38:18 -07004962int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
4963 const char *bridge_ifname)
4964{
4965 if (wpa_s->wpa_state > WPA_SCANNING)
4966 return -EBUSY;
4967
4968 if (bridge_ifname &&
4969 os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname))
4970 return -EINVAL;
4971
4972 if (!bridge_ifname)
4973 bridge_ifname = "";
4974
4975 if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0)
4976 return 0;
4977
4978 if (wpa_s->l2_br) {
4979 l2_packet_deinit(wpa_s->l2_br);
4980 wpa_s->l2_br = NULL;
4981 }
4982
4983 os_strlcpy(wpa_s->bridge_ifname, bridge_ifname,
4984 sizeof(wpa_s->bridge_ifname));
4985
4986 if (wpa_s->bridge_ifname[0]) {
4987 wpa_dbg(wpa_s, MSG_DEBUG,
4988 "Receiving packets from bridge interface '%s'",
4989 wpa_s->bridge_ifname);
4990 wpa_s->l2_br = l2_packet_init_bridge(
4991 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4992 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
4993 if (!wpa_s->l2_br) {
4994 wpa_msg(wpa_s, MSG_ERROR,
4995 "Failed to open l2_packet connection for the bridge interface '%s'",
4996 wpa_s->bridge_ifname);
4997 goto fail;
4998 }
4999 }
5000
5001#ifdef CONFIG_TDLS
5002 if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
5003 goto fail;
5004#endif /* CONFIG_TDLS */
5005
5006 return 0;
5007fail:
5008 wpa_s->bridge_ifname[0] = 0;
5009 if (wpa_s->l2_br) {
5010 l2_packet_deinit(wpa_s->l2_br);
5011 wpa_s->l2_br = NULL;
5012 }
5013#ifdef CONFIG_TDLS
5014 if (!wpa_s->p2p_mgmt)
5015 wpa_tdls_init(wpa_s->wpa);
5016#endif /* CONFIG_TDLS */
5017 return -EIO;
5018}
5019
5020
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005021/**
5022 * wpa_supplicant_driver_init - Initialize driver interface parameters
5023 * @wpa_s: Pointer to wpa_supplicant data
5024 * Returns: 0 on success, -1 on failure
5025 *
5026 * This function is called to initialize driver interface parameters.
5027 * wpa_drv_init() must have been called before this function to initialize the
5028 * driver interface.
5029 */
5030int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
5031{
5032 static int interface_count = 0;
5033
5034 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
5035 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005036
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005037 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
5038 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005039 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005040 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
5041
Hai Shalomb755a2a2020-04-23 21:49:02 -07005042 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005043 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
5044 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005045 wpa_s->l2_br = l2_packet_init_bridge(
5046 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
5047 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005048 if (wpa_s->l2_br == NULL) {
5049 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
5050 "connection for the bridge interface '%s'",
5051 wpa_s->bridge_ifname);
5052 return -1;
5053 }
5054 }
5055
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005056 if (wpa_s->conf->ap_scan == 2 &&
5057 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
5058 wpa_printf(MSG_INFO,
5059 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
5060 }
5061
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005062 wpa_clear_keys(wpa_s, NULL);
5063
5064 /* Make sure that TKIP countermeasures are not left enabled (could
5065 * happen if wpa_supplicant is killed during countermeasures. */
5066 wpa_drv_set_countermeasures(wpa_s, 0);
5067
5068 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
5069 wpa_drv_flush_pmkid(wpa_s);
5070
5071 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005072 wpa_s->prev_scan_wildcard = 0;
5073
Dmitry Shmidt04949592012-07-19 12:16:46 -07005074 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005075 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
5076 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
5077 interface_count = 0;
5078 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005079#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005080 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07005081 wpa_supplicant_delayed_sched_scan(wpa_s,
5082 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005083 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07005084 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005085 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005086#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005087 interface_count++;
5088 } else
5089 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
5090
5091 return 0;
5092}
5093
5094
5095static int wpa_supplicant_daemon(const char *pid_file)
5096{
5097 wpa_printf(MSG_DEBUG, "Daemonize..");
5098 return os_daemonize(pid_file);
5099}
5100
5101
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005102static struct wpa_supplicant *
5103wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005104{
5105 struct wpa_supplicant *wpa_s;
5106
5107 wpa_s = os_zalloc(sizeof(*wpa_s));
5108 if (wpa_s == NULL)
5109 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005110 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005111 wpa_s->scan_interval = 5;
5112 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005113 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005114 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005115 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005116
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005117 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08005118 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07005119#ifdef CONFIG_TESTING_OPTIONS
5120 dl_list_init(&wpa_s->drv_signal_override);
5121#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005122
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005123 return wpa_s;
5124}
5125
5126
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005127#ifdef CONFIG_HT_OVERRIDES
5128
5129static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
5130 struct ieee80211_ht_capabilities *htcaps,
5131 struct ieee80211_ht_capabilities *htcaps_mask,
5132 const char *ht_mcs)
5133{
5134 /* parse ht_mcs into hex array */
5135 int i;
5136 const char *tmp = ht_mcs;
5137 char *end = NULL;
5138
5139 /* If ht_mcs is null, do not set anything */
5140 if (!ht_mcs)
5141 return 0;
5142
5143 /* This is what we are setting in the kernel */
5144 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
5145
5146 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
5147
5148 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08005149 long v;
5150
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005151 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08005152 v = strtol(tmp, &end, 16);
5153
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005154 if (errno == 0) {
5155 wpa_msg(wpa_s, MSG_DEBUG,
5156 "htcap value[%i]: %ld end: %p tmp: %p",
5157 i, v, end, tmp);
5158 if (end == tmp)
5159 break;
5160
5161 htcaps->supported_mcs_set[i] = v;
5162 tmp = end;
5163 } else {
5164 wpa_msg(wpa_s, MSG_ERROR,
5165 "Failed to parse ht-mcs: %s, error: %s\n",
5166 ht_mcs, strerror(errno));
5167 return -1;
5168 }
5169 }
5170
5171 /*
5172 * If we were able to parse any values, then set mask for the MCS set.
5173 */
5174 if (i) {
5175 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5176 IEEE80211_HT_MCS_MASK_LEN - 1);
5177 /* skip the 3 reserved bits */
5178 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5179 0x1f;
5180 }
5181
5182 return 0;
5183}
5184
5185
5186static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5187 struct ieee80211_ht_capabilities *htcaps,
5188 struct ieee80211_ht_capabilities *htcaps_mask,
5189 int disabled)
5190{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005191 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005192
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005193 if (disabled == -1)
5194 return 0;
5195
Hai Shalom74f70d42019-02-11 14:42:39 -08005196 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5197
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005198 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5199 htcaps_mask->ht_capabilities_info |= msk;
5200 if (disabled)
5201 htcaps->ht_capabilities_info &= msk;
5202 else
5203 htcaps->ht_capabilities_info |= msk;
5204
5205 return 0;
5206}
5207
5208
5209static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5210 struct ieee80211_ht_capabilities *htcaps,
5211 struct ieee80211_ht_capabilities *htcaps_mask,
5212 int factor)
5213{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005214 if (factor == -1)
5215 return 0;
5216
Hai Shalom74f70d42019-02-11 14:42:39 -08005217 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5218
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005219 if (factor < 0 || factor > 3) {
5220 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5221 "Must be 0-3 or -1", factor);
5222 return -EINVAL;
5223 }
5224
5225 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5226 htcaps->a_mpdu_params &= ~0x3;
5227 htcaps->a_mpdu_params |= factor & 0x3;
5228
5229 return 0;
5230}
5231
5232
5233static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5234 struct ieee80211_ht_capabilities *htcaps,
5235 struct ieee80211_ht_capabilities *htcaps_mask,
5236 int density)
5237{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005238 if (density == -1)
5239 return 0;
5240
Hai Shalom74f70d42019-02-11 14:42:39 -08005241 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5242
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005243 if (density < 0 || density > 7) {
5244 wpa_msg(wpa_s, MSG_ERROR,
5245 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5246 density);
5247 return -EINVAL;
5248 }
5249
5250 htcaps_mask->a_mpdu_params |= 0x1C;
5251 htcaps->a_mpdu_params &= ~(0x1C);
5252 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5253
5254 return 0;
5255}
5256
5257
5258static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5259 struct ieee80211_ht_capabilities *htcaps,
5260 struct ieee80211_ht_capabilities *htcaps_mask,
5261 int disabled)
5262{
Hai Shalom74f70d42019-02-11 14:42:39 -08005263 if (disabled)
5264 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005265
Paul Stewart092955c2017-02-06 09:13:09 -08005266 set_disable_ht40(htcaps, disabled);
5267 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005268
5269 return 0;
5270}
5271
5272
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005273static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5274 struct ieee80211_ht_capabilities *htcaps,
5275 struct ieee80211_ht_capabilities *htcaps_mask,
5276 int disabled)
5277{
5278 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005279 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5280 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005281
Hai Shalom74f70d42019-02-11 14:42:39 -08005282 if (disabled)
5283 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005284
5285 if (disabled)
5286 htcaps->ht_capabilities_info &= ~msk;
5287 else
5288 htcaps->ht_capabilities_info |= msk;
5289
5290 htcaps_mask->ht_capabilities_info |= msk;
5291
5292 return 0;
5293}
5294
5295
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005296static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5297 struct ieee80211_ht_capabilities *htcaps,
5298 struct ieee80211_ht_capabilities *htcaps_mask,
5299 int disabled)
5300{
5301 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005302 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005303
Hai Shalom74f70d42019-02-11 14:42:39 -08005304 if (disabled)
5305 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005306
5307 if (disabled)
5308 htcaps->ht_capabilities_info &= ~msk;
5309 else
5310 htcaps->ht_capabilities_info |= msk;
5311
5312 htcaps_mask->ht_capabilities_info |= msk;
5313
5314 return 0;
5315}
5316
5317
Hai Shalom74f70d42019-02-11 14:42:39 -08005318static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5319 struct ieee80211_ht_capabilities *htcaps,
5320 struct ieee80211_ht_capabilities *htcaps_mask,
5321 int tx_stbc)
5322{
5323 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5324
5325 if (tx_stbc == -1)
5326 return 0;
5327
5328 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5329
5330 if (tx_stbc < 0 || tx_stbc > 1) {
5331 wpa_msg(wpa_s, MSG_ERROR,
5332 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5333 return -EINVAL;
5334 }
5335
5336 htcaps_mask->ht_capabilities_info |= msk;
5337 htcaps->ht_capabilities_info &= ~msk;
5338 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5339
5340 return 0;
5341}
5342
5343
5344static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5345 struct ieee80211_ht_capabilities *htcaps,
5346 struct ieee80211_ht_capabilities *htcaps_mask,
5347 int rx_stbc)
5348{
5349 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5350
5351 if (rx_stbc == -1)
5352 return 0;
5353
5354 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5355
5356 if (rx_stbc < 0 || rx_stbc > 3) {
5357 wpa_msg(wpa_s, MSG_ERROR,
5358 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5359 return -EINVAL;
5360 }
5361
5362 htcaps_mask->ht_capabilities_info |= msk;
5363 htcaps->ht_capabilities_info &= ~msk;
5364 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5365
5366 return 0;
5367}
5368
5369
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005370void wpa_supplicant_apply_ht_overrides(
5371 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5372 struct wpa_driver_associate_params *params)
5373{
5374 struct ieee80211_ht_capabilities *htcaps;
5375 struct ieee80211_ht_capabilities *htcaps_mask;
5376
5377 if (!ssid)
5378 return;
5379
5380 params->disable_ht = ssid->disable_ht;
5381 if (!params->htcaps || !params->htcaps_mask)
5382 return;
5383
5384 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5385 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5386 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5387 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5388 ssid->disable_max_amsdu);
5389 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5390 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5391 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005392 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005393 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005394 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5395 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005396
5397 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005398 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005399 htcaps->ht_capabilities_info |= bit;
5400 htcaps_mask->ht_capabilities_info |= bit;
5401 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005402}
5403
5404#endif /* CONFIG_HT_OVERRIDES */
5405
5406
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005407#ifdef CONFIG_VHT_OVERRIDES
5408void wpa_supplicant_apply_vht_overrides(
5409 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5410 struct wpa_driver_associate_params *params)
5411{
5412 struct ieee80211_vht_capabilities *vhtcaps;
5413 struct ieee80211_vht_capabilities *vhtcaps_mask;
5414
5415 if (!ssid)
5416 return;
5417
5418 params->disable_vht = ssid->disable_vht;
5419
5420 vhtcaps = (void *) params->vhtcaps;
5421 vhtcaps_mask = (void *) params->vhtcaps_mask;
5422
5423 if (!vhtcaps || !vhtcaps_mask)
5424 return;
5425
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005426 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5427 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005428
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005429#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005430 if (ssid->disable_sgi) {
5431 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5432 VHT_CAP_SHORT_GI_160);
5433 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5434 VHT_CAP_SHORT_GI_160);
5435 wpa_msg(wpa_s, MSG_DEBUG,
5436 "disable-sgi override specified, vht-caps: 0x%x",
5437 vhtcaps->vht_capabilities_info);
5438 }
5439
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005440 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005441 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5442 int max_ampdu;
5443
5444 max_ampdu = (ssid->vht_capa &
5445 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5446 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005447
5448 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5449 wpa_set_ampdu_factor(wpa_s,
5450 (void *) params->htcaps,
5451 (void *) params->htcaps_mask,
5452 max_ampdu);
5453 }
5454#endif /* CONFIG_HT_OVERRIDES */
5455
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005456#define OVERRIDE_MCS(i) \
5457 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5458 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005459 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005460 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005461 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5462 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005463 } \
5464 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5465 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005466 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005467 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005468 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5469 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005470 }
5471
5472 OVERRIDE_MCS(1);
5473 OVERRIDE_MCS(2);
5474 OVERRIDE_MCS(3);
5475 OVERRIDE_MCS(4);
5476 OVERRIDE_MCS(5);
5477 OVERRIDE_MCS(6);
5478 OVERRIDE_MCS(7);
5479 OVERRIDE_MCS(8);
5480}
5481#endif /* CONFIG_VHT_OVERRIDES */
5482
5483
Hai Shalomfdcde762020-04-02 11:19:20 -07005484#ifdef CONFIG_HE_OVERRIDES
5485void wpa_supplicant_apply_he_overrides(
5486 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5487 struct wpa_driver_associate_params *params)
5488{
5489 if (!ssid)
5490 return;
5491
5492 params->disable_he = ssid->disable_he;
5493}
5494#endif /* CONFIG_HE_OVERRIDES */
5495
5496
Dmitry Shmidt04949592012-07-19 12:16:46 -07005497static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5498{
5499#ifdef PCSC_FUNCS
5500 size_t len;
5501
5502 if (!wpa_s->conf->pcsc_reader)
5503 return 0;
5504
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005505 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005506 if (!wpa_s->scard)
5507 return 1;
5508
5509 if (wpa_s->conf->pcsc_pin &&
5510 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5511 scard_deinit(wpa_s->scard);
5512 wpa_s->scard = NULL;
5513 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5514 return -1;
5515 }
5516
5517 len = sizeof(wpa_s->imsi) - 1;
5518 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5519 scard_deinit(wpa_s->scard);
5520 wpa_s->scard = NULL;
5521 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5522 return -1;
5523 }
5524 wpa_s->imsi[len] = '\0';
5525
5526 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5527
5528 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5529 wpa_s->imsi, wpa_s->mnc_len);
5530
5531 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5532 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5533#endif /* PCSC_FUNCS */
5534
5535 return 0;
5536}
5537
5538
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005539int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5540{
5541 char *val, *pos;
5542
5543 ext_password_deinit(wpa_s->ext_pw);
5544 wpa_s->ext_pw = NULL;
5545 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5546
5547 if (!wpa_s->conf->ext_password_backend)
5548 return 0;
5549
5550 val = os_strdup(wpa_s->conf->ext_password_backend);
5551 if (val == NULL)
5552 return -1;
5553 pos = os_strchr(val, ':');
5554 if (pos)
5555 *pos++ = '\0';
5556
5557 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5558
5559 wpa_s->ext_pw = ext_password_init(val, pos);
5560 os_free(val);
5561 if (wpa_s->ext_pw == NULL) {
5562 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5563 return -1;
5564 }
5565 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5566
5567 return 0;
5568}
5569
5570
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005571#ifdef CONFIG_FST
5572
5573static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5574{
5575 struct wpa_supplicant *wpa_s = ctx;
5576
5577 return (is_zero_ether_addr(wpa_s->bssid) ||
5578 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5579}
5580
5581
5582static void wpas_fst_get_channel_info_cb(void *ctx,
5583 enum hostapd_hw_mode *hw_mode,
5584 u8 *channel)
5585{
5586 struct wpa_supplicant *wpa_s = ctx;
5587
5588 if (wpa_s->current_bss) {
5589 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5590 channel);
5591 } else if (wpa_s->hw.num_modes) {
5592 *hw_mode = wpa_s->hw.modes[0].mode;
5593 } else {
5594 WPA_ASSERT(0);
5595 *hw_mode = 0;
5596 }
5597}
5598
5599
5600static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5601{
5602 struct wpa_supplicant *wpa_s = ctx;
5603
5604 *modes = wpa_s->hw.modes;
5605 return wpa_s->hw.num_modes;
5606}
5607
5608
5609static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5610{
5611 struct wpa_supplicant *wpa_s = ctx;
5612
5613 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5614 wpa_s->fst_ies = fst_ies;
5615}
5616
5617
5618static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5619{
5620 struct wpa_supplicant *wpa_s = ctx;
5621
Paul Stewart092955c2017-02-06 09:13:09 -08005622 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5623 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5624 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5625 return -1;
5626 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005627 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005628 wpa_s->own_addr, wpa_s->bssid,
5629 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005630 0);
5631}
5632
5633
5634static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5635{
5636 struct wpa_supplicant *wpa_s = ctx;
5637
5638 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5639 return wpa_s->received_mb_ies;
5640}
5641
5642
5643static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5644 const u8 *buf, size_t size)
5645{
5646 struct wpa_supplicant *wpa_s = ctx;
5647 struct mb_ies_info info;
5648
5649 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5650
5651 if (!mb_ies_info_by_ies(&info, buf, size)) {
5652 wpabuf_free(wpa_s->received_mb_ies);
5653 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5654 }
5655}
5656
5657
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005658static const u8 * wpas_fst_get_peer_first(void *ctx,
5659 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005660 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005661{
5662 struct wpa_supplicant *wpa_s = ctx;
5663
5664 *get_ctx = NULL;
5665 if (!is_zero_ether_addr(wpa_s->bssid))
5666 return (wpa_s->received_mb_ies || !mb_only) ?
5667 wpa_s->bssid : NULL;
5668 return NULL;
5669}
5670
5671
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005672static const u8 * wpas_fst_get_peer_next(void *ctx,
5673 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005674 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005675{
5676 return NULL;
5677}
5678
5679void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5680 struct fst_wpa_obj *iface_obj)
5681{
5682 iface_obj->ctx = wpa_s;
5683 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5684 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5685 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5686 iface_obj->set_ies = wpas_fst_set_ies_cb;
5687 iface_obj->send_action = wpas_fst_send_action_cb;
5688 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5689 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5690 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5691 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5692}
5693#endif /* CONFIG_FST */
5694
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005695static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005696 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005697{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005698 struct wowlan_triggers *triggers;
5699 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005700
5701 if (!wpa_s->conf->wowlan_triggers)
5702 return 0;
5703
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005704 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5705 if (triggers) {
5706 ret = wpa_drv_wowlan(wpa_s, triggers);
5707 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005708 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005709 return ret;
5710}
5711
5712
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005713enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005714{
5715 if (freq < 3000)
5716 return BAND_2_4_GHZ;
5717 if (freq > 50000)
5718 return BAND_60_GHZ;
5719 return BAND_5_GHZ;
5720}
5721
5722
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005723unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005724{
5725 int i;
5726 unsigned int band = 0;
5727
5728 if (freqs) {
5729 /* freqs are specified for the radio work */
5730 for (i = 0; freqs[i]; i++)
5731 band |= wpas_freq_to_band(freqs[i]);
5732 } else {
5733 /*
5734 * freqs are not specified, implies all
5735 * the supported freqs by HW
5736 */
5737 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5738 if (wpa_s->hw.modes[i].num_channels != 0) {
5739 if (wpa_s->hw.modes[i].mode ==
5740 HOSTAPD_MODE_IEEE80211B ||
5741 wpa_s->hw.modes[i].mode ==
5742 HOSTAPD_MODE_IEEE80211G)
5743 band |= BAND_2_4_GHZ;
5744 else if (wpa_s->hw.modes[i].mode ==
5745 HOSTAPD_MODE_IEEE80211A)
5746 band |= BAND_5_GHZ;
5747 else if (wpa_s->hw.modes[i].mode ==
5748 HOSTAPD_MODE_IEEE80211AD)
5749 band |= BAND_60_GHZ;
5750 else if (wpa_s->hw.modes[i].mode ==
5751 HOSTAPD_MODE_IEEE80211ANY)
5752 band = BAND_2_4_GHZ | BAND_5_GHZ |
5753 BAND_60_GHZ;
5754 }
5755 }
5756 }
5757
5758 return band;
5759}
5760
5761
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005762static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5763 const char *rn)
5764{
5765 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5766 struct wpa_radio *radio;
5767
5768 while (rn && iface) {
5769 radio = iface->radio;
5770 if (radio && os_strcmp(rn, radio->name) == 0) {
5771 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5772 wpa_s->ifname, rn);
5773 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5774 return radio;
5775 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005776
5777 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005778 }
5779
5780 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5781 wpa_s->ifname, rn ? rn : "N/A");
5782 radio = os_zalloc(sizeof(*radio));
5783 if (radio == NULL)
5784 return NULL;
5785
5786 if (rn)
5787 os_strlcpy(radio->name, rn, sizeof(radio->name));
5788 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005789 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005790 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5791
5792 return radio;
5793}
5794
5795
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005796static void radio_work_free(struct wpa_radio_work *work)
5797{
5798 if (work->wpa_s->scan_work == work) {
5799 /* This should not really happen. */
5800 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5801 work->type, work, work->started);
5802 work->wpa_s->scan_work = NULL;
5803 }
5804
5805#ifdef CONFIG_P2P
5806 if (work->wpa_s->p2p_scan_work == work) {
5807 /* This should not really happen. */
5808 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5809 work->type, work, work->started);
5810 work->wpa_s->p2p_scan_work = NULL;
5811 }
5812#endif /* CONFIG_P2P */
5813
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005814 if (work->started) {
5815 work->wpa_s->radio->num_active_works--;
5816 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005817 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005818 work->type, work,
5819 work->wpa_s->radio->num_active_works);
5820 }
5821
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005822 dl_list_del(&work->list);
5823 os_free(work);
5824}
5825
5826
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005827static int radio_work_is_connect(struct wpa_radio_work *work)
5828{
5829 return os_strcmp(work->type, "sme-connect") == 0 ||
5830 os_strcmp(work->type, "connect") == 0;
5831}
5832
5833
5834static int radio_work_is_scan(struct wpa_radio_work *work)
5835{
5836 return os_strcmp(work->type, "scan") == 0 ||
5837 os_strcmp(work->type, "p2p-scan") == 0;
5838}
5839
5840
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005841static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5842{
5843 struct wpa_radio_work *active_work = NULL;
5844 struct wpa_radio_work *tmp;
5845
5846 /* Get the active work to know the type and band. */
5847 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5848 if (tmp->started) {
5849 active_work = tmp;
5850 break;
5851 }
5852 }
5853
5854 if (!active_work) {
5855 /* No active work, start one */
5856 radio->num_active_works = 0;
5857 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5858 list) {
5859 if (os_strcmp(tmp->type, "scan") == 0 &&
5860 radio->external_scan_running &&
5861 (((struct wpa_driver_scan_params *)
5862 tmp->ctx)->only_new_results ||
5863 tmp->wpa_s->clear_driver_scan_cache))
5864 continue;
5865 return tmp;
5866 }
5867 return NULL;
5868 }
5869
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005870 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005871 /*
5872 * If the active work is either connect or sme-connect,
5873 * do not parallelize them with other radio works.
5874 */
5875 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5876 "Do not parallelize radio work with %s",
5877 active_work->type);
5878 return NULL;
5879 }
5880
5881 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5882 if (tmp->started)
5883 continue;
5884
5885 /*
5886 * If connect or sme-connect are enqueued, parallelize only
5887 * those operations ahead of them in the queue.
5888 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005889 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005890 break;
5891
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005892 /* Serialize parallel scan and p2p_scan operations on the same
5893 * interface since the driver_nl80211 mechanism for tracking
5894 * scan cookies does not yet have support for this. */
5895 if (active_work->wpa_s == tmp->wpa_s &&
5896 radio_work_is_scan(active_work) &&
5897 radio_work_is_scan(tmp)) {
5898 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5899 "Do not start work '%s' when another work '%s' is already scheduled",
5900 tmp->type, active_work->type);
5901 continue;
5902 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005903 /*
5904 * Check that the radio works are distinct and
5905 * on different bands.
5906 */
5907 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5908 (active_work->bands != tmp->bands)) {
5909 /*
5910 * If a scan has to be scheduled through nl80211 scan
5911 * interface and if an external scan is already running,
5912 * do not schedule the scan since it is likely to get
5913 * rejected by kernel.
5914 */
5915 if (os_strcmp(tmp->type, "scan") == 0 &&
5916 radio->external_scan_running &&
5917 (((struct wpa_driver_scan_params *)
5918 tmp->ctx)->only_new_results ||
5919 tmp->wpa_s->clear_driver_scan_cache))
5920 continue;
5921
5922 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5923 "active_work:%s new_work:%s",
5924 active_work->type, tmp->type);
5925 return tmp;
5926 }
5927 }
5928
5929 /* Did not find a radio work to schedule in parallel. */
5930 return NULL;
5931}
5932
5933
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005934static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5935{
5936 struct wpa_radio *radio = eloop_ctx;
5937 struct wpa_radio_work *work;
5938 struct os_reltime now, diff;
5939 struct wpa_supplicant *wpa_s;
5940
5941 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005942 if (work == NULL) {
5943 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005944 return;
5945 }
5946
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005947 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5948 radio_list);
5949
5950 if (!(wpa_s &&
5951 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5952 if (work->started)
5953 return; /* already started and still in progress */
5954
5955 if (wpa_s && wpa_s->radio->external_scan_running) {
5956 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5957 return;
5958 }
5959 } else {
5960 work = NULL;
5961 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5962 /* get the work to schedule next */
5963 work = radio_work_get_next_work(radio);
5964 }
5965 if (!work)
5966 return;
5967 }
5968
5969 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005970 os_get_reltime(&now);
5971 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005972 wpa_dbg(wpa_s, MSG_DEBUG,
5973 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005974 work->type, work, diff.sec, diff.usec);
5975 work->started = 1;
5976 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005977 radio->num_active_works++;
5978
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005979 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005980
5981 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5982 radio->num_active_works < MAX_ACTIVE_WORKS)
5983 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005984}
5985
5986
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005987/*
5988 * This function removes both started and pending radio works running on
5989 * the provided interface's radio.
5990 * Prior to the removal of the radio work, its callback (cb) is called with
5991 * deinit set to be 1. Each work's callback is responsible for clearing its
5992 * internal data and restoring to a correct state.
5993 * @wpa_s: wpa_supplicant data
5994 * @type: type of works to be removed
5995 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5996 * this interface's works.
5997 */
5998void radio_remove_works(struct wpa_supplicant *wpa_s,
5999 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006000{
6001 struct wpa_radio_work *work, *tmp;
6002 struct wpa_radio *radio = wpa_s->radio;
6003
6004 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
6005 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006006 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006007 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006008
6009 /* skip other ifaces' works */
6010 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006011 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006012
6013 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
6014 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006015 work->cb(work, 1);
6016 radio_work_free(work);
6017 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006018
6019 /* in case we removed the started work */
6020 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006021}
6022
6023
Roshan Pius3a1667e2018-07-03 15:17:14 -07006024void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
6025{
6026 struct wpa_radio_work *work;
6027 struct wpa_radio *radio = wpa_s->radio;
6028
6029 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6030 if (work->ctx != ctx)
6031 continue;
6032 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
6033 work->type, work, work->started ? " (started)" : "");
6034 radio_work_free(work);
6035 break;
6036 }
6037}
6038
6039
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006040static void radio_remove_interface(struct wpa_supplicant *wpa_s)
6041{
6042 struct wpa_radio *radio = wpa_s->radio;
6043
6044 if (!radio)
6045 return;
6046
6047 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
6048 wpa_s->ifname, radio->name);
6049 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006050 radio_remove_works(wpa_s, NULL, 0);
6051 wpa_s->radio = NULL;
6052 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006053 return; /* Interfaces remain for this radio */
6054
6055 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006056 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006057 os_free(radio);
6058}
6059
6060
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006061void radio_work_check_next(struct wpa_supplicant *wpa_s)
6062{
6063 struct wpa_radio *radio = wpa_s->radio;
6064
6065 if (dl_list_empty(&radio->work))
6066 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006067 if (wpa_s->ext_work_in_progress) {
6068 wpa_printf(MSG_DEBUG,
6069 "External radio work in progress - delay start of pending item");
6070 return;
6071 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006072 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
6073 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
6074}
6075
6076
6077/**
6078 * radio_add_work - Add a radio work item
6079 * @wpa_s: Pointer to wpa_supplicant data
6080 * @freq: Frequency of the offchannel operation in MHz or 0
6081 * @type: Unique identifier for each type of work
6082 * @next: Force as the next work to be executed
6083 * @cb: Callback function for indicating when radio is available
6084 * @ctx: Context pointer for the work (work->ctx in cb())
6085 * Returns: 0 on success, -1 on failure
6086 *
6087 * This function is used to request time for an operation that requires
6088 * exclusive radio control. Once the radio is available, the registered callback
6089 * function will be called. radio_work_done() must be called once the exclusive
6090 * radio operation has been completed, so that the radio is freed for other
6091 * operations. The special case of deinit=1 is used to free the context data
6092 * during interface removal. That does not allow the callback function to start
6093 * the radio operation, i.e., it must free any resources allocated for the radio
6094 * work and return.
6095 *
6096 * The @freq parameter can be used to indicate a single channel on which the
6097 * offchannel operation will occur. This may allow multiple radio work
6098 * operations to be performed in parallel if they apply for the same channel.
6099 * Setting this to 0 indicates that the work item may use multiple channels or
6100 * requires exclusive control of the radio.
6101 */
6102int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
6103 const char *type, int next,
6104 void (*cb)(struct wpa_radio_work *work, int deinit),
6105 void *ctx)
6106{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006107 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006108 struct wpa_radio_work *work;
6109 int was_empty;
6110
6111 work = os_zalloc(sizeof(*work));
6112 if (work == NULL)
6113 return -1;
6114 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
6115 os_get_reltime(&work->time);
6116 work->freq = freq;
6117 work->type = type;
6118 work->wpa_s = wpa_s;
6119 work->cb = cb;
6120 work->ctx = ctx;
6121
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006122 if (freq)
6123 work->bands = wpas_freq_to_band(freq);
6124 else if (os_strcmp(type, "scan") == 0 ||
6125 os_strcmp(type, "p2p-scan") == 0)
6126 work->bands = wpas_get_bands(wpa_s,
6127 ((struct wpa_driver_scan_params *)
6128 ctx)->freqs);
6129 else
6130 work->bands = wpas_get_bands(wpa_s, NULL);
6131
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006132 was_empty = dl_list_empty(&wpa_s->radio->work);
6133 if (next)
6134 dl_list_add(&wpa_s->radio->work, &work->list);
6135 else
6136 dl_list_add_tail(&wpa_s->radio->work, &work->list);
6137 if (was_empty) {
6138 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
6139 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006140 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
6141 && radio->num_active_works < MAX_ACTIVE_WORKS) {
6142 wpa_dbg(wpa_s, MSG_DEBUG,
6143 "Try to schedule a radio work (num_active_works=%u)",
6144 radio->num_active_works);
6145 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006146 }
6147
6148 return 0;
6149}
6150
6151
6152/**
6153 * radio_work_done - Indicate that a radio work item has been completed
6154 * @work: Completed work
6155 *
6156 * This function is called once the callback function registered with
6157 * radio_add_work() has completed its work.
6158 */
6159void radio_work_done(struct wpa_radio_work *work)
6160{
6161 struct wpa_supplicant *wpa_s = work->wpa_s;
6162 struct os_reltime now, diff;
6163 unsigned int started = work->started;
6164
6165 os_get_reltime(&now);
6166 os_reltime_sub(&now, &work->time, &diff);
6167 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6168 work->type, work, started ? "done" : "canceled",
6169 diff.sec, diff.usec);
6170 radio_work_free(work);
6171 if (started)
6172 radio_work_check_next(wpa_s);
6173}
6174
6175
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006176struct wpa_radio_work *
6177radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006178{
6179 struct wpa_radio_work *work;
6180 struct wpa_radio *radio = wpa_s->radio;
6181
6182 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6183 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006184 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006185 }
6186
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006187 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006188}
6189
6190
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006191static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006192 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006193{
6194 const char *ifname, *driver, *rn;
6195
6196 driver = iface->driver;
6197next_driver:
6198 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6199 return -1;
6200
6201 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6202 if (wpa_s->drv_priv == NULL) {
6203 const char *pos;
Hai Shalom899fcc72020-10-19 14:38:18 -07006204 int level = MSG_ERROR;
6205
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006206 pos = driver ? os_strchr(driver, ',') : NULL;
6207 if (pos) {
6208 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6209 "driver interface - try next driver wrapper");
6210 driver = pos + 1;
6211 goto next_driver;
6212 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006213
6214#ifdef CONFIG_MATCH_IFACE
6215 if (wpa_s->matched == WPA_IFACE_MATCHED_NULL)
6216 level = MSG_DEBUG;
6217#endif /* CONFIG_MATCH_IFACE */
6218 wpa_msg(wpa_s, level, "Failed to initialize driver interface");
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006219 return -1;
6220 }
6221 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6222 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6223 "driver_param '%s'", wpa_s->conf->driver_param);
6224 return -1;
6225 }
6226
6227 ifname = wpa_drv_get_ifname(wpa_s);
6228 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6229 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6230 "interface name with '%s'", ifname);
6231 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6232 }
6233
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006234 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006235 if (rn && rn[0] == '\0')
6236 rn = NULL;
6237
6238 wpa_s->radio = radio_add_interface(wpa_s, rn);
6239 if (wpa_s->radio == NULL)
6240 return -1;
6241
6242 return 0;
6243}
6244
6245
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006246#ifdef CONFIG_GAS_SERVER
6247
6248static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6249 unsigned int freq, const u8 *dst,
6250 const u8 *src, const u8 *bssid,
6251 const u8 *data, size_t data_len,
6252 enum offchannel_send_action_result result)
6253{
6254 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6255 " result=%s",
6256 freq, MAC2STR(dst),
6257 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6258 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6259 "FAILED"));
6260 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6261 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6262}
6263
6264
6265static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6266 struct wpabuf *buf, unsigned int wait_time)
6267{
6268 struct wpa_supplicant *wpa_s = ctx;
6269 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6270
6271 if (wait_time > wpa_s->max_remain_on_chan)
6272 wait_time = wpa_s->max_remain_on_chan;
6273
6274 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6275 wpabuf_head(buf), wpabuf_len(buf),
6276 wait_time, wpas_gas_server_tx_status, 0);
6277}
6278
6279#endif /* CONFIG_GAS_SERVER */
6280
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006281static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006282 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006283{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006284 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006285 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006286 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006287
6288 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6289 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6290 iface->confname ? iface->confname : "N/A",
6291 iface->driver ? iface->driver : "default",
6292 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6293 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6294
6295 if (iface->confname) {
6296#ifdef CONFIG_BACKEND_FILE
6297 wpa_s->confname = os_rel2abs_path(iface->confname);
6298 if (wpa_s->confname == NULL) {
6299 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6300 "for configuration file '%s'.",
6301 iface->confname);
6302 return -1;
6303 }
6304 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6305 iface->confname, wpa_s->confname);
6306#else /* CONFIG_BACKEND_FILE */
6307 wpa_s->confname = os_strdup(iface->confname);
6308#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006309 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006310 if (wpa_s->conf == NULL) {
6311 wpa_printf(MSG_ERROR, "Failed to read or parse "
6312 "configuration '%s'.", wpa_s->confname);
6313 return -1;
6314 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006315 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006316 if (wpa_s->confanother &&
6317 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6318 wpa_printf(MSG_ERROR,
6319 "Failed to read or parse configuration '%s'.",
6320 wpa_s->confanother);
6321 return -1;
6322 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006323
6324 /*
6325 * Override ctrl_interface and driver_param if set on command
6326 * line.
6327 */
6328 if (iface->ctrl_interface) {
6329 os_free(wpa_s->conf->ctrl_interface);
6330 wpa_s->conf->ctrl_interface =
6331 os_strdup(iface->ctrl_interface);
6332 }
6333
6334 if (iface->driver_param) {
6335 os_free(wpa_s->conf->driver_param);
6336 wpa_s->conf->driver_param =
6337 os_strdup(iface->driver_param);
6338 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006339
6340 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6341 os_free(wpa_s->conf->ctrl_interface);
6342 wpa_s->conf->ctrl_interface = NULL;
6343 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006344 } else
6345 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6346 iface->driver_param);
6347
6348 if (wpa_s->conf == NULL) {
6349 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6350 return -1;
6351 }
6352
6353 if (iface->ifname == NULL) {
6354 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6355 return -1;
6356 }
6357 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6358 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6359 iface->ifname);
6360 return -1;
6361 }
6362 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
Hai Shalom899fcc72020-10-19 14:38:18 -07006363#ifdef CONFIG_MATCH_IFACE
6364 wpa_s->matched = iface->matched;
6365#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006366
6367 if (iface->bridge_ifname) {
6368 if (os_strlen(iface->bridge_ifname) >=
6369 sizeof(wpa_s->bridge_ifname)) {
6370 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6371 "name '%s'.", iface->bridge_ifname);
6372 return -1;
6373 }
6374 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6375 sizeof(wpa_s->bridge_ifname));
6376 }
6377
6378 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006379 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6380 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006381
6382 /* Initialize driver interface and register driver event handler before
6383 * L2 receive handler so that association events are processed before
6384 * EAPOL-Key packets if both become available for the same select()
6385 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006386 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006387 return -1;
6388
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006389 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6390 return -1;
6391
6392 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6393 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6394 NULL);
6395 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6396
6397 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6398 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6399 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6400 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6401 "dot11RSNAConfigPMKLifetime");
6402 return -1;
6403 }
6404
6405 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6406 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6407 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6408 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6409 "dot11RSNAConfigPMKReauthThreshold");
6410 return -1;
6411 }
6412
6413 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6414 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6415 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6416 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6417 "dot11RSNAConfigSATimeout");
6418 return -1;
6419 }
6420
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006421 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6422 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006423 &wpa_s->hw.flags,
6424 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006425 if (wpa_s->hw.modes) {
6426 u16 i;
6427
6428 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6429 if (wpa_s->hw.modes[i].vht_capab) {
6430 wpa_s->hw_capab = CAPAB_VHT;
6431 break;
6432 }
6433
6434 if (wpa_s->hw.modes[i].ht_capab &
6435 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6436 wpa_s->hw_capab = CAPAB_HT40;
6437 else if (wpa_s->hw.modes[i].ht_capab &&
6438 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6439 wpa_s->hw_capab = CAPAB_HT;
6440 }
6441 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006442
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006443 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6444 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006445 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006446 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006447 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006448 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006449 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006450 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006451 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006452 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006453 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6454 wpa_s->max_sched_scan_plan_interval =
6455 capa.max_sched_scan_plan_interval;
6456 wpa_s->max_sched_scan_plan_iterations =
6457 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006458 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6459 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006460 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6461 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006462 wpa_s->extended_capa = capa.extended_capa;
6463 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6464 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006465 wpa_s->num_multichan_concurrent =
6466 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006467 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6468
6469 if (capa.mac_addr_rand_scan_supported)
6470 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6471 if (wpa_s->sched_scan_supported &&
6472 capa.mac_addr_rand_sched_scan_supported)
6473 wpa_s->mac_addr_rand_supported |=
6474 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006475
6476 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6477 if (wpa_s->extended_capa &&
6478 wpa_s->extended_capa_len >= 3 &&
6479 wpa_s->extended_capa[2] & 0x40)
6480 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006481 }
6482 if (wpa_s->max_remain_on_chan == 0)
6483 wpa_s->max_remain_on_chan = 1000;
6484
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006485 /*
6486 * Only take p2p_mgmt parameters when P2P Device is supported.
6487 * Doing it here as it determines whether l2_packet_init() will be done
6488 * during wpa_supplicant_driver_init().
6489 */
6490 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6491 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006492
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006493 if (wpa_s->num_multichan_concurrent == 0)
6494 wpa_s->num_multichan_concurrent = 1;
6495
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006496 if (wpa_supplicant_driver_init(wpa_s) < 0)
6497 return -1;
6498
6499#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006500 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006501 return -1;
6502#endif /* CONFIG_TDLS */
6503
6504 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6505 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6506 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6507 return -1;
6508 }
6509
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006510#ifdef CONFIG_FST
6511 if (wpa_s->conf->fst_group_id) {
6512 struct fst_iface_cfg cfg;
6513 struct fst_wpa_obj iface_obj;
6514
6515 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6516 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6517 sizeof(cfg.group_id));
6518 cfg.priority = wpa_s->conf->fst_priority;
6519 cfg.llt = wpa_s->conf->fst_llt;
6520
6521 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6522 &iface_obj, &cfg);
6523 if (!wpa_s->fst) {
6524 wpa_msg(wpa_s, MSG_ERROR,
6525 "FST: Cannot attach iface %s to group %s",
6526 wpa_s->ifname, cfg.group_id);
6527 return -1;
6528 }
6529 }
6530#endif /* CONFIG_FST */
6531
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006532 if (wpas_wps_init(wpa_s))
6533 return -1;
6534
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006535#ifdef CONFIG_GAS_SERVER
6536 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6537 if (!wpa_s->gas_server) {
6538 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6539 return -1;
6540 }
6541#endif /* CONFIG_GAS_SERVER */
6542
6543#ifdef CONFIG_DPP
6544 if (wpas_dpp_init(wpa_s) < 0)
6545 return -1;
6546#endif /* CONFIG_DPP */
6547
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006548 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6549 return -1;
6550 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6551
6552 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6553 if (wpa_s->ctrl_iface == NULL) {
6554 wpa_printf(MSG_ERROR,
6555 "Failed to initialize control interface '%s'.\n"
6556 "You may have another wpa_supplicant process "
6557 "already running or the file was\n"
6558 "left by an unclean termination of wpa_supplicant "
6559 "in which case you will need\n"
6560 "to manually remove this file before starting "
6561 "wpa_supplicant again.\n",
6562 wpa_s->conf->ctrl_interface);
6563 return -1;
6564 }
6565
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006566 wpa_s->gas = gas_query_init(wpa_s);
6567 if (wpa_s->gas == NULL) {
6568 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6569 return -1;
6570 }
6571
Roshan Pius3a1667e2018-07-03 15:17:14 -07006572 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6573 wpa_s->p2p_mgmt) &&
6574 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006575 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6576 return -1;
6577 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006578
6579 if (wpa_bss_init(wpa_s) < 0)
6580 return -1;
6581
Paul Stewart092955c2017-02-06 09:13:09 -08006582#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6583#ifdef CONFIG_MESH
6584 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6585#endif /* CONFIG_MESH */
6586#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6587
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006588 /*
6589 * Set Wake-on-WLAN triggers, if configured.
6590 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6591 * have effect anyway when the interface is down).
6592 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006593 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006594 return -1;
6595
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006596#ifdef CONFIG_EAP_PROXY
6597{
6598 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006599 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6600 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006601 if (wpa_s->mnc_len > 0) {
6602 wpa_s->imsi[len] = '\0';
6603 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6604 wpa_s->imsi, wpa_s->mnc_len);
6605 } else {
6606 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6607 }
6608}
6609#endif /* CONFIG_EAP_PROXY */
6610
Dmitry Shmidt04949592012-07-19 12:16:46 -07006611 if (pcsc_reader_init(wpa_s) < 0)
6612 return -1;
6613
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006614 if (wpas_init_ext_pw(wpa_s) < 0)
6615 return -1;
6616
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006617 wpas_rrm_reset(wpa_s);
6618
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006619 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6620
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006621#ifdef CONFIG_HS20
6622 hs20_init(wpa_s);
6623#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006624#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006625 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006626 if ((wpa_s->conf->oce & OCE_STA) &&
6627 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6628 wpa_s->enable_oce = OCE_STA;
6629 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6630 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6631 /* TODO: Need to add STA-CFON support */
6632 wpa_printf(MSG_ERROR,
6633 "OCE STA-CFON feature is not yet supported");
6634 }
6635 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006636 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6637#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006638
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006639 wpa_supplicant_set_default_scan_ies(wpa_s);
6640
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006641 return 0;
6642}
6643
6644
6645static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006646 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006647{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006648 struct wpa_global *global = wpa_s->global;
6649 struct wpa_supplicant *iface, *prev;
6650
6651 if (wpa_s == wpa_s->parent)
6652 wpas_p2p_group_remove(wpa_s, "*");
6653
6654 iface = global->ifaces;
6655 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006656 if (iface->p2pdev == wpa_s)
6657 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006658 if (iface == wpa_s || iface->parent != wpa_s) {
6659 iface = iface->next;
6660 continue;
6661 }
6662 wpa_printf(MSG_DEBUG,
6663 "Remove remaining child interface %s from parent %s",
6664 iface->ifname, wpa_s->ifname);
6665 prev = iface;
6666 iface = iface->next;
6667 wpa_supplicant_remove_iface(global, prev, terminate);
6668 }
6669
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006670 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006671 if (wpa_s->drv_priv) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006672 /* Don't deauthenticate if WoWLAN is enabled */
6673 if (!wpa_drv_get_wowlan(wpa_s)) {
6674 wpa_supplicant_deauthenticate(
6675 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006676
Hai Shalomfdcde762020-04-02 11:19:20 -07006677 wpa_drv_set_countermeasures(wpa_s, 0);
6678 wpa_clear_keys(wpa_s, NULL);
6679 } else {
6680 wpa_msg(wpa_s, MSG_INFO,
6681 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6682 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006683 }
6684
6685 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006686 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006687
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006688 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006689 radio_remove_interface(wpa_s);
6690
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006691#ifdef CONFIG_FST
6692 if (wpa_s->fst) {
6693 fst_detach(wpa_s->fst);
6694 wpa_s->fst = NULL;
6695 }
6696 if (wpa_s->received_mb_ies) {
6697 wpabuf_free(wpa_s->received_mb_ies);
6698 wpa_s->received_mb_ies = NULL;
6699 }
6700#endif /* CONFIG_FST */
6701
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006702 if (wpa_s->drv_priv)
6703 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006704
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006705 if (notify)
6706 wpas_notify_iface_removed(wpa_s);
6707
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006708 if (terminate)
6709 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006710
6711 if (wpa_s->ctrl_iface) {
6712 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6713 wpa_s->ctrl_iface = NULL;
6714 }
6715
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006716#ifdef CONFIG_MESH
6717 if (wpa_s->ifmsh) {
6718 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6719 wpa_s->ifmsh = NULL;
6720 }
6721#endif /* CONFIG_MESH */
6722
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006723 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006724 wpa_config_free(wpa_s->conf);
6725 wpa_s->conf = NULL;
6726 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006727
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006728 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006729 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006730
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006731 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006732}
6733
6734
Dmitry Shmidte4663042016-04-04 10:07:49 -07006735#ifdef CONFIG_MATCH_IFACE
6736
6737/**
6738 * wpa_supplicant_match_iface - Match an interface description to a name
6739 * @global: Pointer to global data from wpa_supplicant_init()
6740 * @ifname: Name of the interface to match
6741 * Returns: Pointer to the created interface description or %NULL on failure
6742 */
6743struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6744 const char *ifname)
6745{
6746 int i;
6747 struct wpa_interface *iface, *miface;
6748
6749 for (i = 0; i < global->params.match_iface_count; i++) {
6750 miface = &global->params.match_ifaces[i];
6751 if (!miface->ifname ||
6752 fnmatch(miface->ifname, ifname, 0) == 0) {
6753 iface = os_zalloc(sizeof(*iface));
6754 if (!iface)
6755 return NULL;
6756 *iface = *miface;
Hai Shalom899fcc72020-10-19 14:38:18 -07006757 if (!miface->ifname)
6758 iface->matched = WPA_IFACE_MATCHED_NULL;
6759 else
6760 iface->matched = WPA_IFACE_MATCHED;
Dmitry Shmidte4663042016-04-04 10:07:49 -07006761 iface->ifname = ifname;
6762 return iface;
6763 }
6764 }
6765
6766 return NULL;
6767}
6768
6769
6770/**
6771 * wpa_supplicant_match_existing - Match existing interfaces
6772 * @global: Pointer to global data from wpa_supplicant_init()
6773 * Returns: 0 on success, -1 on failure
6774 */
6775static int wpa_supplicant_match_existing(struct wpa_global *global)
6776{
6777 struct if_nameindex *ifi, *ifp;
6778 struct wpa_supplicant *wpa_s;
6779 struct wpa_interface *iface;
6780
6781 ifp = if_nameindex();
6782 if (!ifp) {
6783 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6784 return -1;
6785 }
6786
6787 for (ifi = ifp; ifi->if_name; ifi++) {
6788 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6789 if (wpa_s)
6790 continue;
6791 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6792 if (iface) {
6793 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6794 os_free(iface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006795 }
6796 }
6797
6798 if_freenameindex(ifp);
6799 return 0;
6800}
6801
6802#endif /* CONFIG_MATCH_IFACE */
6803
6804
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006805/**
6806 * wpa_supplicant_add_iface - Add a new network interface
6807 * @global: Pointer to global data from wpa_supplicant_init()
6808 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006809 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006810 * Returns: Pointer to the created interface or %NULL on failure
6811 *
6812 * This function is used to add new network interfaces for %wpa_supplicant.
6813 * This can be called before wpa_supplicant_run() to add interfaces before the
6814 * main event loop has been started. In addition, new interfaces can be added
6815 * dynamically while %wpa_supplicant is already running. This could happen,
6816 * e.g., when a hotplug network adapter is inserted.
6817 */
6818struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006819 struct wpa_interface *iface,
6820 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006821{
6822 struct wpa_supplicant *wpa_s;
6823 struct wpa_interface t_iface;
6824 struct wpa_ssid *ssid;
6825
6826 if (global == NULL || iface == NULL)
6827 return NULL;
6828
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006829 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006830 if (wpa_s == NULL)
6831 return NULL;
6832
6833 wpa_s->global = global;
6834
6835 t_iface = *iface;
6836 if (global->params.override_driver) {
6837 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6838 "('%s' -> '%s')",
6839 iface->driver, global->params.override_driver);
6840 t_iface.driver = global->params.override_driver;
6841 }
6842 if (global->params.override_ctrl_interface) {
6843 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6844 "ctrl_interface ('%s' -> '%s')",
6845 iface->ctrl_interface,
6846 global->params.override_ctrl_interface);
6847 t_iface.ctrl_interface =
6848 global->params.override_ctrl_interface;
6849 }
6850 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6851 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6852 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006853 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006854 return NULL;
6855 }
6856
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006857 /* Notify the control interfaces about new iface */
6858 if (wpas_notify_iface_added(wpa_s)) {
6859 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6860 return NULL;
6861 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006862
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006863 /* Notify the control interfaces about new networks for non p2p mgmt
6864 * ifaces. */
6865 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006866 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6867 wpas_notify_network_added(wpa_s, ssid);
6868 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006869
6870 wpa_s->next = global->ifaces;
6871 global->ifaces = wpa_s;
6872
6873 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006874 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006875
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006876#ifdef CONFIG_P2P
6877 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006878 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006879 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006880 wpas_p2p_add_p2pdev_interface(
6881 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006882 wpa_printf(MSG_INFO,
6883 "P2P: Failed to enable P2P Device interface");
6884 /* Try to continue without. P2P will be disabled. */
6885 }
6886#endif /* CONFIG_P2P */
6887
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006888 return wpa_s;
6889}
6890
6891
6892/**
6893 * wpa_supplicant_remove_iface - Remove a network interface
6894 * @global: Pointer to global data from wpa_supplicant_init()
6895 * @wpa_s: Pointer to the network interface to be removed
6896 * Returns: 0 if interface was removed, -1 if interface was not found
6897 *
6898 * This function can be used to dynamically remove network interfaces from
6899 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6900 * addition, this function is used to remove all remaining interfaces when
6901 * %wpa_supplicant is terminated.
6902 */
6903int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006904 struct wpa_supplicant *wpa_s,
6905 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006906{
6907 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006908#ifdef CONFIG_MESH
6909 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6910 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006911 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006912#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006913
6914 /* Remove interface from the global list of interfaces */
6915 prev = global->ifaces;
6916 if (prev == wpa_s) {
6917 global->ifaces = wpa_s->next;
6918 } else {
6919 while (prev && prev->next != wpa_s)
6920 prev = prev->next;
6921 if (prev == NULL)
6922 return -1;
6923 prev->next = wpa_s->next;
6924 }
6925
6926 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6927
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006928#ifdef CONFIG_MESH
6929 if (mesh_if_created) {
6930 ifname = os_strdup(wpa_s->ifname);
6931 if (ifname == NULL) {
6932 wpa_dbg(wpa_s, MSG_ERROR,
6933 "mesh: Failed to malloc ifname");
6934 return -1;
6935 }
6936 }
6937#endif /* CONFIG_MESH */
6938
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006939 if (global->p2p_group_formation == wpa_s)
6940 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006941 if (global->p2p_invite_group == wpa_s)
6942 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006943 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006944
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006945#ifdef CONFIG_MESH
6946 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006947 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006948 os_free(ifname);
6949 }
6950#endif /* CONFIG_MESH */
6951
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006952 return 0;
6953}
6954
6955
6956/**
6957 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6958 * @wpa_s: Pointer to the network interface
6959 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6960 */
6961const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6962{
6963 const char *eapol_method;
6964
6965 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6966 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6967 return "NO-EAP";
6968 }
6969
6970 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6971 if (eapol_method == NULL)
6972 return "UNKNOWN-EAP";
6973
6974 return eapol_method;
6975}
6976
6977
6978/**
6979 * wpa_supplicant_get_iface - Get a new network interface
6980 * @global: Pointer to global data from wpa_supplicant_init()
6981 * @ifname: Interface name
6982 * Returns: Pointer to the interface or %NULL if not found
6983 */
6984struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6985 const char *ifname)
6986{
6987 struct wpa_supplicant *wpa_s;
6988
6989 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6990 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6991 return wpa_s;
6992 }
6993 return NULL;
6994}
6995
6996
6997#ifndef CONFIG_NO_WPA_MSG
6998static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6999{
7000 struct wpa_supplicant *wpa_s = ctx;
7001 if (wpa_s == NULL)
7002 return NULL;
7003 return wpa_s->ifname;
7004}
7005#endif /* CONFIG_NO_WPA_MSG */
7006
7007
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007008#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
7009#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
7010#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
7011
7012/* Periodic cleanup tasks */
7013static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
7014{
7015 struct wpa_global *global = eloop_ctx;
7016 struct wpa_supplicant *wpa_s;
7017
7018 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7019 wpas_periodic, global, NULL);
7020
7021#ifdef CONFIG_P2P
7022 if (global->p2p)
7023 p2p_expire_peers(global->p2p);
7024#endif /* CONFIG_P2P */
7025
7026 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7027 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
7028#ifdef CONFIG_AP
7029 ap_periodic(wpa_s);
7030#endif /* CONFIG_AP */
7031 }
7032}
7033
7034
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007035/**
7036 * wpa_supplicant_init - Initialize %wpa_supplicant
7037 * @params: Parameters for %wpa_supplicant
7038 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
7039 *
7040 * This function is used to initialize %wpa_supplicant. After successful
7041 * initialization, the returned data pointer can be used to add and remove
7042 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
7043 */
7044struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
7045{
7046 struct wpa_global *global;
7047 int ret, i;
7048
7049 if (params == NULL)
7050 return NULL;
7051
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007052#ifdef CONFIG_DRIVER_NDIS
7053 {
7054 void driver_ndis_init_ops(void);
7055 driver_ndis_init_ops();
7056 }
7057#endif /* CONFIG_DRIVER_NDIS */
7058
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007059#ifndef CONFIG_NO_WPA_MSG
7060 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
7061#endif /* CONFIG_NO_WPA_MSG */
7062
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007063 if (params->wpa_debug_file_path)
7064 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07007065 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007066 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007067 if (params->wpa_debug_syslog)
7068 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007069 if (params->wpa_debug_tracing) {
7070 ret = wpa_debug_open_linux_tracing();
7071 if (ret) {
7072 wpa_printf(MSG_ERROR,
7073 "Failed to enable trace logging");
7074 return NULL;
7075 }
7076 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007077
7078 ret = eap_register_methods();
7079 if (ret) {
7080 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
7081 if (ret == -2)
7082 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
7083 "the same EAP type.");
7084 return NULL;
7085 }
7086
7087 global = os_zalloc(sizeof(*global));
7088 if (global == NULL)
7089 return NULL;
7090 dl_list_init(&global->p2p_srv_bonjour);
7091 dl_list_init(&global->p2p_srv_upnp);
7092 global->params.daemonize = params->daemonize;
7093 global->params.wait_for_monitor = params->wait_for_monitor;
7094 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
7095 if (params->pid_file)
7096 global->params.pid_file = os_strdup(params->pid_file);
7097 if (params->ctrl_interface)
7098 global->params.ctrl_interface =
7099 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007100 if (params->ctrl_interface_group)
7101 global->params.ctrl_interface_group =
7102 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007103 if (params->override_driver)
7104 global->params.override_driver =
7105 os_strdup(params->override_driver);
7106 if (params->override_ctrl_interface)
7107 global->params.override_ctrl_interface =
7108 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007109#ifdef CONFIG_MATCH_IFACE
7110 global->params.match_iface_count = params->match_iface_count;
7111 if (params->match_iface_count) {
7112 global->params.match_ifaces =
7113 os_calloc(params->match_iface_count,
7114 sizeof(struct wpa_interface));
7115 os_memcpy(global->params.match_ifaces,
7116 params->match_ifaces,
7117 params->match_iface_count *
7118 sizeof(struct wpa_interface));
7119 }
7120#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007121#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007122 if (params->conf_p2p_dev)
7123 global->params.conf_p2p_dev =
7124 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007125#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007126 wpa_debug_level = global->params.wpa_debug_level =
7127 params->wpa_debug_level;
7128 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
7129 params->wpa_debug_show_keys;
7130 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
7131 params->wpa_debug_timestamp;
7132
Hai Shalomfdcde762020-04-02 11:19:20 -07007133 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007134
7135 if (eloop_init()) {
7136 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
7137 wpa_supplicant_deinit(global);
7138 return NULL;
7139 }
7140
Jouni Malinen75ecf522011-06-27 15:19:46 -07007141 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007142
7143 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
7144 if (global->ctrl_iface == NULL) {
7145 wpa_supplicant_deinit(global);
7146 return NULL;
7147 }
7148
7149 if (wpas_notify_supplicant_initialized(global)) {
7150 wpa_supplicant_deinit(global);
7151 return NULL;
7152 }
7153
7154 for (i = 0; wpa_drivers[i]; i++)
7155 global->drv_count++;
7156 if (global->drv_count == 0) {
7157 wpa_printf(MSG_ERROR, "No drivers enabled");
7158 wpa_supplicant_deinit(global);
7159 return NULL;
7160 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007161 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007162 if (global->drv_priv == NULL) {
7163 wpa_supplicant_deinit(global);
7164 return NULL;
7165 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007166
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007167#ifdef CONFIG_WIFI_DISPLAY
7168 if (wifi_display_init(global) < 0) {
7169 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
7170 wpa_supplicant_deinit(global);
7171 return NULL;
7172 }
7173#endif /* CONFIG_WIFI_DISPLAY */
7174
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007175 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
7176 wpas_periodic, global, NULL);
7177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007178 return global;
7179}
7180
7181
7182/**
7183 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7184 * @global: Pointer to global data from wpa_supplicant_init()
7185 * Returns: 0 after successful event loop run, -1 on failure
7186 *
7187 * This function starts the main event loop and continues running as long as
7188 * there are any remaining events. In most cases, this function is running as
7189 * long as the %wpa_supplicant process in still in use.
7190 */
7191int wpa_supplicant_run(struct wpa_global *global)
7192{
7193 struct wpa_supplicant *wpa_s;
7194
7195 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007196 (wpa_supplicant_daemon(global->params.pid_file) ||
7197 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007198 return -1;
7199
Dmitry Shmidte4663042016-04-04 10:07:49 -07007200#ifdef CONFIG_MATCH_IFACE
7201 if (wpa_supplicant_match_existing(global))
7202 return -1;
7203#endif
7204
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007205 if (global->params.wait_for_monitor) {
7206 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007207 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007208 wpa_supplicant_ctrl_iface_wait(
7209 wpa_s->ctrl_iface);
7210 }
7211
7212 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7213 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7214
7215 eloop_run();
7216
7217 return 0;
7218}
7219
7220
7221/**
7222 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7223 * @global: Pointer to global data from wpa_supplicant_init()
7224 *
7225 * This function is called to deinitialize %wpa_supplicant and to free all
7226 * allocated resources. Remaining network interfaces will also be removed.
7227 */
7228void wpa_supplicant_deinit(struct wpa_global *global)
7229{
7230 int i;
7231
7232 if (global == NULL)
7233 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007234
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007235 eloop_cancel_timeout(wpas_periodic, global, NULL);
7236
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007237#ifdef CONFIG_WIFI_DISPLAY
7238 wifi_display_deinit(global);
7239#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007240
7241 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007242 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007243
7244 if (global->ctrl_iface)
7245 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7246
7247 wpas_notify_supplicant_deinitialized(global);
7248
7249 eap_peer_unregister_methods();
7250#ifdef CONFIG_AP
7251 eap_server_unregister_methods();
7252#endif /* CONFIG_AP */
7253
7254 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7255 if (!global->drv_priv[i])
7256 continue;
7257 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7258 }
7259 os_free(global->drv_priv);
7260
7261 random_deinit();
7262
7263 eloop_destroy();
7264
7265 if (global->params.pid_file) {
7266 os_daemonize_terminate(global->params.pid_file);
7267 os_free(global->params.pid_file);
7268 }
7269 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007270 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007271 os_free(global->params.override_driver);
7272 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007273#ifdef CONFIG_MATCH_IFACE
7274 os_free(global->params.match_ifaces);
7275#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007276#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007277 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007278#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007279
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007280 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007281 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007282 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007283
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007284 os_free(global);
7285 wpa_debug_close_syslog();
7286 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007287 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007288}
7289
7290
7291void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7292{
7293 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7294 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7295 char country[3];
7296 country[0] = wpa_s->conf->country[0];
7297 country[1] = wpa_s->conf->country[1];
7298 country[2] = '\0';
7299 if (wpa_drv_set_country(wpa_s, country) < 0) {
7300 wpa_printf(MSG_ERROR, "Failed to set country code "
7301 "'%s'", country);
7302 }
7303 }
7304
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007305 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7306 wpas_init_ext_pw(wpa_s);
7307
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007308 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7309 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7310
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007311 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7312 struct wpa_driver_capa capa;
7313 int res = wpa_drv_get_capa(wpa_s, &capa);
7314
7315 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7316 wpa_printf(MSG_ERROR,
7317 "Failed to update wowlan_triggers to '%s'",
7318 wpa_s->conf->wowlan_triggers);
7319 }
7320
Hai Shalom81f62d82019-07-22 12:10:00 -07007321 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7322 wpa_supplicant_set_default_scan_ies(wpa_s);
7323
Hai Shalom899fcc72020-10-19 14:38:18 -07007324#ifdef CONFIG_BGSCAN
7325 /*
7326 * We default to global bgscan parameters only when per-network bgscan
7327 * parameters aren't set. Only bother resetting bgscan parameters if
7328 * this is the case.
7329 */
7330 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) &&
7331 wpa_s->current_ssid && !wpa_s->current_ssid->bgscan &&
7332 wpa_s->wpa_state == WPA_COMPLETED)
7333 wpa_supplicant_reset_bgscan(wpa_s);
7334#endif /* CONFIG_BGSCAN */
7335
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007336#ifdef CONFIG_WPS
7337 wpas_wps_update_config(wpa_s);
7338#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007339 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007340 wpa_s->conf->changed_parameters = 0;
7341}
7342
7343
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007344void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007345{
7346 int i;
7347
7348 for (i = 0; i < *num_freqs; i++) {
7349 if (freqs[i] == freq)
7350 return;
7351 }
7352
7353 freqs[*num_freqs] = freq;
7354 (*num_freqs)++;
7355}
7356
7357
7358static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7359{
7360 struct wpa_bss *bss, *cbss;
7361 const int max_freqs = 10;
7362 int *freqs;
7363 int num_freqs = 0;
7364
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007365 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007366 if (freqs == NULL)
7367 return NULL;
7368
7369 cbss = wpa_s->current_bss;
7370
7371 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7372 if (bss == cbss)
7373 continue;
7374 if (bss->ssid_len == cbss->ssid_len &&
7375 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
Hai Shalom899fcc72020-10-19 14:38:18 -07007376 !wpa_blacklist_is_blacklisted(wpa_s, bss->bssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007377 add_freq(freqs, &num_freqs, bss->freq);
7378 if (num_freqs == max_freqs)
7379 break;
7380 }
7381 }
7382
7383 if (num_freqs == 0) {
7384 os_free(freqs);
7385 freqs = NULL;
7386 }
7387
7388 return freqs;
7389}
7390
7391
7392void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7393{
7394 int timeout;
7395 int count;
7396 int *freqs = NULL;
7397
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007398 wpas_connect_work_done(wpa_s);
7399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007400 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007401 * Remove possible authentication timeout since the connection failed.
7402 */
7403 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7404
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007405 /*
7406 * There is no point in blacklisting the AP if this event is
7407 * generated based on local request to disconnect.
7408 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007409 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007410 wpa_s->own_disconnect_req = 0;
7411 wpa_dbg(wpa_s, MSG_DEBUG,
7412 "Ignore connection failure due to local request to disconnect");
7413 return;
7414 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007415 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007416 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7417 "indication since interface has been put into "
7418 "disconnected state");
7419 return;
7420 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007421 if (wpa_s->auto_reconnect_disabled) {
7422 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7423 "indication since auto connect is disabled");
7424 return;
7425 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007426
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007427 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007428 * Add the failed BSSID into the blacklist and speed up next scan
7429 * attempt if there could be other APs that could accept association.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007430 */
7431 count = wpa_blacklist_add(wpa_s, bssid);
7432 if (count == 1 && wpa_s->current_bss) {
7433 /*
7434 * This BSS was not in the blacklist before. If there is
7435 * another BSS available for the same ESS, we should try that
7436 * next. Otherwise, we may as well try this one once more
7437 * before allowing other, likely worse, ESSes to be considered.
7438 */
7439 freqs = get_bss_freqs_in_ess(wpa_s);
7440 if (freqs) {
7441 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7442 "has been seen; try it next");
7443 wpa_blacklist_add(wpa_s, bssid);
7444 /*
7445 * On the next scan, go through only the known channels
7446 * used in this ESS based on previous scans to speed up
7447 * common load balancing use case.
7448 */
7449 os_free(wpa_s->next_scan_freqs);
7450 wpa_s->next_scan_freqs = freqs;
7451 }
7452 }
7453
Hai Shalom899fcc72020-10-19 14:38:18 -07007454 wpa_s->consecutive_conn_failures++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007455
Hai Shalom899fcc72020-10-19 14:38:18 -07007456 if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) {
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007457 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7458 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007459 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007460 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007461 /*
7462 * Multiple consecutive connection failures mean that other APs are
7463 * either not available or have already been tried, so we can start
7464 * increasing the delay here to avoid constant scanning.
7465 */
7466 switch (wpa_s->consecutive_conn_failures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007467 case 1:
7468 timeout = 100;
7469 break;
7470 case 2:
7471 timeout = 500;
7472 break;
7473 case 3:
7474 timeout = 1000;
7475 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007476 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007477 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007478 break;
7479 default:
7480 timeout = 10000;
7481 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007482 }
7483
Hai Shalom899fcc72020-10-19 14:38:18 -07007484 wpa_dbg(wpa_s, MSG_DEBUG,
7485 "Consecutive connection failures: %d --> request scan in %d ms",
7486 wpa_s->consecutive_conn_failures, timeout);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007487
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007488 /*
7489 * TODO: if more than one possible AP is available in scan results,
7490 * could try the other ones before requesting a new scan.
7491 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007492
7493 /* speed up the connection attempt with normal scan */
7494 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007495 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7496 1000 * (timeout % 1000));
7497}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007498
7499
Hai Shalomce48b4a2018-09-05 11:41:35 -07007500#ifdef CONFIG_FILS
7501void fils_connection_failure(struct wpa_supplicant *wpa_s)
7502{
7503 struct wpa_ssid *ssid = wpa_s->current_ssid;
7504 const u8 *realm, *username, *rrk;
7505 size_t realm_len, username_len, rrk_len;
7506 u16 next_seq_num;
7507
7508 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7509 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7510 &username, &username_len,
7511 &realm, &realm_len, &next_seq_num,
7512 &rrk, &rrk_len) != 0 ||
7513 !realm)
7514 return;
7515
7516 wpa_hexdump_ascii(MSG_DEBUG,
7517 "FILS: Store last connection failure realm",
7518 realm, realm_len);
7519 os_free(wpa_s->last_con_fail_realm);
7520 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7521 if (wpa_s->last_con_fail_realm) {
7522 wpa_s->last_con_fail_realm_len = realm_len;
7523 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7524 }
7525}
7526#endif /* CONFIG_FILS */
7527
7528
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007529int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7530{
7531 return wpa_s->conf->ap_scan == 2 ||
7532 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7533}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007534
Dmitry Shmidt04949592012-07-19 12:16:46 -07007535
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007536#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007537int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7538 struct wpa_ssid *ssid,
7539 const char *field,
7540 const char *value)
7541{
7542#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007543 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007544
7545 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7546 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7547 (const u8 *) value, os_strlen(value));
7548
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007549 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007550 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007551#else /* IEEE8021X_EAPOL */
7552 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7553 return -1;
7554#endif /* IEEE8021X_EAPOL */
7555}
7556
7557int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7558 struct wpa_ssid *ssid,
7559 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007560 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007561{
7562#ifdef IEEE8021X_EAPOL
7563 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007564 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007565
7566 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007567 case WPA_CTRL_REQ_EAP_IDENTITY:
7568 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007569 os_free(eap->imsi_identity);
7570 if (value == NULL)
7571 return -1;
7572 identity = os_strchr(value, ':');
7573 if (identity == NULL) {
7574 /* plain identity */
7575 eap->identity = (u8 *)os_strdup(value);
7576 eap->identity_len = os_strlen(value);
7577 } else {
7578 /* have both plain identity and encrypted identity */
7579 imsi_identity = value;
7580 *identity++ = '\0';
7581 /* plain identity */
7582 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7583 eap->imsi_identity_len = strlen(imsi_identity);
7584 /* encrypted identity */
7585 eap->identity = (u8 *)dup_binstr(identity,
7586 value_len - strlen(imsi_identity) - 1);
7587 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7588 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007589 eap->pending_req_identity = 0;
7590 if (ssid == wpa_s->current_ssid)
7591 wpa_s->reassociate = 1;
7592 break;
7593 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007594 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007595 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007596 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007597 eap->pending_req_password = 0;
7598 if (ssid == wpa_s->current_ssid)
7599 wpa_s->reassociate = 1;
7600 break;
7601 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007602 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007603 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007604 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007605 eap->pending_req_new_password = 0;
7606 if (ssid == wpa_s->current_ssid)
7607 wpa_s->reassociate = 1;
7608 break;
7609 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007610 str_clear_free(eap->cert.pin);
7611 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007612 eap->pending_req_pin = 0;
7613 if (ssid == wpa_s->current_ssid)
7614 wpa_s->reassociate = 1;
7615 break;
7616 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007617 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007618 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007619 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007620 os_free(eap->pending_req_otp);
7621 eap->pending_req_otp = NULL;
7622 eap->pending_req_otp_len = 0;
7623 break;
7624 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007625 str_clear_free(eap->cert.private_key_passwd);
7626 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007627 eap->pending_req_passphrase = 0;
7628 if (ssid == wpa_s->current_ssid)
7629 wpa_s->reassociate = 1;
7630 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007631 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007632 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007633 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007634 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007635 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007636 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7637 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7638 return -1;
7639 ssid->mem_only_psk = 1;
7640 if (ssid->passphrase)
7641 wpa_config_update_psk(ssid);
7642 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7643 wpa_supplicant_req_scan(wpa_s, 0, 0);
7644 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007645 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7646 if (eap->pending_ext_cert_check != PENDING_CHECK)
7647 return -1;
7648 if (os_strcmp(value, "good") == 0)
7649 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7650 else if (os_strcmp(value, "bad") == 0)
7651 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7652 else
7653 return -1;
7654 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007655 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007656 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007657 return -1;
7658 }
7659
7660 return 0;
7661#else /* IEEE8021X_EAPOL */
7662 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7663 return -1;
7664#endif /* IEEE8021X_EAPOL */
7665}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007666#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007667
7668
7669int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7670{
Hai Shalomfdcde762020-04-02 11:19:20 -07007671#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007672 int i;
7673 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007674#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007675
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007676 if (wpa_s->p2p_mgmt)
7677 return 1; /* no normal network profiles on p2p_mgmt interface */
7678
Dmitry Shmidt04949592012-07-19 12:16:46 -07007679 if (ssid == NULL)
7680 return 1;
7681
7682 if (ssid->disabled)
7683 return 1;
7684
Hai Shalomfdcde762020-04-02 11:19:20 -07007685#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007686 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007687 drv_enc = wpa_s->drv_enc;
7688 else
7689 drv_enc = (unsigned int) -1;
7690
7691 for (i = 0; i < NUM_WEP_KEYS; i++) {
7692 size_t len = ssid->wep_key_len[i];
7693 if (len == 0)
7694 continue;
7695 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7696 continue;
7697 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7698 continue;
7699 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7700 continue;
7701 return 1; /* invalid WEP key */
7702 }
Hai Shalomfdcde762020-04-02 11:19:20 -07007703#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007704
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007705 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007706 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007707 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007708 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007709 return 1;
7710
Dmitry Shmidt04949592012-07-19 12:16:46 -07007711 return 0;
7712}
7713
7714
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007715int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7716{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007717 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7718 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7719 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7720 /*
7721 * Driver does not support BIP -- ignore pmf=1 default
7722 * since the connection with PMF would fail and the
7723 * configuration does not require PMF to be enabled.
7724 */
7725 return NO_MGMT_FRAME_PROTECTION;
7726 }
7727
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007728 if (ssid &&
7729 (ssid->key_mgmt &
7730 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7731 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7732 /*
7733 * Do not use the default PMF value for non-RSN networks
7734 * since PMF is available only with RSN and pmf=2
7735 * configuration would otherwise prevent connections to
7736 * all open networks.
7737 */
7738 return NO_MGMT_FRAME_PROTECTION;
7739 }
7740
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007741 return wpa_s->conf->pmf;
7742 }
7743
7744 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007745}
7746
7747
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007748int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007749{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007750 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007751 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007752 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007753 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007754 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007755}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007756
7757
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007758void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007759{
7760 struct wpa_ssid *ssid = wpa_s->current_ssid;
7761 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007762 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007763
7764 if (ssid == NULL) {
7765 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7766 "SSID block");
7767 return;
7768 }
7769
7770 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7771 return;
7772
7773 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007774
7775#ifdef CONFIG_P2P
7776 if (ssid->p2p_group &&
7777 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7778 /*
7779 * Skip the wait time since there is a short timeout on the
7780 * connection to a P2P group.
7781 */
7782 return;
7783 }
7784#endif /* CONFIG_P2P */
7785
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007786 if (ssid->auth_failures > 50)
7787 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007788 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007789 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007790 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007791 dur = 90;
7792 else if (ssid->auth_failures > 3)
7793 dur = 60;
7794 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007795 dur = 30;
7796 else if (ssid->auth_failures > 1)
7797 dur = 20;
7798 else
7799 dur = 10;
7800
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007801 if (ssid->auth_failures > 1 &&
7802 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7803 dur += os_random() % (ssid->auth_failures * 10);
7804
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007805 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007806 if (now.sec + dur <= ssid->disabled_until.sec)
7807 return;
7808
7809 ssid->disabled_until.sec = now.sec + dur;
7810
7811 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007812 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007813 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007814 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007815}
7816
7817
7818void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7819 struct wpa_ssid *ssid, int clear_failures)
7820{
7821 if (ssid == NULL)
7822 return;
7823
7824 if (ssid->disabled_until.sec) {
7825 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7826 "id=%d ssid=\"%s\"",
7827 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7828 }
7829 ssid->disabled_until.sec = 0;
7830 ssid->disabled_until.usec = 0;
7831 if (clear_failures)
7832 ssid->auth_failures = 0;
7833}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007834
7835
7836int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7837{
7838 size_t i;
7839
7840 if (wpa_s->disallow_aps_bssid == NULL)
7841 return 0;
7842
7843 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7844 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7845 bssid, ETH_ALEN) == 0)
7846 return 1;
7847 }
7848
7849 return 0;
7850}
7851
7852
7853int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7854 size_t ssid_len)
7855{
7856 size_t i;
7857
7858 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7859 return 0;
7860
7861 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7862 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7863 if (ssid_len == s->ssid_len &&
7864 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7865 return 1;
7866 }
7867
7868 return 0;
7869}
7870
7871
7872/**
7873 * wpas_request_connection - Request a new connection
7874 * @wpa_s: Pointer to the network interface
7875 *
7876 * This function is used to request a new connection to be found. It will mark
7877 * the interface to allow reassociation and request a new scan to find a
7878 * suitable network to connect to.
7879 */
7880void wpas_request_connection(struct wpa_supplicant *wpa_s)
7881{
7882 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007883 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007884 wpa_supplicant_reinit_autoscan(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007885 wpa_s->disconnected = 0;
7886 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007887 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007888
7889 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7890 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007891 else
7892 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007893}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007894
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007895
Roshan Pius02242d72016-08-09 15:31:48 -07007896/**
7897 * wpas_request_disconnection - Request disconnection
7898 * @wpa_s: Pointer to the network interface
7899 *
7900 * This function is used to request disconnection from the currently connected
7901 * network. This will stop any ongoing scans and initiate deauthentication.
7902 */
7903void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7904{
7905#ifdef CONFIG_SME
7906 wpa_s->sme.prev_bssid_set = 0;
7907#endif /* CONFIG_SME */
7908 wpa_s->reassociate = 0;
7909 wpa_s->disconnected = 1;
7910 wpa_supplicant_cancel_sched_scan(wpa_s);
7911 wpa_supplicant_cancel_scan(wpa_s);
7912 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7913 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007914 radio_remove_works(wpa_s, "connect", 0);
7915 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007916}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007917
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007918
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007919void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7920 struct wpa_used_freq_data *freqs_data,
7921 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007922{
7923 unsigned int i;
7924
7925 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7926 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007927 for (i = 0; i < len; i++) {
7928 struct wpa_used_freq_data *cur = &freqs_data[i];
7929 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7930 i, cur->freq, cur->flags);
7931 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007932}
7933
7934
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007935/*
7936 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007937 * are using the same radio as the current interface, and in addition, get
7938 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007939 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007940int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7941 struct wpa_used_freq_data *freqs_data,
7942 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007943{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007944 struct wpa_supplicant *ifs;
7945 u8 bssid[ETH_ALEN];
7946 int freq;
7947 unsigned int idx = 0, i;
7948
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007949 wpa_dbg(wpa_s, MSG_DEBUG,
7950 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007951 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007952
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007953 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7954 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007955 if (idx == len)
7956 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007957
7958 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7959 continue;
7960
7961 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007962 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7963 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007964 freq = ifs->current_ssid->frequency;
7965 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7966 freq = ifs->assoc_freq;
7967 else
7968 continue;
7969
7970 /* Hold only distinct freqs */
7971 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007972 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007973 break;
7974
7975 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007976 freqs_data[idx++].freq = freq;
7977
7978 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007979 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007980 WPA_FREQ_USED_BY_P2P_CLIENT :
7981 WPA_FREQ_USED_BY_INFRA_STATION;
7982 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007983 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007984
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007985 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007986 return idx;
7987}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007988
7989
7990/*
7991 * Find the operating frequencies of any of the virtual interfaces that
7992 * are using the same radio as the current interface.
7993 */
7994int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7995 int *freq_array, unsigned int len)
7996{
7997 struct wpa_used_freq_data *freqs_data;
7998 int num, i;
7999
8000 os_memset(freq_array, 0, sizeof(int) * len);
8001
8002 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
8003 if (!freqs_data)
8004 return -1;
8005
8006 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
8007 for (i = 0; i < num; i++)
8008 freq_array[i] = freqs_data[i].freq;
8009
8010 os_free(freqs_data);
8011
8012 return num;
8013}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008014
8015
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008016struct wpa_supplicant *
8017wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
8018{
8019 switch (frame) {
8020#ifdef CONFIG_P2P
8021 case VENDOR_ELEM_PROBE_REQ_P2P:
8022 case VENDOR_ELEM_PROBE_RESP_P2P:
8023 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
8024 case VENDOR_ELEM_BEACON_P2P_GO:
8025 case VENDOR_ELEM_P2P_PD_REQ:
8026 case VENDOR_ELEM_P2P_PD_RESP:
8027 case VENDOR_ELEM_P2P_GO_NEG_REQ:
8028 case VENDOR_ELEM_P2P_GO_NEG_RESP:
8029 case VENDOR_ELEM_P2P_GO_NEG_CONF:
8030 case VENDOR_ELEM_P2P_INV_REQ:
8031 case VENDOR_ELEM_P2P_INV_RESP:
8032 case VENDOR_ELEM_P2P_ASSOC_REQ:
8033 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008034 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08008035#endif /* CONFIG_P2P */
8036 default:
8037 return wpa_s;
8038 }
8039}
8040
8041
8042void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
8043{
8044 unsigned int i;
8045 char buf[30];
8046
8047 wpa_printf(MSG_DEBUG, "Update vendor elements");
8048
8049 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
8050 if (wpa_s->vendor_elem[i]) {
8051 int res;
8052
8053 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
8054 if (!os_snprintf_error(sizeof(buf), res)) {
8055 wpa_hexdump_buf(MSG_DEBUG, buf,
8056 wpa_s->vendor_elem[i]);
8057 }
8058 }
8059 }
8060
8061#ifdef CONFIG_P2P
8062 if (wpa_s->parent == wpa_s &&
8063 wpa_s->global->p2p &&
8064 !wpa_s->global->p2p_disabled)
8065 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
8066#endif /* CONFIG_P2P */
8067}
8068
8069
8070int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
8071 const u8 *elem, size_t len)
8072{
8073 u8 *ie, *end;
8074
8075 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
8076 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
8077
8078 for (; ie + 1 < end; ie += 2 + ie[1]) {
8079 if (ie + len > end)
8080 break;
8081 if (os_memcmp(ie, elem, len) != 0)
8082 continue;
8083
8084 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
8085 wpabuf_free(wpa_s->vendor_elem[frame]);
8086 wpa_s->vendor_elem[frame] = NULL;
8087 } else {
8088 os_memmove(ie, ie + len, end - (ie + len));
8089 wpa_s->vendor_elem[frame]->used -= len;
8090 }
8091 wpas_vendor_elem_update(wpa_s);
8092 return 0;
8093 }
8094
8095 return -1;
8096}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008097
8098
8099struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07008100 u16 num_modes, enum hostapd_hw_mode mode,
8101 int is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008102{
8103 u16 i;
8104
8105 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07008106 if (modes[i].mode != mode ||
8107 !modes[i].num_channels || !modes[i].channels)
8108 continue;
8109 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
8110 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008111 return &modes[i];
8112 }
8113
8114 return NULL;
8115}
8116
8117
8118static struct
8119wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
8120 const u8 *bssid)
8121{
8122 struct wpa_bss_tmp_disallowed *bss;
8123
8124 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
8125 struct wpa_bss_tmp_disallowed, list) {
8126 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
8127 return bss;
8128 }
8129
8130 return NULL;
8131}
8132
8133
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008134static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
8135{
8136 struct wpa_bss_tmp_disallowed *tmp;
8137 unsigned int num_bssid = 0;
8138 u8 *bssids;
8139 int ret;
8140
8141 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
8142 if (!bssids)
8143 return -1;
8144 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8145 struct wpa_bss_tmp_disallowed, list) {
8146 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
8147 ETH_ALEN);
8148 num_bssid++;
8149 }
Hai Shalom899fcc72020-10-19 14:38:18 -07008150 ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008151 os_free(bssids);
8152 return ret;
8153}
8154
8155
8156static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
8157{
8158 struct wpa_supplicant *wpa_s = eloop_ctx;
8159 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
8160
8161 /* Make sure the bss is not already freed */
8162 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
8163 struct wpa_bss_tmp_disallowed, list) {
8164 if (bss == tmp) {
8165 dl_list_del(&tmp->list);
8166 os_free(tmp);
8167 wpa_set_driver_tmp_disallow_list(wpa_s);
8168 break;
8169 }
8170 }
8171}
8172
8173
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008174void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08008175 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008176{
8177 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008178
8179 bss = wpas_get_disallowed_bss(wpa_s, bssid);
8180 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008181 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08008182 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008183 }
8184
8185 bss = os_malloc(sizeof(*bss));
8186 if (!bss) {
8187 wpa_printf(MSG_DEBUG,
8188 "Failed to allocate memory for temp disallow BSS");
8189 return;
8190 }
8191
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008192 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8193 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008194 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008195
8196finish:
8197 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008198 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8199 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008200}
8201
8202
Hai Shalom74f70d42019-02-11 14:42:39 -08008203int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8204 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008205{
Hai Shalom74f70d42019-02-11 14:42:39 -08008206 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008207
8208 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8209 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008210 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8211 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008212 break;
8213 }
8214 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008215 if (!disallowed)
8216 return 0;
8217
8218 if (disallowed->rssi_threshold != 0 &&
8219 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008220 return 0;
8221
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008222 return 1;
8223}
Hai Shalom81f62d82019-07-22 12:10:00 -07008224
8225
8226int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8227 unsigned int type, const u8 *addr,
8228 const u8 *mask)
8229{
8230 if ((addr && !mask) || (!addr && mask)) {
8231 wpa_printf(MSG_INFO,
8232 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8233 return -1;
8234 }
8235
8236 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8237 wpa_printf(MSG_INFO,
8238 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8239 return -1;
8240 }
8241
8242 if (type & MAC_ADDR_RAND_SCAN) {
8243 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8244 addr, mask))
8245 return -1;
8246 }
8247
8248 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8249 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8250 addr, mask))
8251 return -1;
8252
8253 if (wpa_s->sched_scanning && !wpa_s->pno)
8254 wpas_scan_restart_sched_scan(wpa_s);
8255 }
8256
8257 if (type & MAC_ADDR_RAND_PNO) {
8258 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8259 addr, mask))
8260 return -1;
8261
8262 if (wpa_s->pno) {
8263 wpas_stop_pno(wpa_s);
8264 wpas_start_pno(wpa_s);
8265 }
8266 }
8267
8268 return 0;
8269}
8270
8271
8272int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8273 unsigned int type)
8274{
8275 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8276 if (wpa_s->pno) {
8277 if (type & MAC_ADDR_RAND_PNO) {
8278 wpas_stop_pno(wpa_s);
8279 wpas_start_pno(wpa_s);
8280 }
8281 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8282 wpas_scan_restart_sched_scan(wpa_s);
8283 }
8284
8285 return 0;
8286}
Hai Shalomfdcde762020-04-02 11:19:20 -07008287
8288
8289int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8290 struct wpa_signal_info *si)
8291{
8292 int res;
8293
8294 if (!wpa_s->driver->signal_poll)
8295 return -1;
8296
8297 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8298
8299#ifdef CONFIG_TESTING_OPTIONS
8300 if (res == 0) {
8301 struct driver_signal_override *dso;
8302
8303 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8304 struct driver_signal_override, list) {
8305 if (os_memcmp(wpa_s->bssid, dso->bssid,
8306 ETH_ALEN) != 0)
8307 continue;
8308 wpa_printf(MSG_DEBUG,
8309 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8310 si->current_signal,
8311 dso->si_current_signal,
8312 si->avg_signal,
8313 dso->si_avg_signal,
8314 si->avg_beacon_signal,
8315 dso->si_avg_beacon_signal,
8316 si->current_noise,
8317 dso->si_current_noise);
8318 si->current_signal = dso->si_current_signal;
8319 si->avg_signal = dso->si_avg_signal;
8320 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8321 si->current_noise = dso->si_current_noise;
8322 break;
8323 }
8324 }
8325#endif /* CONFIG_TESTING_OPTIONS */
8326
8327 return res;
8328}
8329
8330
8331struct wpa_scan_results *
8332wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8333{
8334 struct wpa_scan_results *scan_res;
8335#ifdef CONFIG_TESTING_OPTIONS
8336 size_t idx;
8337#endif /* CONFIG_TESTING_OPTIONS */
8338
8339 if (!wpa_s->driver->get_scan_results2)
8340 return NULL;
8341
8342 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8343
8344#ifdef CONFIG_TESTING_OPTIONS
8345 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8346 struct driver_signal_override *dso;
8347 struct wpa_scan_res *res = scan_res->res[idx];
8348
8349 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8350 struct driver_signal_override, list) {
8351 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8352 continue;
8353 wpa_printf(MSG_DEBUG,
8354 "Override driver scan signal level %d->%d for "
8355 MACSTR,
8356 res->level, dso->scan_level,
8357 MAC2STR(res->bssid));
8358 res->flags |= WPA_SCAN_QUAL_INVALID;
8359 if (dso->scan_level < 0)
8360 res->flags |= WPA_SCAN_LEVEL_DBM;
8361 else
8362 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8363 res->level = dso->scan_level;
8364 break;
8365 }
8366 }
8367#endif /* CONFIG_TESTING_OPTIONS */
8368
8369 return scan_res;
8370}