blob: a01a4e534f8b8d83acd0bed836289d6b662d2f73 [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
807static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
808{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800809 const char *name;
810
811 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
812 name = wpa_s->current_ssid->bgscan;
813 else
814 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800815 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800816 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800817 if (wpas_driver_bss_selection(wpa_s))
818 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
820 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800821#ifdef CONFIG_P2P
822 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
823 return;
824#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700825
826 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800827 if (wpa_s->current_ssid) {
828 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700829 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
830 "bgscan");
831 /*
832 * Live without bgscan; it is only used as a roaming
833 * optimization, so the initial connection is not
834 * affected.
835 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700836 } else {
837 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700838 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700839 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
840 0);
841 if (scan_res) {
842 bgscan_notify_scan(wpa_s, scan_res);
843 wpa_scan_results_free(scan_res);
844 }
845 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700846 } else
847 wpa_s->bgscan_ssid = NULL;
848}
849
850
851static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
852{
853 if (wpa_s->bgscan_ssid != NULL) {
854 bgscan_deinit(wpa_s);
855 wpa_s->bgscan_ssid = NULL;
856 }
857}
858
859#endif /* CONFIG_BGSCAN */
860
861
Dmitry Shmidt04949592012-07-19 12:16:46 -0700862static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
863{
864 if (autoscan_init(wpa_s, 0))
865 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
866}
867
868
869static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
870{
871 autoscan_deinit(wpa_s);
872}
873
874
875void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
876{
877 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
878 wpa_s->wpa_state == WPA_SCANNING) {
879 autoscan_deinit(wpa_s);
880 wpa_supplicant_start_autoscan(wpa_s);
881 }
882}
883
884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885/**
886 * wpa_supplicant_set_state - Set current connection state
887 * @wpa_s: Pointer to wpa_supplicant data
888 * @state: The new connection state
889 *
890 * This function is called whenever the connection state changes, e.g.,
891 * association is completed for WPA/WPA2 4-Way Handshake is started.
892 */
893void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
894 enum wpa_states state)
895{
896 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700897#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
Hai Shalome21d4e82020-04-29 16:34:06 -0700898 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700899#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700900
901 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
902 wpa_supplicant_state_txt(wpa_s->wpa_state),
903 wpa_supplicant_state_txt(state));
904
Hai Shalom74f70d42019-02-11 14:42:39 -0800905 if (state == WPA_COMPLETED &&
906 os_reltime_initialized(&wpa_s->roam_start)) {
907 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
908 wpa_s->roam_start.sec = 0;
909 wpa_s->roam_start.usec = 0;
910 wpas_notify_auth_changed(wpa_s);
911 wpas_notify_roam_time(wpa_s);
912 wpas_notify_roam_complete(wpa_s);
913 } else if (state == WPA_DISCONNECTED &&
914 os_reltime_initialized(&wpa_s->roam_start)) {
915 wpa_s->roam_start.sec = 0;
916 wpa_s->roam_start.usec = 0;
917 wpa_s->roam_time.sec = 0;
918 wpa_s->roam_time.usec = 0;
919 wpas_notify_roam_complete(wpa_s);
920 }
921
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800922 if (state == WPA_INTERFACE_DISABLED) {
923 /* Assure normal scan when interface is restored */
924 wpa_s->normal_scans = 0;
925 }
926
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700927 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800928 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700929 /* Reinitialize normal_scan counter */
930 wpa_s->normal_scans = 0;
931 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800932
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700933#ifdef CONFIG_P2P
934 /*
935 * P2PS client has to reply to Probe Request frames received on the
936 * group operating channel. Enable Probe Request frame reporting for
937 * P2P connected client in case p2p_cli_probe configuration property is
938 * set to 1.
939 */
940 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
941 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
942 wpa_s->current_ssid->p2p_group) {
943 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
944 wpa_dbg(wpa_s, MSG_DEBUG,
945 "P2P: Enable CLI Probe Request RX reporting");
946 wpa_s->p2p_cli_probe =
947 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
948 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
949 wpa_dbg(wpa_s, MSG_DEBUG,
950 "P2P: Disable CLI Probe Request RX reporting");
951 wpa_s->p2p_cli_probe = 0;
952 wpa_drv_probe_req_report(wpa_s, 0);
953 }
954 }
955#endif /* CONFIG_P2P */
956
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700957 if (state != WPA_SCANNING)
958 wpa_supplicant_notify_scanning(wpa_s, 0);
959
960 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700961 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700962 int fils_hlp_sent = 0;
963
964#ifdef CONFIG_SME
965 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
966 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
967 fils_hlp_sent = 1;
968#endif /* CONFIG_SME */
969 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
970 wpa_auth_alg_fils(wpa_s->auth_alg))
971 fils_hlp_sent = 1;
972
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700973#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700975 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800976 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700977 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700978 ssid && ssid->id_str ? ssid->id_str : "",
979 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700981 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700982 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800983 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700984 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700985 wpa_drv_set_operstate(wpa_s, 1);
986#ifndef IEEE8021X_EAPOL
987 wpa_drv_set_supp_port(wpa_s, 1);
988#endif /* IEEE8021X_EAPOL */
989 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700990 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700992
993 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700994
995#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
996 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalome21d4e82020-04-29 16:34:06 -0700997 update_fils_connect_params = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700998#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700999#ifdef CONFIG_OWE
1000 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1001 wpas_update_owe_connect_params(wpa_s);
1002#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1004 state == WPA_ASSOCIATED) {
1005 wpa_s->new_connection = 1;
1006 wpa_drv_set_operstate(wpa_s, 0);
1007#ifndef IEEE8021X_EAPOL
1008 wpa_drv_set_supp_port(wpa_s, 0);
1009#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001010 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001011 }
1012 wpa_s->wpa_state = state;
1013
1014#ifdef CONFIG_BGSCAN
1015 if (state == WPA_COMPLETED)
1016 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001017 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001018 wpa_supplicant_stop_bgscan(wpa_s);
1019#endif /* CONFIG_BGSCAN */
1020
Hai Shalom5f92bc92019-04-18 11:54:11 -07001021 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001022 wpa_supplicant_stop_autoscan(wpa_s);
1023
1024 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1025 wpa_supplicant_start_autoscan(wpa_s);
1026
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001027 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1028 wmm_ac_notify_disassoc(wpa_s);
1029
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 if (wpa_s->wpa_state != old_state) {
1031 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1032
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001033 /*
1034 * Notify the P2P Device interface about a state change in one
1035 * of the interfaces.
1036 */
1037 wpas_p2p_indicate_state_change(wpa_s);
1038
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 if (wpa_s->wpa_state == WPA_COMPLETED ||
1040 old_state == WPA_COMPLETED)
1041 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001042#ifdef CONFIG_DPP2
1043 if (wpa_s->wpa_state == WPA_COMPLETED)
1044 wpas_dpp_connected(wpa_s);
1045#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 }
Hai Shalomc3565922019-10-28 11:58:20 -07001047#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1048 if (update_fils_connect_params)
1049 wpas_update_fils_connect_params(wpa_s);
1050#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001051}
1052
1053
1054void wpa_supplicant_terminate_proc(struct wpa_global *global)
1055{
1056 int pending = 0;
1057#ifdef CONFIG_WPS
1058 struct wpa_supplicant *wpa_s = global->ifaces;
1059 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001060 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001061 if (wpas_wps_terminate_pending(wpa_s) == 1)
1062 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001063#ifdef CONFIG_P2P
1064 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1065 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1066 wpas_p2p_disconnect(wpa_s);
1067#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001068 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069 }
1070#endif /* CONFIG_WPS */
1071 if (pending)
1072 return;
1073 eloop_terminate();
1074}
1075
1076
1077static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1078{
1079 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001080 wpa_supplicant_terminate_proc(global);
1081}
1082
1083
1084void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1085{
1086 enum wpa_states old_state = wpa_s->wpa_state;
1087
1088 wpa_s->pairwise_cipher = 0;
1089 wpa_s->group_cipher = 0;
1090 wpa_s->mgmt_group_cipher = 0;
1091 wpa_s->key_mgmt = 0;
1092 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001093 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001094
1095 if (wpa_s->wpa_state != old_state)
1096 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1097}
1098
1099
1100/**
1101 * wpa_supplicant_reload_configuration - Reload configuration data
1102 * @wpa_s: Pointer to wpa_supplicant data
1103 * Returns: 0 on success or -1 if configuration parsing failed
1104 *
1105 * This function can be used to request that the configuration data is reloaded
1106 * (e.g., after configuration file change). This function is reloading
1107 * configuration only for one interface, so this may need to be called multiple
1108 * times if %wpa_supplicant is controlling multiple interfaces and all
1109 * interfaces need reconfiguration.
1110 */
1111int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1112{
1113 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001114 int reconf_ctrl;
1115 int old_ap_scan;
1116
1117 if (wpa_s->confname == NULL)
1118 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001119 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120 if (conf == NULL) {
1121 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1122 "file '%s' - exiting", wpa_s->confname);
1123 return -1;
1124 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001125 if (wpa_s->confanother &&
1126 !wpa_config_read(wpa_s->confanother, conf)) {
1127 wpa_msg(wpa_s, MSG_ERROR,
1128 "Failed to parse the configuration file '%s' - exiting",
1129 wpa_s->confanother);
1130 return -1;
1131 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001132
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001133 conf->changed_parameters = (unsigned int) -1;
1134
1135 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1136 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1137 os_strcmp(conf->ctrl_interface,
1138 wpa_s->conf->ctrl_interface) != 0);
1139
1140 if (reconf_ctrl && wpa_s->ctrl_iface) {
1141 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1142 wpa_s->ctrl_iface = NULL;
1143 }
1144
1145 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001146 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001147 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1148 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001149 wpa_supplicant_deauthenticate(wpa_s,
1150 WLAN_REASON_DEAUTH_LEAVING);
1151 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152
1153 /*
1154 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001155 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001156 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001157 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1158 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1159 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160 /*
1161 * Clear forced success to clear EAP state for next
1162 * authentication.
1163 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001164 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 }
1166 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1167 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001168 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001169 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1170 rsn_preauth_deinit(wpa_s->wpa);
1171
1172 old_ap_scan = wpa_s->conf->ap_scan;
1173 wpa_config_free(wpa_s->conf);
1174 wpa_s->conf = conf;
1175 if (old_ap_scan != wpa_s->conf->ap_scan)
1176 wpas_notify_ap_scan_changed(wpa_s);
1177
1178 if (reconf_ctrl)
1179 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1180
1181 wpa_supplicant_update_config(wpa_s);
1182
1183 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001184 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001185 wpa_s->reassociate = 1;
1186 wpa_supplicant_req_scan(wpa_s, 0, 0);
1187 }
1188 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1189 return 0;
1190}
1191
1192
1193static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1194{
1195 struct wpa_global *global = signal_ctx;
1196 struct wpa_supplicant *wpa_s;
1197 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1198 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1199 sig);
1200 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1201 wpa_supplicant_terminate_proc(global);
1202 }
1203 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001204
1205 if (wpa_debug_reopen_file() < 0) {
1206 /* Ignore errors since we cannot really do much to fix this */
1207 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1208 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209}
1210
1211
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001212static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1213 struct wpa_ssid *ssid,
1214 struct wpa_ie_data *ie)
1215{
1216 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1217 if (ret) {
1218 if (ret == -2) {
1219 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1220 "from association info");
1221 }
1222 return -1;
1223 }
1224
1225 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1226 "cipher suites");
1227 if (!(ie->group_cipher & ssid->group_cipher)) {
1228 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1229 "cipher 0x%x (mask 0x%x) - reject",
1230 ie->group_cipher, ssid->group_cipher);
1231 return -1;
1232 }
1233 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1234 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1235 "cipher 0x%x (mask 0x%x) - reject",
1236 ie->pairwise_cipher, ssid->pairwise_cipher);
1237 return -1;
1238 }
1239 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1240 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1241 "management 0x%x (mask 0x%x) - reject",
1242 ie->key_mgmt, ssid->key_mgmt);
1243 return -1;
1244 }
1245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001246 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001247 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001248 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1249 "that does not support management frame protection - "
1250 "reject");
1251 return -1;
1252 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001253
1254 return 0;
1255}
1256
1257
Hai Shalom021b0b52019-04-10 11:17:58 -07001258static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1259 int freq)
1260{
1261 if (!ie->has_group)
1262 ie->group_cipher = wpa_default_rsn_cipher(freq);
1263 if (!ie->has_pairwise)
1264 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1265 return (ie->group_cipher & ssid->group_cipher) &&
1266 (ie->pairwise_cipher & ssid->pairwise_cipher);
1267}
1268
1269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001270/**
1271 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1272 * @wpa_s: Pointer to wpa_supplicant data
1273 * @bss: Scan results for the selected BSS, or %NULL if not available
1274 * @ssid: Configuration data for the selected network
1275 * @wpa_ie: Buffer for the WPA/RSN IE
1276 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1277 * used buffer length in case the functions returns success.
1278 * Returns: 0 on success or -1 on failure
1279 *
1280 * This function is used to configure authentication and encryption parameters
1281 * based on the network configuration and scan result for the selected BSS (if
1282 * available).
1283 */
1284int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1285 struct wpa_bss *bss, struct wpa_ssid *ssid,
1286 u8 *wpa_ie, size_t *wpa_ie_len)
1287{
1288 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001289 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001290 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001291
1292 if (bss) {
1293 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1294 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001295 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001296 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001297 } else {
1298 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1299 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300
1301 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1302 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001303 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001304 (ie.key_mgmt & ssid->key_mgmt)) {
1305 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1306 proto = WPA_PROTO_RSN;
1307 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001308 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001309 (ie.group_cipher & ssid->group_cipher) &&
1310 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1311 (ie.key_mgmt & ssid->key_mgmt)) {
1312 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1313 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001314#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001315 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1316 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1317 (ie.group_cipher & ssid->group_cipher) &&
1318 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1319 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001320 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001321 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001322 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1323 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1324 (ie.group_cipher & ssid->group_cipher) &&
1325 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1326 (ie.key_mgmt & ssid->key_mgmt)) {
1327 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1328 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001329#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 } else if (bss) {
1331 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001332 wpa_dbg(wpa_s, MSG_DEBUG,
1333 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1334 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1335 ssid->key_mgmt);
1336 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1337 MAC2STR(bss->bssid),
1338 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1339 bss_wpa ? " WPA" : "",
1340 bss_rsn ? " RSN" : "",
1341 bss_osen ? " OSEN" : "");
1342 if (bss_rsn) {
1343 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1344 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1345 wpa_dbg(wpa_s, MSG_DEBUG,
1346 "Could not parse RSN element");
1347 } else {
1348 wpa_dbg(wpa_s, MSG_DEBUG,
1349 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1350 ie.pairwise_cipher, ie.group_cipher,
1351 ie.key_mgmt);
1352 }
1353 }
1354 if (bss_wpa) {
1355 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1356 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1357 wpa_dbg(wpa_s, MSG_DEBUG,
1358 "Could not parse WPA element");
1359 } else {
1360 wpa_dbg(wpa_s, MSG_DEBUG,
1361 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1362 ie.pairwise_cipher, ie.group_cipher,
1363 ie.key_mgmt);
1364 }
1365 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366 return -1;
1367 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001368 if (ssid->proto & WPA_PROTO_OSEN)
1369 proto = WPA_PROTO_OSEN;
1370 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001371 proto = WPA_PROTO_RSN;
1372 else
1373 proto = WPA_PROTO_WPA;
1374 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1375 os_memset(&ie, 0, sizeof(ie));
1376 ie.group_cipher = ssid->group_cipher;
1377 ie.pairwise_cipher = ssid->pairwise_cipher;
1378 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001379 ie.mgmt_group_cipher = 0;
1380 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1381 if (ssid->group_mgmt_cipher &
1382 WPA_CIPHER_BIP_GMAC_256)
1383 ie.mgmt_group_cipher =
1384 WPA_CIPHER_BIP_GMAC_256;
1385 else if (ssid->group_mgmt_cipher &
1386 WPA_CIPHER_BIP_CMAC_256)
1387 ie.mgmt_group_cipher =
1388 WPA_CIPHER_BIP_CMAC_256;
1389 else if (ssid->group_mgmt_cipher &
1390 WPA_CIPHER_BIP_GMAC_128)
1391 ie.mgmt_group_cipher =
1392 WPA_CIPHER_BIP_GMAC_128;
1393 else
1394 ie.mgmt_group_cipher =
1395 WPA_CIPHER_AES_128_CMAC;
1396 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001397#ifdef CONFIG_OWE
1398 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1399 !ssid->owe_only &&
1400 !bss_wpa && !bss_rsn && !bss_osen) {
1401 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1402 wpa_s->wpa_proto = 0;
1403 *wpa_ie_len = 0;
1404 return 0;
1405 }
1406#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001407 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1408 "based on configuration");
1409 } else
1410 proto = ie.proto;
1411 }
1412
1413 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1414 "pairwise %d key_mgmt %d proto %d",
1415 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416 if (ssid->ieee80211w) {
1417 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1418 ie.mgmt_group_cipher);
1419 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001421 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001422 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1423 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001424 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001425
1426 if (bss || !wpa_s->ap_ies_from_associnfo) {
1427 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1428 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1429 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001430 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1431 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1432 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433 return -1;
1434 }
1435
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001436#ifdef CONFIG_NO_WPA
1437 wpa_s->group_cipher = WPA_CIPHER_NONE;
1438 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1439#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001440 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001441 wpa_dbg(wpa_s, MSG_DEBUG,
1442 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1443 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001444 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1445 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1447 "cipher");
1448 return -1;
1449 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001450 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1451 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001452
1453 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001454 wpa_dbg(wpa_s, MSG_DEBUG,
1455 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1456 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001457 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1458 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1460 "cipher");
1461 return -1;
1462 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001463 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1464 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001465#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466
1467 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001468#ifdef CONFIG_SAE
1469 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1470 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1471#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001472#ifdef CONFIG_IEEE80211R
1473 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1474 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1475 sel &= ~WPA_KEY_MGMT_FT;
1476#endif /* CONFIG_IEEE80211R */
1477 wpa_dbg(wpa_s, MSG_DEBUG,
1478 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1479 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001480 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001481#ifdef CONFIG_IEEE80211R
1482#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001483 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1484 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001485 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1486 wpa_dbg(wpa_s, MSG_DEBUG,
1487 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001488 if (!ssid->ft_eap_pmksa_caching &&
1489 pmksa_cache_get_current(wpa_s->wpa)) {
1490 /* PMKSA caching with FT may have interoperability
1491 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001492 wpa_dbg(wpa_s, MSG_DEBUG,
1493 "WPA: Disable PMKSA caching for FT/802.1X connection");
1494 pmksa_cache_clear_current(wpa_s->wpa);
1495 }
1496#endif /* CONFIG_SHA384 */
1497#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001498#ifdef CONFIG_SUITEB192
1499 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1500 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1501 wpa_dbg(wpa_s, MSG_DEBUG,
1502 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1503#endif /* CONFIG_SUITEB192 */
1504#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001505 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1506 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1507 wpa_dbg(wpa_s, MSG_DEBUG,
1508 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001509#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001510#ifdef CONFIG_FILS
1511#ifdef CONFIG_IEEE80211R
1512 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1513 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1514 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1515 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1516 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1517 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1518#endif /* CONFIG_IEEE80211R */
1519 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1520 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1521 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1522 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1523 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1524 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1525#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001526#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001527 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1528 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1530 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001531 if (!ssid->ft_eap_pmksa_caching &&
1532 pmksa_cache_get_current(wpa_s->wpa)) {
1533 /* PMKSA caching with FT may have interoperability
1534 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001535 wpa_dbg(wpa_s, MSG_DEBUG,
1536 "WPA: Disable PMKSA caching for FT/802.1X connection");
1537 pmksa_cache_clear_current(wpa_s->wpa);
1538 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001539#endif /* CONFIG_IEEE80211R */
1540#ifdef CONFIG_DPP
1541 } else if (sel & WPA_KEY_MGMT_DPP) {
1542 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1543 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1544#endif /* CONFIG_DPP */
1545#ifdef CONFIG_SAE
1546 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1547 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1548 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1549 } else if (sel & WPA_KEY_MGMT_SAE) {
1550 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1551 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1552#endif /* CONFIG_SAE */
1553#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001554 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1555 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1556 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1557#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1559 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1560 wpa_dbg(wpa_s, MSG_DEBUG,
1561 "WPA: using KEY_MGMT 802.1X with SHA256");
1562 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1563 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1564 wpa_dbg(wpa_s, MSG_DEBUG,
1565 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001566 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1567 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1568 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1569 } else if (sel & WPA_KEY_MGMT_PSK) {
1570 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1571 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1572 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1573 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1574 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001575#ifdef CONFIG_HS20
1576 } else if (sel & WPA_KEY_MGMT_OSEN) {
1577 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1578 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1579#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001580#ifdef CONFIG_OWE
1581 } else if (sel & WPA_KEY_MGMT_OWE) {
1582 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1583 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1584#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001585 } else {
1586 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1587 "authenticated key management type");
1588 return -1;
1589 }
1590
1591 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1592 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1593 wpa_s->pairwise_cipher);
1594 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1595
Hai Shalomc3565922019-10-28 11:58:20 -07001596 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1597 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1598 wpa_msg(wpa_s, MSG_INFO,
1599 "RSN: Management frame protection required but the selected AP does not enable it");
1600 return -1;
1601 }
1602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001603 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001604 if (ssid->group_mgmt_cipher)
1605 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001606 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001607 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1608 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001609 wpa_dbg(wpa_s, MSG_DEBUG,
1610 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1611 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001612 if (sel & WPA_CIPHER_AES_128_CMAC) {
1613 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1614 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1615 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001616 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1617 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1618 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1619 "BIP-GMAC-128");
1620 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1621 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1622 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1623 "BIP-GMAC-256");
1624 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1625 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1626 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1627 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001628 } else {
1629 wpa_s->mgmt_group_cipher = 0;
1630 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1631 }
1632 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1633 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001634 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001635 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001636#ifdef CONFIG_OCV
1637 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
1638#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001639 sae_pwe = wpa_s->conf->sae_pwe;
1640 if (ssid->sae_password_id && sae_pwe != 3)
1641 sae_pwe = 1;
1642 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001643#ifdef CONFIG_TESTING_OPTIONS
1644 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1645 wpa_s->ft_rsnxe_used);
1646#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001647
1648 /* Extended Key ID is only supported in infrastructure BSS so far */
1649 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1650 (ssid->proto & WPA_PROTO_RSN) &&
1651 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1652 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1653 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1654 int use_ext_key_id = 0;
1655
1656 wpa_msg(wpa_s, MSG_DEBUG,
1657 "WPA: Enable Extended Key ID support");
1658 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1659 wpa_s->conf->extended_key_id);
1660 if (bss_rsn &&
1661 wpa_s->conf->extended_key_id &&
1662 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1663 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1664 use_ext_key_id = 1;
1665 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1666 use_ext_key_id);
1667 } else {
1668 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1669 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1670 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671
1672 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1673 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1674 return -1;
1675 }
1676
Hai Shalomc3565922019-10-28 11:58:20 -07001677 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1678 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1679 &wpa_s->rsnxe_len)) {
1680 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1681 return -1;
1682 }
1683
Hai Shalom021b0b52019-04-10 11:17:58 -07001684 if (0) {
1685#ifdef CONFIG_DPP
1686 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1687 /* Use PMK from DPP network introduction (PMKSA entry) */
1688 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001689#ifdef CONFIG_DPP2
1690 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1691#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001692#endif /* CONFIG_DPP */
1693 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001694 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001695 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001696
Roshan Pius3a1667e2018-07-03 15:17:14 -07001697 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1698 WPA_KEY_MGMT_FT_PSK |
1699 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1700
1701 if (ssid->psk_set && !sae_only) {
1702 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1703 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001704 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1705 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001706 psk_set = 1;
1707 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001708
Roshan Pius3a1667e2018-07-03 15:17:14 -07001709 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1710 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001711 psk_set = 1;
1712
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001713#ifndef CONFIG_NO_PBKDF2
1714 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001715 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001716 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001717 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1718 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001719 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1720 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001721 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001722 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001723 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001724 }
1725#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001726#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001727 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001728 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1729 ssid->ext_psk);
1730 char pw_str[64 + 1];
1731 u8 psk[PMK_LEN];
1732
1733 if (pw == NULL) {
1734 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1735 "found from external storage");
1736 return -1;
1737 }
1738
1739 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1740 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1741 "PSK length %d in external storage",
1742 (int) wpabuf_len(pw));
1743 ext_password_free(pw);
1744 return -1;
1745 }
1746
1747 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1748 pw_str[wpabuf_len(pw)] = '\0';
1749
1750#ifndef CONFIG_NO_PBKDF2
1751 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1752 {
1753 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1754 4096, psk, PMK_LEN);
1755 os_memset(pw_str, 0, sizeof(pw_str));
1756 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1757 "external passphrase)",
1758 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001759 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1760 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001761 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001762 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001763 } else
1764#endif /* CONFIG_NO_PBKDF2 */
1765 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1766 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1767 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1768 "Invalid PSK hex string");
1769 os_memset(pw_str, 0, sizeof(pw_str));
1770 ext_password_free(pw);
1771 return -1;
1772 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001773 wpa_hexdump_key(MSG_MSGDUMP,
1774 "PSK (from external PSK)",
1775 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001776 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1777 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001778 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001779 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001780 } else {
1781 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1782 "PSK available");
1783 os_memset(pw_str, 0, sizeof(pw_str));
1784 ext_password_free(pw);
1785 return -1;
1786 }
1787
1788 os_memset(pw_str, 0, sizeof(pw_str));
1789 ext_password_free(pw);
1790 }
1791#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001792
1793 if (!psk_set) {
1794 wpa_msg(wpa_s, MSG_INFO,
1795 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001796 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001797 return -1;
1798 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001799#ifdef CONFIG_OWE
1800 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1801 /* OWE Diffie-Hellman exchange in (Re)Association
1802 * Request/Response frames set the PMK, so do not override it
1803 * here. */
1804#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001805 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001806 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1807
Hai Shalomfdcde762020-04-02 11:19:20 -07001808 if (ssid->mode != WPAS_MODE_IBSS &&
1809 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1810 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1811 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1812 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1813 wpa_msg(wpa_s, MSG_INFO,
1814 "Disable PTK0 rekey support - replaced with reconnect");
1815 wpa_s->deny_ptk0_rekey = 1;
1816 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1817 } else {
1818 wpa_s->deny_ptk0_rekey = 0;
1819 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1820 }
1821
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001822 return 0;
1823}
1824
1825
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001826static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1827{
1828 *pos = 0x00;
1829
1830 switch (idx) {
1831 case 0: /* Bits 0-7 */
1832 break;
1833 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001834 if (wpa_s->conf->coloc_intf_reporting) {
1835 /* Bit 13 - Collocated Interference Reporting */
1836 *pos |= 0x20;
1837 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001838 break;
1839 case 2: /* Bits 16-23 */
1840#ifdef CONFIG_WNM
1841 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001842 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001843 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001844#endif /* CONFIG_WNM */
1845 break;
1846 case 3: /* Bits 24-31 */
1847#ifdef CONFIG_WNM
1848 *pos |= 0x02; /* Bit 25 - SSID List */
1849#endif /* CONFIG_WNM */
1850#ifdef CONFIG_INTERWORKING
1851 if (wpa_s->conf->interworking)
1852 *pos |= 0x80; /* Bit 31 - Interworking */
1853#endif /* CONFIG_INTERWORKING */
1854 break;
1855 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001856#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001857 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001858 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001859#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001860 break;
1861 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001862#ifdef CONFIG_HS20
1863 if (wpa_s->conf->hs20)
1864 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1865#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001866#ifdef CONFIG_MBO
1867 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1868#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001869 break;
1870 case 6: /* Bits 48-55 */
1871 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001872 case 7: /* Bits 56-63 */
1873 break;
1874 case 8: /* Bits 64-71 */
1875 if (wpa_s->conf->ftm_responder)
1876 *pos |= 0x40; /* Bit 70 - FTM responder */
1877 if (wpa_s->conf->ftm_initiator)
1878 *pos |= 0x80; /* Bit 71 - FTM initiator */
1879 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001880 case 9: /* Bits 72-79 */
1881#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001882 if (!wpa_s->disable_fils)
1883 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001884#endif /* CONFIG_FILS */
1885 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001886 }
1887}
1888
1889
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001890int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001891{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001892 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001893 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001894
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001895 if (len < wpa_s->extended_capa_len)
1896 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001897 if (buflen < (size_t) len + 2) {
1898 wpa_printf(MSG_INFO,
1899 "Not enough room for building extended capabilities element");
1900 return -1;
1901 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001902
1903 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001904 *pos++ = len;
1905 for (i = 0; i < len; i++, pos++) {
1906 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001907
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001908 if (i < wpa_s->extended_capa_len) {
1909 *pos &= ~wpa_s->extended_capa_mask[i];
1910 *pos |= wpa_s->extended_capa[i];
1911 }
1912 }
1913
1914 while (len > 0 && buf[1 + len] == 0) {
1915 len--;
1916 buf[1] = len;
1917 }
1918 if (len == 0)
1919 return 0;
1920
1921 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001922}
1923
1924
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001925static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1926 struct wpa_bss *test_bss)
1927{
1928 struct wpa_bss *bss;
1929
1930 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1931 if (bss == test_bss)
1932 return 1;
1933 }
1934
1935 return 0;
1936}
1937
1938
1939static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1940 struct wpa_ssid *test_ssid)
1941{
1942 struct wpa_ssid *ssid;
1943
1944 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1945 if (ssid == test_ssid)
1946 return 1;
1947 }
1948
1949 return 0;
1950}
1951
1952
1953int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1954 struct wpa_ssid *test_ssid)
1955{
1956 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1957 return 0;
1958
1959 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1960}
1961
1962
1963void wpas_connect_work_free(struct wpa_connect_work *cwork)
1964{
1965 if (cwork == NULL)
1966 return;
1967 os_free(cwork);
1968}
1969
1970
1971void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1972{
1973 struct wpa_connect_work *cwork;
1974 struct wpa_radio_work *work = wpa_s->connect_work;
1975
1976 if (!work)
1977 return;
1978
1979 wpa_s->connect_work = NULL;
1980 cwork = work->ctx;
1981 work->ctx = NULL;
1982 wpas_connect_work_free(cwork);
1983 radio_work_done(work);
1984}
1985
1986
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001987int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1988{
1989 struct os_reltime now;
1990 u8 addr[ETH_ALEN];
1991
1992 os_get_reltime(&now);
1993 if (wpa_s->last_mac_addr_style == style &&
1994 wpa_s->last_mac_addr_change.sec != 0 &&
1995 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1996 wpa_s->conf->rand_addr_lifetime)) {
1997 wpa_msg(wpa_s, MSG_DEBUG,
1998 "Previously selected random MAC address has not yet expired");
1999 return 0;
2000 }
2001
2002 switch (style) {
2003 case 1:
2004 if (random_mac_addr(addr) < 0)
2005 return -1;
2006 break;
2007 case 2:
2008 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2009 if (random_mac_addr_keep_oui(addr) < 0)
2010 return -1;
2011 break;
2012 default:
2013 return -1;
2014 }
2015
2016 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2017 wpa_msg(wpa_s, MSG_INFO,
2018 "Failed to set random MAC address");
2019 return -1;
2020 }
2021
2022 os_get_reltime(&wpa_s->last_mac_addr_change);
2023 wpa_s->mac_addr_changed = 1;
2024 wpa_s->last_mac_addr_style = style;
2025
2026 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2027 wpa_msg(wpa_s, MSG_INFO,
2028 "Could not update MAC address information");
2029 return -1;
2030 }
2031
2032 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2033 MAC2STR(addr));
2034
2035 return 0;
2036}
2037
2038
2039int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2040{
2041 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2042 !wpa_s->conf->preassoc_mac_addr)
2043 return 0;
2044
2045 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2046}
2047
2048
Hai Shalomc3565922019-10-28 11:58:20 -07002049static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2050{
2051#ifdef CONFIG_SAE
2052 int *groups = conf->sae_groups;
2053 int default_groups[] = { 19, 20, 21, 0 };
2054 const char *password;
2055
2056 if (!groups || groups[0] <= 0)
2057 groups = default_groups;
2058
2059 password = ssid->sae_password;
2060 if (!password)
2061 password = ssid->passphrase;
2062
Hai Shalomfdcde762020-04-02 11:19:20 -07002063 if ((conf->sae_pwe == 0 && !ssid->sae_password_id) || !password ||
2064 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002065 /* PT derivation not needed */
2066 sae_deinit_pt(ssid->pt);
2067 ssid->pt = NULL;
2068 return;
2069 }
2070
2071 if (ssid->pt)
2072 return; /* PT already derived */
2073 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2074 (const u8 *) password, os_strlen(password),
2075 ssid->sae_password_id);
2076#endif /* CONFIG_SAE */
2077}
2078
2079
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002080static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2081{
2082#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2083 os_free(wpa_s->sme.sae_rejected_groups);
2084 wpa_s->sme.sae_rejected_groups = NULL;
2085#ifdef CONFIG_TESTING_OPTIONS
2086 if (wpa_s->extra_sae_rejected_groups) {
2087 int i, *groups = wpa_s->extra_sae_rejected_groups;
2088
2089 for (i = 0; groups[i]; i++) {
2090 wpa_printf(MSG_DEBUG,
2091 "TESTING: Indicate rejection of an extra SAE group %d",
2092 groups[i]);
2093 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2094 groups[i]);
2095 }
2096 }
2097#endif /* CONFIG_TESTING_OPTIONS */
2098#endif /* CONFIG_SAE && CONFIG_SME */
2099}
2100
2101
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002102static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002104/**
2105 * wpa_supplicant_associate - Request association
2106 * @wpa_s: Pointer to wpa_supplicant data
2107 * @bss: Scan results for the selected BSS, or %NULL if not available
2108 * @ssid: Configuration data for the selected network
2109 *
2110 * This function is used to request %wpa_supplicant to associate with a BSS.
2111 */
2112void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2113 struct wpa_bss *bss, struct wpa_ssid *ssid)
2114{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002115 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002116 int rand_style;
2117
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002118 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002119 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002120
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002121 /*
2122 * If we are starting a new connection, any previously pending EAPOL
2123 * RX cannot be valid anymore.
2124 */
2125 wpabuf_free(wpa_s->pending_eapol_rx);
2126 wpa_s->pending_eapol_rx = NULL;
2127
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002128 if (ssid->mac_addr == -1)
2129 rand_style = wpa_s->conf->mac_addr;
2130 else
2131 rand_style = ssid->mac_addr;
2132
Hai Shalomfdcde762020-04-02 11:19:20 -07002133 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002134 wmm_ac_clear_saved_tspecs(wpa_s);
2135 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002136 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002137#ifdef CONFIG_TESTING_OPTIONS
2138 wpa_s->testing_resend_assoc = 0;
2139#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002140
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002141 if (wpa_s->last_ssid == ssid) {
2142 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002143 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002144 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2145 wmm_ac_save_tspecs(wpa_s);
2146 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002147 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2148 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002149 }
Hai Shalomc3565922019-10-28 11:58:20 -07002150 } else {
2151#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002152 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002153 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2154#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002155 }
2156
2157 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002158 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2159 return;
2160 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002161 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002162 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2163 wpa_msg(wpa_s, MSG_INFO,
2164 "Could not restore permanent MAC address");
2165 return;
2166 }
2167 wpa_s->mac_addr_changed = 0;
2168 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2169 wpa_msg(wpa_s, MSG_INFO,
2170 "Could not update MAC address information");
2171 return;
2172 }
2173 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2174 }
2175 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002176
2177#ifdef CONFIG_IBSS_RSN
2178 ibss_rsn_deinit(wpa_s->ibss_rsn);
2179 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002180#else /* CONFIG_IBSS_RSN */
2181 if (ssid->mode == WPAS_MODE_IBSS &&
2182 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2183 wpa_msg(wpa_s, MSG_INFO,
2184 "IBSS RSN not supported in the build");
2185 return;
2186 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002187#endif /* CONFIG_IBSS_RSN */
2188
2189 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2190 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2191#ifdef CONFIG_AP
2192 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2193 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2194 "mode");
2195 return;
2196 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002197 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2198 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002199 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2200 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002201 return;
2202 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002203 wpa_s->current_bss = bss;
2204#else /* CONFIG_AP */
2205 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2206 "the build");
2207#endif /* CONFIG_AP */
2208 return;
2209 }
2210
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002211 if (ssid->mode == WPAS_MODE_MESH) {
2212#ifdef CONFIG_MESH
2213 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2214 wpa_msg(wpa_s, MSG_INFO,
2215 "Driver does not support mesh mode");
2216 return;
2217 }
2218 if (bss)
2219 ssid->frequency = bss->freq;
2220 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2221 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2222 return;
2223 }
2224 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002225 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
2226 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
2227 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002228 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002229#else /* CONFIG_MESH */
2230 wpa_msg(wpa_s, MSG_ERROR,
2231 "mesh mode support not included in the build");
2232#endif /* CONFIG_MESH */
2233 return;
2234 }
2235
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002236 /*
2237 * Set WPA state machine configuration to match the selected network now
2238 * so that the information is available before wpas_start_assoc_cb()
2239 * gets called. This is needed at least for RSN pre-authentication where
2240 * candidate APs are added to a list based on scan result processing
2241 * before completion of the first association.
2242 */
2243 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2244
2245#ifdef CONFIG_DPP
2246 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2247 return;
2248#endif /* CONFIG_DPP */
2249
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002250#ifdef CONFIG_TDLS
2251 if (bss)
2252 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2253 bss->ie_len);
2254#endif /* CONFIG_TDLS */
2255
Hai Shalomc3565922019-10-28 11:58:20 -07002256#ifdef CONFIG_MBO
2257 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2258#endif /* CONFIG_MBO */
2259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002260 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002261 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002262 sme_authenticate(wpa_s, bss, ssid);
2263 return;
2264 }
2265
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002266 if (wpa_s->connect_work) {
2267 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2268 return;
2269 }
2270
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002271 if (radio_work_pending(wpa_s, "connect")) {
2272 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2273 return;
2274 }
2275
Dmitry Shmidt29333592017-01-09 12:27:11 -08002276#ifdef CONFIG_SME
2277 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2278 /* Clear possibly set auth_alg, if any, from last attempt. */
2279 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2280 }
2281#endif /* CONFIG_SME */
2282
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002283 wpas_abort_ongoing_scan(wpa_s);
2284
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002285 cwork = os_zalloc(sizeof(*cwork));
2286 if (cwork == NULL)
2287 return;
2288
2289 cwork->bss = bss;
2290 cwork->ssid = ssid;
2291
2292 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2293 wpas_start_assoc_cb, cwork) < 0) {
2294 os_free(cwork);
2295 }
2296}
2297
2298
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002299static int bss_is_ibss(struct wpa_bss *bss)
2300{
2301 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2302 IEEE80211_CAP_IBSS;
2303}
2304
2305
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002306static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2307 const struct wpa_ssid *ssid)
2308{
2309 enum hostapd_hw_mode hw_mode;
2310 struct hostapd_hw_modes *mode = NULL;
2311 u8 channel;
2312 int i;
2313
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002314 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2315 if (hw_mode == NUM_HOSTAPD_MODES)
2316 return 0;
2317 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2318 if (wpa_s->hw.modes[i].mode == hw_mode) {
2319 mode = &wpa_s->hw.modes[i];
2320 break;
2321 }
2322 }
2323
2324 if (!mode)
2325 return 0;
2326
2327 return mode->vht_capab != 0;
2328}
2329
2330
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002331void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2332 const struct wpa_ssid *ssid,
2333 struct hostapd_freq_params *freq)
2334{
Hai Shalom81f62d82019-07-22 12:10:00 -07002335 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002336 enum hostapd_hw_mode hw_mode;
2337 struct hostapd_hw_modes *mode = NULL;
2338 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2339 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002340 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002341 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2342 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002343 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002344 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002345 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002346 int chwidth, seg0, seg1;
2347 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002348 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002349
2350 freq->freq = ssid->frequency;
2351
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002352 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2353 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2354
2355 if (ssid->mode != WPAS_MODE_IBSS)
2356 break;
2357
2358 /* Don't adjust control freq in case of fixed_freq */
2359 if (ssid->fixed_freq)
2360 break;
2361
2362 if (!bss_is_ibss(bss))
2363 continue;
2364
2365 if (ssid->ssid_len == bss->ssid_len &&
2366 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2367 wpa_printf(MSG_DEBUG,
2368 "IBSS already found in scan results, adjust control freq: %d",
2369 bss->freq);
2370 freq->freq = bss->freq;
2371 obss_scan = 0;
2372 break;
2373 }
2374 }
2375
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002376 /* For IBSS check HT_IBSS flag */
2377 if (ssid->mode == WPAS_MODE_IBSS &&
2378 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2379 return;
2380
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002381 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2382 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2383 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2384 wpa_printf(MSG_DEBUG,
2385 "IBSS: WEP/TKIP detected, do not try to enable HT");
2386 return;
2387 }
2388
2389 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002390 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2391 if (wpa_s->hw.modes[i].mode == hw_mode) {
2392 mode = &wpa_s->hw.modes[i];
2393 break;
2394 }
2395 }
2396
2397 if (!mode)
2398 return;
2399
Hai Shalomc3565922019-10-28 11:58:20 -07002400 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2401 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002402
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002403#ifdef CONFIG_HT_OVERRIDES
2404 if (ssid->disable_ht) {
2405 freq->ht_enabled = 0;
2406 return;
2407 }
2408#endif /* CONFIG_HT_OVERRIDES */
2409
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002410 freq->ht_enabled = ht_supported(mode);
2411 if (!freq->ht_enabled)
2412 return;
2413
Hai Shalomc3565922019-10-28 11:58:20 -07002414 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2415 if (is_24ghz)
2416 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002417#ifdef CONFIG_HE_OVERRIDES
2418 if (is_24ghz && ssid->disable_he)
2419 freq->he_enabled = 0;
2420#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002421
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002422 /* Setup higher BW only for 5 GHz */
2423 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2424 return;
2425
2426 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2427 pri_chan = &mode->channels[chan_idx];
2428 if (pri_chan->chan == channel)
2429 break;
2430 pri_chan = NULL;
2431 }
2432 if (!pri_chan)
2433 return;
2434
2435 /* Check primary channel flags */
2436 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2437 return;
2438
Hai Shalom74f70d42019-02-11 14:42:39 -08002439 freq->channel = pri_chan->chan;
2440
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002441#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002442 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002443#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002444 if (ssid->disable_vht)
2445 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002446#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002447 goto skip_ht40;
2448 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002449#endif /* CONFIG_HT_OVERRIDES */
2450
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002451 /* Check/setup HT40+/HT40- */
2452 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2453 if (ht40plus[j] == channel) {
2454 ht40 = 1;
2455 break;
2456 }
2457 }
2458
2459 /* Find secondary channel */
2460 for (i = 0; i < mode->num_channels; i++) {
2461 sec_chan = &mode->channels[i];
2462 if (sec_chan->chan == channel + ht40 * 4)
2463 break;
2464 sec_chan = NULL;
2465 }
2466 if (!sec_chan)
2467 return;
2468
2469 /* Check secondary channel flags */
2470 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2471 return;
2472
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002473 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002474 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2475 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002476 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002477 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2478 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002479 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002480 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002481
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002482 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002483 struct wpa_scan_results *scan_res;
2484
2485 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2486 if (scan_res == NULL) {
2487 /* Back to HT20 */
2488 freq->sec_channel_offset = 0;
2489 return;
2490 }
2491
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002492 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002493 switch (res) {
2494 case 0:
2495 /* Back to HT20 */
2496 freq->sec_channel_offset = 0;
2497 break;
2498 case 1:
2499 /* Configuration allowed */
2500 break;
2501 case 2:
2502 /* Switch pri/sec channels */
2503 freq->freq = hw_get_freq(mode, sec_chan->chan);
2504 freq->sec_channel_offset = -freq->sec_channel_offset;
2505 freq->channel = sec_chan->chan;
2506 break;
2507 default:
2508 freq->sec_channel_offset = 0;
2509 break;
2510 }
2511
2512 wpa_scan_results_free(scan_res);
2513 }
2514
Hai Shalom74f70d42019-02-11 14:42:39 -08002515#ifdef CONFIG_HT_OVERRIDES
2516skip_ht40:
2517#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002518 wpa_printf(MSG_DEBUG,
2519 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2520 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002521
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002522 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002523 return;
2524
2525 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002526 if (ssid->mode == WPAS_MODE_IBSS &&
2527 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002528 return;
2529
2530 vht_freq = *freq;
2531
Paul Stewart092955c2017-02-06 09:13:09 -08002532#ifdef CONFIG_VHT_OVERRIDES
2533 if (ssid->disable_vht) {
2534 freq->vht_enabled = 0;
2535 return;
2536 }
2537#endif /* CONFIG_VHT_OVERRIDES */
2538
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002539 vht_freq.vht_enabled = vht_supported(mode);
2540 if (!vht_freq.vht_enabled)
2541 return;
2542
Hai Shalomfdcde762020-04-02 11:19:20 -07002543 /* Enable HE with VHT for 5 GHz */
2544 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002545
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002546 /* setup center_freq1, bandwidth */
2547 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2548 if (freq->channel >= vht80[j] &&
2549 freq->channel < vht80[j] + 16)
2550 break;
2551 }
2552
2553 if (j == ARRAY_SIZE(vht80))
2554 return;
2555
2556 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2557 struct hostapd_channel_data *chan;
2558
2559 chan = hw_get_channel_chan(mode, i, NULL);
2560 if (!chan)
2561 return;
2562
2563 /* Back to HT configuration if channel not usable */
2564 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2565 return;
2566 }
2567
Hai Shalom81f62d82019-07-22 12:10:00 -07002568 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002569 seg0 = vht80[j] + 6;
2570 seg1 = 0;
2571
Hai Shalom81f62d82019-07-22 12:10:00 -07002572 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002573 /* setup center_freq2, bandwidth */
2574 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2575 /* Only accept 80 MHz segments separated by a gap */
2576 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2577 continue;
2578 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2579 struct hostapd_channel_data *chan;
2580
2581 chan = hw_get_channel_chan(mode, i, NULL);
2582 if (!chan)
2583 continue;
2584
2585 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2586 HOSTAPD_CHAN_NO_IR |
2587 HOSTAPD_CHAN_RADAR))
2588 continue;
2589
2590 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002591 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002592 vht_caps |=
2593 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2594 seg1 = vht80[k] + 6;
2595 }
2596
Hai Shalom81f62d82019-07-22 12:10:00 -07002597 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002598 break;
2599 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002600 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002601 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002602 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002603 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2604 seg0 = 50;
2605 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002606 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002607 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2608 seg0 = 114;
2609 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002610 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2611 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002612 seg0 = vht80[j] + 2;
2613#ifdef CONFIG_HT_OVERRIDES
2614 if (ssid->disable_ht40)
2615 seg0 = 0;
2616#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002617 }
2618
Hai Shalomfdcde762020-04-02 11:19:20 -07002619#ifdef CONFIG_HE_OVERRIDES
2620 if (ssid->disable_he) {
2621 vht_freq.he_enabled = 0;
2622 freq->he_enabled = 0;
2623 }
2624#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002625 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002626 freq->channel, ssid->enable_edmg,
2627 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002628 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002629 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002630 chwidth, seg0, seg1, vht_caps,
2631 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002632 return;
2633
2634 *freq = vht_freq;
2635
2636 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2637 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002638}
2639
2640
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002641#ifdef CONFIG_FILS
2642static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2643 size_t ie_buf_len)
2644{
2645 struct fils_hlp_req *req;
2646 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2647 const u8 *pos;
2648 u8 *buf = ie_buf;
2649
2650 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2651 list) {
2652 rem_len = ie_buf_len - ie_len;
2653 pos = wpabuf_head(req->pkt);
2654 hdr_len = 1 + 2 * ETH_ALEN + 6;
2655 hlp_len = wpabuf_len(req->pkt);
2656
2657 if (rem_len < 2 + hdr_len + hlp_len) {
2658 wpa_printf(MSG_ERROR,
2659 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2660 (unsigned long) rem_len,
2661 (unsigned long) (2 + hdr_len + hlp_len));
2662 break;
2663 }
2664
2665 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2666 /* Element ID */
2667 *buf++ = WLAN_EID_EXTENSION;
2668 /* Length */
2669 *buf++ = len;
2670 /* Element ID Extension */
2671 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2672 /* Destination MAC address */
2673 os_memcpy(buf, req->dst, ETH_ALEN);
2674 buf += ETH_ALEN;
2675 /* Source MAC address */
2676 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2677 buf += ETH_ALEN;
2678 /* LLC/SNAP Header */
2679 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2680 buf += 6;
2681 /* HLP Packet */
2682 os_memcpy(buf, pos, len - hdr_len);
2683 buf += len - hdr_len;
2684 pos += len - hdr_len;
2685
2686 hlp_len -= len - hdr_len;
2687 ie_len += 2 + len;
2688 rem_len -= 2 + len;
2689
2690 while (hlp_len) {
2691 len = (hlp_len > 255) ? 255 : hlp_len;
2692 if (rem_len < 2 + len)
2693 break;
2694 *buf++ = WLAN_EID_FRAGMENT;
2695 *buf++ = len;
2696 os_memcpy(buf, pos, len);
2697 buf += len;
2698 pos += len;
2699
2700 hlp_len -= len;
2701 ie_len += 2 + len;
2702 rem_len -= 2 + len;
2703 }
2704 }
2705
2706 return ie_len;
2707}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002708
2709
2710int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2711{
2712 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2713 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2714 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2715 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2716}
2717
2718
2719int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2720{
2721#ifdef CONFIG_FILS_SK_PFS
2722 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2723 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2724#else /* CONFIG_FILS_SK_PFS */
2725 return 0;
2726#endif /* CONFIG_FILS_SK_PFS */
2727}
2728
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002729#endif /* CONFIG_FILS */
2730
2731
2732static u8 * wpas_populate_assoc_ies(
2733 struct wpa_supplicant *wpa_s,
2734 struct wpa_bss *bss, struct wpa_ssid *ssid,
2735 struct wpa_driver_associate_params *params,
2736 enum wpa_drv_update_connect_params_mask *mask)
2737{
2738 u8 *wpa_ie;
2739 size_t max_wpa_ie_len = 500;
2740 size_t wpa_ie_len;
2741 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002742#ifdef CONFIG_MBO
2743 const u8 *mbo_ie;
2744#endif
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302745#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2746 int pmksa_cached = 0;
2747#endif /* CONFIG_SAE || CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002748#ifdef CONFIG_FILS
2749 const u8 *realm, *username, *rrk;
2750 size_t realm_len, username_len, rrk_len;
2751 u16 next_seq_num;
2752 struct fils_hlp_req *req;
2753
2754 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2755 list) {
2756 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2757 2 + 2 * wpabuf_len(req->pkt) / 255;
2758 }
2759#endif /* CONFIG_FILS */
2760
2761 wpa_ie = os_malloc(max_wpa_ie_len);
2762 if (!wpa_ie) {
2763 wpa_printf(MSG_ERROR,
2764 "Failed to allocate connect IE buffer for %lu bytes",
2765 (unsigned long) max_wpa_ie_len);
2766 return NULL;
2767 }
2768
2769 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2770 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2771 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2772 int try_opportunistic;
2773 const u8 *cache_id = NULL;
2774
2775 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2776 wpa_s->conf->okc :
2777 ssid->proactive_key_caching) &&
2778 (ssid->proto & WPA_PROTO_RSN);
2779#ifdef CONFIG_FILS
2780 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2781 cache_id = wpa_bss_get_fils_cache_id(bss);
2782#endif /* CONFIG_FILS */
2783 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2784 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002785 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002786 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302787#if defined(CONFIG_SAE) || defined(CONFIG_FILS)
2788 pmksa_cached = 1;
2789#endif /* CONFIG_SAE || CONFIG_FILS */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002790 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002791 wpa_ie_len = max_wpa_ie_len;
2792 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2793 wpa_ie, &wpa_ie_len)) {
2794 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2795 "key management and encryption suites");
2796 os_free(wpa_ie);
2797 return NULL;
2798 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002799#ifdef CONFIG_HS20
2800 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2801 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2802 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2803 wpa_ie_len = max_wpa_ie_len;
2804 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2805 wpa_ie, &wpa_ie_len)) {
2806 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2807 "key management and encryption suites");
2808 os_free(wpa_ie);
2809 return NULL;
2810 }
2811#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002812 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2813 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2814 /*
2815 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2816 * use non-WPA since the scan results did not indicate that the
2817 * AP is using WPA or WPA2.
2818 */
2819 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2820 wpa_ie_len = 0;
2821 wpa_s->wpa_proto = 0;
2822 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2823 wpa_ie_len = max_wpa_ie_len;
2824 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2825 wpa_ie, &wpa_ie_len)) {
2826 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2827 "key management and encryption suites (no "
2828 "scan results)");
2829 os_free(wpa_ie);
2830 return NULL;
2831 }
2832#ifdef CONFIG_WPS
2833 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2834 struct wpabuf *wps_ie;
2835 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2836 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2837 wpa_ie_len = wpabuf_len(wps_ie);
2838 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2839 } else
2840 wpa_ie_len = 0;
2841 wpabuf_free(wps_ie);
2842 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2843 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2844 params->wps = WPS_MODE_PRIVACY;
2845 else
2846 params->wps = WPS_MODE_OPEN;
2847 wpa_s->wpa_proto = 0;
2848#endif /* CONFIG_WPS */
2849 } else {
2850 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2851 wpa_ie_len = 0;
2852 wpa_s->wpa_proto = 0;
2853 }
2854
2855#ifdef IEEE8021X_EAPOL
2856 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2857 if (ssid->leap) {
2858 if (ssid->non_leap == 0)
2859 algs = WPA_AUTH_ALG_LEAP;
2860 else
2861 algs |= WPA_AUTH_ALG_LEAP;
2862 }
2863 }
2864
2865#ifdef CONFIG_FILS
2866 /* Clear FILS association */
2867 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2868
2869 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2870 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2871 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2872 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002873 &next_seq_num, &rrk, &rrk_len) == 0 &&
2874 (!wpa_s->last_con_fail_realm ||
2875 wpa_s->last_con_fail_realm_len != realm_len ||
2876 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002877 algs = WPA_AUTH_ALG_FILS;
2878 params->fils_erp_username = username;
2879 params->fils_erp_username_len = username_len;
2880 params->fils_erp_realm = realm;
2881 params->fils_erp_realm_len = realm_len;
2882 params->fils_erp_next_seq_num = next_seq_num;
2883 params->fils_erp_rrk = rrk;
2884 params->fils_erp_rrk_len = rrk_len;
2885
2886 if (mask)
2887 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302888 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2889 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2890 pmksa_cached) {
2891 algs = WPA_AUTH_ALG_FILS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002892 }
2893#endif /* CONFIG_FILS */
2894#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002895#ifdef CONFIG_SAE
2896 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2897 algs = WPA_AUTH_ALG_SAE;
2898#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002899
2900 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2901 if (ssid->auth_alg) {
2902 algs = ssid->auth_alg;
2903 wpa_dbg(wpa_s, MSG_DEBUG,
2904 "Overriding auth_alg selection: 0x%x", algs);
2905 }
2906
Hai Shalom5f92bc92019-04-18 11:54:11 -07002907#ifdef CONFIG_SAE
Vinita S. Maloofb3a4442020-05-19 17:43:22 +05302908 if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07002909 wpa_dbg(wpa_s, MSG_DEBUG,
2910 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2911 algs = WPA_AUTH_ALG_OPEN;
2912 }
2913#endif /* CONFIG_SAE */
2914
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002915#ifdef CONFIG_P2P
2916 if (wpa_s->global->p2p) {
2917 u8 *pos;
2918 size_t len;
2919 int res;
2920 pos = wpa_ie + wpa_ie_len;
2921 len = max_wpa_ie_len - wpa_ie_len;
2922 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2923 ssid->p2p_group);
2924 if (res >= 0)
2925 wpa_ie_len += res;
2926 }
2927
2928 wpa_s->cross_connect_disallowed = 0;
2929 if (bss) {
2930 struct wpabuf *p2p;
2931 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2932 if (p2p) {
2933 wpa_s->cross_connect_disallowed =
2934 p2p_get_cross_connect_disallowed(p2p);
2935 wpabuf_free(p2p);
2936 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2937 "connection",
2938 wpa_s->cross_connect_disallowed ?
2939 "disallows" : "allows");
2940 }
2941 }
2942
2943 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2944#endif /* CONFIG_P2P */
2945
2946 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002947 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002948 wpa_ie + wpa_ie_len,
2949 max_wpa_ie_len -
2950 wpa_ie_len);
2951 }
2952
2953 /*
2954 * Workaround: Add Extended Capabilities element only if the AP
2955 * included this element in Beacon/Probe Response frames. Some older
2956 * APs seem to have interoperability issues if this element is
2957 * included, so while the standard may require us to include the
2958 * element in all cases, it is justifiable to skip it to avoid
2959 * interoperability issues.
2960 */
2961 if (ssid->p2p_group)
2962 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2963 else
2964 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2965
2966 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2967 u8 ext_capab[18];
2968 int ext_capab_len;
2969 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2970 sizeof(ext_capab));
2971 if (ext_capab_len > 0 &&
2972 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2973 u8 *pos = wpa_ie;
2974 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2975 pos += 2 + pos[1];
2976 os_memmove(pos + ext_capab_len, pos,
2977 wpa_ie_len - (pos - wpa_ie));
2978 wpa_ie_len += ext_capab_len;
2979 os_memcpy(pos, ext_capab, ext_capab_len);
2980 }
2981 }
2982
2983#ifdef CONFIG_HS20
2984 if (is_hs20_network(wpa_s, ssid, bss)) {
2985 struct wpabuf *hs20;
2986
Roshan Pius3a1667e2018-07-03 15:17:14 -07002987 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002988 if (hs20) {
2989 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2990 size_t len;
2991
Hai Shalom74f70d42019-02-11 14:42:39 -08002992 wpas_hs20_add_indication(hs20, pps_mo_id,
2993 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002994 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002995 len = max_wpa_ie_len - wpa_ie_len;
2996 if (wpabuf_len(hs20) <= len) {
2997 os_memcpy(wpa_ie + wpa_ie_len,
2998 wpabuf_head(hs20), wpabuf_len(hs20));
2999 wpa_ie_len += wpabuf_len(hs20);
3000 }
3001 wpabuf_free(hs20);
3002
3003 hs20_configure_frame_filters(wpa_s);
3004 }
3005 }
3006#endif /* CONFIG_HS20 */
3007
3008 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3009 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3010 size_t len;
3011
3012 len = max_wpa_ie_len - wpa_ie_len;
3013 if (wpabuf_len(buf) <= len) {
3014 os_memcpy(wpa_ie + wpa_ie_len,
3015 wpabuf_head(buf), wpabuf_len(buf));
3016 wpa_ie_len += wpabuf_len(buf);
3017 }
3018 }
3019
3020#ifdef CONFIG_FST
3021 if (wpa_s->fst_ies) {
3022 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3023
3024 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3025 os_memcpy(wpa_ie + wpa_ie_len,
3026 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3027 wpa_ie_len += fst_ies_len;
3028 }
3029 }
3030#endif /* CONFIG_FST */
3031
3032#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003033 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003034 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003035 int len;
3036
3037 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003038 max_wpa_ie_len - wpa_ie_len,
3039 !!mbo_attr_from_mbo_ie(mbo_ie,
3040 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003041 if (len >= 0)
3042 wpa_ie_len += len;
3043 }
3044#endif /* CONFIG_MBO */
3045
3046#ifdef CONFIG_FILS
3047 if (algs == WPA_AUTH_ALG_FILS) {
3048 size_t len;
3049
3050 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3051 max_wpa_ie_len - wpa_ie_len);
3052 wpa_ie_len += len;
3053 }
3054#endif /* CONFIG_FILS */
3055
3056#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003057#ifdef CONFIG_TESTING_OPTIONS
3058 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3059 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3060 } else
3061#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003062 if (algs == WPA_AUTH_ALG_OPEN &&
3063 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3064 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003065 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003066
Roshan Pius3a1667e2018-07-03 15:17:14 -07003067 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003068 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003069 } else if (wpa_s->assoc_status_code ==
3070 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003071 if (wpa_s->last_owe_group == 19)
3072 group = 20;
3073 else if (wpa_s->last_owe_group == 20)
3074 group = 21;
3075 else
3076 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003077 } else {
3078 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003079 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003080
Roshan Pius3a1667e2018-07-03 15:17:14 -07003081 wpa_s->last_owe_group = group;
3082 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003083 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3084 if (owe_ie &&
3085 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3086 os_memcpy(wpa_ie + wpa_ie_len,
3087 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3088 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003089 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003090 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003091 }
3092#endif /* CONFIG_OWE */
3093
Hai Shalom021b0b52019-04-10 11:17:58 -07003094#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003095 if (DPP_VERSION > 1 &&
3096 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003097 ssid->dpp_netaccesskey &&
3098 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003099 struct rsn_pmksa_cache_entry *pmksa;
3100
3101 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3102 if (!pmksa || !pmksa->dpp_pfs)
3103 goto pfs_fail;
3104
Hai Shalom021b0b52019-04-10 11:17:58 -07003105 dpp_pfs_free(wpa_s->dpp_pfs);
3106 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3107 ssid->dpp_netaccesskey_len);
3108 if (!wpa_s->dpp_pfs) {
3109 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3110 /* Try to continue without PFS */
3111 goto pfs_fail;
3112 }
3113 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3114 max_wpa_ie_len - wpa_ie_len) {
3115 os_memcpy(wpa_ie + wpa_ie_len,
3116 wpabuf_head(wpa_s->dpp_pfs->ie),
3117 wpabuf_len(wpa_s->dpp_pfs->ie));
3118 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3119 }
3120 }
3121pfs_fail:
3122#endif /* CONFIG_DPP2 */
3123
Roshan Pius3a1667e2018-07-03 15:17:14 -07003124#ifdef CONFIG_IEEE80211R
3125 /*
3126 * Add MDIE under these conditions: the network profile allows FT,
3127 * the AP supports FT, and the mobility domain ID matches.
3128 */
3129 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3130 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3131
3132 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3133 size_t len = 0;
3134 const u8 *md = mdie + 2;
3135 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3136
3137 if (os_memcmp(md, wpa_md,
3138 MOBILITY_DOMAIN_ID_LEN) == 0) {
3139 /* Add mobility domain IE */
3140 len = wpa_ft_add_mdie(
3141 wpa_s->wpa, wpa_ie + wpa_ie_len,
3142 max_wpa_ie_len - wpa_ie_len, mdie);
3143 wpa_ie_len += len;
3144 }
3145#ifdef CONFIG_SME
3146 if (len > 0 && wpa_s->sme.ft_used &&
3147 wpa_sm_has_ptk(wpa_s->wpa)) {
3148 wpa_dbg(wpa_s, MSG_DEBUG,
3149 "SME: Trying to use FT over-the-air");
3150 algs |= WPA_AUTH_ALG_FT;
3151 }
3152#endif /* CONFIG_SME */
3153 }
3154 }
3155#endif /* CONFIG_IEEE80211R */
3156
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003157#ifdef CONFIG_TESTING_OPTIONS
3158 if (wpa_s->rsnxe_override_assoc &&
3159 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3160 max_wpa_ie_len - wpa_ie_len) {
3161 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3162 os_memcpy(wpa_ie + wpa_ie_len,
3163 wpabuf_head(wpa_s->rsnxe_override_assoc),
3164 wpabuf_len(wpa_s->rsnxe_override_assoc));
3165 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3166 } else
3167#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003168 if (wpa_s->rsnxe_len > 0 &&
3169 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3170 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3171 wpa_ie_len += wpa_s->rsnxe_len;
3172 }
3173
Hai Shalom74f70d42019-02-11 14:42:39 -08003174 if (ssid->multi_ap_backhaul_sta) {
3175 size_t multi_ap_ie_len;
3176
3177 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3178 max_wpa_ie_len - wpa_ie_len,
3179 MULTI_AP_BACKHAUL_STA);
3180 if (multi_ap_ie_len == 0) {
3181 wpa_printf(MSG_ERROR,
3182 "Multi-AP: Failed to build Multi-AP IE");
3183 os_free(wpa_ie);
3184 return NULL;
3185 }
3186 wpa_ie_len += multi_ap_ie_len;
3187 }
3188
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003189 params->wpa_ie = wpa_ie;
3190 params->wpa_ie_len = wpa_ie_len;
3191 params->auth_alg = algs;
3192 if (mask)
3193 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3194
3195 return wpa_ie;
3196}
3197
3198
Hai Shalomc3565922019-10-28 11:58:20 -07003199#ifdef CONFIG_OWE
3200static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3201{
3202 struct wpa_driver_associate_params params;
3203 u8 *wpa_ie;
3204
3205 os_memset(&params, 0, sizeof(params));
3206 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3207 wpa_s->current_ssid, &params, NULL);
3208 if (!wpa_ie)
3209 return;
3210
3211 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3212 os_free(wpa_ie);
3213}
3214#endif /* CONFIG_OWE */
3215
3216
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003217#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3218static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3219{
3220 struct wpa_driver_associate_params params;
3221 enum wpa_drv_update_connect_params_mask mask = 0;
3222 u8 *wpa_ie;
3223
3224 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3225 return; /* nothing to do */
3226
3227 os_memset(&params, 0, sizeof(params));
3228 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3229 wpa_s->current_ssid, &params, &mask);
3230 if (!wpa_ie)
3231 return;
3232
3233 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3234 os_free(wpa_ie);
3235 return;
3236 }
3237
3238 wpa_s->auth_alg = params.auth_alg;
3239 wpa_drv_update_connect_params(wpa_s, &params, mask);
3240 os_free(wpa_ie);
3241}
3242#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3243
3244
Hai Shalomc3565922019-10-28 11:58:20 -07003245static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3246{
3247 if (!edmg_ie || edmg_ie[1] < 6)
3248 return 0;
3249 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3250}
3251
3252
3253static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3254{
3255 if (!edmg_ie || edmg_ie[1] < 6)
3256 return 0;
3257 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3258}
3259
3260
3261/* Returns the intersection of two EDMG configurations.
3262 * Note: The current implementation is limited to CB2 only (CB1 included),
3263 * i.e., the implementation supports up to 2 contiguous channels.
3264 * For supporting non-contiguous (aggregated) channels and for supporting
3265 * CB3 and above, this function will need to be extended.
3266 */
3267static struct ieee80211_edmg_config
3268get_edmg_intersection(struct ieee80211_edmg_config a,
3269 struct ieee80211_edmg_config b,
3270 u8 primary_channel)
3271{
3272 struct ieee80211_edmg_config result;
3273 int i, contiguous = 0;
3274 int max_contiguous = 0;
3275
3276 result.channels = b.channels & a.channels;
3277 if (!result.channels) {
3278 wpa_printf(MSG_DEBUG,
3279 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3280 a.channels, b.channels);
3281 goto fail;
3282 }
3283
3284 if (!(result.channels & BIT(primary_channel - 1))) {
3285 wpa_printf(MSG_DEBUG,
3286 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3287 primary_channel, result.channels);
3288 goto fail;
3289 }
3290
3291 /* Find max contiguous channels */
3292 for (i = 0; i < 6; i++) {
3293 if (result.channels & BIT(i))
3294 contiguous++;
3295 else
3296 contiguous = 0;
3297
3298 if (contiguous > max_contiguous)
3299 max_contiguous = contiguous;
3300 }
3301
3302 /* Assuming AP and STA supports ONLY contiguous channels,
3303 * bw configuration can have value between 4-7.
3304 */
3305 if ((b.bw_config < a.bw_config))
3306 result.bw_config = b.bw_config;
3307 else
3308 result.bw_config = a.bw_config;
3309
3310 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3311 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3312 wpa_printf(MSG_DEBUG,
3313 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3314 max_contiguous);
3315 goto fail;
3316 }
3317
3318 return result;
3319
3320fail:
3321 result.channels = 0;
3322 result.bw_config = 0;
3323 return result;
3324}
3325
3326
3327static struct ieee80211_edmg_config
3328get_supported_edmg(struct wpa_supplicant *wpa_s,
3329 struct hostapd_freq_params *freq,
3330 struct ieee80211_edmg_config request_edmg)
3331{
3332 enum hostapd_hw_mode hw_mode;
3333 struct hostapd_hw_modes *mode = NULL;
3334 u8 primary_channel;
3335
3336 if (!wpa_s->hw.modes)
3337 goto fail;
3338
3339 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3340 if (hw_mode == NUM_HOSTAPD_MODES)
3341 goto fail;
3342
Hai Shalomfdcde762020-04-02 11:19:20 -07003343 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003344 if (!mode)
3345 goto fail;
3346
3347 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3348
3349fail:
3350 request_edmg.channels = 0;
3351 request_edmg.bw_config = 0;
3352 return request_edmg;
3353}
3354
3355
Hai Shalom021b0b52019-04-10 11:17:58 -07003356#ifdef CONFIG_MBO
3357void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3358{
3359 struct wpa_driver_associate_params params;
3360 u8 *wpa_ie;
3361
3362 /*
3363 * Update MBO connect params only in case of change of MBO attributes
3364 * when connected, if the AP support MBO.
3365 */
3366
3367 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3368 !wpa_s->current_bss ||
3369 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3370 return;
3371
3372 os_memset(&params, 0, sizeof(params));
3373 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3374 wpa_s->current_ssid, &params, NULL);
3375 if (!wpa_ie)
3376 return;
3377
3378 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3379 os_free(wpa_ie);
3380}
3381#endif /* CONFIG_MBO */
3382
3383
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003384static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3385{
3386 struct wpa_connect_work *cwork = work->ctx;
3387 struct wpa_bss *bss = cwork->bss;
3388 struct wpa_ssid *ssid = cwork->ssid;
3389 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003390 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003391 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003392 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003393 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003394 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003395#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003396 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003397#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003398 int assoc_failed = 0;
3399 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003400 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003401#ifdef CONFIG_HT_OVERRIDES
3402 struct ieee80211_ht_capabilities htcaps;
3403 struct ieee80211_ht_capabilities htcaps_mask;
3404#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003405#ifdef CONFIG_VHT_OVERRIDES
3406 struct ieee80211_vht_capabilities vhtcaps;
3407 struct ieee80211_vht_capabilities vhtcaps_mask;
3408#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003409
3410 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003411 if (work->started) {
3412 wpa_s->connect_work = NULL;
3413
3414 /* cancel possible auth. timeout */
3415 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3416 NULL);
3417 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003418 wpas_connect_work_free(cwork);
3419 return;
3420 }
3421
3422 wpa_s->connect_work = work;
3423
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003424 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3425 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003426 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3427 wpas_connect_work_done(wpa_s);
3428 return;
3429 }
3430
Dmitry Shmidte4663042016-04-04 10:07:49 -07003431 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003432 os_memset(&params, 0, sizeof(params));
3433 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003434 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003435 if (bss &&
3436 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003437#ifdef CONFIG_IEEE80211R
3438 const u8 *ie, *md = NULL;
3439#endif /* CONFIG_IEEE80211R */
3440 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3441 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3442 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3443 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3444 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3445 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3446 if (bssid_changed)
3447 wpas_notify_bssid_changed(wpa_s);
3448#ifdef CONFIG_IEEE80211R
3449 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3450 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3451 md = ie + 2;
3452 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3453 if (md) {
3454 /* Prepare for the next transition */
3455 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3456 }
3457#endif /* CONFIG_IEEE80211R */
3458#ifdef CONFIG_WPS
3459 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3460 wpa_s->conf->ap_scan == 2 &&
3461 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3462 /* Use ap_scan==1 style network selection to find the network
3463 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003464 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003465 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466 wpa_s->reassociate = 1;
3467 wpa_supplicant_req_scan(wpa_s, 0, 0);
3468 return;
3469#endif /* CONFIG_WPS */
3470 } else {
3471 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3472 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003473 if (bss)
3474 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3475 else
3476 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003478 if (!wpa_s->pno)
3479 wpa_supplicant_cancel_sched_scan(wpa_s);
3480
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003481 wpa_supplicant_cancel_scan(wpa_s);
3482
3483 /* Starting new association, so clear the possibly used WPA IE from the
3484 * previous association. */
3485 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003486 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3487 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003488
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003489 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3490 if (!wpa_ie) {
3491 wpas_connect_work_done(wpa_s);
3492 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003493 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003494
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003495 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3496 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003497 cipher_pairwise = wpa_s->pairwise_cipher;
3498 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003499 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003500 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3501 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3502 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3503 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003504#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003505 if (wpa_set_wep_keys(wpa_s, ssid)) {
3506 use_crypt = 1;
3507 wep_keys_set = 1;
3508 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003509#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003510 }
3511 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3512 use_crypt = 0;
3513
3514#ifdef IEEE8021X_EAPOL
3515 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3516 if ((ssid->eapol_flags &
3517 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3518 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3519 !wep_keys_set) {
3520 use_crypt = 0;
3521 } else {
3522 /* Assume that dynamic WEP-104 keys will be used and
3523 * set cipher suites in order for drivers to expect
3524 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003525 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003526 }
3527 }
3528#endif /* IEEE8021X_EAPOL */
3529
3530 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3531 /* Set the key before (and later after) association */
3532 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3533 }
3534
3535 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3536 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003537 params.ssid = bss->ssid;
3538 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003539 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3540 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003541 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3542 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003543 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003544 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003545 ssid->bssid_set,
3546 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003547 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003548 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003549 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003550 params.bssid_hint = bss->bssid;
3551 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003552 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003553 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003554 if (ssid->bssid_hint_set)
3555 params.bssid_hint = ssid->bssid_hint;
3556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003557 params.ssid = ssid->ssid;
3558 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003559 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003560 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003561
3562 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3563 wpa_s->conf->ap_scan == 2) {
3564 params.bssid = ssid->bssid;
3565 params.fixed_bssid = 1;
3566 }
3567
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003568 /* Initial frequency for IBSS/mesh */
3569 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003570 ssid->frequency > 0 && params.freq.freq == 0)
3571 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003572
3573 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003574 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003575 if (ssid->beacon_int)
3576 params.beacon_int = ssid->beacon_int;
3577 else
3578 params.beacon_int = wpa_s->conf->beacon_int;
3579 }
3580
Hai Shalomc3565922019-10-28 11:58:20 -07003581 if (bss && ssid->enable_edmg)
3582 edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len,
3583 WLAN_EID_EXT_EDMG_OPERATION);
3584 else
3585 edmg_ie_oper = NULL;
3586
3587 if (edmg_ie_oper) {
3588 params.freq.edmg.channels =
3589 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3590 params.freq.edmg.bw_config =
3591 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3592 wpa_printf(MSG_DEBUG,
3593 "AP supports EDMG channels 0x%x, bw_config %d",
3594 params.freq.edmg.channels,
3595 params.freq.edmg.bw_config);
3596
3597 /* User may ask for specific EDMG channel for EDMG connection
3598 * (must be supported by AP)
3599 */
3600 if (ssid->edmg_channel) {
3601 struct ieee80211_edmg_config configured_edmg;
3602 enum hostapd_hw_mode hw_mode;
3603 u8 primary_channel;
3604
3605 hw_mode = ieee80211_freq_to_chan(bss->freq,
3606 &primary_channel);
3607 if (hw_mode == NUM_HOSTAPD_MODES)
3608 goto edmg_fail;
3609
3610 hostapd_encode_edmg_chan(ssid->enable_edmg,
3611 ssid->edmg_channel,
3612 primary_channel,
3613 &configured_edmg);
3614
3615 if (ieee802_edmg_is_allowed(params.freq.edmg,
3616 configured_edmg)) {
3617 params.freq.edmg = configured_edmg;
3618 wpa_printf(MSG_DEBUG,
3619 "Use EDMG channel %d for connection",
3620 ssid->edmg_channel);
3621 } else {
3622 edmg_fail:
3623 params.freq.edmg.channels = 0;
3624 params.freq.edmg.bw_config = 0;
3625 wpa_printf(MSG_WARNING,
3626 "EDMG channel %d not supported by AP, fallback to DMG",
3627 ssid->edmg_channel);
3628 }
3629 }
3630
3631 if (params.freq.edmg.channels) {
3632 wpa_printf(MSG_DEBUG,
3633 "EDMG before: channels 0x%x, bw_config %d",
3634 params.freq.edmg.channels,
3635 params.freq.edmg.bw_config);
3636 params.freq.edmg = get_supported_edmg(wpa_s,
3637 &params.freq,
3638 params.freq.edmg);
3639 wpa_printf(MSG_DEBUG,
3640 "EDMG after: channels 0x%x, bw_config %d",
3641 params.freq.edmg.channels,
3642 params.freq.edmg.bw_config);
3643 }
3644 }
3645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646 params.pairwise_suite = cipher_pairwise;
3647 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003648 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003649 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003650 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003651 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003653 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003654#ifdef CONFIG_WEP
3655 {
3656 int i;
3657
3658 for (i = 0; i < NUM_WEP_KEYS; i++) {
3659 if (ssid->wep_key_len[i])
3660 params.wep_key[i] = ssid->wep_key[i];
3661 params.wep_key_len[i] = ssid->wep_key_len[i];
3662 }
3663 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003664 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003665#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003666
Hai Shalom74f70d42019-02-11 14:42:39 -08003667 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003668 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3669 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003670 params.passphrase = ssid->passphrase;
3671 if (ssid->psk_set)
3672 params.psk = ssid->psk;
3673 }
3674
Hai Shalom74f70d42019-02-11 14:42:39 -08003675 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3676 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3677 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3678 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3679 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003680 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003681
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003682 if (wpa_s->conf->key_mgmt_offload) {
3683 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3684 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003685 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3686 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003687 params.req_key_mgmt_offload =
3688 ssid->proactive_key_caching < 0 ?
3689 wpa_s->conf->okc : ssid->proactive_key_caching;
3690 else
3691 params.req_key_mgmt_offload = 1;
3692
3693 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3694 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3695 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3696 ssid->psk_set)
3697 params.psk = ssid->psk;
3698 }
3699
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003700 params.drop_unencrypted = use_crypt;
3701
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003702 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003703 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003704 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3705 struct wpa_ie_data ie;
3706 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3707 ie.capabilities &
3708 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3709 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3710 "MFP: require MFP");
3711 params.mgmt_frame_protection =
3712 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003713#ifdef CONFIG_OWE
3714 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3715 !ssid->owe_only) {
3716 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3717#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003718 }
3719 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003720
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003721 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003722
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003723 if (wpa_s->p2pdev->set_sta_uapsd)
3724 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003725 else
3726 params.uapsd = -1;
3727
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003728#ifdef CONFIG_HT_OVERRIDES
3729 os_memset(&htcaps, 0, sizeof(htcaps));
3730 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3731 params.htcaps = (u8 *) &htcaps;
3732 params.htcaps_mask = (u8 *) &htcaps_mask;
3733 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3734#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003735#ifdef CONFIG_VHT_OVERRIDES
3736 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3737 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3738 params.vhtcaps = &vhtcaps;
3739 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003740 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003741#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003742#ifdef CONFIG_HE_OVERRIDES
3743 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3744#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003745
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003746#ifdef CONFIG_P2P
3747 /*
3748 * If multi-channel concurrency is not supported, check for any
3749 * frequency conflict. In case of any frequency conflict, remove the
3750 * least prioritized connection.
3751 */
3752 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003753 int freq, num;
3754 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003755 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003756 wpa_printf(MSG_DEBUG,
3757 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003758 freq, params.freq.freq);
3759 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003760 wpa_s, params.freq.freq, ssid) < 0) {
3761 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003762 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003763 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003764 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003765 }
3766 }
3767#endif /* CONFIG_P2P */
3768
Dmitry Shmidte4663042016-04-04 10:07:49 -07003769 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3770 wpa_s->current_ssid)
3771 params.prev_bssid = prev_bssid;
3772
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003773 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003774 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003775 if (ret < 0) {
3776 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3777 "failed");
3778 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3779 /*
3780 * The driver is known to mean what is saying, so we
3781 * can stop right here; the association will not
3782 * succeed.
3783 */
3784 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003785 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003786 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3787 return;
3788 }
3789 /* try to continue anyway; new association will be tried again
3790 * after timeout */
3791 assoc_failed = 1;
3792 }
3793
3794 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3795 /* Set the key after the association just in case association
3796 * cleared the previously configured key. */
3797 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3798 /* No need to timeout authentication since there is no key
3799 * management. */
3800 wpa_supplicant_cancel_auth_timeout(wpa_s);
3801 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3802#ifdef CONFIG_IBSS_RSN
3803 } else if (ssid->mode == WPAS_MODE_IBSS &&
3804 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3805 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3806 /*
3807 * RSN IBSS authentication is per-STA and we can disable the
3808 * per-BSSID authentication.
3809 */
3810 wpa_supplicant_cancel_auth_timeout(wpa_s);
3811#endif /* CONFIG_IBSS_RSN */
3812 } else {
3813 /* Timeout for IEEE 802.11 authentication and association */
3814 int timeout = 60;
3815
3816 if (assoc_failed) {
3817 /* give IBSS a bit more time */
3818 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3819 } else if (wpa_s->conf->ap_scan == 1) {
3820 /* give IBSS a bit more time */
3821 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3822 }
3823 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3824 }
3825
Hai Shalomfdcde762020-04-02 11:19:20 -07003826#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003827 if (wep_keys_set &&
3828 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003829 /* Set static WEP keys again */
3830 wpa_set_wep_keys(wpa_s, ssid);
3831 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003832#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003833
3834 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3835 /*
3836 * Do not allow EAP session resumption between different
3837 * network configurations.
3838 */
3839 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3840 }
3841 old_ssid = wpa_s->current_ssid;
3842 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003843
3844 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003845 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003846#ifdef CONFIG_HS20
3847 hs20_configure_frame_filters(wpa_s);
3848#endif /* CONFIG_HS20 */
3849 }
3850
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003851 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3852 wpa_supplicant_initiate_eapol(wpa_s);
3853 if (old_ssid != wpa_s->current_ssid)
3854 wpas_notify_network_changed(wpa_s);
3855}
3856
3857
3858static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3859 const u8 *addr)
3860{
3861 struct wpa_ssid *old_ssid;
3862
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003863 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003864 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003865 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003866 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003867 wpa_sm_set_config(wpa_s->wpa, NULL);
3868 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3869 if (old_ssid != wpa_s->current_ssid)
3870 wpas_notify_network_changed(wpa_s);
3871 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3872}
3873
3874
3875/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003876 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3877 * @wpa_s: Pointer to wpa_supplicant data
3878 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3879 *
3880 * This function is used to request %wpa_supplicant to deauthenticate from the
3881 * current AP.
3882 */
3883void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003884 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003885{
3886 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003887 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003888 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003889
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003890 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003891 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003892 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003893 reason_code, reason2str(reason_code),
3894 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003895
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003896 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3897 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3898 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003899 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003900 else if (!is_zero_ether_addr(wpa_s->bssid))
3901 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003902 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3903 /*
3904 * When using driver-based BSS selection, we may not know the
3905 * BSSID with which we are currently trying to associate. We
3906 * need to notify the driver of this disconnection even in such
3907 * a case, so use the all zeros address here.
3908 */
3909 addr = wpa_s->bssid;
3910 zero_addr = 1;
3911 }
3912
Hai Shalom74f70d42019-02-11 14:42:39 -08003913 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3914 wpa_s->enabled_4addr_mode = 0;
3915
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003916#ifdef CONFIG_TDLS
3917 wpa_tdls_teardown_peers(wpa_s->wpa);
3918#endif /* CONFIG_TDLS */
3919
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003920#ifdef CONFIG_MESH
3921 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003922 struct mesh_conf *mconf;
3923
3924 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003925 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3926 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003927 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3928 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003929 wpa_supplicant_leave_mesh(wpa_s);
3930 }
3931#endif /* CONFIG_MESH */
3932
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003933 if (addr) {
3934 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003935 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07003936 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003937 event.deauth_info.locally_generated = 1;
3938 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003939 if (zero_addr)
3940 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003941 }
3942
3943 wpa_supplicant_clear_connection(wpa_s, addr);
3944}
3945
Hai Shalomfdcde762020-04-02 11:19:20 -07003946
3947void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
3948{
3949 wpa_s->own_reconnect_req = 1;
3950 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
3951
3952}
3953
3954
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003955static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3956 struct wpa_ssid *ssid)
3957{
3958 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3959 return;
3960
3961 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003962 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003963 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3964 wpas_notify_network_enabled_changed(wpa_s, ssid);
3965
3966 /*
3967 * Try to reassociate since there is no current configuration and a new
3968 * network was made available.
3969 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003970 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003971 wpa_s->reassociate = 1;
3972}
3973
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003974
Roshan Pius950bec92016-07-19 09:49:24 -07003975/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003976 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003977 * @wpa_s: wpa_supplicant structure for a network interface
3978 * Returns: The new network configuration or %NULL if operation failed
3979 *
3980 * This function performs the following operations:
3981 * 1. Adds a new network.
3982 * 2. Send network addition notification.
3983 * 3. Marks the network disabled.
3984 * 4. Set network default parameters.
3985 */
3986struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3987{
3988 struct wpa_ssid *ssid;
3989
3990 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003991 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003992 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003993 wpas_notify_network_added(wpa_s, ssid);
3994 ssid->disabled = 1;
3995 wpa_config_set_network_defaults(ssid);
3996
3997 return ssid;
3998}
3999
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004000
Roshan Pius950bec92016-07-19 09:49:24 -07004001/**
4002 * wpa_supplicant_remove_network - Remove a configured network based on id
4003 * @wpa_s: wpa_supplicant structure for a network interface
4004 * @id: Unique network id to search for
4005 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4006 * could not be removed
4007 *
4008 * This function performs the following operations:
4009 * 1. Removes the network.
4010 * 2. Send network removal notification.
4011 * 3. Update internal state machines.
4012 * 4. Stop any running sched scans.
4013 */
4014int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4015{
4016 struct wpa_ssid *ssid;
4017 int was_disabled;
4018
4019 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004020 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004021 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004022 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004023
4024 if (wpa_s->last_ssid == ssid)
4025 wpa_s->last_ssid = NULL;
4026
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004027 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004028#ifdef CONFIG_SME
4029 wpa_s->sme.prev_bssid_set = 0;
4030#endif /* CONFIG_SME */
4031 /*
4032 * Invalidate the EAP session cache if the current or
4033 * previously used network is removed.
4034 */
4035 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4036 }
4037
4038 if (ssid == wpa_s->current_ssid) {
4039 wpa_sm_set_config(wpa_s->wpa, NULL);
4040 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4041
4042 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4043 wpa_s->own_disconnect_req = 1;
4044 wpa_supplicant_deauthenticate(wpa_s,
4045 WLAN_REASON_DEAUTH_LEAVING);
4046 }
4047
4048 was_disabled = ssid->disabled;
4049
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004050 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004051 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004052
4053 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004054 wpa_printf(MSG_DEBUG,
4055 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004056 wpa_supplicant_cancel_sched_scan(wpa_s);
4057 wpa_supplicant_req_scan(wpa_s, 0, 0);
4058 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004059
Roshan Pius950bec92016-07-19 09:49:24 -07004060 return 0;
4061}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004062
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004063
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004064/**
4065 * wpa_supplicant_enable_network - Mark a configured network as enabled
4066 * @wpa_s: wpa_supplicant structure for a network interface
4067 * @ssid: wpa_ssid structure for a configured network or %NULL
4068 *
4069 * Enables the specified network or all networks if no network specified.
4070 */
4071void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4072 struct wpa_ssid *ssid)
4073{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004074 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004075 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4076 wpa_supplicant_enable_one_network(wpa_s, ssid);
4077 } else
4078 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004079
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004080 if (wpa_s->reassociate && !wpa_s->disconnected &&
4081 (!wpa_s->current_ssid ||
4082 wpa_s->wpa_state == WPA_DISCONNECTED ||
4083 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004084 if (wpa_s->sched_scanning) {
4085 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4086 "new network to scan filters");
4087 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004088 }
4089
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004090 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4091 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004092 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004093 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004094 }
4095}
4096
4097
4098/**
4099 * wpa_supplicant_disable_network - Mark a configured network as disabled
4100 * @wpa_s: wpa_supplicant structure for a network interface
4101 * @ssid: wpa_ssid structure for a configured network or %NULL
4102 *
4103 * Disables the specified network or all networks if no network specified.
4104 */
4105void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4106 struct wpa_ssid *ssid)
4107{
4108 struct wpa_ssid *other_ssid;
4109 int was_disabled;
4110
4111 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004112 if (wpa_s->sched_scanning)
4113 wpa_supplicant_cancel_sched_scan(wpa_s);
4114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004115 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4116 other_ssid = other_ssid->next) {
4117 was_disabled = other_ssid->disabled;
4118 if (was_disabled == 2)
4119 continue; /* do not change persistent P2P group
4120 * data */
4121
4122 other_ssid->disabled = 1;
4123
4124 if (was_disabled != other_ssid->disabled)
4125 wpas_notify_network_enabled_changed(
4126 wpa_s, other_ssid);
4127 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004128 if (wpa_s->current_ssid) {
4129 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4130 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004131 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004132 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004133 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004134 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004135 if (ssid == wpa_s->current_ssid) {
4136 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4137 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004138 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004139 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004140 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004141
4142 was_disabled = ssid->disabled;
4143
4144 ssid->disabled = 1;
4145
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004146 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004147 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004148 if (wpa_s->sched_scanning) {
4149 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4150 "to remove network from filters");
4151 wpa_supplicant_cancel_sched_scan(wpa_s);
4152 wpa_supplicant_req_scan(wpa_s, 0, 0);
4153 }
4154 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004155 }
4156}
4157
4158
4159/**
4160 * wpa_supplicant_select_network - Attempt association with a network
4161 * @wpa_s: wpa_supplicant structure for a network interface
4162 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4163 */
4164void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4165 struct wpa_ssid *ssid)
4166{
4167
4168 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004169 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004170
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004171 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004172 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4173 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004174 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004175 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004176 disconnected = 1;
4177 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004178
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004179 if (ssid)
4180 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4181
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004182 /*
4183 * Mark all other networks disabled or mark all networks enabled if no
4184 * network specified.
4185 */
4186 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4187 other_ssid = other_ssid->next) {
4188 int was_disabled = other_ssid->disabled;
4189 if (was_disabled == 2)
4190 continue; /* do not change persistent P2P group data */
4191
4192 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004193 if (was_disabled && !other_ssid->disabled)
4194 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004195
4196 if (was_disabled != other_ssid->disabled)
4197 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4198 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004199
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004200 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4201 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004202 /* We are already associated with the selected network */
4203 wpa_printf(MSG_DEBUG, "Already associated with the "
4204 "selected network - do nothing");
4205 return;
4206 }
4207
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004208 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004209 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004210 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004211 wpa_s->connect_without_scan =
4212 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004213
4214 /*
4215 * Don't optimize next scan freqs since a new ESS has been
4216 * selected.
4217 */
4218 os_free(wpa_s->next_scan_freqs);
4219 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004220 } else {
4221 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004222 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004223
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004224 wpa_s->disconnected = 0;
4225 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004226 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004227 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004228 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004229 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004230 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4231 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004232
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004233 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004234 wpa_supplicant_fast_associate(wpa_s) != 1) {
4235 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004236 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004237 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004238 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004239
4240 if (ssid)
4241 wpas_notify_network_selected(wpa_s, ssid);
4242}
4243
4244
4245/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004246 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4247 * @wpa_s: wpa_supplicant structure for a network interface
4248 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4249 * @pkcs11_module_path: PKCS #11 module path or NULL
4250 * Returns: 0 on success; -1 on failure
4251 *
4252 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4253 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4254 * module path fails the paths will be reset to the default value (NULL).
4255 */
4256int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4257 const char *pkcs11_engine_path,
4258 const char *pkcs11_module_path)
4259{
4260 char *pkcs11_engine_path_copy = NULL;
4261 char *pkcs11_module_path_copy = NULL;
4262
4263 if (pkcs11_engine_path != NULL) {
4264 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4265 if (pkcs11_engine_path_copy == NULL)
4266 return -1;
4267 }
4268 if (pkcs11_module_path != NULL) {
4269 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004270 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004271 os_free(pkcs11_engine_path_copy);
4272 return -1;
4273 }
4274 }
4275
4276 os_free(wpa_s->conf->pkcs11_engine_path);
4277 os_free(wpa_s->conf->pkcs11_module_path);
4278 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4279 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4280
4281 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4282 eapol_sm_deinit(wpa_s->eapol);
4283 wpa_s->eapol = NULL;
4284 if (wpa_supplicant_init_eapol(wpa_s)) {
4285 /* Error -> Reset paths to the default value (NULL) once. */
4286 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4287 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4288 NULL);
4289
4290 return -1;
4291 }
4292 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4293
4294 return 0;
4295}
4296
4297
4298/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004299 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4300 * @wpa_s: wpa_supplicant structure for a network interface
4301 * @ap_scan: AP scan mode
4302 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4303 *
4304 */
4305int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4306{
4307
4308 int old_ap_scan;
4309
4310 if (ap_scan < 0 || ap_scan > 2)
4311 return -1;
4312
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004313 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4314 wpa_printf(MSG_INFO,
4315 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4316 }
4317
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004318#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004319 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4320 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4321 wpa_s->wpa_state < WPA_COMPLETED) {
4322 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4323 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004324 return 0;
4325 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004326#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004327
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004328 old_ap_scan = wpa_s->conf->ap_scan;
4329 wpa_s->conf->ap_scan = ap_scan;
4330
4331 if (old_ap_scan != wpa_s->conf->ap_scan)
4332 wpas_notify_ap_scan_changed(wpa_s);
4333
4334 return 0;
4335}
4336
4337
4338/**
4339 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4340 * @wpa_s: wpa_supplicant structure for a network interface
4341 * @expire_age: Expiration age in seconds
4342 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4343 *
4344 */
4345int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4346 unsigned int bss_expire_age)
4347{
4348 if (bss_expire_age < 10) {
4349 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4350 bss_expire_age);
4351 return -1;
4352 }
4353 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4354 bss_expire_age);
4355 wpa_s->conf->bss_expiration_age = bss_expire_age;
4356
4357 return 0;
4358}
4359
4360
4361/**
4362 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4363 * @wpa_s: wpa_supplicant structure for a network interface
4364 * @expire_count: number of scans after which an unseen BSS is reclaimed
4365 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4366 *
4367 */
4368int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4369 unsigned int bss_expire_count)
4370{
4371 if (bss_expire_count < 1) {
4372 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4373 bss_expire_count);
4374 return -1;
4375 }
4376 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4377 bss_expire_count);
4378 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4379
4380 return 0;
4381}
4382
4383
4384/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004385 * wpa_supplicant_set_scan_interval - Set scan interval
4386 * @wpa_s: wpa_supplicant structure for a network interface
4387 * @scan_interval: scan interval in seconds
4388 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4389 *
4390 */
4391int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4392 int scan_interval)
4393{
4394 if (scan_interval < 0) {
4395 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4396 scan_interval);
4397 return -1;
4398 }
4399 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4400 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004401 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004402
4403 return 0;
4404}
4405
4406
4407/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004408 * wpa_supplicant_set_debug_params - Set global debug params
4409 * @global: wpa_global structure
4410 * @debug_level: debug level
4411 * @debug_timestamp: determines if show timestamp in debug data
4412 * @debug_show_keys: determines if show keys in debug data
4413 * Returns: 0 if succeed or -1 if debug_level has wrong value
4414 */
4415int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4416 int debug_timestamp, int debug_show_keys)
4417{
4418
4419 int old_level, old_timestamp, old_show_keys;
4420
4421 /* check for allowed debuglevels */
4422 if (debug_level != MSG_EXCESSIVE &&
4423 debug_level != MSG_MSGDUMP &&
4424 debug_level != MSG_DEBUG &&
4425 debug_level != MSG_INFO &&
4426 debug_level != MSG_WARNING &&
4427 debug_level != MSG_ERROR)
4428 return -1;
4429
4430 old_level = wpa_debug_level;
4431 old_timestamp = wpa_debug_timestamp;
4432 old_show_keys = wpa_debug_show_keys;
4433
4434 wpa_debug_level = debug_level;
4435 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4436 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4437
4438 if (wpa_debug_level != old_level)
4439 wpas_notify_debug_level_changed(global);
4440 if (wpa_debug_timestamp != old_timestamp)
4441 wpas_notify_debug_timestamp_changed(global);
4442 if (wpa_debug_show_keys != old_show_keys)
4443 wpas_notify_debug_show_keys_changed(global);
4444
4445 return 0;
4446}
4447
4448
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004449#ifdef CONFIG_OWE
4450static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4451 const u8 *entry_ssid, size_t entry_ssid_len)
4452{
4453 const u8 *owe, *pos, *end;
4454 u8 ssid_len;
4455 struct wpa_bss *bss;
4456
4457 /* Check network profile SSID aganst the SSID in the
4458 * OWE Transition Mode element. */
4459
4460 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4461 if (!bss)
4462 return 0;
4463
4464 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4465 if (!owe)
4466 return 0;
4467
4468 pos = owe + 6;
4469 end = owe + 2 + owe[1];
4470
4471 if (end - pos < ETH_ALEN + 1)
4472 return 0;
4473 pos += ETH_ALEN;
4474 ssid_len = *pos++;
4475 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4476 return 0;
4477
4478 return entry_ssid_len == ssid_len &&
4479 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4480}
4481#endif /* CONFIG_OWE */
4482
4483
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004484/**
4485 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4486 * @wpa_s: Pointer to wpa_supplicant data
4487 * Returns: A pointer to the current network structure or %NULL on failure
4488 */
4489struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4490{
4491 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004492 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004493 int res;
4494 size_t ssid_len;
4495 u8 bssid[ETH_ALEN];
4496 int wired;
4497
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004498 res = wpa_drv_get_ssid(wpa_s, ssid);
4499 if (res < 0) {
4500 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4501 "driver");
4502 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004503 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004504 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004505
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004506 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004507 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4508 "driver");
4509 return NULL;
4510 }
4511
4512 wired = wpa_s->conf->ap_scan == 0 &&
4513 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4514
4515 entry = wpa_s->conf->ssid;
4516 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004517 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004518 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004519 (!entry->ssid ||
4520 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4521 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004522 (!entry->bssid_set ||
4523 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4524 return entry;
4525#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004526 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004527 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4528 (entry->ssid == NULL || entry->ssid_len == 0) &&
4529 (!entry->bssid_set ||
4530 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4531 return entry;
4532#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004533
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004534#ifdef CONFIG_OWE
4535 if (!wpas_network_disabled(wpa_s, entry) &&
4536 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4537 entry->ssid_len) &&
4538 (!entry->bssid_set ||
4539 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4540 return entry;
4541#endif /* CONFIG_OWE */
4542
Dmitry Shmidt04949592012-07-19 12:16:46 -07004543 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004544 entry->ssid_len == 0 &&
4545 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4546 return entry;
4547
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004548 entry = entry->next;
4549 }
4550
4551 return NULL;
4552}
4553
4554
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004555static int select_driver(struct wpa_supplicant *wpa_s, int i)
4556{
4557 struct wpa_global *global = wpa_s->global;
4558
4559 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004560 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004561 if (global->drv_priv[i] == NULL) {
4562 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4563 "'%s'", wpa_drivers[i]->name);
4564 return -1;
4565 }
4566 }
4567
4568 wpa_s->driver = wpa_drivers[i];
4569 wpa_s->global_drv_priv = global->drv_priv[i];
4570
4571 return 0;
4572}
4573
4574
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004575static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4576 const char *name)
4577{
4578 int i;
4579 size_t len;
4580 const char *pos, *driver = name;
4581
4582 if (wpa_s == NULL)
4583 return -1;
4584
4585 if (wpa_drivers[0] == NULL) {
4586 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4587 "wpa_supplicant");
4588 return -1;
4589 }
4590
4591 if (name == NULL) {
4592 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004593 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004594 }
4595
4596 do {
4597 pos = os_strchr(driver, ',');
4598 if (pos)
4599 len = pos - driver;
4600 else
4601 len = os_strlen(driver);
4602
4603 for (i = 0; wpa_drivers[i]; i++) {
4604 if (os_strlen(wpa_drivers[i]->name) == len &&
4605 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004606 0) {
4607 /* First driver that succeeds wins */
4608 if (select_driver(wpa_s, i) == 0)
4609 return 0;
4610 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004611 }
4612
4613 driver = pos + 1;
4614 } while (pos);
4615
4616 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4617 return -1;
4618}
4619
4620
4621/**
4622 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4623 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4624 * with struct wpa_driver_ops::init()
4625 * @src_addr: Source address of the EAPOL frame
4626 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4627 * @len: Length of the EAPOL data
4628 *
4629 * This function is called for each received EAPOL frame. Most driver
4630 * interfaces rely on more generic OS mechanism for receiving frames through
4631 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4632 * take care of received EAPOL frames and deliver them to the core supplicant
4633 * code by calling this function.
4634 */
4635void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4636 const u8 *buf, size_t len)
4637{
4638 struct wpa_supplicant *wpa_s = ctx;
4639
4640 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4641 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4642
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004643#ifdef CONFIG_TESTING_OPTIONS
4644 if (wpa_s->ignore_auth_resp) {
4645 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4646 return;
4647 }
4648#endif /* CONFIG_TESTING_OPTIONS */
4649
Jouni Malinena05074c2012-12-21 21:35:35 +02004650 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4651 (wpa_s->last_eapol_matches_bssid &&
4652#ifdef CONFIG_AP
4653 !wpa_s->ap_iface &&
4654#endif /* CONFIG_AP */
4655 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004656 /*
4657 * There is possible race condition between receiving the
4658 * association event and the EAPOL frame since they are coming
4659 * through different paths from the driver. In order to avoid
4660 * issues in trying to process the EAPOL frame before receiving
4661 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004662 * the association event is received. This may also be needed in
4663 * driver-based roaming case, so also use src_addr != BSSID as a
4664 * trigger if we have previously confirmed that the
4665 * Authenticator uses BSSID as the src_addr (which is not the
4666 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004667 */
4668 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004669 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4670 wpa_supplicant_state_txt(wpa_s->wpa_state),
4671 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004672 wpabuf_free(wpa_s->pending_eapol_rx);
4673 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4674 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004675 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004676 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4677 ETH_ALEN);
4678 }
4679 return;
4680 }
4681
Jouni Malinena05074c2012-12-21 21:35:35 +02004682 wpa_s->last_eapol_matches_bssid =
4683 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4684
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004685#ifdef CONFIG_AP
4686 if (wpa_s->ap_iface) {
4687 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4688 return;
4689 }
4690#endif /* CONFIG_AP */
4691
4692 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4693 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4694 "no key management is configured");
4695 return;
4696 }
4697
4698 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004699 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004700 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4701 wpa_s->wpa_state != WPA_COMPLETED) &&
4702 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004703 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004704 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004705 int timeout = 10;
4706
4707 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4708 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4709 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4710 /* Use longer timeout for IEEE 802.1X/EAP */
4711 timeout = 70;
4712 }
4713
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004714#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004715 if (wpa_s->current_ssid && wpa_s->current_bss &&
4716 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4717 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4718 /*
4719 * Use shorter timeout if going through WPS AP iteration
4720 * for PIN config method with an AP that does not
4721 * advertise Selected Registrar.
4722 */
4723 struct wpabuf *wps_ie;
4724
4725 wps_ie = wpa_bss_get_vendor_ie_multi(
4726 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4727 if (wps_ie &&
4728 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4729 timeout = 10;
4730 wpabuf_free(wps_ie);
4731 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004732#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004733
4734 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004735 }
4736 wpa_s->eapol_received++;
4737
4738 if (wpa_s->countermeasures) {
4739 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4740 "EAPOL packet");
4741 return;
4742 }
4743
4744#ifdef CONFIG_IBSS_RSN
4745 if (wpa_s->current_ssid &&
4746 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4747 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4748 return;
4749 }
4750#endif /* CONFIG_IBSS_RSN */
4751
4752 /* Source address of the incoming EAPOL frame could be compared to the
4753 * current BSSID. However, it is possible that a centralized
4754 * Authenticator could be using another MAC address than the BSSID of
4755 * an AP, so just allow any address to be used for now. The replies are
4756 * still sent to the current BSSID (if available), though. */
4757
4758 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4759 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004760 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4761 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004762 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4763 return;
4764 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004765 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004766 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4767 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4768 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07004769 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004770 * handshake processing which would normally set portValid. We
4771 * need this to allow the EAPOL state machines to be completed
4772 * without going through EAPOL-Key handshake.
4773 */
Hai Shalome21d4e82020-04-29 16:34:06 -07004774 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004775 }
4776}
4777
4778
Hai Shalomb755a2a2020-04-23 21:49:02 -07004779static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
4780{
4781 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
4782 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
4783}
4784
4785
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004786int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004787{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004788 if ((!wpa_s->p2p_mgmt ||
4789 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4790 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004791 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004792 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4793 wpa_drv_get_mac_addr(wpa_s),
4794 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07004795 wpas_eapol_needs_l2_packet(wpa_s) ?
4796 wpa_supplicant_rx_eapol : NULL,
4797 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004798 if (wpa_s->l2 == NULL)
4799 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004800
4801 if (l2_packet_set_packet_filter(wpa_s->l2,
4802 L2_PACKET_FILTER_PKTTYPE))
4803 wpa_dbg(wpa_s, MSG_DEBUG,
4804 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07004805
4806 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4807 wpa_msg(wpa_s, MSG_ERROR,
4808 "Failed to get own L2 address");
4809 return -1;
4810 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004811 } else {
4812 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4813 if (addr)
4814 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4815 }
4816
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004817 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004818 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004819
Hai Shalomc3565922019-10-28 11:58:20 -07004820#ifdef CONFIG_FST
4821 if (wpa_s->fst)
4822 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4823#endif /* CONFIG_FST */
4824
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004825 return 0;
4826}
4827
4828
Dmitry Shmidt04949592012-07-19 12:16:46 -07004829static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4830 const u8 *buf, size_t len)
4831{
4832 struct wpa_supplicant *wpa_s = ctx;
4833 const struct l2_ethhdr *eth;
4834
4835 if (len < sizeof(*eth))
4836 return;
4837 eth = (const struct l2_ethhdr *) buf;
4838
4839 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4840 !(eth->h_dest[0] & 0x01)) {
4841 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4842 " (bridge - not for this interface - ignore)",
4843 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4844 return;
4845 }
4846
4847 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4848 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4849 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4850 len - sizeof(*eth));
4851}
4852
4853
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004854/**
4855 * wpa_supplicant_driver_init - Initialize driver interface parameters
4856 * @wpa_s: Pointer to wpa_supplicant data
4857 * Returns: 0 on success, -1 on failure
4858 *
4859 * This function is called to initialize driver interface parameters.
4860 * wpa_drv_init() must have been called before this function to initialize the
4861 * driver interface.
4862 */
4863int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4864{
4865 static int interface_count = 0;
4866
4867 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4868 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004869
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004870 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4871 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004872 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004873 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4874
Hai Shalomb755a2a2020-04-23 21:49:02 -07004875 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004876 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4877 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004878 wpa_s->l2_br = l2_packet_init_bridge(
4879 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4880 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004881 if (wpa_s->l2_br == NULL) {
4882 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4883 "connection for the bridge interface '%s'",
4884 wpa_s->bridge_ifname);
4885 return -1;
4886 }
4887 }
4888
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004889 if (wpa_s->conf->ap_scan == 2 &&
4890 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4891 wpa_printf(MSG_INFO,
4892 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4893 }
4894
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004895 wpa_clear_keys(wpa_s, NULL);
4896
4897 /* Make sure that TKIP countermeasures are not left enabled (could
4898 * happen if wpa_supplicant is killed during countermeasures. */
4899 wpa_drv_set_countermeasures(wpa_s, 0);
4900
4901 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4902 wpa_drv_flush_pmkid(wpa_s);
4903
4904 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004905 wpa_s->prev_scan_wildcard = 0;
4906
Dmitry Shmidt04949592012-07-19 12:16:46 -07004907 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004908 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4909 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4910 interface_count = 0;
4911 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004912#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004913 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004914 wpa_supplicant_delayed_sched_scan(wpa_s,
4915 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004916 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004917 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004918 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004919#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004920 interface_count++;
4921 } else
4922 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4923
4924 return 0;
4925}
4926
4927
4928static int wpa_supplicant_daemon(const char *pid_file)
4929{
4930 wpa_printf(MSG_DEBUG, "Daemonize..");
4931 return os_daemonize(pid_file);
4932}
4933
4934
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004935static struct wpa_supplicant *
4936wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004937{
4938 struct wpa_supplicant *wpa_s;
4939
4940 wpa_s = os_zalloc(sizeof(*wpa_s));
4941 if (wpa_s == NULL)
4942 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004943 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004944 wpa_s->scan_interval = 5;
4945 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004946 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004947 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004948 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004949
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004950 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004951 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07004952#ifdef CONFIG_TESTING_OPTIONS
4953 dl_list_init(&wpa_s->drv_signal_override);
4954#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004955
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004956 return wpa_s;
4957}
4958
4959
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004960#ifdef CONFIG_HT_OVERRIDES
4961
4962static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4963 struct ieee80211_ht_capabilities *htcaps,
4964 struct ieee80211_ht_capabilities *htcaps_mask,
4965 const char *ht_mcs)
4966{
4967 /* parse ht_mcs into hex array */
4968 int i;
4969 const char *tmp = ht_mcs;
4970 char *end = NULL;
4971
4972 /* If ht_mcs is null, do not set anything */
4973 if (!ht_mcs)
4974 return 0;
4975
4976 /* This is what we are setting in the kernel */
4977 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4978
4979 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4980
4981 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004982 long v;
4983
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004984 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004985 v = strtol(tmp, &end, 16);
4986
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004987 if (errno == 0) {
4988 wpa_msg(wpa_s, MSG_DEBUG,
4989 "htcap value[%i]: %ld end: %p tmp: %p",
4990 i, v, end, tmp);
4991 if (end == tmp)
4992 break;
4993
4994 htcaps->supported_mcs_set[i] = v;
4995 tmp = end;
4996 } else {
4997 wpa_msg(wpa_s, MSG_ERROR,
4998 "Failed to parse ht-mcs: %s, error: %s\n",
4999 ht_mcs, strerror(errno));
5000 return -1;
5001 }
5002 }
5003
5004 /*
5005 * If we were able to parse any values, then set mask for the MCS set.
5006 */
5007 if (i) {
5008 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5009 IEEE80211_HT_MCS_MASK_LEN - 1);
5010 /* skip the 3 reserved bits */
5011 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5012 0x1f;
5013 }
5014
5015 return 0;
5016}
5017
5018
5019static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5020 struct ieee80211_ht_capabilities *htcaps,
5021 struct ieee80211_ht_capabilities *htcaps_mask,
5022 int disabled)
5023{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005024 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005025
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005026 if (disabled == -1)
5027 return 0;
5028
Hai Shalom74f70d42019-02-11 14:42:39 -08005029 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5030
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005031 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5032 htcaps_mask->ht_capabilities_info |= msk;
5033 if (disabled)
5034 htcaps->ht_capabilities_info &= msk;
5035 else
5036 htcaps->ht_capabilities_info |= msk;
5037
5038 return 0;
5039}
5040
5041
5042static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5043 struct ieee80211_ht_capabilities *htcaps,
5044 struct ieee80211_ht_capabilities *htcaps_mask,
5045 int factor)
5046{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005047 if (factor == -1)
5048 return 0;
5049
Hai Shalom74f70d42019-02-11 14:42:39 -08005050 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5051
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005052 if (factor < 0 || factor > 3) {
5053 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5054 "Must be 0-3 or -1", factor);
5055 return -EINVAL;
5056 }
5057
5058 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5059 htcaps->a_mpdu_params &= ~0x3;
5060 htcaps->a_mpdu_params |= factor & 0x3;
5061
5062 return 0;
5063}
5064
5065
5066static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5067 struct ieee80211_ht_capabilities *htcaps,
5068 struct ieee80211_ht_capabilities *htcaps_mask,
5069 int density)
5070{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005071 if (density == -1)
5072 return 0;
5073
Hai Shalom74f70d42019-02-11 14:42:39 -08005074 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5075
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005076 if (density < 0 || density > 7) {
5077 wpa_msg(wpa_s, MSG_ERROR,
5078 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5079 density);
5080 return -EINVAL;
5081 }
5082
5083 htcaps_mask->a_mpdu_params |= 0x1C;
5084 htcaps->a_mpdu_params &= ~(0x1C);
5085 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5086
5087 return 0;
5088}
5089
5090
5091static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5092 struct ieee80211_ht_capabilities *htcaps,
5093 struct ieee80211_ht_capabilities *htcaps_mask,
5094 int disabled)
5095{
Hai Shalom74f70d42019-02-11 14:42:39 -08005096 if (disabled)
5097 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005098
Paul Stewart092955c2017-02-06 09:13:09 -08005099 set_disable_ht40(htcaps, disabled);
5100 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005101
5102 return 0;
5103}
5104
5105
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005106static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5107 struct ieee80211_ht_capabilities *htcaps,
5108 struct ieee80211_ht_capabilities *htcaps_mask,
5109 int disabled)
5110{
5111 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005112 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5113 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005114
Hai Shalom74f70d42019-02-11 14:42:39 -08005115 if (disabled)
5116 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005117
5118 if (disabled)
5119 htcaps->ht_capabilities_info &= ~msk;
5120 else
5121 htcaps->ht_capabilities_info |= msk;
5122
5123 htcaps_mask->ht_capabilities_info |= msk;
5124
5125 return 0;
5126}
5127
5128
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005129static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5130 struct ieee80211_ht_capabilities *htcaps,
5131 struct ieee80211_ht_capabilities *htcaps_mask,
5132 int disabled)
5133{
5134 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005135 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005136
Hai Shalom74f70d42019-02-11 14:42:39 -08005137 if (disabled)
5138 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005139
5140 if (disabled)
5141 htcaps->ht_capabilities_info &= ~msk;
5142 else
5143 htcaps->ht_capabilities_info |= msk;
5144
5145 htcaps_mask->ht_capabilities_info |= msk;
5146
5147 return 0;
5148}
5149
5150
Hai Shalom74f70d42019-02-11 14:42:39 -08005151static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5152 struct ieee80211_ht_capabilities *htcaps,
5153 struct ieee80211_ht_capabilities *htcaps_mask,
5154 int tx_stbc)
5155{
5156 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5157
5158 if (tx_stbc == -1)
5159 return 0;
5160
5161 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5162
5163 if (tx_stbc < 0 || tx_stbc > 1) {
5164 wpa_msg(wpa_s, MSG_ERROR,
5165 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5166 return -EINVAL;
5167 }
5168
5169 htcaps_mask->ht_capabilities_info |= msk;
5170 htcaps->ht_capabilities_info &= ~msk;
5171 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5172
5173 return 0;
5174}
5175
5176
5177static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5178 struct ieee80211_ht_capabilities *htcaps,
5179 struct ieee80211_ht_capabilities *htcaps_mask,
5180 int rx_stbc)
5181{
5182 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5183
5184 if (rx_stbc == -1)
5185 return 0;
5186
5187 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5188
5189 if (rx_stbc < 0 || rx_stbc > 3) {
5190 wpa_msg(wpa_s, MSG_ERROR,
5191 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5192 return -EINVAL;
5193 }
5194
5195 htcaps_mask->ht_capabilities_info |= msk;
5196 htcaps->ht_capabilities_info &= ~msk;
5197 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5198
5199 return 0;
5200}
5201
5202
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005203void wpa_supplicant_apply_ht_overrides(
5204 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5205 struct wpa_driver_associate_params *params)
5206{
5207 struct ieee80211_ht_capabilities *htcaps;
5208 struct ieee80211_ht_capabilities *htcaps_mask;
5209
5210 if (!ssid)
5211 return;
5212
5213 params->disable_ht = ssid->disable_ht;
5214 if (!params->htcaps || !params->htcaps_mask)
5215 return;
5216
5217 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5218 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5219 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5220 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5221 ssid->disable_max_amsdu);
5222 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5223 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5224 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005225 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005226 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005227 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5228 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005229
5230 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005231 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005232 htcaps->ht_capabilities_info |= bit;
5233 htcaps_mask->ht_capabilities_info |= bit;
5234 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005235}
5236
5237#endif /* CONFIG_HT_OVERRIDES */
5238
5239
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005240#ifdef CONFIG_VHT_OVERRIDES
5241void wpa_supplicant_apply_vht_overrides(
5242 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5243 struct wpa_driver_associate_params *params)
5244{
5245 struct ieee80211_vht_capabilities *vhtcaps;
5246 struct ieee80211_vht_capabilities *vhtcaps_mask;
5247
5248 if (!ssid)
5249 return;
5250
5251 params->disable_vht = ssid->disable_vht;
5252
5253 vhtcaps = (void *) params->vhtcaps;
5254 vhtcaps_mask = (void *) params->vhtcaps_mask;
5255
5256 if (!vhtcaps || !vhtcaps_mask)
5257 return;
5258
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005259 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5260 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005261
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005262#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005263 if (ssid->disable_sgi) {
5264 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5265 VHT_CAP_SHORT_GI_160);
5266 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5267 VHT_CAP_SHORT_GI_160);
5268 wpa_msg(wpa_s, MSG_DEBUG,
5269 "disable-sgi override specified, vht-caps: 0x%x",
5270 vhtcaps->vht_capabilities_info);
5271 }
5272
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005273 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005274 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5275 int max_ampdu;
5276
5277 max_ampdu = (ssid->vht_capa &
5278 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5279 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005280
5281 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5282 wpa_set_ampdu_factor(wpa_s,
5283 (void *) params->htcaps,
5284 (void *) params->htcaps_mask,
5285 max_ampdu);
5286 }
5287#endif /* CONFIG_HT_OVERRIDES */
5288
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005289#define OVERRIDE_MCS(i) \
5290 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5291 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005292 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005293 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005294 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5295 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005296 } \
5297 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5298 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005299 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005300 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005301 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5302 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005303 }
5304
5305 OVERRIDE_MCS(1);
5306 OVERRIDE_MCS(2);
5307 OVERRIDE_MCS(3);
5308 OVERRIDE_MCS(4);
5309 OVERRIDE_MCS(5);
5310 OVERRIDE_MCS(6);
5311 OVERRIDE_MCS(7);
5312 OVERRIDE_MCS(8);
5313}
5314#endif /* CONFIG_VHT_OVERRIDES */
5315
5316
Hai Shalomfdcde762020-04-02 11:19:20 -07005317#ifdef CONFIG_HE_OVERRIDES
5318void wpa_supplicant_apply_he_overrides(
5319 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5320 struct wpa_driver_associate_params *params)
5321{
5322 if (!ssid)
5323 return;
5324
5325 params->disable_he = ssid->disable_he;
5326}
5327#endif /* CONFIG_HE_OVERRIDES */
5328
5329
Dmitry Shmidt04949592012-07-19 12:16:46 -07005330static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5331{
5332#ifdef PCSC_FUNCS
5333 size_t len;
5334
5335 if (!wpa_s->conf->pcsc_reader)
5336 return 0;
5337
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005338 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005339 if (!wpa_s->scard)
5340 return 1;
5341
5342 if (wpa_s->conf->pcsc_pin &&
5343 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5344 scard_deinit(wpa_s->scard);
5345 wpa_s->scard = NULL;
5346 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5347 return -1;
5348 }
5349
5350 len = sizeof(wpa_s->imsi) - 1;
5351 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5352 scard_deinit(wpa_s->scard);
5353 wpa_s->scard = NULL;
5354 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5355 return -1;
5356 }
5357 wpa_s->imsi[len] = '\0';
5358
5359 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5360
5361 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5362 wpa_s->imsi, wpa_s->mnc_len);
5363
5364 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5365 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5366#endif /* PCSC_FUNCS */
5367
5368 return 0;
5369}
5370
5371
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005372int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5373{
5374 char *val, *pos;
5375
5376 ext_password_deinit(wpa_s->ext_pw);
5377 wpa_s->ext_pw = NULL;
5378 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5379
5380 if (!wpa_s->conf->ext_password_backend)
5381 return 0;
5382
5383 val = os_strdup(wpa_s->conf->ext_password_backend);
5384 if (val == NULL)
5385 return -1;
5386 pos = os_strchr(val, ':');
5387 if (pos)
5388 *pos++ = '\0';
5389
5390 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5391
5392 wpa_s->ext_pw = ext_password_init(val, pos);
5393 os_free(val);
5394 if (wpa_s->ext_pw == NULL) {
5395 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5396 return -1;
5397 }
5398 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5399
5400 return 0;
5401}
5402
5403
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005404#ifdef CONFIG_FST
5405
5406static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5407{
5408 struct wpa_supplicant *wpa_s = ctx;
5409
5410 return (is_zero_ether_addr(wpa_s->bssid) ||
5411 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5412}
5413
5414
5415static void wpas_fst_get_channel_info_cb(void *ctx,
5416 enum hostapd_hw_mode *hw_mode,
5417 u8 *channel)
5418{
5419 struct wpa_supplicant *wpa_s = ctx;
5420
5421 if (wpa_s->current_bss) {
5422 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5423 channel);
5424 } else if (wpa_s->hw.num_modes) {
5425 *hw_mode = wpa_s->hw.modes[0].mode;
5426 } else {
5427 WPA_ASSERT(0);
5428 *hw_mode = 0;
5429 }
5430}
5431
5432
5433static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5434{
5435 struct wpa_supplicant *wpa_s = ctx;
5436
5437 *modes = wpa_s->hw.modes;
5438 return wpa_s->hw.num_modes;
5439}
5440
5441
5442static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5443{
5444 struct wpa_supplicant *wpa_s = ctx;
5445
5446 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5447 wpa_s->fst_ies = fst_ies;
5448}
5449
5450
5451static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5452{
5453 struct wpa_supplicant *wpa_s = ctx;
5454
Paul Stewart092955c2017-02-06 09:13:09 -08005455 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5456 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5457 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5458 return -1;
5459 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005460 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005461 wpa_s->own_addr, wpa_s->bssid,
5462 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005463 0);
5464}
5465
5466
5467static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5468{
5469 struct wpa_supplicant *wpa_s = ctx;
5470
5471 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5472 return wpa_s->received_mb_ies;
5473}
5474
5475
5476static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5477 const u8 *buf, size_t size)
5478{
5479 struct wpa_supplicant *wpa_s = ctx;
5480 struct mb_ies_info info;
5481
5482 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5483
5484 if (!mb_ies_info_by_ies(&info, buf, size)) {
5485 wpabuf_free(wpa_s->received_mb_ies);
5486 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5487 }
5488}
5489
5490
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005491static const u8 * wpas_fst_get_peer_first(void *ctx,
5492 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005493 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005494{
5495 struct wpa_supplicant *wpa_s = ctx;
5496
5497 *get_ctx = NULL;
5498 if (!is_zero_ether_addr(wpa_s->bssid))
5499 return (wpa_s->received_mb_ies || !mb_only) ?
5500 wpa_s->bssid : NULL;
5501 return NULL;
5502}
5503
5504
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005505static const u8 * wpas_fst_get_peer_next(void *ctx,
5506 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005507 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005508{
5509 return NULL;
5510}
5511
5512void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5513 struct fst_wpa_obj *iface_obj)
5514{
5515 iface_obj->ctx = wpa_s;
5516 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5517 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5518 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5519 iface_obj->set_ies = wpas_fst_set_ies_cb;
5520 iface_obj->send_action = wpas_fst_send_action_cb;
5521 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5522 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5523 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5524 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5525}
5526#endif /* CONFIG_FST */
5527
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005528static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005529 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005530{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005531 struct wowlan_triggers *triggers;
5532 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005533
5534 if (!wpa_s->conf->wowlan_triggers)
5535 return 0;
5536
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005537 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5538 if (triggers) {
5539 ret = wpa_drv_wowlan(wpa_s, triggers);
5540 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005541 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005542 return ret;
5543}
5544
5545
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005546enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005547{
5548 if (freq < 3000)
5549 return BAND_2_4_GHZ;
5550 if (freq > 50000)
5551 return BAND_60_GHZ;
5552 return BAND_5_GHZ;
5553}
5554
5555
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005556unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005557{
5558 int i;
5559 unsigned int band = 0;
5560
5561 if (freqs) {
5562 /* freqs are specified for the radio work */
5563 for (i = 0; freqs[i]; i++)
5564 band |= wpas_freq_to_band(freqs[i]);
5565 } else {
5566 /*
5567 * freqs are not specified, implies all
5568 * the supported freqs by HW
5569 */
5570 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5571 if (wpa_s->hw.modes[i].num_channels != 0) {
5572 if (wpa_s->hw.modes[i].mode ==
5573 HOSTAPD_MODE_IEEE80211B ||
5574 wpa_s->hw.modes[i].mode ==
5575 HOSTAPD_MODE_IEEE80211G)
5576 band |= BAND_2_4_GHZ;
5577 else if (wpa_s->hw.modes[i].mode ==
5578 HOSTAPD_MODE_IEEE80211A)
5579 band |= BAND_5_GHZ;
5580 else if (wpa_s->hw.modes[i].mode ==
5581 HOSTAPD_MODE_IEEE80211AD)
5582 band |= BAND_60_GHZ;
5583 else if (wpa_s->hw.modes[i].mode ==
5584 HOSTAPD_MODE_IEEE80211ANY)
5585 band = BAND_2_4_GHZ | BAND_5_GHZ |
5586 BAND_60_GHZ;
5587 }
5588 }
5589 }
5590
5591 return band;
5592}
5593
5594
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005595static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5596 const char *rn)
5597{
5598 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5599 struct wpa_radio *radio;
5600
5601 while (rn && iface) {
5602 radio = iface->radio;
5603 if (radio && os_strcmp(rn, radio->name) == 0) {
5604 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5605 wpa_s->ifname, rn);
5606 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5607 return radio;
5608 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005609
5610 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005611 }
5612
5613 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5614 wpa_s->ifname, rn ? rn : "N/A");
5615 radio = os_zalloc(sizeof(*radio));
5616 if (radio == NULL)
5617 return NULL;
5618
5619 if (rn)
5620 os_strlcpy(radio->name, rn, sizeof(radio->name));
5621 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005622 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005623 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5624
5625 return radio;
5626}
5627
5628
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005629static void radio_work_free(struct wpa_radio_work *work)
5630{
5631 if (work->wpa_s->scan_work == work) {
5632 /* This should not really happen. */
5633 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5634 work->type, work, work->started);
5635 work->wpa_s->scan_work = NULL;
5636 }
5637
5638#ifdef CONFIG_P2P
5639 if (work->wpa_s->p2p_scan_work == work) {
5640 /* This should not really happen. */
5641 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5642 work->type, work, work->started);
5643 work->wpa_s->p2p_scan_work = NULL;
5644 }
5645#endif /* CONFIG_P2P */
5646
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005647 if (work->started) {
5648 work->wpa_s->radio->num_active_works--;
5649 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005650 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005651 work->type, work,
5652 work->wpa_s->radio->num_active_works);
5653 }
5654
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005655 dl_list_del(&work->list);
5656 os_free(work);
5657}
5658
5659
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005660static int radio_work_is_connect(struct wpa_radio_work *work)
5661{
5662 return os_strcmp(work->type, "sme-connect") == 0 ||
5663 os_strcmp(work->type, "connect") == 0;
5664}
5665
5666
5667static int radio_work_is_scan(struct wpa_radio_work *work)
5668{
5669 return os_strcmp(work->type, "scan") == 0 ||
5670 os_strcmp(work->type, "p2p-scan") == 0;
5671}
5672
5673
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005674static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5675{
5676 struct wpa_radio_work *active_work = NULL;
5677 struct wpa_radio_work *tmp;
5678
5679 /* Get the active work to know the type and band. */
5680 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5681 if (tmp->started) {
5682 active_work = tmp;
5683 break;
5684 }
5685 }
5686
5687 if (!active_work) {
5688 /* No active work, start one */
5689 radio->num_active_works = 0;
5690 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5691 list) {
5692 if (os_strcmp(tmp->type, "scan") == 0 &&
5693 radio->external_scan_running &&
5694 (((struct wpa_driver_scan_params *)
5695 tmp->ctx)->only_new_results ||
5696 tmp->wpa_s->clear_driver_scan_cache))
5697 continue;
5698 return tmp;
5699 }
5700 return NULL;
5701 }
5702
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005703 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005704 /*
5705 * If the active work is either connect or sme-connect,
5706 * do not parallelize them with other radio works.
5707 */
5708 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5709 "Do not parallelize radio work with %s",
5710 active_work->type);
5711 return NULL;
5712 }
5713
5714 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5715 if (tmp->started)
5716 continue;
5717
5718 /*
5719 * If connect or sme-connect are enqueued, parallelize only
5720 * those operations ahead of them in the queue.
5721 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005722 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005723 break;
5724
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005725 /* Serialize parallel scan and p2p_scan operations on the same
5726 * interface since the driver_nl80211 mechanism for tracking
5727 * scan cookies does not yet have support for this. */
5728 if (active_work->wpa_s == tmp->wpa_s &&
5729 radio_work_is_scan(active_work) &&
5730 radio_work_is_scan(tmp)) {
5731 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5732 "Do not start work '%s' when another work '%s' is already scheduled",
5733 tmp->type, active_work->type);
5734 continue;
5735 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005736 /*
5737 * Check that the radio works are distinct and
5738 * on different bands.
5739 */
5740 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5741 (active_work->bands != tmp->bands)) {
5742 /*
5743 * If a scan has to be scheduled through nl80211 scan
5744 * interface and if an external scan is already running,
5745 * do not schedule the scan since it is likely to get
5746 * rejected by kernel.
5747 */
5748 if (os_strcmp(tmp->type, "scan") == 0 &&
5749 radio->external_scan_running &&
5750 (((struct wpa_driver_scan_params *)
5751 tmp->ctx)->only_new_results ||
5752 tmp->wpa_s->clear_driver_scan_cache))
5753 continue;
5754
5755 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5756 "active_work:%s new_work:%s",
5757 active_work->type, tmp->type);
5758 return tmp;
5759 }
5760 }
5761
5762 /* Did not find a radio work to schedule in parallel. */
5763 return NULL;
5764}
5765
5766
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005767static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5768{
5769 struct wpa_radio *radio = eloop_ctx;
5770 struct wpa_radio_work *work;
5771 struct os_reltime now, diff;
5772 struct wpa_supplicant *wpa_s;
5773
5774 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005775 if (work == NULL) {
5776 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005777 return;
5778 }
5779
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005780 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5781 radio_list);
5782
5783 if (!(wpa_s &&
5784 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5785 if (work->started)
5786 return; /* already started and still in progress */
5787
5788 if (wpa_s && wpa_s->radio->external_scan_running) {
5789 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5790 return;
5791 }
5792 } else {
5793 work = NULL;
5794 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5795 /* get the work to schedule next */
5796 work = radio_work_get_next_work(radio);
5797 }
5798 if (!work)
5799 return;
5800 }
5801
5802 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005803 os_get_reltime(&now);
5804 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005805 wpa_dbg(wpa_s, MSG_DEBUG,
5806 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005807 work->type, work, diff.sec, diff.usec);
5808 work->started = 1;
5809 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005810 radio->num_active_works++;
5811
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005812 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005813
5814 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5815 radio->num_active_works < MAX_ACTIVE_WORKS)
5816 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005817}
5818
5819
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005820/*
5821 * This function removes both started and pending radio works running on
5822 * the provided interface's radio.
5823 * Prior to the removal of the radio work, its callback (cb) is called with
5824 * deinit set to be 1. Each work's callback is responsible for clearing its
5825 * internal data and restoring to a correct state.
5826 * @wpa_s: wpa_supplicant data
5827 * @type: type of works to be removed
5828 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5829 * this interface's works.
5830 */
5831void radio_remove_works(struct wpa_supplicant *wpa_s,
5832 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005833{
5834 struct wpa_radio_work *work, *tmp;
5835 struct wpa_radio *radio = wpa_s->radio;
5836
5837 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5838 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005839 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005840 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005841
5842 /* skip other ifaces' works */
5843 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005844 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005845
5846 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5847 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005848 work->cb(work, 1);
5849 radio_work_free(work);
5850 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005851
5852 /* in case we removed the started work */
5853 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005854}
5855
5856
Roshan Pius3a1667e2018-07-03 15:17:14 -07005857void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5858{
5859 struct wpa_radio_work *work;
5860 struct wpa_radio *radio = wpa_s->radio;
5861
5862 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5863 if (work->ctx != ctx)
5864 continue;
5865 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5866 work->type, work, work->started ? " (started)" : "");
5867 radio_work_free(work);
5868 break;
5869 }
5870}
5871
5872
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005873static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5874{
5875 struct wpa_radio *radio = wpa_s->radio;
5876
5877 if (!radio)
5878 return;
5879
5880 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5881 wpa_s->ifname, radio->name);
5882 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005883 radio_remove_works(wpa_s, NULL, 0);
5884 wpa_s->radio = NULL;
5885 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005886 return; /* Interfaces remain for this radio */
5887
5888 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005889 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005890 os_free(radio);
5891}
5892
5893
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005894void radio_work_check_next(struct wpa_supplicant *wpa_s)
5895{
5896 struct wpa_radio *radio = wpa_s->radio;
5897
5898 if (dl_list_empty(&radio->work))
5899 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005900 if (wpa_s->ext_work_in_progress) {
5901 wpa_printf(MSG_DEBUG,
5902 "External radio work in progress - delay start of pending item");
5903 return;
5904 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005905 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5906 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5907}
5908
5909
5910/**
5911 * radio_add_work - Add a radio work item
5912 * @wpa_s: Pointer to wpa_supplicant data
5913 * @freq: Frequency of the offchannel operation in MHz or 0
5914 * @type: Unique identifier for each type of work
5915 * @next: Force as the next work to be executed
5916 * @cb: Callback function for indicating when radio is available
5917 * @ctx: Context pointer for the work (work->ctx in cb())
5918 * Returns: 0 on success, -1 on failure
5919 *
5920 * This function is used to request time for an operation that requires
5921 * exclusive radio control. Once the radio is available, the registered callback
5922 * function will be called. radio_work_done() must be called once the exclusive
5923 * radio operation has been completed, so that the radio is freed for other
5924 * operations. The special case of deinit=1 is used to free the context data
5925 * during interface removal. That does not allow the callback function to start
5926 * the radio operation, i.e., it must free any resources allocated for the radio
5927 * work and return.
5928 *
5929 * The @freq parameter can be used to indicate a single channel on which the
5930 * offchannel operation will occur. This may allow multiple radio work
5931 * operations to be performed in parallel if they apply for the same channel.
5932 * Setting this to 0 indicates that the work item may use multiple channels or
5933 * requires exclusive control of the radio.
5934 */
5935int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5936 const char *type, int next,
5937 void (*cb)(struct wpa_radio_work *work, int deinit),
5938 void *ctx)
5939{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005940 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005941 struct wpa_radio_work *work;
5942 int was_empty;
5943
5944 work = os_zalloc(sizeof(*work));
5945 if (work == NULL)
5946 return -1;
5947 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5948 os_get_reltime(&work->time);
5949 work->freq = freq;
5950 work->type = type;
5951 work->wpa_s = wpa_s;
5952 work->cb = cb;
5953 work->ctx = ctx;
5954
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005955 if (freq)
5956 work->bands = wpas_freq_to_band(freq);
5957 else if (os_strcmp(type, "scan") == 0 ||
5958 os_strcmp(type, "p2p-scan") == 0)
5959 work->bands = wpas_get_bands(wpa_s,
5960 ((struct wpa_driver_scan_params *)
5961 ctx)->freqs);
5962 else
5963 work->bands = wpas_get_bands(wpa_s, NULL);
5964
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005965 was_empty = dl_list_empty(&wpa_s->radio->work);
5966 if (next)
5967 dl_list_add(&wpa_s->radio->work, &work->list);
5968 else
5969 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5970 if (was_empty) {
5971 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5972 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005973 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5974 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5975 wpa_dbg(wpa_s, MSG_DEBUG,
5976 "Try to schedule a radio work (num_active_works=%u)",
5977 radio->num_active_works);
5978 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005979 }
5980
5981 return 0;
5982}
5983
5984
5985/**
5986 * radio_work_done - Indicate that a radio work item has been completed
5987 * @work: Completed work
5988 *
5989 * This function is called once the callback function registered with
5990 * radio_add_work() has completed its work.
5991 */
5992void radio_work_done(struct wpa_radio_work *work)
5993{
5994 struct wpa_supplicant *wpa_s = work->wpa_s;
5995 struct os_reltime now, diff;
5996 unsigned int started = work->started;
5997
5998 os_get_reltime(&now);
5999 os_reltime_sub(&now, &work->time, &diff);
6000 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
6001 work->type, work, started ? "done" : "canceled",
6002 diff.sec, diff.usec);
6003 radio_work_free(work);
6004 if (started)
6005 radio_work_check_next(wpa_s);
6006}
6007
6008
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006009struct wpa_radio_work *
6010radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006011{
6012 struct wpa_radio_work *work;
6013 struct wpa_radio *radio = wpa_s->radio;
6014
6015 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6016 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006017 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006018 }
6019
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006020 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006021}
6022
6023
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006024static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006025 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006026{
6027 const char *ifname, *driver, *rn;
6028
6029 driver = iface->driver;
6030next_driver:
6031 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6032 return -1;
6033
6034 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6035 if (wpa_s->drv_priv == NULL) {
6036 const char *pos;
6037 pos = driver ? os_strchr(driver, ',') : NULL;
6038 if (pos) {
6039 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6040 "driver interface - try next driver wrapper");
6041 driver = pos + 1;
6042 goto next_driver;
6043 }
6044 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
6045 "interface");
6046 return -1;
6047 }
6048 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6049 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6050 "driver_param '%s'", wpa_s->conf->driver_param);
6051 return -1;
6052 }
6053
6054 ifname = wpa_drv_get_ifname(wpa_s);
6055 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6056 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6057 "interface name with '%s'", ifname);
6058 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6059 }
6060
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006061 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006062 if (rn && rn[0] == '\0')
6063 rn = NULL;
6064
6065 wpa_s->radio = radio_add_interface(wpa_s, rn);
6066 if (wpa_s->radio == NULL)
6067 return -1;
6068
6069 return 0;
6070}
6071
6072
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006073#ifdef CONFIG_GAS_SERVER
6074
6075static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6076 unsigned int freq, const u8 *dst,
6077 const u8 *src, const u8 *bssid,
6078 const u8 *data, size_t data_len,
6079 enum offchannel_send_action_result result)
6080{
6081 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6082 " result=%s",
6083 freq, MAC2STR(dst),
6084 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6085 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6086 "FAILED"));
6087 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6088 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6089}
6090
6091
6092static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6093 struct wpabuf *buf, unsigned int wait_time)
6094{
6095 struct wpa_supplicant *wpa_s = ctx;
6096 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6097
6098 if (wait_time > wpa_s->max_remain_on_chan)
6099 wait_time = wpa_s->max_remain_on_chan;
6100
6101 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6102 wpabuf_head(buf), wpabuf_len(buf),
6103 wait_time, wpas_gas_server_tx_status, 0);
6104}
6105
6106#endif /* CONFIG_GAS_SERVER */
6107
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006108static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006109 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006110{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006111 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006112 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006113 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006114
6115 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6116 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6117 iface->confname ? iface->confname : "N/A",
6118 iface->driver ? iface->driver : "default",
6119 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6120 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6121
6122 if (iface->confname) {
6123#ifdef CONFIG_BACKEND_FILE
6124 wpa_s->confname = os_rel2abs_path(iface->confname);
6125 if (wpa_s->confname == NULL) {
6126 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6127 "for configuration file '%s'.",
6128 iface->confname);
6129 return -1;
6130 }
6131 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6132 iface->confname, wpa_s->confname);
6133#else /* CONFIG_BACKEND_FILE */
6134 wpa_s->confname = os_strdup(iface->confname);
6135#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006136 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006137 if (wpa_s->conf == NULL) {
6138 wpa_printf(MSG_ERROR, "Failed to read or parse "
6139 "configuration '%s'.", wpa_s->confname);
6140 return -1;
6141 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006142 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006143 if (wpa_s->confanother &&
6144 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6145 wpa_printf(MSG_ERROR,
6146 "Failed to read or parse configuration '%s'.",
6147 wpa_s->confanother);
6148 return -1;
6149 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006150
6151 /*
6152 * Override ctrl_interface and driver_param if set on command
6153 * line.
6154 */
6155 if (iface->ctrl_interface) {
6156 os_free(wpa_s->conf->ctrl_interface);
6157 wpa_s->conf->ctrl_interface =
6158 os_strdup(iface->ctrl_interface);
6159 }
6160
6161 if (iface->driver_param) {
6162 os_free(wpa_s->conf->driver_param);
6163 wpa_s->conf->driver_param =
6164 os_strdup(iface->driver_param);
6165 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006166
6167 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6168 os_free(wpa_s->conf->ctrl_interface);
6169 wpa_s->conf->ctrl_interface = NULL;
6170 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006171 } else
6172 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6173 iface->driver_param);
6174
6175 if (wpa_s->conf == NULL) {
6176 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6177 return -1;
6178 }
6179
6180 if (iface->ifname == NULL) {
6181 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6182 return -1;
6183 }
6184 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6185 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6186 iface->ifname);
6187 return -1;
6188 }
6189 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
6190
6191 if (iface->bridge_ifname) {
6192 if (os_strlen(iface->bridge_ifname) >=
6193 sizeof(wpa_s->bridge_ifname)) {
6194 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6195 "name '%s'.", iface->bridge_ifname);
6196 return -1;
6197 }
6198 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6199 sizeof(wpa_s->bridge_ifname));
6200 }
6201
6202 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006203 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6204 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006205
6206 /* Initialize driver interface and register driver event handler before
6207 * L2 receive handler so that association events are processed before
6208 * EAPOL-Key packets if both become available for the same select()
6209 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006210 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006211 return -1;
6212
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006213 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6214 return -1;
6215
6216 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6217 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6218 NULL);
6219 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6220
6221 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6222 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6223 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6224 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6225 "dot11RSNAConfigPMKLifetime");
6226 return -1;
6227 }
6228
6229 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6230 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6231 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6232 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6233 "dot11RSNAConfigPMKReauthThreshold");
6234 return -1;
6235 }
6236
6237 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6238 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6239 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6240 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6241 "dot11RSNAConfigSATimeout");
6242 return -1;
6243 }
6244
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006245 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6246 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006247 &wpa_s->hw.flags,
6248 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006249 if (wpa_s->hw.modes) {
6250 u16 i;
6251
6252 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6253 if (wpa_s->hw.modes[i].vht_capab) {
6254 wpa_s->hw_capab = CAPAB_VHT;
6255 break;
6256 }
6257
6258 if (wpa_s->hw.modes[i].ht_capab &
6259 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6260 wpa_s->hw_capab = CAPAB_HT40;
6261 else if (wpa_s->hw.modes[i].ht_capab &&
6262 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6263 wpa_s->hw_capab = CAPAB_HT;
6264 }
6265 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006266
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006267 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6268 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006269 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006270 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006271 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006272 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006273 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006274 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006275 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006276 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006277 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6278 wpa_s->max_sched_scan_plan_interval =
6279 capa.max_sched_scan_plan_interval;
6280 wpa_s->max_sched_scan_plan_iterations =
6281 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006282 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6283 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006284 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6285 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006286 wpa_s->extended_capa = capa.extended_capa;
6287 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6288 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006289 wpa_s->num_multichan_concurrent =
6290 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006291 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6292
6293 if (capa.mac_addr_rand_scan_supported)
6294 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6295 if (wpa_s->sched_scan_supported &&
6296 capa.mac_addr_rand_sched_scan_supported)
6297 wpa_s->mac_addr_rand_supported |=
6298 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006299
6300 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6301 if (wpa_s->extended_capa &&
6302 wpa_s->extended_capa_len >= 3 &&
6303 wpa_s->extended_capa[2] & 0x40)
6304 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006305 }
6306 if (wpa_s->max_remain_on_chan == 0)
6307 wpa_s->max_remain_on_chan = 1000;
6308
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006309 /*
6310 * Only take p2p_mgmt parameters when P2P Device is supported.
6311 * Doing it here as it determines whether l2_packet_init() will be done
6312 * during wpa_supplicant_driver_init().
6313 */
6314 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6315 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006316
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006317 if (wpa_s->num_multichan_concurrent == 0)
6318 wpa_s->num_multichan_concurrent = 1;
6319
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006320 if (wpa_supplicant_driver_init(wpa_s) < 0)
6321 return -1;
6322
6323#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006324 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006325 return -1;
6326#endif /* CONFIG_TDLS */
6327
6328 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6329 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6330 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6331 return -1;
6332 }
6333
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006334#ifdef CONFIG_FST
6335 if (wpa_s->conf->fst_group_id) {
6336 struct fst_iface_cfg cfg;
6337 struct fst_wpa_obj iface_obj;
6338
6339 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6340 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6341 sizeof(cfg.group_id));
6342 cfg.priority = wpa_s->conf->fst_priority;
6343 cfg.llt = wpa_s->conf->fst_llt;
6344
6345 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6346 &iface_obj, &cfg);
6347 if (!wpa_s->fst) {
6348 wpa_msg(wpa_s, MSG_ERROR,
6349 "FST: Cannot attach iface %s to group %s",
6350 wpa_s->ifname, cfg.group_id);
6351 return -1;
6352 }
6353 }
6354#endif /* CONFIG_FST */
6355
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006356 if (wpas_wps_init(wpa_s))
6357 return -1;
6358
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006359#ifdef CONFIG_GAS_SERVER
6360 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6361 if (!wpa_s->gas_server) {
6362 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6363 return -1;
6364 }
6365#endif /* CONFIG_GAS_SERVER */
6366
6367#ifdef CONFIG_DPP
6368 if (wpas_dpp_init(wpa_s) < 0)
6369 return -1;
6370#endif /* CONFIG_DPP */
6371
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006372 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6373 return -1;
6374 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6375
6376 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6377 if (wpa_s->ctrl_iface == NULL) {
6378 wpa_printf(MSG_ERROR,
6379 "Failed to initialize control interface '%s'.\n"
6380 "You may have another wpa_supplicant process "
6381 "already running or the file was\n"
6382 "left by an unclean termination of wpa_supplicant "
6383 "in which case you will need\n"
6384 "to manually remove this file before starting "
6385 "wpa_supplicant again.\n",
6386 wpa_s->conf->ctrl_interface);
6387 return -1;
6388 }
6389
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006390 wpa_s->gas = gas_query_init(wpa_s);
6391 if (wpa_s->gas == NULL) {
6392 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6393 return -1;
6394 }
6395
Roshan Pius3a1667e2018-07-03 15:17:14 -07006396 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6397 wpa_s->p2p_mgmt) &&
6398 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006399 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6400 return -1;
6401 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006402
6403 if (wpa_bss_init(wpa_s) < 0)
6404 return -1;
6405
Paul Stewart092955c2017-02-06 09:13:09 -08006406#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6407#ifdef CONFIG_MESH
6408 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6409#endif /* CONFIG_MESH */
6410#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6411
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006412 /*
6413 * Set Wake-on-WLAN triggers, if configured.
6414 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6415 * have effect anyway when the interface is down).
6416 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006417 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006418 return -1;
6419
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006420#ifdef CONFIG_EAP_PROXY
6421{
6422 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006423 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6424 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006425 if (wpa_s->mnc_len > 0) {
6426 wpa_s->imsi[len] = '\0';
6427 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6428 wpa_s->imsi, wpa_s->mnc_len);
6429 } else {
6430 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6431 }
6432}
6433#endif /* CONFIG_EAP_PROXY */
6434
Dmitry Shmidt04949592012-07-19 12:16:46 -07006435 if (pcsc_reader_init(wpa_s) < 0)
6436 return -1;
6437
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006438 if (wpas_init_ext_pw(wpa_s) < 0)
6439 return -1;
6440
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006441 wpas_rrm_reset(wpa_s);
6442
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006443 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6444
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006445#ifdef CONFIG_HS20
6446 hs20_init(wpa_s);
6447#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006448#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006449 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006450 if ((wpa_s->conf->oce & OCE_STA) &&
6451 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6452 wpa_s->enable_oce = OCE_STA;
6453 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6454 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6455 /* TODO: Need to add STA-CFON support */
6456 wpa_printf(MSG_ERROR,
6457 "OCE STA-CFON feature is not yet supported");
6458 }
6459 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006460 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6461#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006462
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006463 wpa_supplicant_set_default_scan_ies(wpa_s);
6464
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006465 return 0;
6466}
6467
6468
6469static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006470 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006471{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006472 struct wpa_global *global = wpa_s->global;
6473 struct wpa_supplicant *iface, *prev;
6474
6475 if (wpa_s == wpa_s->parent)
6476 wpas_p2p_group_remove(wpa_s, "*");
6477
6478 iface = global->ifaces;
6479 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006480 if (iface->p2pdev == wpa_s)
6481 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006482 if (iface == wpa_s || iface->parent != wpa_s) {
6483 iface = iface->next;
6484 continue;
6485 }
6486 wpa_printf(MSG_DEBUG,
6487 "Remove remaining child interface %s from parent %s",
6488 iface->ifname, wpa_s->ifname);
6489 prev = iface;
6490 iface = iface->next;
6491 wpa_supplicant_remove_iface(global, prev, terminate);
6492 }
6493
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006494 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006495 if (wpa_s->drv_priv) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006496 /* Don't deauthenticate if WoWLAN is enabled */
6497 if (!wpa_drv_get_wowlan(wpa_s)) {
6498 wpa_supplicant_deauthenticate(
6499 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006500
Hai Shalomfdcde762020-04-02 11:19:20 -07006501 wpa_drv_set_countermeasures(wpa_s, 0);
6502 wpa_clear_keys(wpa_s, NULL);
6503 } else {
6504 wpa_msg(wpa_s, MSG_INFO,
6505 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6506 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006507 }
6508
6509 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006510 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006511
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006512 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006513 radio_remove_interface(wpa_s);
6514
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006515#ifdef CONFIG_FST
6516 if (wpa_s->fst) {
6517 fst_detach(wpa_s->fst);
6518 wpa_s->fst = NULL;
6519 }
6520 if (wpa_s->received_mb_ies) {
6521 wpabuf_free(wpa_s->received_mb_ies);
6522 wpa_s->received_mb_ies = NULL;
6523 }
6524#endif /* CONFIG_FST */
6525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006526 if (wpa_s->drv_priv)
6527 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006528
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006529 if (notify)
6530 wpas_notify_iface_removed(wpa_s);
6531
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006532 if (terminate)
6533 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006534
6535 if (wpa_s->ctrl_iface) {
6536 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6537 wpa_s->ctrl_iface = NULL;
6538 }
6539
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006540#ifdef CONFIG_MESH
6541 if (wpa_s->ifmsh) {
6542 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6543 wpa_s->ifmsh = NULL;
6544 }
6545#endif /* CONFIG_MESH */
6546
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006547 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006548 wpa_config_free(wpa_s->conf);
6549 wpa_s->conf = NULL;
6550 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006551
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006552 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006553 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006554
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006555 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006556}
6557
6558
Dmitry Shmidte4663042016-04-04 10:07:49 -07006559#ifdef CONFIG_MATCH_IFACE
6560
6561/**
6562 * wpa_supplicant_match_iface - Match an interface description to a name
6563 * @global: Pointer to global data from wpa_supplicant_init()
6564 * @ifname: Name of the interface to match
6565 * Returns: Pointer to the created interface description or %NULL on failure
6566 */
6567struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6568 const char *ifname)
6569{
6570 int i;
6571 struct wpa_interface *iface, *miface;
6572
6573 for (i = 0; i < global->params.match_iface_count; i++) {
6574 miface = &global->params.match_ifaces[i];
6575 if (!miface->ifname ||
6576 fnmatch(miface->ifname, ifname, 0) == 0) {
6577 iface = os_zalloc(sizeof(*iface));
6578 if (!iface)
6579 return NULL;
6580 *iface = *miface;
6581 iface->ifname = ifname;
6582 return iface;
6583 }
6584 }
6585
6586 return NULL;
6587}
6588
6589
6590/**
6591 * wpa_supplicant_match_existing - Match existing interfaces
6592 * @global: Pointer to global data from wpa_supplicant_init()
6593 * Returns: 0 on success, -1 on failure
6594 */
6595static int wpa_supplicant_match_existing(struct wpa_global *global)
6596{
6597 struct if_nameindex *ifi, *ifp;
6598 struct wpa_supplicant *wpa_s;
6599 struct wpa_interface *iface;
6600
6601 ifp = if_nameindex();
6602 if (!ifp) {
6603 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6604 return -1;
6605 }
6606
6607 for (ifi = ifp; ifi->if_name; ifi++) {
6608 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6609 if (wpa_s)
6610 continue;
6611 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6612 if (iface) {
6613 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6614 os_free(iface);
6615 if (wpa_s)
6616 wpa_s->matched = 1;
6617 }
6618 }
6619
6620 if_freenameindex(ifp);
6621 return 0;
6622}
6623
6624#endif /* CONFIG_MATCH_IFACE */
6625
6626
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006627/**
6628 * wpa_supplicant_add_iface - Add a new network interface
6629 * @global: Pointer to global data from wpa_supplicant_init()
6630 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006631 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006632 * Returns: Pointer to the created interface or %NULL on failure
6633 *
6634 * This function is used to add new network interfaces for %wpa_supplicant.
6635 * This can be called before wpa_supplicant_run() to add interfaces before the
6636 * main event loop has been started. In addition, new interfaces can be added
6637 * dynamically while %wpa_supplicant is already running. This could happen,
6638 * e.g., when a hotplug network adapter is inserted.
6639 */
6640struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006641 struct wpa_interface *iface,
6642 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006643{
6644 struct wpa_supplicant *wpa_s;
6645 struct wpa_interface t_iface;
6646 struct wpa_ssid *ssid;
6647
6648 if (global == NULL || iface == NULL)
6649 return NULL;
6650
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006651 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006652 if (wpa_s == NULL)
6653 return NULL;
6654
6655 wpa_s->global = global;
6656
6657 t_iface = *iface;
6658 if (global->params.override_driver) {
6659 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6660 "('%s' -> '%s')",
6661 iface->driver, global->params.override_driver);
6662 t_iface.driver = global->params.override_driver;
6663 }
6664 if (global->params.override_ctrl_interface) {
6665 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6666 "ctrl_interface ('%s' -> '%s')",
6667 iface->ctrl_interface,
6668 global->params.override_ctrl_interface);
6669 t_iface.ctrl_interface =
6670 global->params.override_ctrl_interface;
6671 }
6672 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6673 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6674 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006675 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006676 return NULL;
6677 }
6678
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006679 /* Notify the control interfaces about new iface */
6680 if (wpas_notify_iface_added(wpa_s)) {
6681 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6682 return NULL;
6683 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006684
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006685 /* Notify the control interfaces about new networks for non p2p mgmt
6686 * ifaces. */
6687 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006688 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6689 wpas_notify_network_added(wpa_s, ssid);
6690 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006691
6692 wpa_s->next = global->ifaces;
6693 global->ifaces = wpa_s;
6694
6695 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006696 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006697
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006698#ifdef CONFIG_P2P
6699 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006700 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006701 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006702 wpas_p2p_add_p2pdev_interface(
6703 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006704 wpa_printf(MSG_INFO,
6705 "P2P: Failed to enable P2P Device interface");
6706 /* Try to continue without. P2P will be disabled. */
6707 }
6708#endif /* CONFIG_P2P */
6709
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006710 return wpa_s;
6711}
6712
6713
6714/**
6715 * wpa_supplicant_remove_iface - Remove a network interface
6716 * @global: Pointer to global data from wpa_supplicant_init()
6717 * @wpa_s: Pointer to the network interface to be removed
6718 * Returns: 0 if interface was removed, -1 if interface was not found
6719 *
6720 * This function can be used to dynamically remove network interfaces from
6721 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6722 * addition, this function is used to remove all remaining interfaces when
6723 * %wpa_supplicant is terminated.
6724 */
6725int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006726 struct wpa_supplicant *wpa_s,
6727 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006728{
6729 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006730#ifdef CONFIG_MESH
6731 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6732 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006733 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006734#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006735
6736 /* Remove interface from the global list of interfaces */
6737 prev = global->ifaces;
6738 if (prev == wpa_s) {
6739 global->ifaces = wpa_s->next;
6740 } else {
6741 while (prev && prev->next != wpa_s)
6742 prev = prev->next;
6743 if (prev == NULL)
6744 return -1;
6745 prev->next = wpa_s->next;
6746 }
6747
6748 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6749
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006750#ifdef CONFIG_MESH
6751 if (mesh_if_created) {
6752 ifname = os_strdup(wpa_s->ifname);
6753 if (ifname == NULL) {
6754 wpa_dbg(wpa_s, MSG_ERROR,
6755 "mesh: Failed to malloc ifname");
6756 return -1;
6757 }
6758 }
6759#endif /* CONFIG_MESH */
6760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006761 if (global->p2p_group_formation == wpa_s)
6762 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006763 if (global->p2p_invite_group == wpa_s)
6764 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006765 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006766
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006767#ifdef CONFIG_MESH
6768 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006769 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006770 os_free(ifname);
6771 }
6772#endif /* CONFIG_MESH */
6773
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006774 return 0;
6775}
6776
6777
6778/**
6779 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6780 * @wpa_s: Pointer to the network interface
6781 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6782 */
6783const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6784{
6785 const char *eapol_method;
6786
6787 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6788 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6789 return "NO-EAP";
6790 }
6791
6792 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6793 if (eapol_method == NULL)
6794 return "UNKNOWN-EAP";
6795
6796 return eapol_method;
6797}
6798
6799
6800/**
6801 * wpa_supplicant_get_iface - Get a new network interface
6802 * @global: Pointer to global data from wpa_supplicant_init()
6803 * @ifname: Interface name
6804 * Returns: Pointer to the interface or %NULL if not found
6805 */
6806struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6807 const char *ifname)
6808{
6809 struct wpa_supplicant *wpa_s;
6810
6811 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6812 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6813 return wpa_s;
6814 }
6815 return NULL;
6816}
6817
6818
6819#ifndef CONFIG_NO_WPA_MSG
6820static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6821{
6822 struct wpa_supplicant *wpa_s = ctx;
6823 if (wpa_s == NULL)
6824 return NULL;
6825 return wpa_s->ifname;
6826}
6827#endif /* CONFIG_NO_WPA_MSG */
6828
6829
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006830#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6831#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6832#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6833
6834/* Periodic cleanup tasks */
6835static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6836{
6837 struct wpa_global *global = eloop_ctx;
6838 struct wpa_supplicant *wpa_s;
6839
6840 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6841 wpas_periodic, global, NULL);
6842
6843#ifdef CONFIG_P2P
6844 if (global->p2p)
6845 p2p_expire_peers(global->p2p);
6846#endif /* CONFIG_P2P */
6847
6848 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6849 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6850#ifdef CONFIG_AP
6851 ap_periodic(wpa_s);
6852#endif /* CONFIG_AP */
6853 }
6854}
6855
6856
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006857/**
6858 * wpa_supplicant_init - Initialize %wpa_supplicant
6859 * @params: Parameters for %wpa_supplicant
6860 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6861 *
6862 * This function is used to initialize %wpa_supplicant. After successful
6863 * initialization, the returned data pointer can be used to add and remove
6864 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6865 */
6866struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6867{
6868 struct wpa_global *global;
6869 int ret, i;
6870
6871 if (params == NULL)
6872 return NULL;
6873
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006874#ifdef CONFIG_DRIVER_NDIS
6875 {
6876 void driver_ndis_init_ops(void);
6877 driver_ndis_init_ops();
6878 }
6879#endif /* CONFIG_DRIVER_NDIS */
6880
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006881#ifndef CONFIG_NO_WPA_MSG
6882 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6883#endif /* CONFIG_NO_WPA_MSG */
6884
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006885 if (params->wpa_debug_file_path)
6886 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07006887 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006888 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006889 if (params->wpa_debug_syslog)
6890 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006891 if (params->wpa_debug_tracing) {
6892 ret = wpa_debug_open_linux_tracing();
6893 if (ret) {
6894 wpa_printf(MSG_ERROR,
6895 "Failed to enable trace logging");
6896 return NULL;
6897 }
6898 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006899
6900 ret = eap_register_methods();
6901 if (ret) {
6902 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6903 if (ret == -2)
6904 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6905 "the same EAP type.");
6906 return NULL;
6907 }
6908
6909 global = os_zalloc(sizeof(*global));
6910 if (global == NULL)
6911 return NULL;
6912 dl_list_init(&global->p2p_srv_bonjour);
6913 dl_list_init(&global->p2p_srv_upnp);
6914 global->params.daemonize = params->daemonize;
6915 global->params.wait_for_monitor = params->wait_for_monitor;
6916 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6917 if (params->pid_file)
6918 global->params.pid_file = os_strdup(params->pid_file);
6919 if (params->ctrl_interface)
6920 global->params.ctrl_interface =
6921 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006922 if (params->ctrl_interface_group)
6923 global->params.ctrl_interface_group =
6924 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006925 if (params->override_driver)
6926 global->params.override_driver =
6927 os_strdup(params->override_driver);
6928 if (params->override_ctrl_interface)
6929 global->params.override_ctrl_interface =
6930 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006931#ifdef CONFIG_MATCH_IFACE
6932 global->params.match_iface_count = params->match_iface_count;
6933 if (params->match_iface_count) {
6934 global->params.match_ifaces =
6935 os_calloc(params->match_iface_count,
6936 sizeof(struct wpa_interface));
6937 os_memcpy(global->params.match_ifaces,
6938 params->match_ifaces,
6939 params->match_iface_count *
6940 sizeof(struct wpa_interface));
6941 }
6942#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006943#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006944 if (params->conf_p2p_dev)
6945 global->params.conf_p2p_dev =
6946 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006947#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006948 wpa_debug_level = global->params.wpa_debug_level =
6949 params->wpa_debug_level;
6950 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6951 params->wpa_debug_show_keys;
6952 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6953 params->wpa_debug_timestamp;
6954
Hai Shalomfdcde762020-04-02 11:19:20 -07006955 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006956
6957 if (eloop_init()) {
6958 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6959 wpa_supplicant_deinit(global);
6960 return NULL;
6961 }
6962
Jouni Malinen75ecf522011-06-27 15:19:46 -07006963 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006964
6965 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6966 if (global->ctrl_iface == NULL) {
6967 wpa_supplicant_deinit(global);
6968 return NULL;
6969 }
6970
6971 if (wpas_notify_supplicant_initialized(global)) {
6972 wpa_supplicant_deinit(global);
6973 return NULL;
6974 }
6975
6976 for (i = 0; wpa_drivers[i]; i++)
6977 global->drv_count++;
6978 if (global->drv_count == 0) {
6979 wpa_printf(MSG_ERROR, "No drivers enabled");
6980 wpa_supplicant_deinit(global);
6981 return NULL;
6982 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006983 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006984 if (global->drv_priv == NULL) {
6985 wpa_supplicant_deinit(global);
6986 return NULL;
6987 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006988
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006989#ifdef CONFIG_WIFI_DISPLAY
6990 if (wifi_display_init(global) < 0) {
6991 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6992 wpa_supplicant_deinit(global);
6993 return NULL;
6994 }
6995#endif /* CONFIG_WIFI_DISPLAY */
6996
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006997 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6998 wpas_periodic, global, NULL);
6999
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007000 return global;
7001}
7002
7003
7004/**
7005 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7006 * @global: Pointer to global data from wpa_supplicant_init()
7007 * Returns: 0 after successful event loop run, -1 on failure
7008 *
7009 * This function starts the main event loop and continues running as long as
7010 * there are any remaining events. In most cases, this function is running as
7011 * long as the %wpa_supplicant process in still in use.
7012 */
7013int wpa_supplicant_run(struct wpa_global *global)
7014{
7015 struct wpa_supplicant *wpa_s;
7016
7017 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007018 (wpa_supplicant_daemon(global->params.pid_file) ||
7019 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007020 return -1;
7021
Dmitry Shmidte4663042016-04-04 10:07:49 -07007022#ifdef CONFIG_MATCH_IFACE
7023 if (wpa_supplicant_match_existing(global))
7024 return -1;
7025#endif
7026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007027 if (global->params.wait_for_monitor) {
7028 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007029 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007030 wpa_supplicant_ctrl_iface_wait(
7031 wpa_s->ctrl_iface);
7032 }
7033
7034 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7035 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7036
7037 eloop_run();
7038
7039 return 0;
7040}
7041
7042
7043/**
7044 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7045 * @global: Pointer to global data from wpa_supplicant_init()
7046 *
7047 * This function is called to deinitialize %wpa_supplicant and to free all
7048 * allocated resources. Remaining network interfaces will also be removed.
7049 */
7050void wpa_supplicant_deinit(struct wpa_global *global)
7051{
7052 int i;
7053
7054 if (global == NULL)
7055 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007056
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007057 eloop_cancel_timeout(wpas_periodic, global, NULL);
7058
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007059#ifdef CONFIG_WIFI_DISPLAY
7060 wifi_display_deinit(global);
7061#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007062
7063 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007064 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007065
7066 if (global->ctrl_iface)
7067 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7068
7069 wpas_notify_supplicant_deinitialized(global);
7070
7071 eap_peer_unregister_methods();
7072#ifdef CONFIG_AP
7073 eap_server_unregister_methods();
7074#endif /* CONFIG_AP */
7075
7076 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7077 if (!global->drv_priv[i])
7078 continue;
7079 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7080 }
7081 os_free(global->drv_priv);
7082
7083 random_deinit();
7084
7085 eloop_destroy();
7086
7087 if (global->params.pid_file) {
7088 os_daemonize_terminate(global->params.pid_file);
7089 os_free(global->params.pid_file);
7090 }
7091 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007092 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007093 os_free(global->params.override_driver);
7094 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007095#ifdef CONFIG_MATCH_IFACE
7096 os_free(global->params.match_ifaces);
7097#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007098#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007099 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007100#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007101
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007102 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007103 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007104 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007105
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007106 os_free(global);
7107 wpa_debug_close_syslog();
7108 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007109 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007110}
7111
7112
7113void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7114{
7115 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7116 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7117 char country[3];
7118 country[0] = wpa_s->conf->country[0];
7119 country[1] = wpa_s->conf->country[1];
7120 country[2] = '\0';
7121 if (wpa_drv_set_country(wpa_s, country) < 0) {
7122 wpa_printf(MSG_ERROR, "Failed to set country code "
7123 "'%s'", country);
7124 }
7125 }
7126
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007127 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7128 wpas_init_ext_pw(wpa_s);
7129
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007130 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7131 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7132
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007133 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7134 struct wpa_driver_capa capa;
7135 int res = wpa_drv_get_capa(wpa_s, &capa);
7136
7137 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7138 wpa_printf(MSG_ERROR,
7139 "Failed to update wowlan_triggers to '%s'",
7140 wpa_s->conf->wowlan_triggers);
7141 }
7142
Hai Shalom81f62d82019-07-22 12:10:00 -07007143 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7144 wpa_supplicant_set_default_scan_ies(wpa_s);
7145
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007146#ifdef CONFIG_WPS
7147 wpas_wps_update_config(wpa_s);
7148#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007149 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007150 wpa_s->conf->changed_parameters = 0;
7151}
7152
7153
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007154void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007155{
7156 int i;
7157
7158 for (i = 0; i < *num_freqs; i++) {
7159 if (freqs[i] == freq)
7160 return;
7161 }
7162
7163 freqs[*num_freqs] = freq;
7164 (*num_freqs)++;
7165}
7166
7167
7168static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7169{
7170 struct wpa_bss *bss, *cbss;
7171 const int max_freqs = 10;
7172 int *freqs;
7173 int num_freqs = 0;
7174
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007175 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007176 if (freqs == NULL)
7177 return NULL;
7178
7179 cbss = wpa_s->current_bss;
7180
7181 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7182 if (bss == cbss)
7183 continue;
7184 if (bss->ssid_len == cbss->ssid_len &&
7185 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
7186 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
7187 add_freq(freqs, &num_freqs, bss->freq);
7188 if (num_freqs == max_freqs)
7189 break;
7190 }
7191 }
7192
7193 if (num_freqs == 0) {
7194 os_free(freqs);
7195 freqs = NULL;
7196 }
7197
7198 return freqs;
7199}
7200
7201
7202void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7203{
7204 int timeout;
7205 int count;
7206 int *freqs = NULL;
7207
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007208 wpas_connect_work_done(wpa_s);
7209
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007210 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007211 * Remove possible authentication timeout since the connection failed.
7212 */
7213 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7214
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007215 /*
7216 * There is no point in blacklisting the AP if this event is
7217 * generated based on local request to disconnect.
7218 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007219 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007220 wpa_s->own_disconnect_req = 0;
7221 wpa_dbg(wpa_s, MSG_DEBUG,
7222 "Ignore connection failure due to local request to disconnect");
7223 return;
7224 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007225 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007226 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7227 "indication since interface has been put into "
7228 "disconnected state");
7229 return;
7230 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007231 if (wpa_s->auto_reconnect_disabled) {
7232 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7233 "indication since auto connect is disabled");
7234 return;
7235 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007236
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007237 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007238 * Add the failed BSSID into the blacklist and speed up next scan
7239 * attempt if there could be other APs that could accept association.
7240 * The current blacklist count indicates how many times we have tried
7241 * connecting to this AP and multiple attempts mean that other APs are
7242 * either not available or has already been tried, so that we can start
7243 * increasing the delay here to avoid constant scanning.
7244 */
7245 count = wpa_blacklist_add(wpa_s, bssid);
7246 if (count == 1 && wpa_s->current_bss) {
7247 /*
7248 * This BSS was not in the blacklist before. If there is
7249 * another BSS available for the same ESS, we should try that
7250 * next. Otherwise, we may as well try this one once more
7251 * before allowing other, likely worse, ESSes to be considered.
7252 */
7253 freqs = get_bss_freqs_in_ess(wpa_s);
7254 if (freqs) {
7255 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7256 "has been seen; try it next");
7257 wpa_blacklist_add(wpa_s, bssid);
7258 /*
7259 * On the next scan, go through only the known channels
7260 * used in this ESS based on previous scans to speed up
7261 * common load balancing use case.
7262 */
7263 os_free(wpa_s->next_scan_freqs);
7264 wpa_s->next_scan_freqs = freqs;
7265 }
7266 }
7267
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007268 /*
7269 * Add previous failure count in case the temporary blacklist was
7270 * cleared due to no other BSSes being available.
7271 */
7272 count += wpa_s->extra_blacklist_count;
7273
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007274 if (count > 3 && wpa_s->current_ssid) {
7275 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7276 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007277 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007278 }
7279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007280 switch (count) {
7281 case 1:
7282 timeout = 100;
7283 break;
7284 case 2:
7285 timeout = 500;
7286 break;
7287 case 3:
7288 timeout = 1000;
7289 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007290 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007291 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007292 break;
7293 default:
7294 timeout = 10000;
7295 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007296 }
7297
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007298 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
7299 "ms", count, timeout);
7300
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007301 /*
7302 * TODO: if more than one possible AP is available in scan results,
7303 * could try the other ones before requesting a new scan.
7304 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007305
7306 /* speed up the connection attempt with normal scan */
7307 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007308 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7309 1000 * (timeout % 1000));
7310}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007311
7312
Hai Shalomce48b4a2018-09-05 11:41:35 -07007313#ifdef CONFIG_FILS
7314void fils_connection_failure(struct wpa_supplicant *wpa_s)
7315{
7316 struct wpa_ssid *ssid = wpa_s->current_ssid;
7317 const u8 *realm, *username, *rrk;
7318 size_t realm_len, username_len, rrk_len;
7319 u16 next_seq_num;
7320
7321 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7322 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7323 &username, &username_len,
7324 &realm, &realm_len, &next_seq_num,
7325 &rrk, &rrk_len) != 0 ||
7326 !realm)
7327 return;
7328
7329 wpa_hexdump_ascii(MSG_DEBUG,
7330 "FILS: Store last connection failure realm",
7331 realm, realm_len);
7332 os_free(wpa_s->last_con_fail_realm);
7333 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7334 if (wpa_s->last_con_fail_realm) {
7335 wpa_s->last_con_fail_realm_len = realm_len;
7336 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7337 }
7338}
7339#endif /* CONFIG_FILS */
7340
7341
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007342int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7343{
7344 return wpa_s->conf->ap_scan == 2 ||
7345 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7346}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007347
Dmitry Shmidt04949592012-07-19 12:16:46 -07007348
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007349#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007350int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7351 struct wpa_ssid *ssid,
7352 const char *field,
7353 const char *value)
7354{
7355#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007356 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007357
7358 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7359 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7360 (const u8 *) value, os_strlen(value));
7361
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007362 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007363 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007364#else /* IEEE8021X_EAPOL */
7365 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7366 return -1;
7367#endif /* IEEE8021X_EAPOL */
7368}
7369
7370int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7371 struct wpa_ssid *ssid,
7372 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007373 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007374{
7375#ifdef IEEE8021X_EAPOL
7376 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007377 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007378
7379 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007380 case WPA_CTRL_REQ_EAP_IDENTITY:
7381 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007382 os_free(eap->imsi_identity);
7383 if (value == NULL)
7384 return -1;
7385 identity = os_strchr(value, ':');
7386 if (identity == NULL) {
7387 /* plain identity */
7388 eap->identity = (u8 *)os_strdup(value);
7389 eap->identity_len = os_strlen(value);
7390 } else {
7391 /* have both plain identity and encrypted identity */
7392 imsi_identity = value;
7393 *identity++ = '\0';
7394 /* plain identity */
7395 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7396 eap->imsi_identity_len = strlen(imsi_identity);
7397 /* encrypted identity */
7398 eap->identity = (u8 *)dup_binstr(identity,
7399 value_len - strlen(imsi_identity) - 1);
7400 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7401 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007402 eap->pending_req_identity = 0;
7403 if (ssid == wpa_s->current_ssid)
7404 wpa_s->reassociate = 1;
7405 break;
7406 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007407 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007408 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007409 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007410 eap->pending_req_password = 0;
7411 if (ssid == wpa_s->current_ssid)
7412 wpa_s->reassociate = 1;
7413 break;
7414 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007415 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007416 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007417 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007418 eap->pending_req_new_password = 0;
7419 if (ssid == wpa_s->current_ssid)
7420 wpa_s->reassociate = 1;
7421 break;
7422 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007423 str_clear_free(eap->cert.pin);
7424 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007425 eap->pending_req_pin = 0;
7426 if (ssid == wpa_s->current_ssid)
7427 wpa_s->reassociate = 1;
7428 break;
7429 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007430 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007431 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007432 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007433 os_free(eap->pending_req_otp);
7434 eap->pending_req_otp = NULL;
7435 eap->pending_req_otp_len = 0;
7436 break;
7437 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007438 str_clear_free(eap->cert.private_key_passwd);
7439 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007440 eap->pending_req_passphrase = 0;
7441 if (ssid == wpa_s->current_ssid)
7442 wpa_s->reassociate = 1;
7443 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007444 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007445 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007446 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007447 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007448 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007449 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7450 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7451 return -1;
7452 ssid->mem_only_psk = 1;
7453 if (ssid->passphrase)
7454 wpa_config_update_psk(ssid);
7455 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7456 wpa_supplicant_req_scan(wpa_s, 0, 0);
7457 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007458 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7459 if (eap->pending_ext_cert_check != PENDING_CHECK)
7460 return -1;
7461 if (os_strcmp(value, "good") == 0)
7462 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7463 else if (os_strcmp(value, "bad") == 0)
7464 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7465 else
7466 return -1;
7467 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007468 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007469 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007470 return -1;
7471 }
7472
7473 return 0;
7474#else /* IEEE8021X_EAPOL */
7475 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7476 return -1;
7477#endif /* IEEE8021X_EAPOL */
7478}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007479#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007480
7481
7482int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7483{
Hai Shalomfdcde762020-04-02 11:19:20 -07007484#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007485 int i;
7486 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007487#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007488
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007489 if (wpa_s->p2p_mgmt)
7490 return 1; /* no normal network profiles on p2p_mgmt interface */
7491
Dmitry Shmidt04949592012-07-19 12:16:46 -07007492 if (ssid == NULL)
7493 return 1;
7494
7495 if (ssid->disabled)
7496 return 1;
7497
Hai Shalomfdcde762020-04-02 11:19:20 -07007498#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007499 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007500 drv_enc = wpa_s->drv_enc;
7501 else
7502 drv_enc = (unsigned int) -1;
7503
7504 for (i = 0; i < NUM_WEP_KEYS; i++) {
7505 size_t len = ssid->wep_key_len[i];
7506 if (len == 0)
7507 continue;
7508 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7509 continue;
7510 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7511 continue;
7512 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7513 continue;
7514 return 1; /* invalid WEP key */
7515 }
Hai Shalomfdcde762020-04-02 11:19:20 -07007516#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007517
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007518 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007519 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007520 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007521 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007522 return 1;
7523
Dmitry Shmidt04949592012-07-19 12:16:46 -07007524 return 0;
7525}
7526
7527
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007528int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7529{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007530 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7531 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7532 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7533 /*
7534 * Driver does not support BIP -- ignore pmf=1 default
7535 * since the connection with PMF would fail and the
7536 * configuration does not require PMF to be enabled.
7537 */
7538 return NO_MGMT_FRAME_PROTECTION;
7539 }
7540
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007541 if (ssid &&
7542 (ssid->key_mgmt &
7543 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7544 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7545 /*
7546 * Do not use the default PMF value for non-RSN networks
7547 * since PMF is available only with RSN and pmf=2
7548 * configuration would otherwise prevent connections to
7549 * all open networks.
7550 */
7551 return NO_MGMT_FRAME_PROTECTION;
7552 }
7553
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007554 return wpa_s->conf->pmf;
7555 }
7556
7557 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007558}
7559
7560
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007561int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007562{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007563 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007564 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007565 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007566 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007567 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007568}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007569
7570
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007571void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007572{
7573 struct wpa_ssid *ssid = wpa_s->current_ssid;
7574 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007575 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007576
7577 if (ssid == NULL) {
7578 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7579 "SSID block");
7580 return;
7581 }
7582
7583 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7584 return;
7585
7586 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007587
7588#ifdef CONFIG_P2P
7589 if (ssid->p2p_group &&
7590 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7591 /*
7592 * Skip the wait time since there is a short timeout on the
7593 * connection to a P2P group.
7594 */
7595 return;
7596 }
7597#endif /* CONFIG_P2P */
7598
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007599 if (ssid->auth_failures > 50)
7600 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007601 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007602 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007603 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007604 dur = 90;
7605 else if (ssid->auth_failures > 3)
7606 dur = 60;
7607 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007608 dur = 30;
7609 else if (ssid->auth_failures > 1)
7610 dur = 20;
7611 else
7612 dur = 10;
7613
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007614 if (ssid->auth_failures > 1 &&
7615 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7616 dur += os_random() % (ssid->auth_failures * 10);
7617
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007618 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007619 if (now.sec + dur <= ssid->disabled_until.sec)
7620 return;
7621
7622 ssid->disabled_until.sec = now.sec + dur;
7623
7624 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007625 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007626 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007627 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007628}
7629
7630
7631void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7632 struct wpa_ssid *ssid, int clear_failures)
7633{
7634 if (ssid == NULL)
7635 return;
7636
7637 if (ssid->disabled_until.sec) {
7638 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7639 "id=%d ssid=\"%s\"",
7640 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7641 }
7642 ssid->disabled_until.sec = 0;
7643 ssid->disabled_until.usec = 0;
7644 if (clear_failures)
7645 ssid->auth_failures = 0;
7646}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007647
7648
7649int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7650{
7651 size_t i;
7652
7653 if (wpa_s->disallow_aps_bssid == NULL)
7654 return 0;
7655
7656 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7657 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7658 bssid, ETH_ALEN) == 0)
7659 return 1;
7660 }
7661
7662 return 0;
7663}
7664
7665
7666int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7667 size_t ssid_len)
7668{
7669 size_t i;
7670
7671 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7672 return 0;
7673
7674 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7675 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7676 if (ssid_len == s->ssid_len &&
7677 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7678 return 1;
7679 }
7680
7681 return 0;
7682}
7683
7684
7685/**
7686 * wpas_request_connection - Request a new connection
7687 * @wpa_s: Pointer to the network interface
7688 *
7689 * This function is used to request a new connection to be found. It will mark
7690 * the interface to allow reassociation and request a new scan to find a
7691 * suitable network to connect to.
7692 */
7693void wpas_request_connection(struct wpa_supplicant *wpa_s)
7694{
7695 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007696 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007697 wpa_supplicant_reinit_autoscan(wpa_s);
7698 wpa_s->extra_blacklist_count = 0;
7699 wpa_s->disconnected = 0;
7700 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007701 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007702
7703 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7704 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007705 else
7706 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007707}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007708
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007709
Roshan Pius02242d72016-08-09 15:31:48 -07007710/**
7711 * wpas_request_disconnection - Request disconnection
7712 * @wpa_s: Pointer to the network interface
7713 *
7714 * This function is used to request disconnection from the currently connected
7715 * network. This will stop any ongoing scans and initiate deauthentication.
7716 */
7717void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7718{
7719#ifdef CONFIG_SME
7720 wpa_s->sme.prev_bssid_set = 0;
7721#endif /* CONFIG_SME */
7722 wpa_s->reassociate = 0;
7723 wpa_s->disconnected = 1;
7724 wpa_supplicant_cancel_sched_scan(wpa_s);
7725 wpa_supplicant_cancel_scan(wpa_s);
7726 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7727 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007728 radio_remove_works(wpa_s, "connect", 0);
7729 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007730}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007731
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007732
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007733void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7734 struct wpa_used_freq_data *freqs_data,
7735 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007736{
7737 unsigned int i;
7738
7739 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7740 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007741 for (i = 0; i < len; i++) {
7742 struct wpa_used_freq_data *cur = &freqs_data[i];
7743 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7744 i, cur->freq, cur->flags);
7745 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007746}
7747
7748
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007749/*
7750 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007751 * are using the same radio as the current interface, and in addition, get
7752 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007753 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007754int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7755 struct wpa_used_freq_data *freqs_data,
7756 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007757{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007758 struct wpa_supplicant *ifs;
7759 u8 bssid[ETH_ALEN];
7760 int freq;
7761 unsigned int idx = 0, i;
7762
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007763 wpa_dbg(wpa_s, MSG_DEBUG,
7764 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007765 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007766
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007767 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7768 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007769 if (idx == len)
7770 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007771
7772 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7773 continue;
7774
7775 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007776 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7777 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007778 freq = ifs->current_ssid->frequency;
7779 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7780 freq = ifs->assoc_freq;
7781 else
7782 continue;
7783
7784 /* Hold only distinct freqs */
7785 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007786 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007787 break;
7788
7789 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007790 freqs_data[idx++].freq = freq;
7791
7792 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007793 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007794 WPA_FREQ_USED_BY_P2P_CLIENT :
7795 WPA_FREQ_USED_BY_INFRA_STATION;
7796 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007797 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007798
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007799 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007800 return idx;
7801}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007802
7803
7804/*
7805 * Find the operating frequencies of any of the virtual interfaces that
7806 * are using the same radio as the current interface.
7807 */
7808int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7809 int *freq_array, unsigned int len)
7810{
7811 struct wpa_used_freq_data *freqs_data;
7812 int num, i;
7813
7814 os_memset(freq_array, 0, sizeof(int) * len);
7815
7816 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7817 if (!freqs_data)
7818 return -1;
7819
7820 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7821 for (i = 0; i < num; i++)
7822 freq_array[i] = freqs_data[i].freq;
7823
7824 os_free(freqs_data);
7825
7826 return num;
7827}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007828
7829
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007830struct wpa_supplicant *
7831wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7832{
7833 switch (frame) {
7834#ifdef CONFIG_P2P
7835 case VENDOR_ELEM_PROBE_REQ_P2P:
7836 case VENDOR_ELEM_PROBE_RESP_P2P:
7837 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7838 case VENDOR_ELEM_BEACON_P2P_GO:
7839 case VENDOR_ELEM_P2P_PD_REQ:
7840 case VENDOR_ELEM_P2P_PD_RESP:
7841 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7842 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7843 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7844 case VENDOR_ELEM_P2P_INV_REQ:
7845 case VENDOR_ELEM_P2P_INV_RESP:
7846 case VENDOR_ELEM_P2P_ASSOC_REQ:
7847 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007848 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007849#endif /* CONFIG_P2P */
7850 default:
7851 return wpa_s;
7852 }
7853}
7854
7855
7856void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7857{
7858 unsigned int i;
7859 char buf[30];
7860
7861 wpa_printf(MSG_DEBUG, "Update vendor elements");
7862
7863 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7864 if (wpa_s->vendor_elem[i]) {
7865 int res;
7866
7867 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7868 if (!os_snprintf_error(sizeof(buf), res)) {
7869 wpa_hexdump_buf(MSG_DEBUG, buf,
7870 wpa_s->vendor_elem[i]);
7871 }
7872 }
7873 }
7874
7875#ifdef CONFIG_P2P
7876 if (wpa_s->parent == wpa_s &&
7877 wpa_s->global->p2p &&
7878 !wpa_s->global->p2p_disabled)
7879 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7880#endif /* CONFIG_P2P */
7881}
7882
7883
7884int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7885 const u8 *elem, size_t len)
7886{
7887 u8 *ie, *end;
7888
7889 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7890 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7891
7892 for (; ie + 1 < end; ie += 2 + ie[1]) {
7893 if (ie + len > end)
7894 break;
7895 if (os_memcmp(ie, elem, len) != 0)
7896 continue;
7897
7898 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7899 wpabuf_free(wpa_s->vendor_elem[frame]);
7900 wpa_s->vendor_elem[frame] = NULL;
7901 } else {
7902 os_memmove(ie, ie + len, end - (ie + len));
7903 wpa_s->vendor_elem[frame]->used -= len;
7904 }
7905 wpas_vendor_elem_update(wpa_s);
7906 return 0;
7907 }
7908
7909 return -1;
7910}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007911
7912
7913struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07007914 u16 num_modes, enum hostapd_hw_mode mode,
7915 int is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007916{
7917 u16 i;
7918
7919 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007920 if (modes[i].mode != mode ||
7921 !modes[i].num_channels || !modes[i].channels)
7922 continue;
7923 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
7924 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007925 return &modes[i];
7926 }
7927
7928 return NULL;
7929}
7930
7931
7932static struct
7933wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7934 const u8 *bssid)
7935{
7936 struct wpa_bss_tmp_disallowed *bss;
7937
7938 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7939 struct wpa_bss_tmp_disallowed, list) {
7940 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7941 return bss;
7942 }
7943
7944 return NULL;
7945}
7946
7947
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007948static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7949{
7950 struct wpa_bss_tmp_disallowed *tmp;
7951 unsigned int num_bssid = 0;
7952 u8 *bssids;
7953 int ret;
7954
7955 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7956 if (!bssids)
7957 return -1;
7958 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7959 struct wpa_bss_tmp_disallowed, list) {
7960 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7961 ETH_ALEN);
7962 num_bssid++;
7963 }
7964 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7965 os_free(bssids);
7966 return ret;
7967}
7968
7969
7970static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7971{
7972 struct wpa_supplicant *wpa_s = eloop_ctx;
7973 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7974
7975 /* Make sure the bss is not already freed */
7976 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7977 struct wpa_bss_tmp_disallowed, list) {
7978 if (bss == tmp) {
7979 dl_list_del(&tmp->list);
7980 os_free(tmp);
7981 wpa_set_driver_tmp_disallow_list(wpa_s);
7982 break;
7983 }
7984 }
7985}
7986
7987
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007988void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08007989 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007990{
7991 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007992
7993 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7994 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007995 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08007996 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007997 }
7998
7999 bss = os_malloc(sizeof(*bss));
8000 if (!bss) {
8001 wpa_printf(MSG_DEBUG,
8002 "Failed to allocate memory for temp disallow BSS");
8003 return;
8004 }
8005
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008006 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8007 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008008 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008009
8010finish:
8011 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008012 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8013 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008014}
8015
8016
Hai Shalom74f70d42019-02-11 14:42:39 -08008017int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8018 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008019{
Hai Shalom74f70d42019-02-11 14:42:39 -08008020 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008021
8022 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8023 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008024 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8025 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008026 break;
8027 }
8028 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008029 if (!disallowed)
8030 return 0;
8031
8032 if (disallowed->rssi_threshold != 0 &&
8033 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008034 return 0;
8035
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008036 return 1;
8037}
Hai Shalom81f62d82019-07-22 12:10:00 -07008038
8039
8040int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8041 unsigned int type, const u8 *addr,
8042 const u8 *mask)
8043{
8044 if ((addr && !mask) || (!addr && mask)) {
8045 wpa_printf(MSG_INFO,
8046 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8047 return -1;
8048 }
8049
8050 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8051 wpa_printf(MSG_INFO,
8052 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8053 return -1;
8054 }
8055
8056 if (type & MAC_ADDR_RAND_SCAN) {
8057 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8058 addr, mask))
8059 return -1;
8060 }
8061
8062 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8063 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8064 addr, mask))
8065 return -1;
8066
8067 if (wpa_s->sched_scanning && !wpa_s->pno)
8068 wpas_scan_restart_sched_scan(wpa_s);
8069 }
8070
8071 if (type & MAC_ADDR_RAND_PNO) {
8072 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8073 addr, mask))
8074 return -1;
8075
8076 if (wpa_s->pno) {
8077 wpas_stop_pno(wpa_s);
8078 wpas_start_pno(wpa_s);
8079 }
8080 }
8081
8082 return 0;
8083}
8084
8085
8086int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8087 unsigned int type)
8088{
8089 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8090 if (wpa_s->pno) {
8091 if (type & MAC_ADDR_RAND_PNO) {
8092 wpas_stop_pno(wpa_s);
8093 wpas_start_pno(wpa_s);
8094 }
8095 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8096 wpas_scan_restart_sched_scan(wpa_s);
8097 }
8098
8099 return 0;
8100}
Hai Shalomfdcde762020-04-02 11:19:20 -07008101
8102
8103int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8104 struct wpa_signal_info *si)
8105{
8106 int res;
8107
8108 if (!wpa_s->driver->signal_poll)
8109 return -1;
8110
8111 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8112
8113#ifdef CONFIG_TESTING_OPTIONS
8114 if (res == 0) {
8115 struct driver_signal_override *dso;
8116
8117 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8118 struct driver_signal_override, list) {
8119 if (os_memcmp(wpa_s->bssid, dso->bssid,
8120 ETH_ALEN) != 0)
8121 continue;
8122 wpa_printf(MSG_DEBUG,
8123 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8124 si->current_signal,
8125 dso->si_current_signal,
8126 si->avg_signal,
8127 dso->si_avg_signal,
8128 si->avg_beacon_signal,
8129 dso->si_avg_beacon_signal,
8130 si->current_noise,
8131 dso->si_current_noise);
8132 si->current_signal = dso->si_current_signal;
8133 si->avg_signal = dso->si_avg_signal;
8134 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8135 si->current_noise = dso->si_current_noise;
8136 break;
8137 }
8138 }
8139#endif /* CONFIG_TESTING_OPTIONS */
8140
8141 return res;
8142}
8143
8144
8145struct wpa_scan_results *
8146wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8147{
8148 struct wpa_scan_results *scan_res;
8149#ifdef CONFIG_TESTING_OPTIONS
8150 size_t idx;
8151#endif /* CONFIG_TESTING_OPTIONS */
8152
8153 if (!wpa_s->driver->get_scan_results2)
8154 return NULL;
8155
8156 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8157
8158#ifdef CONFIG_TESTING_OPTIONS
8159 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8160 struct driver_signal_override *dso;
8161 struct wpa_scan_res *res = scan_res->res[idx];
8162
8163 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8164 struct driver_signal_override, list) {
8165 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8166 continue;
8167 wpa_printf(MSG_DEBUG,
8168 "Override driver scan signal level %d->%d for "
8169 MACSTR,
8170 res->level, dso->scan_level,
8171 MAC2STR(res->bssid));
8172 res->flags |= WPA_SCAN_QUAL_INVALID;
8173 if (dso->scan_level < 0)
8174 res->flags |= WPA_SCAN_LEVEL_DBM;
8175 else
8176 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8177 res->level = dso->scan_level;
8178 break;
8179 }
8180 }
8181#endif /* CONFIG_TESTING_OPTIONS */
8182
8183 return scan_res;
8184}