blob: e14bffd159f06844a2bf5fe13fc2c59dcd6b9551 [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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700133/* Configure default/group WEP keys for static WEP */
134int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
135{
136 int i, set = 0;
137
138 for (i = 0; i < NUM_WEP_KEYS; i++) {
139 if (ssid->wep_key_len[i] == 0)
140 continue;
141
142 set = 1;
143 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
144 i, i == ssid->wep_tx_keyidx, NULL, 0,
145 ssid->wep_key[i], ssid->wep_key_len[i]);
146 }
147
148 return set;
149}
150
151
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700152int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
153 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700154{
155 u8 key[32];
156 size_t keylen;
157 enum wpa_alg alg;
158 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800159 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160
161 /* IBSS/WPA-None uses only one key (Group) for both receiving and
162 * sending unicast and multicast packets. */
163
164 if (ssid->mode != WPAS_MODE_IBSS) {
165 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
166 "IBSS/ad-hoc) for WPA-None", ssid->mode);
167 return -1;
168 }
169
170 if (!ssid->psk_set) {
171 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
172 "WPA-None");
173 return -1;
174 }
175
176 switch (wpa_s->group_cipher) {
177 case WPA_CIPHER_CCMP:
178 os_memcpy(key, ssid->psk, 16);
179 keylen = 16;
180 alg = WPA_ALG_CCMP;
181 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700182 case WPA_CIPHER_GCMP:
183 os_memcpy(key, ssid->psk, 16);
184 keylen = 16;
185 alg = WPA_ALG_GCMP;
186 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700187 case WPA_CIPHER_TKIP:
188 /* WPA-None uses the same Michael MIC key for both TX and RX */
189 os_memcpy(key, ssid->psk, 16 + 8);
190 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
191 keylen = 32;
192 alg = WPA_ALG_TKIP;
193 break;
194 default:
195 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
196 "WPA-None", wpa_s->group_cipher);
197 return -1;
198 }
199
200 /* TODO: should actually remember the previously used seq#, both for TX
201 * and RX from each STA.. */
202
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800203 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
204 os_memset(key, 0, sizeof(key));
205 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700206}
207
208
209static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
210{
211 struct wpa_supplicant *wpa_s = eloop_ctx;
212 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700213 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
214 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
215 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700216 bssid = wpa_s->pending_bssid;
217 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
218 MAC2STR(bssid));
219 wpa_blacklist_add(wpa_s, bssid);
220 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800221 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700222 wpa_s->reassociate = 1;
Roshan Pius38e96762017-01-23 14:52:00 -0800223 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700224
225 /*
226 * If we timed out, the AP or the local radio may be busy.
227 * So, wait a second until scanning again.
228 */
229 wpa_supplicant_req_scan(wpa_s, 1, 0);
230}
231
232
233/**
234 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
235 * @wpa_s: Pointer to wpa_supplicant data
236 * @sec: Number of seconds after which to time out authentication
237 * @usec: Number of microseconds after which to time out authentication
238 *
239 * This function is used to schedule a timeout for the current authentication
240 * attempt.
241 */
242void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
243 int sec, int usec)
244{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700245 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700246 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
247 return;
248
249 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
250 "%d usec", sec, usec);
251 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700252 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700253 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
254}
255
256
Roshan Pius3a1667e2018-07-03 15:17:14 -0700257/*
258 * wpas_auth_timeout_restart - Restart and change timeout for authentication
259 * @wpa_s: Pointer to wpa_supplicant data
260 * @sec_diff: difference in seconds applied to original timeout value
261 */
262void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
263{
264 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
265
266 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
267 wpa_dbg(wpa_s, MSG_DEBUG,
268 "Authentication timeout restart: %d sec", new_sec);
269 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
270 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
271 wpa_s, NULL);
272 }
273}
274
275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276/**
277 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
278 * @wpa_s: Pointer to wpa_supplicant data
279 *
280 * This function is used to cancel authentication timeout scheduled with
281 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
282 * been completed.
283 */
284void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
285{
286 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
287 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
288 wpa_blacklist_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700289 os_free(wpa_s->last_con_fail_realm);
290 wpa_s->last_con_fail_realm = NULL;
291 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700292}
293
294
295/**
296 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
297 * @wpa_s: Pointer to wpa_supplicant data
298 *
299 * This function is used to configure EAPOL state machine based on the selected
300 * authentication mode.
301 */
302void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
303{
304#ifdef IEEE8021X_EAPOL
305 struct eapol_config eapol_conf;
306 struct wpa_ssid *ssid = wpa_s->current_ssid;
307
308#ifdef CONFIG_IBSS_RSN
309 if (ssid->mode == WPAS_MODE_IBSS &&
310 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
311 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
312 /*
313 * RSN IBSS authentication is per-STA and we can disable the
314 * per-BSSID EAPOL authentication.
315 */
316 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
317 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
318 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
319 return;
320 }
321#endif /* CONFIG_IBSS_RSN */
322
323 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
324 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
325
326 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
327 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
328 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
329 else
330 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
331
332 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
333 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
334 eapol_conf.accept_802_1x_keys = 1;
335 eapol_conf.required_keys = 0;
336 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
337 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
338 }
339 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
340 eapol_conf.required_keys |=
341 EAPOL_REQUIRE_KEY_BROADCAST;
342 }
343
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700344 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700345 eapol_conf.required_keys = 0;
346 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700347 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700348 eapol_conf.workaround = ssid->eap_workaround;
349 eapol_conf.eap_disabled =
350 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
351 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
352 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700353 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800354
355#ifdef CONFIG_WPS
356 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
357 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
358 if (wpa_s->current_bss) {
359 struct wpabuf *ie;
360 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
361 WPS_IE_VENDOR_TYPE);
362 if (ie) {
363 if (wps_is_20(ie))
364 eapol_conf.wps |=
365 EAPOL_PEER_IS_WPS20_AP;
366 wpabuf_free(ie);
367 }
368 }
369 }
370#endif /* CONFIG_WPS */
371
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700372 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700373
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800374#ifdef CONFIG_MACSEC
375 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
376 ieee802_1x_create_preshared_mka(wpa_s, ssid);
377 else
378 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
379#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800380#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700381}
382
383
384/**
385 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
386 * @wpa_s: Pointer to wpa_supplicant data
387 * @ssid: Configuration data for the network
388 *
389 * This function is used to configure WPA state machine and related parameters
390 * to a mode where WPA is not enabled. This is called as part of the
391 * authentication configuration when the selected network does not use WPA.
392 */
393void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
394 struct wpa_ssid *ssid)
395{
396 int i;
397
398 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
399 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
400 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
401 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
402 else
403 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
404 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
405 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700406 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700407 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700408 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
409 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700410 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
411 wpa_s->group_cipher = WPA_CIPHER_NONE;
412 wpa_s->mgmt_group_cipher = 0;
413
414 for (i = 0; i < NUM_WEP_KEYS; i++) {
415 if (ssid->wep_key_len[i] > 5) {
416 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
417 wpa_s->group_cipher = WPA_CIPHER_WEP104;
418 break;
419 } else if (ssid->wep_key_len[i] > 0) {
420 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
421 wpa_s->group_cipher = WPA_CIPHER_WEP40;
422 break;
423 }
424 }
425
426 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
427 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
428 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
429 wpa_s->pairwise_cipher);
430 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700431 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
432 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700433
434 pmksa_cache_clear_current(wpa_s->wpa);
435}
436
437
Dmitry Shmidt04949592012-07-19 12:16:46 -0700438void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800439{
440 int i;
441 if (wpa_s->hw.modes == NULL)
442 return;
443
444 for (i = 0; i < wpa_s->hw.num_modes; i++) {
445 os_free(wpa_s->hw.modes[i].channels);
446 os_free(wpa_s->hw.modes[i].rates);
447 }
448
449 os_free(wpa_s->hw.modes);
450 wpa_s->hw.modes = NULL;
451}
452
453
Hai Shalom74f70d42019-02-11 14:42:39 -0800454void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800455{
456 struct wpa_bss_tmp_disallowed *bss, *prev;
457
458 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
459 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700460 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800461 dl_list_del(&bss->list);
462 os_free(bss);
463 }
464}
465
466
Paul Stewart092955c2017-02-06 09:13:09 -0800467void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
468{
469 struct fils_hlp_req *req;
470
471 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
472 list)) != NULL) {
473 dl_list_del(&req->list);
474 wpabuf_free(req->pkt);
475 os_free(req);
476 }
477}
478
479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700480static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
481{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700482 int i;
483
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700484 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700485 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700486 scard_deinit(wpa_s->scard);
487 wpa_s->scard = NULL;
488 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
489 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
490 l2_packet_deinit(wpa_s->l2);
491 wpa_s->l2 = NULL;
492 if (wpa_s->l2_br) {
493 l2_packet_deinit(wpa_s->l2_br);
494 wpa_s->l2_br = NULL;
495 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800496#ifdef CONFIG_TESTING_OPTIONS
497 l2_packet_deinit(wpa_s->l2_test);
498 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800499 os_free(wpa_s->get_pref_freq_list_override);
500 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700501 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
502 wpa_s->last_assoc_req_wpa_ie = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800503#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700504
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700505 if (wpa_s->conf != NULL) {
506 struct wpa_ssid *ssid;
507 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
508 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700509 }
510
511 os_free(wpa_s->confname);
512 wpa_s->confname = NULL;
513
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700514 os_free(wpa_s->confanother);
515 wpa_s->confanother = NULL;
516
Hai Shalomce48b4a2018-09-05 11:41:35 -0700517 os_free(wpa_s->last_con_fail_realm);
518 wpa_s->last_con_fail_realm = NULL;
519 wpa_s->last_con_fail_realm_len = 0;
520
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700521 wpa_sm_set_eapol(wpa_s->wpa, NULL);
522 eapol_sm_deinit(wpa_s->eapol);
523 wpa_s->eapol = NULL;
524
525 rsn_preauth_deinit(wpa_s->wpa);
526
527#ifdef CONFIG_TDLS
528 wpa_tdls_deinit(wpa_s->wpa);
529#endif /* CONFIG_TDLS */
530
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800531 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700532 pmksa_candidate_free(wpa_s->wpa);
533 wpa_sm_deinit(wpa_s->wpa);
534 wpa_s->wpa = NULL;
535 wpa_blacklist_clear(wpa_s);
536
537 wpa_bss_deinit(wpa_s);
538
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700539 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700540 wpa_supplicant_cancel_scan(wpa_s);
541 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800542 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
543#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
544 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
545 wpa_s, NULL);
546#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700547
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700548 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700550 wpas_wps_deinit(wpa_s);
551
552 wpabuf_free(wpa_s->pending_eapol_rx);
553 wpa_s->pending_eapol_rx = NULL;
554
555#ifdef CONFIG_IBSS_RSN
556 ibss_rsn_deinit(wpa_s->ibss_rsn);
557 wpa_s->ibss_rsn = NULL;
558#endif /* CONFIG_IBSS_RSN */
559
560 sme_deinit(wpa_s);
561
562#ifdef CONFIG_AP
563 wpa_supplicant_ap_deinit(wpa_s);
564#endif /* CONFIG_AP */
565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700566 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700567
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800568#ifdef CONFIG_OFFCHANNEL
569 offchannel_deinit(wpa_s);
570#endif /* CONFIG_OFFCHANNEL */
571
572 wpa_supplicant_cancel_sched_scan(wpa_s);
573
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700574 os_free(wpa_s->next_scan_freqs);
575 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800576
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800577 os_free(wpa_s->manual_scan_freqs);
578 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700579 os_free(wpa_s->select_network_scan_freqs);
580 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800581
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700582 os_free(wpa_s->manual_sched_scan_freqs);
583 wpa_s->manual_sched_scan_freqs = NULL;
584
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800585 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
586
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700587 /*
588 * Need to remove any pending gas-query radio work before the
589 * gas_query_deinit() call because gas_query::work has not yet been set
590 * for works that have not been started. gas_query_free() will be unable
591 * to cancel such pending radio works and once the pending gas-query
592 * radio work eventually gets removed, the deinit notification call to
593 * gas_query_start_cb() would result in dereferencing freed memory.
594 */
595 if (wpa_s->radio)
596 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800597 gas_query_deinit(wpa_s->gas);
598 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700599 gas_server_deinit(wpa_s->gas_server);
600 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800601
602 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700603
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700604 ieee802_1x_dealloc_kay_sm(wpa_s);
605
Dmitry Shmidt04949592012-07-19 12:16:46 -0700606 os_free(wpa_s->bssid_filter);
607 wpa_s->bssid_filter = NULL;
608
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800609 os_free(wpa_s->disallow_aps_bssid);
610 wpa_s->disallow_aps_bssid = NULL;
611 os_free(wpa_s->disallow_aps_ssid);
612 wpa_s->disallow_aps_ssid = NULL;
613
Dmitry Shmidt04949592012-07-19 12:16:46 -0700614 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700615#ifdef CONFIG_WNM
616 wnm_deallocate_memory(wpa_s);
617#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700618
619 ext_password_deinit(wpa_s->ext_pw);
620 wpa_s->ext_pw = NULL;
621
622 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800623 wpa_s->last_gas_resp = NULL;
624 wpabuf_free(wpa_s->prev_gas_resp);
625 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700626
627 os_free(wpa_s->last_scan_res);
628 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800629
630#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700631 if (wpa_s->drv_priv)
632 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700633 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800634#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700635
636 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
637 wpabuf_free(wpa_s->vendor_elem[i]);
638 wpa_s->vendor_elem[i] = NULL;
639 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800640
641 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800642
643 wpa_s->sched_scan_plans_num = 0;
644 os_free(wpa_s->sched_scan_plans);
645 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800646
647#ifdef CONFIG_MBO
648 wpa_s->non_pref_chan_num = 0;
649 os_free(wpa_s->non_pref_chan);
650 wpa_s->non_pref_chan = NULL;
651#endif /* CONFIG_MBO */
652
653 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700654
655 wpabuf_free(wpa_s->lci);
656 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800657 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800658
659#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
660#ifdef CONFIG_MESH
661 {
662 struct external_pmksa_cache *entry;
663
664 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
665 struct external_pmksa_cache,
666 list)) != NULL) {
667 dl_list_del(&entry->list);
668 os_free(entry->pmksa_cache);
669 os_free(entry);
670 }
671 }
672#endif /* CONFIG_MESH */
673#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
674
675 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800676
677 wpabuf_free(wpa_s->ric_ies);
678 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700679
680#ifdef CONFIG_DPP
681 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700682 dpp_global_deinit(wpa_s->dpp);
683 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700684#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685}
686
687
688/**
689 * wpa_clear_keys - Clear keys configured for the driver
690 * @wpa_s: Pointer to wpa_supplicant data
691 * @addr: Previously used BSSID or %NULL if not available
692 *
693 * This function clears the encryption keys that has been previously configured
694 * for the driver.
695 */
696void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
697{
Hai Shalomc3565922019-10-28 11:58:20 -0700698 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700699
700 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800701 for (i = 0; i < max; i++) {
702 if (wpa_s->keys_cleared & BIT(i))
703 continue;
704 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
705 NULL, 0);
706 }
707 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
708 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
710 0);
711 /* MLME-SETPROTECTION.request(None) */
712 wpa_drv_mlme_setprotection(
713 wpa_s, addr,
714 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
715 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
716 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800717 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700718}
719
720
721/**
722 * wpa_supplicant_state_txt - Get the connection state name as a text string
723 * @state: State (wpa_state; WPA_*)
724 * Returns: The state name as a printable text string
725 */
726const char * wpa_supplicant_state_txt(enum wpa_states state)
727{
728 switch (state) {
729 case WPA_DISCONNECTED:
730 return "DISCONNECTED";
731 case WPA_INACTIVE:
732 return "INACTIVE";
733 case WPA_INTERFACE_DISABLED:
734 return "INTERFACE_DISABLED";
735 case WPA_SCANNING:
736 return "SCANNING";
737 case WPA_AUTHENTICATING:
738 return "AUTHENTICATING";
739 case WPA_ASSOCIATING:
740 return "ASSOCIATING";
741 case WPA_ASSOCIATED:
742 return "ASSOCIATED";
743 case WPA_4WAY_HANDSHAKE:
744 return "4WAY_HANDSHAKE";
745 case WPA_GROUP_HANDSHAKE:
746 return "GROUP_HANDSHAKE";
747 case WPA_COMPLETED:
748 return "COMPLETED";
749 default:
750 return "UNKNOWN";
751 }
752}
753
754
755#ifdef CONFIG_BGSCAN
756
757static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
758{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800759 const char *name;
760
761 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
762 name = wpa_s->current_ssid->bgscan;
763 else
764 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800765 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800766 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800767 if (wpas_driver_bss_selection(wpa_s))
768 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700769 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
770 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800771#ifdef CONFIG_P2P
772 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
773 return;
774#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700775
776 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800777 if (wpa_s->current_ssid) {
778 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
780 "bgscan");
781 /*
782 * Live without bgscan; it is only used as a roaming
783 * optimization, so the initial connection is not
784 * affected.
785 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700786 } else {
787 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700788 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700789 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
790 0);
791 if (scan_res) {
792 bgscan_notify_scan(wpa_s, scan_res);
793 wpa_scan_results_free(scan_res);
794 }
795 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796 } else
797 wpa_s->bgscan_ssid = NULL;
798}
799
800
801static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
802{
803 if (wpa_s->bgscan_ssid != NULL) {
804 bgscan_deinit(wpa_s);
805 wpa_s->bgscan_ssid = NULL;
806 }
807}
808
809#endif /* CONFIG_BGSCAN */
810
811
Dmitry Shmidt04949592012-07-19 12:16:46 -0700812static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
813{
814 if (autoscan_init(wpa_s, 0))
815 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
816}
817
818
819static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
820{
821 autoscan_deinit(wpa_s);
822}
823
824
825void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
826{
827 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
828 wpa_s->wpa_state == WPA_SCANNING) {
829 autoscan_deinit(wpa_s);
830 wpa_supplicant_start_autoscan(wpa_s);
831 }
832}
833
834
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700835/**
836 * wpa_supplicant_set_state - Set current connection state
837 * @wpa_s: Pointer to wpa_supplicant data
838 * @state: The new connection state
839 *
840 * This function is called whenever the connection state changes, e.g.,
841 * association is completed for WPA/WPA2 4-Way Handshake is started.
842 */
843void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
844 enum wpa_states state)
845{
846 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700847#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
848 Boolean update_fils_connect_params = FALSE;
849#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700850
851 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
852 wpa_supplicant_state_txt(wpa_s->wpa_state),
853 wpa_supplicant_state_txt(state));
854
Hai Shalom74f70d42019-02-11 14:42:39 -0800855 if (state == WPA_COMPLETED &&
856 os_reltime_initialized(&wpa_s->roam_start)) {
857 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
858 wpa_s->roam_start.sec = 0;
859 wpa_s->roam_start.usec = 0;
860 wpas_notify_auth_changed(wpa_s);
861 wpas_notify_roam_time(wpa_s);
862 wpas_notify_roam_complete(wpa_s);
863 } else if (state == WPA_DISCONNECTED &&
864 os_reltime_initialized(&wpa_s->roam_start)) {
865 wpa_s->roam_start.sec = 0;
866 wpa_s->roam_start.usec = 0;
867 wpa_s->roam_time.sec = 0;
868 wpa_s->roam_time.usec = 0;
869 wpas_notify_roam_complete(wpa_s);
870 }
871
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800872 if (state == WPA_INTERFACE_DISABLED) {
873 /* Assure normal scan when interface is restored */
874 wpa_s->normal_scans = 0;
875 }
876
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700877 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800878 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700879 /* Reinitialize normal_scan counter */
880 wpa_s->normal_scans = 0;
881 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800882
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700883#ifdef CONFIG_P2P
884 /*
885 * P2PS client has to reply to Probe Request frames received on the
886 * group operating channel. Enable Probe Request frame reporting for
887 * P2P connected client in case p2p_cli_probe configuration property is
888 * set to 1.
889 */
890 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
891 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
892 wpa_s->current_ssid->p2p_group) {
893 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
894 wpa_dbg(wpa_s, MSG_DEBUG,
895 "P2P: Enable CLI Probe Request RX reporting");
896 wpa_s->p2p_cli_probe =
897 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
898 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
899 wpa_dbg(wpa_s, MSG_DEBUG,
900 "P2P: Disable CLI Probe Request RX reporting");
901 wpa_s->p2p_cli_probe = 0;
902 wpa_drv_probe_req_report(wpa_s, 0);
903 }
904 }
905#endif /* CONFIG_P2P */
906
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700907 if (state != WPA_SCANNING)
908 wpa_supplicant_notify_scanning(wpa_s, 0);
909
910 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700911 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700912 int fils_hlp_sent = 0;
913
914#ifdef CONFIG_SME
915 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
916 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
917 fils_hlp_sent = 1;
918#endif /* CONFIG_SME */
919 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
920 wpa_auth_alg_fils(wpa_s->auth_alg))
921 fils_hlp_sent = 1;
922
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700923#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700924 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700925 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800926 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700927 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700928 ssid && ssid->id_str ? ssid->id_str : "",
929 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700931 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700932 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800933 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700934 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935 wpa_drv_set_operstate(wpa_s, 1);
936#ifndef IEEE8021X_EAPOL
937 wpa_drv_set_supp_port(wpa_s, 1);
938#endif /* IEEE8021X_EAPOL */
939 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700940 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700941 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700942
943 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700944
945#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
946 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalomc3565922019-10-28 11:58:20 -0700947 update_fils_connect_params = TRUE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700948#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700949#ifdef CONFIG_OWE
950 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
951 wpas_update_owe_connect_params(wpa_s);
952#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700953 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
954 state == WPA_ASSOCIATED) {
955 wpa_s->new_connection = 1;
956 wpa_drv_set_operstate(wpa_s, 0);
957#ifndef IEEE8021X_EAPOL
958 wpa_drv_set_supp_port(wpa_s, 0);
959#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700960 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700961 }
962 wpa_s->wpa_state = state;
963
964#ifdef CONFIG_BGSCAN
965 if (state == WPA_COMPLETED)
966 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800967 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700968 wpa_supplicant_stop_bgscan(wpa_s);
969#endif /* CONFIG_BGSCAN */
970
Hai Shalom5f92bc92019-04-18 11:54:11 -0700971 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700972 wpa_supplicant_stop_autoscan(wpa_s);
973
974 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
975 wpa_supplicant_start_autoscan(wpa_s);
976
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800977 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
978 wmm_ac_notify_disassoc(wpa_s);
979
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980 if (wpa_s->wpa_state != old_state) {
981 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
982
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700983 /*
984 * Notify the P2P Device interface about a state change in one
985 * of the interfaces.
986 */
987 wpas_p2p_indicate_state_change(wpa_s);
988
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989 if (wpa_s->wpa_state == WPA_COMPLETED ||
990 old_state == WPA_COMPLETED)
991 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700992#ifdef CONFIG_DPP2
993 if (wpa_s->wpa_state == WPA_COMPLETED)
994 wpas_dpp_connected(wpa_s);
995#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996 }
Hai Shalomc3565922019-10-28 11:58:20 -0700997#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
998 if (update_fils_connect_params)
999 wpas_update_fils_connect_params(wpa_s);
1000#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001}
1002
1003
1004void wpa_supplicant_terminate_proc(struct wpa_global *global)
1005{
1006 int pending = 0;
1007#ifdef CONFIG_WPS
1008 struct wpa_supplicant *wpa_s = global->ifaces;
1009 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001010 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001011 if (wpas_wps_terminate_pending(wpa_s) == 1)
1012 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001013#ifdef CONFIG_P2P
1014 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1015 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1016 wpas_p2p_disconnect(wpa_s);
1017#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001018 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019 }
1020#endif /* CONFIG_WPS */
1021 if (pending)
1022 return;
1023 eloop_terminate();
1024}
1025
1026
1027static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1028{
1029 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 wpa_supplicant_terminate_proc(global);
1031}
1032
1033
1034void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1035{
1036 enum wpa_states old_state = wpa_s->wpa_state;
1037
1038 wpa_s->pairwise_cipher = 0;
1039 wpa_s->group_cipher = 0;
1040 wpa_s->mgmt_group_cipher = 0;
1041 wpa_s->key_mgmt = 0;
1042 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001043 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001044
1045 if (wpa_s->wpa_state != old_state)
1046 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1047}
1048
1049
1050/**
1051 * wpa_supplicant_reload_configuration - Reload configuration data
1052 * @wpa_s: Pointer to wpa_supplicant data
1053 * Returns: 0 on success or -1 if configuration parsing failed
1054 *
1055 * This function can be used to request that the configuration data is reloaded
1056 * (e.g., after configuration file change). This function is reloading
1057 * configuration only for one interface, so this may need to be called multiple
1058 * times if %wpa_supplicant is controlling multiple interfaces and all
1059 * interfaces need reconfiguration.
1060 */
1061int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1062{
1063 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001064 int reconf_ctrl;
1065 int old_ap_scan;
1066
1067 if (wpa_s->confname == NULL)
1068 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001069 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070 if (conf == NULL) {
1071 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1072 "file '%s' - exiting", wpa_s->confname);
1073 return -1;
1074 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001075 if (wpa_s->confanother &&
1076 !wpa_config_read(wpa_s->confanother, conf)) {
1077 wpa_msg(wpa_s, MSG_ERROR,
1078 "Failed to parse the configuration file '%s' - exiting",
1079 wpa_s->confanother);
1080 return -1;
1081 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001083 conf->changed_parameters = (unsigned int) -1;
1084
1085 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1086 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1087 os_strcmp(conf->ctrl_interface,
1088 wpa_s->conf->ctrl_interface) != 0);
1089
1090 if (reconf_ctrl && wpa_s->ctrl_iface) {
1091 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1092 wpa_s->ctrl_iface = NULL;
1093 }
1094
1095 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001096 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001097 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1098 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001099 wpa_supplicant_deauthenticate(wpa_s,
1100 WLAN_REASON_DEAUTH_LEAVING);
1101 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001102
1103 /*
1104 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001105 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001106 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001107 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1108 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1109 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001110 /*
1111 * Clear forced success to clear EAP state for next
1112 * authentication.
1113 */
1114 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1115 }
1116 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1117 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001118 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1120 rsn_preauth_deinit(wpa_s->wpa);
1121
1122 old_ap_scan = wpa_s->conf->ap_scan;
1123 wpa_config_free(wpa_s->conf);
1124 wpa_s->conf = conf;
1125 if (old_ap_scan != wpa_s->conf->ap_scan)
1126 wpas_notify_ap_scan_changed(wpa_s);
1127
1128 if (reconf_ctrl)
1129 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1130
1131 wpa_supplicant_update_config(wpa_s);
1132
1133 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001134 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001135 wpa_s->reassociate = 1;
1136 wpa_supplicant_req_scan(wpa_s, 0, 0);
1137 }
1138 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1139 return 0;
1140}
1141
1142
1143static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1144{
1145 struct wpa_global *global = signal_ctx;
1146 struct wpa_supplicant *wpa_s;
1147 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1148 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1149 sig);
1150 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1151 wpa_supplicant_terminate_proc(global);
1152 }
1153 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001154
1155 if (wpa_debug_reopen_file() < 0) {
1156 /* Ignore errors since we cannot really do much to fix this */
1157 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1158 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001159}
1160
1161
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001162static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1163 struct wpa_ssid *ssid,
1164 struct wpa_ie_data *ie)
1165{
1166 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1167 if (ret) {
1168 if (ret == -2) {
1169 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1170 "from association info");
1171 }
1172 return -1;
1173 }
1174
1175 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1176 "cipher suites");
1177 if (!(ie->group_cipher & ssid->group_cipher)) {
1178 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1179 "cipher 0x%x (mask 0x%x) - reject",
1180 ie->group_cipher, ssid->group_cipher);
1181 return -1;
1182 }
1183 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1184 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1185 "cipher 0x%x (mask 0x%x) - reject",
1186 ie->pairwise_cipher, ssid->pairwise_cipher);
1187 return -1;
1188 }
1189 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1190 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1191 "management 0x%x (mask 0x%x) - reject",
1192 ie->key_mgmt, ssid->key_mgmt);
1193 return -1;
1194 }
1195
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001196 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001197 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001198 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1199 "that does not support management frame protection - "
1200 "reject");
1201 return -1;
1202 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001203
1204 return 0;
1205}
1206
1207
Hai Shalom021b0b52019-04-10 11:17:58 -07001208static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1209 int freq)
1210{
1211 if (!ie->has_group)
1212 ie->group_cipher = wpa_default_rsn_cipher(freq);
1213 if (!ie->has_pairwise)
1214 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1215 return (ie->group_cipher & ssid->group_cipher) &&
1216 (ie->pairwise_cipher & ssid->pairwise_cipher);
1217}
1218
1219
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001220/**
1221 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1222 * @wpa_s: Pointer to wpa_supplicant data
1223 * @bss: Scan results for the selected BSS, or %NULL if not available
1224 * @ssid: Configuration data for the selected network
1225 * @wpa_ie: Buffer for the WPA/RSN IE
1226 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1227 * used buffer length in case the functions returns success.
1228 * Returns: 0 on success or -1 on failure
1229 *
1230 * This function is used to configure authentication and encryption parameters
1231 * based on the network configuration and scan result for the selected BSS (if
1232 * available).
1233 */
1234int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1235 struct wpa_bss *bss, struct wpa_ssid *ssid,
1236 u8 *wpa_ie, size_t *wpa_ie_len)
1237{
1238 struct wpa_ie_data ie;
1239 int sel, proto;
Hai Shalomc3565922019-10-28 11:58:20 -07001240 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001241
1242 if (bss) {
1243 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1244 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001245 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001246 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001247 } else {
1248 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1249 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001250
1251 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1252 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001253 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001254 (ie.key_mgmt & ssid->key_mgmt)) {
1255 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1256 proto = WPA_PROTO_RSN;
1257 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001258 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001259 (ie.group_cipher & ssid->group_cipher) &&
1260 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1261 (ie.key_mgmt & ssid->key_mgmt)) {
1262 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1263 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001264#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001265 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1266 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1267 (ie.group_cipher & ssid->group_cipher) &&
1268 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1269 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001270 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001271 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001272 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1273 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1274 (ie.group_cipher & ssid->group_cipher) &&
1275 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1276 (ie.key_mgmt & ssid->key_mgmt)) {
1277 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1278 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001279#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001280 } else if (bss) {
1281 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001282 wpa_dbg(wpa_s, MSG_DEBUG,
1283 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1284 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1285 ssid->key_mgmt);
1286 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1287 MAC2STR(bss->bssid),
1288 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1289 bss_wpa ? " WPA" : "",
1290 bss_rsn ? " RSN" : "",
1291 bss_osen ? " OSEN" : "");
1292 if (bss_rsn) {
1293 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1294 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1295 wpa_dbg(wpa_s, MSG_DEBUG,
1296 "Could not parse RSN element");
1297 } else {
1298 wpa_dbg(wpa_s, MSG_DEBUG,
1299 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1300 ie.pairwise_cipher, ie.group_cipher,
1301 ie.key_mgmt);
1302 }
1303 }
1304 if (bss_wpa) {
1305 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1306 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1307 wpa_dbg(wpa_s, MSG_DEBUG,
1308 "Could not parse WPA element");
1309 } else {
1310 wpa_dbg(wpa_s, MSG_DEBUG,
1311 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1312 ie.pairwise_cipher, ie.group_cipher,
1313 ie.key_mgmt);
1314 }
1315 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001316 return -1;
1317 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001318 if (ssid->proto & WPA_PROTO_OSEN)
1319 proto = WPA_PROTO_OSEN;
1320 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001321 proto = WPA_PROTO_RSN;
1322 else
1323 proto = WPA_PROTO_WPA;
1324 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1325 os_memset(&ie, 0, sizeof(ie));
1326 ie.group_cipher = ssid->group_cipher;
1327 ie.pairwise_cipher = ssid->pairwise_cipher;
1328 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001329 ie.mgmt_group_cipher = 0;
1330 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1331 if (ssid->group_mgmt_cipher &
1332 WPA_CIPHER_BIP_GMAC_256)
1333 ie.mgmt_group_cipher =
1334 WPA_CIPHER_BIP_GMAC_256;
1335 else if (ssid->group_mgmt_cipher &
1336 WPA_CIPHER_BIP_CMAC_256)
1337 ie.mgmt_group_cipher =
1338 WPA_CIPHER_BIP_CMAC_256;
1339 else if (ssid->group_mgmt_cipher &
1340 WPA_CIPHER_BIP_GMAC_128)
1341 ie.mgmt_group_cipher =
1342 WPA_CIPHER_BIP_GMAC_128;
1343 else
1344 ie.mgmt_group_cipher =
1345 WPA_CIPHER_AES_128_CMAC;
1346 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001347#ifdef CONFIG_OWE
1348 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1349 !ssid->owe_only &&
1350 !bss_wpa && !bss_rsn && !bss_osen) {
1351 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1352 wpa_s->wpa_proto = 0;
1353 *wpa_ie_len = 0;
1354 return 0;
1355 }
1356#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001357 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1358 "based on configuration");
1359 } else
1360 proto = ie.proto;
1361 }
1362
1363 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1364 "pairwise %d key_mgmt %d proto %d",
1365 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366 if (ssid->ieee80211w) {
1367 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1368 ie.mgmt_group_cipher);
1369 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001371 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001372 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1373 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001374 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001375
1376 if (bss || !wpa_s->ap_ies_from_associnfo) {
1377 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1378 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1379 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001380 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1381 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1382 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001383 return -1;
1384 }
1385
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001386#ifdef CONFIG_NO_WPA
1387 wpa_s->group_cipher = WPA_CIPHER_NONE;
1388 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1389#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001390 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001391 wpa_dbg(wpa_s, MSG_DEBUG,
1392 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1393 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001394 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1395 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001396 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1397 "cipher");
1398 return -1;
1399 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001400 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1401 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001402
1403 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001404 wpa_dbg(wpa_s, MSG_DEBUG,
1405 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1406 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001407 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1408 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001409 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1410 "cipher");
1411 return -1;
1412 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001413 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1414 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001415#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416
1417 sel = ie.key_mgmt & ssid->key_mgmt;
Hai Shalom021b0b52019-04-10 11:17:58 -07001418 wpa_dbg(wpa_s, MSG_DEBUG,
1419 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1420 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001421#ifdef CONFIG_SAE
1422 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1423 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1424#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001425 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001426#ifdef CONFIG_IEEE80211R
1427#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001428 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1429 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001430 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1431 wpa_dbg(wpa_s, MSG_DEBUG,
1432 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001433 if (!ssid->ft_eap_pmksa_caching &&
1434 pmksa_cache_get_current(wpa_s->wpa)) {
1435 /* PMKSA caching with FT may have interoperability
1436 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001437 wpa_dbg(wpa_s, MSG_DEBUG,
1438 "WPA: Disable PMKSA caching for FT/802.1X connection");
1439 pmksa_cache_clear_current(wpa_s->wpa);
1440 }
1441#endif /* CONFIG_SHA384 */
1442#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001443#ifdef CONFIG_SUITEB192
1444 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1445 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1446 wpa_dbg(wpa_s, MSG_DEBUG,
1447 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1448#endif /* CONFIG_SUITEB192 */
1449#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001450 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1451 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1452 wpa_dbg(wpa_s, MSG_DEBUG,
1453 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001454#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001455#ifdef CONFIG_FILS
1456#ifdef CONFIG_IEEE80211R
1457 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1458 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1459 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1460 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1461 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1462 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1463#endif /* CONFIG_IEEE80211R */
1464 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1465 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1466 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1467 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1468 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1469 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1470#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001471#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001472 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1473 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001474 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1475 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001476 if (!ssid->ft_eap_pmksa_caching &&
1477 pmksa_cache_get_current(wpa_s->wpa)) {
1478 /* PMKSA caching with FT may have interoperability
1479 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001480 wpa_dbg(wpa_s, MSG_DEBUG,
1481 "WPA: Disable PMKSA caching for FT/802.1X connection");
1482 pmksa_cache_clear_current(wpa_s->wpa);
1483 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001484#endif /* CONFIG_IEEE80211R */
1485#ifdef CONFIG_DPP
1486 } else if (sel & WPA_KEY_MGMT_DPP) {
1487 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1488 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1489#endif /* CONFIG_DPP */
1490#ifdef CONFIG_SAE
1491 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1492 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1493 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1494 } else if (sel & WPA_KEY_MGMT_SAE) {
1495 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1496 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1497#endif /* CONFIG_SAE */
1498#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001499 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1500 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1501 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1502#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001503 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1504 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1505 wpa_dbg(wpa_s, MSG_DEBUG,
1506 "WPA: using KEY_MGMT 802.1X with SHA256");
1507 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1508 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1509 wpa_dbg(wpa_s, MSG_DEBUG,
1510 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001511 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1512 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1513 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1514 } else if (sel & WPA_KEY_MGMT_PSK) {
1515 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1516 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1517 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1518 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1519 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001520#ifdef CONFIG_HS20
1521 } else if (sel & WPA_KEY_MGMT_OSEN) {
1522 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1523 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1524#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001525#ifdef CONFIG_OWE
1526 } else if (sel & WPA_KEY_MGMT_OWE) {
1527 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1528 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1529#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001530 } else {
1531 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1532 "authenticated key management type");
1533 return -1;
1534 }
1535
1536 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1537 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1538 wpa_s->pairwise_cipher);
1539 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1540
Hai Shalomc3565922019-10-28 11:58:20 -07001541 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1542 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1543 wpa_msg(wpa_s, MSG_INFO,
1544 "RSN: Management frame protection required but the selected AP does not enable it");
1545 return -1;
1546 }
1547
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001548 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001549 if (ssid->group_mgmt_cipher)
1550 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001551 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1553 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001554 wpa_dbg(wpa_s, MSG_DEBUG,
1555 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1556 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001557 if (sel & WPA_CIPHER_AES_128_CMAC) {
1558 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1559 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1560 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001561 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1562 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1563 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1564 "BIP-GMAC-128");
1565 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1566 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1567 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1568 "BIP-GMAC-256");
1569 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1570 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1571 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1572 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001573 } else {
1574 wpa_s->mgmt_group_cipher = 0;
1575 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1576 }
1577 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1578 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001579 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001580 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001581#ifdef CONFIG_OCV
1582 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
1583#endif /* CONFIG_OCV */
Hai Shalomc3565922019-10-28 11:58:20 -07001584 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, wpa_s->conf->sae_pwe);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001585
1586 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1587 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1588 return -1;
1589 }
1590
Hai Shalomc3565922019-10-28 11:58:20 -07001591 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1592 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1593 &wpa_s->rsnxe_len)) {
1594 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1595 return -1;
1596 }
1597
Hai Shalom021b0b52019-04-10 11:17:58 -07001598 if (0) {
1599#ifdef CONFIG_DPP
1600 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1601 /* Use PMK from DPP network introduction (PMKSA entry) */
1602 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1603#endif /* CONFIG_DPP */
1604 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001605 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001606 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001607
Roshan Pius3a1667e2018-07-03 15:17:14 -07001608 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1609 WPA_KEY_MGMT_FT_PSK |
1610 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1611
1612 if (ssid->psk_set && !sae_only) {
1613 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1614 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001615 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1616 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001617 psk_set = 1;
1618 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001619
Roshan Pius3a1667e2018-07-03 15:17:14 -07001620 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1621 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001622 psk_set = 1;
1623
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001624#ifndef CONFIG_NO_PBKDF2
1625 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001626 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001627 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001628 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1629 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001630 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1631 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001632 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001633 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001634 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001635 }
1636#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001637#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001638 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001639 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1640 ssid->ext_psk);
1641 char pw_str[64 + 1];
1642 u8 psk[PMK_LEN];
1643
1644 if (pw == NULL) {
1645 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1646 "found from external storage");
1647 return -1;
1648 }
1649
1650 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1651 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1652 "PSK length %d in external storage",
1653 (int) wpabuf_len(pw));
1654 ext_password_free(pw);
1655 return -1;
1656 }
1657
1658 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1659 pw_str[wpabuf_len(pw)] = '\0';
1660
1661#ifndef CONFIG_NO_PBKDF2
1662 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1663 {
1664 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1665 4096, psk, PMK_LEN);
1666 os_memset(pw_str, 0, sizeof(pw_str));
1667 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1668 "external passphrase)",
1669 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001670 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1671 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001672 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001673 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001674 } else
1675#endif /* CONFIG_NO_PBKDF2 */
1676 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1677 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1678 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1679 "Invalid PSK hex string");
1680 os_memset(pw_str, 0, sizeof(pw_str));
1681 ext_password_free(pw);
1682 return -1;
1683 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001684 wpa_hexdump_key(MSG_MSGDUMP,
1685 "PSK (from external PSK)",
1686 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001687 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1688 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001689 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001690 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001691 } else {
1692 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1693 "PSK available");
1694 os_memset(pw_str, 0, sizeof(pw_str));
1695 ext_password_free(pw);
1696 return -1;
1697 }
1698
1699 os_memset(pw_str, 0, sizeof(pw_str));
1700 ext_password_free(pw);
1701 }
1702#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001703
1704 if (!psk_set) {
1705 wpa_msg(wpa_s, MSG_INFO,
1706 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001707 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001708 return -1;
1709 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001710#ifdef CONFIG_OWE
1711 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1712 /* OWE Diffie-Hellman exchange in (Re)Association
1713 * Request/Response frames set the PMK, so do not override it
1714 * here. */
1715#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001716 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001717 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1718
1719 return 0;
1720}
1721
1722
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001723static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1724{
1725 *pos = 0x00;
1726
1727 switch (idx) {
1728 case 0: /* Bits 0-7 */
1729 break;
1730 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001731 if (wpa_s->conf->coloc_intf_reporting) {
1732 /* Bit 13 - Collocated Interference Reporting */
1733 *pos |= 0x20;
1734 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001735 break;
1736 case 2: /* Bits 16-23 */
1737#ifdef CONFIG_WNM
1738 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001739 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001740 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001741#endif /* CONFIG_WNM */
1742 break;
1743 case 3: /* Bits 24-31 */
1744#ifdef CONFIG_WNM
1745 *pos |= 0x02; /* Bit 25 - SSID List */
1746#endif /* CONFIG_WNM */
1747#ifdef CONFIG_INTERWORKING
1748 if (wpa_s->conf->interworking)
1749 *pos |= 0x80; /* Bit 31 - Interworking */
1750#endif /* CONFIG_INTERWORKING */
1751 break;
1752 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001753#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001754 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001755 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001756#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001757 break;
1758 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001759#ifdef CONFIG_HS20
1760 if (wpa_s->conf->hs20)
1761 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1762#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001763#ifdef CONFIG_MBO
1764 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1765#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001766 break;
1767 case 6: /* Bits 48-55 */
1768 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001769 case 7: /* Bits 56-63 */
1770 break;
1771 case 8: /* Bits 64-71 */
1772 if (wpa_s->conf->ftm_responder)
1773 *pos |= 0x40; /* Bit 70 - FTM responder */
1774 if (wpa_s->conf->ftm_initiator)
1775 *pos |= 0x80; /* Bit 71 - FTM initiator */
1776 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001777 case 9: /* Bits 72-79 */
1778#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001779 if (!wpa_s->disable_fils)
1780 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001781#endif /* CONFIG_FILS */
1782 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001783 }
1784}
1785
1786
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001787int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001788{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001789 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001790 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001791
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001792 if (len < wpa_s->extended_capa_len)
1793 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001794 if (buflen < (size_t) len + 2) {
1795 wpa_printf(MSG_INFO,
1796 "Not enough room for building extended capabilities element");
1797 return -1;
1798 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001799
1800 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001801 *pos++ = len;
1802 for (i = 0; i < len; i++, pos++) {
1803 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001804
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001805 if (i < wpa_s->extended_capa_len) {
1806 *pos &= ~wpa_s->extended_capa_mask[i];
1807 *pos |= wpa_s->extended_capa[i];
1808 }
1809 }
1810
1811 while (len > 0 && buf[1 + len] == 0) {
1812 len--;
1813 buf[1] = len;
1814 }
1815 if (len == 0)
1816 return 0;
1817
1818 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001819}
1820
1821
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001822static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1823 struct wpa_bss *test_bss)
1824{
1825 struct wpa_bss *bss;
1826
1827 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1828 if (bss == test_bss)
1829 return 1;
1830 }
1831
1832 return 0;
1833}
1834
1835
1836static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1837 struct wpa_ssid *test_ssid)
1838{
1839 struct wpa_ssid *ssid;
1840
1841 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1842 if (ssid == test_ssid)
1843 return 1;
1844 }
1845
1846 return 0;
1847}
1848
1849
1850int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1851 struct wpa_ssid *test_ssid)
1852{
1853 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1854 return 0;
1855
1856 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1857}
1858
1859
1860void wpas_connect_work_free(struct wpa_connect_work *cwork)
1861{
1862 if (cwork == NULL)
1863 return;
1864 os_free(cwork);
1865}
1866
1867
1868void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1869{
1870 struct wpa_connect_work *cwork;
1871 struct wpa_radio_work *work = wpa_s->connect_work;
1872
1873 if (!work)
1874 return;
1875
1876 wpa_s->connect_work = NULL;
1877 cwork = work->ctx;
1878 work->ctx = NULL;
1879 wpas_connect_work_free(cwork);
1880 radio_work_done(work);
1881}
1882
1883
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001884int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1885{
1886 struct os_reltime now;
1887 u8 addr[ETH_ALEN];
1888
1889 os_get_reltime(&now);
1890 if (wpa_s->last_mac_addr_style == style &&
1891 wpa_s->last_mac_addr_change.sec != 0 &&
1892 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1893 wpa_s->conf->rand_addr_lifetime)) {
1894 wpa_msg(wpa_s, MSG_DEBUG,
1895 "Previously selected random MAC address has not yet expired");
1896 return 0;
1897 }
1898
1899 switch (style) {
1900 case 1:
1901 if (random_mac_addr(addr) < 0)
1902 return -1;
1903 break;
1904 case 2:
1905 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1906 if (random_mac_addr_keep_oui(addr) < 0)
1907 return -1;
1908 break;
1909 default:
1910 return -1;
1911 }
1912
1913 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1914 wpa_msg(wpa_s, MSG_INFO,
1915 "Failed to set random MAC address");
1916 return -1;
1917 }
1918
1919 os_get_reltime(&wpa_s->last_mac_addr_change);
1920 wpa_s->mac_addr_changed = 1;
1921 wpa_s->last_mac_addr_style = style;
1922
1923 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1924 wpa_msg(wpa_s, MSG_INFO,
1925 "Could not update MAC address information");
1926 return -1;
1927 }
1928
1929 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1930 MAC2STR(addr));
1931
1932 return 0;
1933}
1934
1935
1936int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1937{
1938 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1939 !wpa_s->conf->preassoc_mac_addr)
1940 return 0;
1941
1942 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1943}
1944
1945
Hai Shalomc3565922019-10-28 11:58:20 -07001946static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
1947{
1948#ifdef CONFIG_SAE
1949 int *groups = conf->sae_groups;
1950 int default_groups[] = { 19, 20, 21, 0 };
1951 const char *password;
1952
1953 if (!groups || groups[0] <= 0)
1954 groups = default_groups;
1955
1956 password = ssid->sae_password;
1957 if (!password)
1958 password = ssid->passphrase;
1959
1960 if (conf->sae_pwe == 0 || !password) {
1961 /* PT derivation not needed */
1962 sae_deinit_pt(ssid->pt);
1963 ssid->pt = NULL;
1964 return;
1965 }
1966
1967 if (ssid->pt)
1968 return; /* PT already derived */
1969 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
1970 (const u8 *) password, os_strlen(password),
1971 ssid->sae_password_id);
1972#endif /* CONFIG_SAE */
1973}
1974
1975
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001976static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1977
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001978/**
1979 * wpa_supplicant_associate - Request association
1980 * @wpa_s: Pointer to wpa_supplicant data
1981 * @bss: Scan results for the selected BSS, or %NULL if not available
1982 * @ssid: Configuration data for the selected network
1983 *
1984 * This function is used to request %wpa_supplicant to associate with a BSS.
1985 */
1986void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1987 struct wpa_bss *bss, struct wpa_ssid *ssid)
1988{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001989 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001990 int rand_style;
1991
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001992 wpa_s->own_disconnect_req = 0;
1993
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001994 /*
1995 * If we are starting a new connection, any previously pending EAPOL
1996 * RX cannot be valid anymore.
1997 */
1998 wpabuf_free(wpa_s->pending_eapol_rx);
1999 wpa_s->pending_eapol_rx = NULL;
2000
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002001 if (ssid->mac_addr == -1)
2002 rand_style = wpa_s->conf->mac_addr;
2003 else
2004 rand_style = ssid->mac_addr;
2005
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002006 wmm_ac_clear_saved_tspecs(wpa_s);
2007 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002008 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002009#ifdef CONFIG_TESTING_OPTIONS
2010 wpa_s->testing_resend_assoc = 0;
2011#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002012
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002013 if (wpa_s->last_ssid == ssid) {
2014 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002015 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002016 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2017 wmm_ac_save_tspecs(wpa_s);
2018 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002019 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2020 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002021 }
Hai Shalomc3565922019-10-28 11:58:20 -07002022 } else {
2023#ifdef CONFIG_SAE
2024#ifdef CONFIG_SME
2025 os_free(wpa_s->sme.sae_rejected_groups);
2026 wpa_s->sme.sae_rejected_groups = NULL;
2027#endif /* CONFIG_SME */
2028 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2029#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002030 }
2031
2032 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002033 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2034 return;
2035 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002036 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002037 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2038 wpa_msg(wpa_s, MSG_INFO,
2039 "Could not restore permanent MAC address");
2040 return;
2041 }
2042 wpa_s->mac_addr_changed = 0;
2043 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2044 wpa_msg(wpa_s, MSG_INFO,
2045 "Could not update MAC address information");
2046 return;
2047 }
2048 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2049 }
2050 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002051
2052#ifdef CONFIG_IBSS_RSN
2053 ibss_rsn_deinit(wpa_s->ibss_rsn);
2054 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002055#else /* CONFIG_IBSS_RSN */
2056 if (ssid->mode == WPAS_MODE_IBSS &&
2057 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2058 wpa_msg(wpa_s, MSG_INFO,
2059 "IBSS RSN not supported in the build");
2060 return;
2061 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002062#endif /* CONFIG_IBSS_RSN */
2063
2064 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2065 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2066#ifdef CONFIG_AP
2067 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2068 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2069 "mode");
2070 return;
2071 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002072 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2073 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002074 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2075 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002076 return;
2077 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002078 wpa_s->current_bss = bss;
2079#else /* CONFIG_AP */
2080 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2081 "the build");
2082#endif /* CONFIG_AP */
2083 return;
2084 }
2085
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002086 if (ssid->mode == WPAS_MODE_MESH) {
2087#ifdef CONFIG_MESH
2088 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2089 wpa_msg(wpa_s, MSG_INFO,
2090 "Driver does not support mesh mode");
2091 return;
2092 }
2093 if (bss)
2094 ssid->frequency = bss->freq;
2095 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2096 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2097 return;
2098 }
2099 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002100 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
2101 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
2102 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002103 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002104#else /* CONFIG_MESH */
2105 wpa_msg(wpa_s, MSG_ERROR,
2106 "mesh mode support not included in the build");
2107#endif /* CONFIG_MESH */
2108 return;
2109 }
2110
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002111 /*
2112 * Set WPA state machine configuration to match the selected network now
2113 * so that the information is available before wpas_start_assoc_cb()
2114 * gets called. This is needed at least for RSN pre-authentication where
2115 * candidate APs are added to a list based on scan result processing
2116 * before completion of the first association.
2117 */
2118 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2119
2120#ifdef CONFIG_DPP
2121 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2122 return;
2123#endif /* CONFIG_DPP */
2124
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002125#ifdef CONFIG_TDLS
2126 if (bss)
2127 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2128 bss->ie_len);
2129#endif /* CONFIG_TDLS */
2130
Hai Shalomc3565922019-10-28 11:58:20 -07002131#ifdef CONFIG_MBO
2132 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2133#endif /* CONFIG_MBO */
2134
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002135 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002136 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 sme_authenticate(wpa_s, bss, ssid);
2138 return;
2139 }
2140
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002141 if (wpa_s->connect_work) {
2142 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2143 return;
2144 }
2145
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002146 if (radio_work_pending(wpa_s, "connect")) {
2147 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2148 return;
2149 }
2150
Dmitry Shmidt29333592017-01-09 12:27:11 -08002151#ifdef CONFIG_SME
2152 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2153 /* Clear possibly set auth_alg, if any, from last attempt. */
2154 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2155 }
2156#endif /* CONFIG_SME */
2157
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002158 wpas_abort_ongoing_scan(wpa_s);
2159
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002160 cwork = os_zalloc(sizeof(*cwork));
2161 if (cwork == NULL)
2162 return;
2163
2164 cwork->bss = bss;
2165 cwork->ssid = ssid;
2166
2167 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2168 wpas_start_assoc_cb, cwork) < 0) {
2169 os_free(cwork);
2170 }
2171}
2172
2173
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002174static int bss_is_ibss(struct wpa_bss *bss)
2175{
2176 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2177 IEEE80211_CAP_IBSS;
2178}
2179
2180
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002181static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2182 const struct wpa_ssid *ssid)
2183{
2184 enum hostapd_hw_mode hw_mode;
2185 struct hostapd_hw_modes *mode = NULL;
2186 u8 channel;
2187 int i;
2188
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002189 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2190 if (hw_mode == NUM_HOSTAPD_MODES)
2191 return 0;
2192 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2193 if (wpa_s->hw.modes[i].mode == hw_mode) {
2194 mode = &wpa_s->hw.modes[i];
2195 break;
2196 }
2197 }
2198
2199 if (!mode)
2200 return 0;
2201
2202 return mode->vht_capab != 0;
2203}
2204
2205
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002206void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2207 const struct wpa_ssid *ssid,
2208 struct hostapd_freq_params *freq)
2209{
Hai Shalom81f62d82019-07-22 12:10:00 -07002210 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002211 enum hostapd_hw_mode hw_mode;
2212 struct hostapd_hw_modes *mode = NULL;
2213 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2214 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002215 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002216 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2217 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002218 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002219 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002220 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002221 int chwidth, seg0, seg1;
2222 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002223 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002224
2225 freq->freq = ssid->frequency;
2226
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002227 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2228 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2229
2230 if (ssid->mode != WPAS_MODE_IBSS)
2231 break;
2232
2233 /* Don't adjust control freq in case of fixed_freq */
2234 if (ssid->fixed_freq)
2235 break;
2236
2237 if (!bss_is_ibss(bss))
2238 continue;
2239
2240 if (ssid->ssid_len == bss->ssid_len &&
2241 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2242 wpa_printf(MSG_DEBUG,
2243 "IBSS already found in scan results, adjust control freq: %d",
2244 bss->freq);
2245 freq->freq = bss->freq;
2246 obss_scan = 0;
2247 break;
2248 }
2249 }
2250
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002251 /* For IBSS check HT_IBSS flag */
2252 if (ssid->mode == WPAS_MODE_IBSS &&
2253 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2254 return;
2255
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002256 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2257 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2258 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2259 wpa_printf(MSG_DEBUG,
2260 "IBSS: WEP/TKIP detected, do not try to enable HT");
2261 return;
2262 }
2263
2264 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002265 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2266 if (wpa_s->hw.modes[i].mode == hw_mode) {
2267 mode = &wpa_s->hw.modes[i];
2268 break;
2269 }
2270 }
2271
2272 if (!mode)
2273 return;
2274
Hai Shalomc3565922019-10-28 11:58:20 -07002275 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2276 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002277
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002278#ifdef CONFIG_HT_OVERRIDES
2279 if (ssid->disable_ht) {
2280 freq->ht_enabled = 0;
2281 return;
2282 }
2283#endif /* CONFIG_HT_OVERRIDES */
2284
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002285 freq->ht_enabled = ht_supported(mode);
2286 if (!freq->ht_enabled)
2287 return;
2288
Hai Shalomc3565922019-10-28 11:58:20 -07002289 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2290 if (is_24ghz)
2291 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
2292
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002293 /* Setup higher BW only for 5 GHz */
2294 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2295 return;
2296
2297 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2298 pri_chan = &mode->channels[chan_idx];
2299 if (pri_chan->chan == channel)
2300 break;
2301 pri_chan = NULL;
2302 }
2303 if (!pri_chan)
2304 return;
2305
2306 /* Check primary channel flags */
2307 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2308 return;
2309
Hai Shalom74f70d42019-02-11 14:42:39 -08002310 freq->channel = pri_chan->chan;
2311
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002312#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002313 if (ssid->disable_ht40) {
2314 if (ssid->disable_vht)
2315 return;
2316 goto skip_ht40;
2317 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002318#endif /* CONFIG_HT_OVERRIDES */
2319
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002320 /* Check/setup HT40+/HT40- */
2321 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2322 if (ht40plus[j] == channel) {
2323 ht40 = 1;
2324 break;
2325 }
2326 }
2327
2328 /* Find secondary channel */
2329 for (i = 0; i < mode->num_channels; i++) {
2330 sec_chan = &mode->channels[i];
2331 if (sec_chan->chan == channel + ht40 * 4)
2332 break;
2333 sec_chan = NULL;
2334 }
2335 if (!sec_chan)
2336 return;
2337
2338 /* Check secondary channel flags */
2339 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2340 return;
2341
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002342 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002343 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2344 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002345 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002346 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2347 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002348 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002349 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002350
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002351 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002352 struct wpa_scan_results *scan_res;
2353
2354 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2355 if (scan_res == NULL) {
2356 /* Back to HT20 */
2357 freq->sec_channel_offset = 0;
2358 return;
2359 }
2360
2361 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2362 sec_chan->chan);
2363 switch (res) {
2364 case 0:
2365 /* Back to HT20 */
2366 freq->sec_channel_offset = 0;
2367 break;
2368 case 1:
2369 /* Configuration allowed */
2370 break;
2371 case 2:
2372 /* Switch pri/sec channels */
2373 freq->freq = hw_get_freq(mode, sec_chan->chan);
2374 freq->sec_channel_offset = -freq->sec_channel_offset;
2375 freq->channel = sec_chan->chan;
2376 break;
2377 default:
2378 freq->sec_channel_offset = 0;
2379 break;
2380 }
2381
2382 wpa_scan_results_free(scan_res);
2383 }
2384
Hai Shalom74f70d42019-02-11 14:42:39 -08002385#ifdef CONFIG_HT_OVERRIDES
2386skip_ht40:
2387#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002388 wpa_printf(MSG_DEBUG,
2389 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2390 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002391
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002392 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002393 return;
2394
2395 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002396 if (ssid->mode == WPAS_MODE_IBSS &&
2397 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002398 return;
2399
2400 vht_freq = *freq;
2401
Paul Stewart092955c2017-02-06 09:13:09 -08002402#ifdef CONFIG_VHT_OVERRIDES
2403 if (ssid->disable_vht) {
2404 freq->vht_enabled = 0;
2405 return;
2406 }
2407#endif /* CONFIG_VHT_OVERRIDES */
2408
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002409 vht_freq.vht_enabled = vht_supported(mode);
2410 if (!vht_freq.vht_enabled)
2411 return;
2412
Hai Shalomc3565922019-10-28 11:58:20 -07002413 /* Enable HE for VHT */
2414 vht_freq.he_enabled = mode->he_capab[ieee80211_mode].he_supported;
2415
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002416 /* setup center_freq1, bandwidth */
2417 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2418 if (freq->channel >= vht80[j] &&
2419 freq->channel < vht80[j] + 16)
2420 break;
2421 }
2422
2423 if (j == ARRAY_SIZE(vht80))
2424 return;
2425
2426 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2427 struct hostapd_channel_data *chan;
2428
2429 chan = hw_get_channel_chan(mode, i, NULL);
2430 if (!chan)
2431 return;
2432
2433 /* Back to HT configuration if channel not usable */
2434 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2435 return;
2436 }
2437
Hai Shalom81f62d82019-07-22 12:10:00 -07002438 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002439 seg0 = vht80[j] + 6;
2440 seg1 = 0;
2441
Hai Shalom81f62d82019-07-22 12:10:00 -07002442 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002443 /* setup center_freq2, bandwidth */
2444 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2445 /* Only accept 80 MHz segments separated by a gap */
2446 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2447 continue;
2448 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2449 struct hostapd_channel_data *chan;
2450
2451 chan = hw_get_channel_chan(mode, i, NULL);
2452 if (!chan)
2453 continue;
2454
2455 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2456 HOSTAPD_CHAN_NO_IR |
2457 HOSTAPD_CHAN_RADAR))
2458 continue;
2459
2460 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002461 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002462 vht_caps |=
2463 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2464 seg1 = vht80[k] + 6;
2465 }
2466
Hai Shalom81f62d82019-07-22 12:10:00 -07002467 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002468 break;
2469 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002470 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002471 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002472 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002473 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2474 seg0 = 50;
2475 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002476 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002477 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2478 seg0 = 114;
2479 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002480 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2481 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002482 seg0 = vht80[j] + 2;
2483#ifdef CONFIG_HT_OVERRIDES
2484 if (ssid->disable_ht40)
2485 seg0 = 0;
2486#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002487 }
2488
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002489 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002490 freq->channel, ssid->enable_edmg,
2491 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002492 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002493 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002494 chwidth, seg0, seg1, vht_caps,
2495 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002496 return;
2497
2498 *freq = vht_freq;
2499
2500 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2501 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002502}
2503
2504
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002505#ifdef CONFIG_FILS
2506static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2507 size_t ie_buf_len)
2508{
2509 struct fils_hlp_req *req;
2510 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2511 const u8 *pos;
2512 u8 *buf = ie_buf;
2513
2514 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2515 list) {
2516 rem_len = ie_buf_len - ie_len;
2517 pos = wpabuf_head(req->pkt);
2518 hdr_len = 1 + 2 * ETH_ALEN + 6;
2519 hlp_len = wpabuf_len(req->pkt);
2520
2521 if (rem_len < 2 + hdr_len + hlp_len) {
2522 wpa_printf(MSG_ERROR,
2523 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2524 (unsigned long) rem_len,
2525 (unsigned long) (2 + hdr_len + hlp_len));
2526 break;
2527 }
2528
2529 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2530 /* Element ID */
2531 *buf++ = WLAN_EID_EXTENSION;
2532 /* Length */
2533 *buf++ = len;
2534 /* Element ID Extension */
2535 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2536 /* Destination MAC address */
2537 os_memcpy(buf, req->dst, ETH_ALEN);
2538 buf += ETH_ALEN;
2539 /* Source MAC address */
2540 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2541 buf += ETH_ALEN;
2542 /* LLC/SNAP Header */
2543 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2544 buf += 6;
2545 /* HLP Packet */
2546 os_memcpy(buf, pos, len - hdr_len);
2547 buf += len - hdr_len;
2548 pos += len - hdr_len;
2549
2550 hlp_len -= len - hdr_len;
2551 ie_len += 2 + len;
2552 rem_len -= 2 + len;
2553
2554 while (hlp_len) {
2555 len = (hlp_len > 255) ? 255 : hlp_len;
2556 if (rem_len < 2 + len)
2557 break;
2558 *buf++ = WLAN_EID_FRAGMENT;
2559 *buf++ = len;
2560 os_memcpy(buf, pos, len);
2561 buf += len;
2562 pos += len;
2563
2564 hlp_len -= len;
2565 ie_len += 2 + len;
2566 rem_len -= 2 + len;
2567 }
2568 }
2569
2570 return ie_len;
2571}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002572
2573
2574int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2575{
2576 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2577 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2578 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2579 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2580}
2581
2582
2583int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2584{
2585#ifdef CONFIG_FILS_SK_PFS
2586 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2587 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2588#else /* CONFIG_FILS_SK_PFS */
2589 return 0;
2590#endif /* CONFIG_FILS_SK_PFS */
2591}
2592
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002593#endif /* CONFIG_FILS */
2594
2595
2596static u8 * wpas_populate_assoc_ies(
2597 struct wpa_supplicant *wpa_s,
2598 struct wpa_bss *bss, struct wpa_ssid *ssid,
2599 struct wpa_driver_associate_params *params,
2600 enum wpa_drv_update_connect_params_mask *mask)
2601{
2602 u8 *wpa_ie;
2603 size_t max_wpa_ie_len = 500;
2604 size_t wpa_ie_len;
2605 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002606#ifdef CONFIG_MBO
2607 const u8 *mbo_ie;
2608#endif
Hai Shalom5f92bc92019-04-18 11:54:11 -07002609#ifdef CONFIG_SAE
2610 int sae_pmksa_cached = 0;
2611#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002612#ifdef CONFIG_FILS
2613 const u8 *realm, *username, *rrk;
2614 size_t realm_len, username_len, rrk_len;
2615 u16 next_seq_num;
2616 struct fils_hlp_req *req;
2617
2618 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2619 list) {
2620 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2621 2 + 2 * wpabuf_len(req->pkt) / 255;
2622 }
2623#endif /* CONFIG_FILS */
2624
2625 wpa_ie = os_malloc(max_wpa_ie_len);
2626 if (!wpa_ie) {
2627 wpa_printf(MSG_ERROR,
2628 "Failed to allocate connect IE buffer for %lu bytes",
2629 (unsigned long) max_wpa_ie_len);
2630 return NULL;
2631 }
2632
2633 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2634 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2635 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2636 int try_opportunistic;
2637 const u8 *cache_id = NULL;
2638
2639 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2640 wpa_s->conf->okc :
2641 ssid->proactive_key_caching) &&
2642 (ssid->proto & WPA_PROTO_RSN);
2643#ifdef CONFIG_FILS
2644 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2645 cache_id = wpa_bss_get_fils_cache_id(bss);
2646#endif /* CONFIG_FILS */
2647 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2648 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002649 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002650 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Hai Shalom5f92bc92019-04-18 11:54:11 -07002651#ifdef CONFIG_SAE
2652 sae_pmksa_cached = 1;
2653#endif /* CONFIG_SAE */
2654 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002655 wpa_ie_len = max_wpa_ie_len;
2656 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2657 wpa_ie, &wpa_ie_len)) {
2658 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2659 "key management and encryption suites");
2660 os_free(wpa_ie);
2661 return NULL;
2662 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002663#ifdef CONFIG_HS20
2664 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2665 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2666 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2667 wpa_ie_len = max_wpa_ie_len;
2668 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2669 wpa_ie, &wpa_ie_len)) {
2670 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2671 "key management and encryption suites");
2672 os_free(wpa_ie);
2673 return NULL;
2674 }
2675#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002676 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2677 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2678 /*
2679 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2680 * use non-WPA since the scan results did not indicate that the
2681 * AP is using WPA or WPA2.
2682 */
2683 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2684 wpa_ie_len = 0;
2685 wpa_s->wpa_proto = 0;
2686 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2687 wpa_ie_len = max_wpa_ie_len;
2688 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2689 wpa_ie, &wpa_ie_len)) {
2690 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2691 "key management and encryption suites (no "
2692 "scan results)");
2693 os_free(wpa_ie);
2694 return NULL;
2695 }
2696#ifdef CONFIG_WPS
2697 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2698 struct wpabuf *wps_ie;
2699 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2700 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2701 wpa_ie_len = wpabuf_len(wps_ie);
2702 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2703 } else
2704 wpa_ie_len = 0;
2705 wpabuf_free(wps_ie);
2706 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2707 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2708 params->wps = WPS_MODE_PRIVACY;
2709 else
2710 params->wps = WPS_MODE_OPEN;
2711 wpa_s->wpa_proto = 0;
2712#endif /* CONFIG_WPS */
2713 } else {
2714 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2715 wpa_ie_len = 0;
2716 wpa_s->wpa_proto = 0;
2717 }
2718
2719#ifdef IEEE8021X_EAPOL
2720 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2721 if (ssid->leap) {
2722 if (ssid->non_leap == 0)
2723 algs = WPA_AUTH_ALG_LEAP;
2724 else
2725 algs |= WPA_AUTH_ALG_LEAP;
2726 }
2727 }
2728
2729#ifdef CONFIG_FILS
2730 /* Clear FILS association */
2731 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2732
2733 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2734 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2735 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2736 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002737 &next_seq_num, &rrk, &rrk_len) == 0 &&
2738 (!wpa_s->last_con_fail_realm ||
2739 wpa_s->last_con_fail_realm_len != realm_len ||
2740 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002741 algs = WPA_AUTH_ALG_FILS;
2742 params->fils_erp_username = username;
2743 params->fils_erp_username_len = username_len;
2744 params->fils_erp_realm = realm;
2745 params->fils_erp_realm_len = realm_len;
2746 params->fils_erp_next_seq_num = next_seq_num;
2747 params->fils_erp_rrk = rrk;
2748 params->fils_erp_rrk_len = rrk_len;
2749
2750 if (mask)
2751 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2752 }
2753#endif /* CONFIG_FILS */
2754#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002755#ifdef CONFIG_SAE
2756 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2757 algs = WPA_AUTH_ALG_SAE;
2758#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002759
2760 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2761 if (ssid->auth_alg) {
2762 algs = ssid->auth_alg;
2763 wpa_dbg(wpa_s, MSG_DEBUG,
2764 "Overriding auth_alg selection: 0x%x", algs);
2765 }
2766
Hai Shalom5f92bc92019-04-18 11:54:11 -07002767#ifdef CONFIG_SAE
2768 if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
2769 wpa_dbg(wpa_s, MSG_DEBUG,
2770 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2771 algs = WPA_AUTH_ALG_OPEN;
2772 }
2773#endif /* CONFIG_SAE */
2774
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002775#ifdef CONFIG_P2P
2776 if (wpa_s->global->p2p) {
2777 u8 *pos;
2778 size_t len;
2779 int res;
2780 pos = wpa_ie + wpa_ie_len;
2781 len = max_wpa_ie_len - wpa_ie_len;
2782 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2783 ssid->p2p_group);
2784 if (res >= 0)
2785 wpa_ie_len += res;
2786 }
2787
2788 wpa_s->cross_connect_disallowed = 0;
2789 if (bss) {
2790 struct wpabuf *p2p;
2791 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2792 if (p2p) {
2793 wpa_s->cross_connect_disallowed =
2794 p2p_get_cross_connect_disallowed(p2p);
2795 wpabuf_free(p2p);
2796 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2797 "connection",
2798 wpa_s->cross_connect_disallowed ?
2799 "disallows" : "allows");
2800 }
2801 }
2802
2803 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2804#endif /* CONFIG_P2P */
2805
2806 if (bss) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002807 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002808 wpa_ie + wpa_ie_len,
2809 max_wpa_ie_len -
2810 wpa_ie_len);
2811 }
2812
2813 /*
2814 * Workaround: Add Extended Capabilities element only if the AP
2815 * included this element in Beacon/Probe Response frames. Some older
2816 * APs seem to have interoperability issues if this element is
2817 * included, so while the standard may require us to include the
2818 * element in all cases, it is justifiable to skip it to avoid
2819 * interoperability issues.
2820 */
2821 if (ssid->p2p_group)
2822 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2823 else
2824 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2825
2826 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2827 u8 ext_capab[18];
2828 int ext_capab_len;
2829 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2830 sizeof(ext_capab));
2831 if (ext_capab_len > 0 &&
2832 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2833 u8 *pos = wpa_ie;
2834 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2835 pos += 2 + pos[1];
2836 os_memmove(pos + ext_capab_len, pos,
2837 wpa_ie_len - (pos - wpa_ie));
2838 wpa_ie_len += ext_capab_len;
2839 os_memcpy(pos, ext_capab, ext_capab_len);
2840 }
2841 }
2842
2843#ifdef CONFIG_HS20
2844 if (is_hs20_network(wpa_s, ssid, bss)) {
2845 struct wpabuf *hs20;
2846
Roshan Pius3a1667e2018-07-03 15:17:14 -07002847 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002848 if (hs20) {
2849 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2850 size_t len;
2851
Hai Shalom74f70d42019-02-11 14:42:39 -08002852 wpas_hs20_add_indication(hs20, pps_mo_id,
2853 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002854 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002855 len = max_wpa_ie_len - wpa_ie_len;
2856 if (wpabuf_len(hs20) <= len) {
2857 os_memcpy(wpa_ie + wpa_ie_len,
2858 wpabuf_head(hs20), wpabuf_len(hs20));
2859 wpa_ie_len += wpabuf_len(hs20);
2860 }
2861 wpabuf_free(hs20);
2862
2863 hs20_configure_frame_filters(wpa_s);
2864 }
2865 }
2866#endif /* CONFIG_HS20 */
2867
2868 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2869 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2870 size_t len;
2871
2872 len = max_wpa_ie_len - wpa_ie_len;
2873 if (wpabuf_len(buf) <= len) {
2874 os_memcpy(wpa_ie + wpa_ie_len,
2875 wpabuf_head(buf), wpabuf_len(buf));
2876 wpa_ie_len += wpabuf_len(buf);
2877 }
2878 }
2879
2880#ifdef CONFIG_FST
2881 if (wpa_s->fst_ies) {
2882 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2883
2884 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
2885 os_memcpy(wpa_ie + wpa_ie_len,
2886 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2887 wpa_ie_len += fst_ies_len;
2888 }
2889 }
2890#endif /* CONFIG_FST */
2891
2892#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07002893 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07002894 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002895 int len;
2896
2897 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002898 max_wpa_ie_len - wpa_ie_len,
2899 !!mbo_attr_from_mbo_ie(mbo_ie,
2900 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002901 if (len >= 0)
2902 wpa_ie_len += len;
2903 }
2904#endif /* CONFIG_MBO */
2905
2906#ifdef CONFIG_FILS
2907 if (algs == WPA_AUTH_ALG_FILS) {
2908 size_t len;
2909
2910 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
2911 max_wpa_ie_len - wpa_ie_len);
2912 wpa_ie_len += len;
2913 }
2914#endif /* CONFIG_FILS */
2915
2916#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002917#ifdef CONFIG_TESTING_OPTIONS
2918 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
2919 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2920 } else
2921#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002922 if (algs == WPA_AUTH_ALG_OPEN &&
2923 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
2924 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002925 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002926
Roshan Pius3a1667e2018-07-03 15:17:14 -07002927 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002928 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08002929 } else if (wpa_s->assoc_status_code ==
2930 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002931 if (wpa_s->last_owe_group == 19)
2932 group = 20;
2933 else if (wpa_s->last_owe_group == 20)
2934 group = 21;
2935 else
2936 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002937 } else {
2938 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002939 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002940
Roshan Pius3a1667e2018-07-03 15:17:14 -07002941 wpa_s->last_owe_group = group;
2942 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002943 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2944 if (owe_ie &&
2945 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
2946 os_memcpy(wpa_ie + wpa_ie_len,
2947 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2948 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002949 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002950 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002951 }
2952#endif /* CONFIG_OWE */
2953
Hai Shalom021b0b52019-04-10 11:17:58 -07002954#ifdef CONFIG_DPP2
2955 if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
2956 ssid->dpp_netaccesskey) {
2957 dpp_pfs_free(wpa_s->dpp_pfs);
2958 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
2959 ssid->dpp_netaccesskey_len);
2960 if (!wpa_s->dpp_pfs) {
2961 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
2962 /* Try to continue without PFS */
2963 goto pfs_fail;
2964 }
2965 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
2966 max_wpa_ie_len - wpa_ie_len) {
2967 os_memcpy(wpa_ie + wpa_ie_len,
2968 wpabuf_head(wpa_s->dpp_pfs->ie),
2969 wpabuf_len(wpa_s->dpp_pfs->ie));
2970 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
2971 }
2972 }
2973pfs_fail:
2974#endif /* CONFIG_DPP2 */
2975
Roshan Pius3a1667e2018-07-03 15:17:14 -07002976#ifdef CONFIG_IEEE80211R
2977 /*
2978 * Add MDIE under these conditions: the network profile allows FT,
2979 * the AP supports FT, and the mobility domain ID matches.
2980 */
2981 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
2982 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2983
2984 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
2985 size_t len = 0;
2986 const u8 *md = mdie + 2;
2987 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
2988
2989 if (os_memcmp(md, wpa_md,
2990 MOBILITY_DOMAIN_ID_LEN) == 0) {
2991 /* Add mobility domain IE */
2992 len = wpa_ft_add_mdie(
2993 wpa_s->wpa, wpa_ie + wpa_ie_len,
2994 max_wpa_ie_len - wpa_ie_len, mdie);
2995 wpa_ie_len += len;
2996 }
2997#ifdef CONFIG_SME
2998 if (len > 0 && wpa_s->sme.ft_used &&
2999 wpa_sm_has_ptk(wpa_s->wpa)) {
3000 wpa_dbg(wpa_s, MSG_DEBUG,
3001 "SME: Trying to use FT over-the-air");
3002 algs |= WPA_AUTH_ALG_FT;
3003 }
3004#endif /* CONFIG_SME */
3005 }
3006 }
3007#endif /* CONFIG_IEEE80211R */
3008
Hai Shalomc3565922019-10-28 11:58:20 -07003009 if (wpa_s->rsnxe_len > 0 &&
3010 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3011 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3012 wpa_ie_len += wpa_s->rsnxe_len;
3013 }
3014
Hai Shalom74f70d42019-02-11 14:42:39 -08003015 if (ssid->multi_ap_backhaul_sta) {
3016 size_t multi_ap_ie_len;
3017
3018 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3019 max_wpa_ie_len - wpa_ie_len,
3020 MULTI_AP_BACKHAUL_STA);
3021 if (multi_ap_ie_len == 0) {
3022 wpa_printf(MSG_ERROR,
3023 "Multi-AP: Failed to build Multi-AP IE");
3024 os_free(wpa_ie);
3025 return NULL;
3026 }
3027 wpa_ie_len += multi_ap_ie_len;
3028 }
3029
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003030 params->wpa_ie = wpa_ie;
3031 params->wpa_ie_len = wpa_ie_len;
3032 params->auth_alg = algs;
3033 if (mask)
3034 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3035
3036 return wpa_ie;
3037}
3038
3039
Hai Shalomc3565922019-10-28 11:58:20 -07003040#ifdef CONFIG_OWE
3041static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3042{
3043 struct wpa_driver_associate_params params;
3044 u8 *wpa_ie;
3045
3046 os_memset(&params, 0, sizeof(params));
3047 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3048 wpa_s->current_ssid, &params, NULL);
3049 if (!wpa_ie)
3050 return;
3051
3052 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3053 os_free(wpa_ie);
3054}
3055#endif /* CONFIG_OWE */
3056
3057
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003058#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3059static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3060{
3061 struct wpa_driver_associate_params params;
3062 enum wpa_drv_update_connect_params_mask mask = 0;
3063 u8 *wpa_ie;
3064
3065 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3066 return; /* nothing to do */
3067
3068 os_memset(&params, 0, sizeof(params));
3069 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3070 wpa_s->current_ssid, &params, &mask);
3071 if (!wpa_ie)
3072 return;
3073
3074 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3075 os_free(wpa_ie);
3076 return;
3077 }
3078
3079 wpa_s->auth_alg = params.auth_alg;
3080 wpa_drv_update_connect_params(wpa_s, &params, mask);
3081 os_free(wpa_ie);
3082}
3083#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3084
3085
Hai Shalomc3565922019-10-28 11:58:20 -07003086static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3087{
3088 if (!edmg_ie || edmg_ie[1] < 6)
3089 return 0;
3090 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3091}
3092
3093
3094static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3095{
3096 if (!edmg_ie || edmg_ie[1] < 6)
3097 return 0;
3098 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3099}
3100
3101
3102/* Returns the intersection of two EDMG configurations.
3103 * Note: The current implementation is limited to CB2 only (CB1 included),
3104 * i.e., the implementation supports up to 2 contiguous channels.
3105 * For supporting non-contiguous (aggregated) channels and for supporting
3106 * CB3 and above, this function will need to be extended.
3107 */
3108static struct ieee80211_edmg_config
3109get_edmg_intersection(struct ieee80211_edmg_config a,
3110 struct ieee80211_edmg_config b,
3111 u8 primary_channel)
3112{
3113 struct ieee80211_edmg_config result;
3114 int i, contiguous = 0;
3115 int max_contiguous = 0;
3116
3117 result.channels = b.channels & a.channels;
3118 if (!result.channels) {
3119 wpa_printf(MSG_DEBUG,
3120 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3121 a.channels, b.channels);
3122 goto fail;
3123 }
3124
3125 if (!(result.channels & BIT(primary_channel - 1))) {
3126 wpa_printf(MSG_DEBUG,
3127 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3128 primary_channel, result.channels);
3129 goto fail;
3130 }
3131
3132 /* Find max contiguous channels */
3133 for (i = 0; i < 6; i++) {
3134 if (result.channels & BIT(i))
3135 contiguous++;
3136 else
3137 contiguous = 0;
3138
3139 if (contiguous > max_contiguous)
3140 max_contiguous = contiguous;
3141 }
3142
3143 /* Assuming AP and STA supports ONLY contiguous channels,
3144 * bw configuration can have value between 4-7.
3145 */
3146 if ((b.bw_config < a.bw_config))
3147 result.bw_config = b.bw_config;
3148 else
3149 result.bw_config = a.bw_config;
3150
3151 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3152 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3153 wpa_printf(MSG_DEBUG,
3154 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3155 max_contiguous);
3156 goto fail;
3157 }
3158
3159 return result;
3160
3161fail:
3162 result.channels = 0;
3163 result.bw_config = 0;
3164 return result;
3165}
3166
3167
3168static struct ieee80211_edmg_config
3169get_supported_edmg(struct wpa_supplicant *wpa_s,
3170 struct hostapd_freq_params *freq,
3171 struct ieee80211_edmg_config request_edmg)
3172{
3173 enum hostapd_hw_mode hw_mode;
3174 struct hostapd_hw_modes *mode = NULL;
3175 u8 primary_channel;
3176
3177 if (!wpa_s->hw.modes)
3178 goto fail;
3179
3180 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3181 if (hw_mode == NUM_HOSTAPD_MODES)
3182 goto fail;
3183
3184 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode);
3185 if (!mode)
3186 goto fail;
3187
3188 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3189
3190fail:
3191 request_edmg.channels = 0;
3192 request_edmg.bw_config = 0;
3193 return request_edmg;
3194}
3195
3196
Hai Shalom021b0b52019-04-10 11:17:58 -07003197#ifdef CONFIG_MBO
3198void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3199{
3200 struct wpa_driver_associate_params params;
3201 u8 *wpa_ie;
3202
3203 /*
3204 * Update MBO connect params only in case of change of MBO attributes
3205 * when connected, if the AP support MBO.
3206 */
3207
3208 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3209 !wpa_s->current_bss ||
3210 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3211 return;
3212
3213 os_memset(&params, 0, sizeof(params));
3214 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3215 wpa_s->current_ssid, &params, NULL);
3216 if (!wpa_ie)
3217 return;
3218
3219 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3220 os_free(wpa_ie);
3221}
3222#endif /* CONFIG_MBO */
3223
3224
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003225static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3226{
3227 struct wpa_connect_work *cwork = work->ctx;
3228 struct wpa_bss *bss = cwork->bss;
3229 struct wpa_ssid *ssid = cwork->ssid;
3230 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003231 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003232 const u8 *edmg_ie_oper;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003233 int use_crypt, ret, i, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003234 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003235 struct wpa_driver_associate_params params;
3236 int wep_keys_set = 0;
3237 int assoc_failed = 0;
3238 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003239 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003240#ifdef CONFIG_HT_OVERRIDES
3241 struct ieee80211_ht_capabilities htcaps;
3242 struct ieee80211_ht_capabilities htcaps_mask;
3243#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003244#ifdef CONFIG_VHT_OVERRIDES
3245 struct ieee80211_vht_capabilities vhtcaps;
3246 struct ieee80211_vht_capabilities vhtcaps_mask;
3247#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003248
3249 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003250 if (work->started) {
3251 wpa_s->connect_work = NULL;
3252
3253 /* cancel possible auth. timeout */
3254 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3255 NULL);
3256 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003257 wpas_connect_work_free(cwork);
3258 return;
3259 }
3260
3261 wpa_s->connect_work = work;
3262
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003263 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3264 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003265 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3266 wpas_connect_work_done(wpa_s);
3267 return;
3268 }
3269
Dmitry Shmidte4663042016-04-04 10:07:49 -07003270 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003271 os_memset(&params, 0, sizeof(params));
3272 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003273 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003274 if (bss &&
3275 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003276#ifdef CONFIG_IEEE80211R
3277 const u8 *ie, *md = NULL;
3278#endif /* CONFIG_IEEE80211R */
3279 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3280 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3281 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3282 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3283 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3284 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3285 if (bssid_changed)
3286 wpas_notify_bssid_changed(wpa_s);
3287#ifdef CONFIG_IEEE80211R
3288 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3289 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3290 md = ie + 2;
3291 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3292 if (md) {
3293 /* Prepare for the next transition */
3294 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3295 }
3296#endif /* CONFIG_IEEE80211R */
3297#ifdef CONFIG_WPS
3298 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3299 wpa_s->conf->ap_scan == 2 &&
3300 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3301 /* Use ap_scan==1 style network selection to find the network
3302 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003303 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003304 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003305 wpa_s->reassociate = 1;
3306 wpa_supplicant_req_scan(wpa_s, 0, 0);
3307 return;
3308#endif /* CONFIG_WPS */
3309 } else {
3310 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3311 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003312 if (bss)
3313 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3314 else
3315 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003316 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003317 if (!wpa_s->pno)
3318 wpa_supplicant_cancel_sched_scan(wpa_s);
3319
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003320 wpa_supplicant_cancel_scan(wpa_s);
3321
3322 /* Starting new association, so clear the possibly used WPA IE from the
3323 * previous association. */
3324 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003325 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3326 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003328 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3329 if (!wpa_ie) {
3330 wpas_connect_work_done(wpa_s);
3331 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003332 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003333
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003334 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3335 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003336 cipher_pairwise = wpa_s->pairwise_cipher;
3337 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003338 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003339 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3340 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3341 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3342 use_crypt = 0;
3343 if (wpa_set_wep_keys(wpa_s, ssid)) {
3344 use_crypt = 1;
3345 wep_keys_set = 1;
3346 }
3347 }
3348 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3349 use_crypt = 0;
3350
3351#ifdef IEEE8021X_EAPOL
3352 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3353 if ((ssid->eapol_flags &
3354 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3355 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3356 !wep_keys_set) {
3357 use_crypt = 0;
3358 } else {
3359 /* Assume that dynamic WEP-104 keys will be used and
3360 * set cipher suites in order for drivers to expect
3361 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003362 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003363 }
3364 }
3365#endif /* IEEE8021X_EAPOL */
3366
3367 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3368 /* Set the key before (and later after) association */
3369 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3370 }
3371
3372 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3373 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003374 params.ssid = bss->ssid;
3375 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003376 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3377 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003378 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3379 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003380 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003381 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003382 ssid->bssid_set,
3383 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003384 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003385 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003386 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003387 params.bssid_hint = bss->bssid;
3388 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003389 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003390 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003391 if (ssid->bssid_hint_set)
3392 params.bssid_hint = ssid->bssid_hint;
3393
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003394 params.ssid = ssid->ssid;
3395 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003396 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003397 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003398
3399 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3400 wpa_s->conf->ap_scan == 2) {
3401 params.bssid = ssid->bssid;
3402 params.fixed_bssid = 1;
3403 }
3404
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003405 /* Initial frequency for IBSS/mesh */
3406 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003407 ssid->frequency > 0 && params.freq.freq == 0)
3408 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003409
3410 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003411 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003412 if (ssid->beacon_int)
3413 params.beacon_int = ssid->beacon_int;
3414 else
3415 params.beacon_int = wpa_s->conf->beacon_int;
3416 }
3417
Hai Shalomc3565922019-10-28 11:58:20 -07003418 if (bss && ssid->enable_edmg)
3419 edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len,
3420 WLAN_EID_EXT_EDMG_OPERATION);
3421 else
3422 edmg_ie_oper = NULL;
3423
3424 if (edmg_ie_oper) {
3425 params.freq.edmg.channels =
3426 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3427 params.freq.edmg.bw_config =
3428 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3429 wpa_printf(MSG_DEBUG,
3430 "AP supports EDMG channels 0x%x, bw_config %d",
3431 params.freq.edmg.channels,
3432 params.freq.edmg.bw_config);
3433
3434 /* User may ask for specific EDMG channel for EDMG connection
3435 * (must be supported by AP)
3436 */
3437 if (ssid->edmg_channel) {
3438 struct ieee80211_edmg_config configured_edmg;
3439 enum hostapd_hw_mode hw_mode;
3440 u8 primary_channel;
3441
3442 hw_mode = ieee80211_freq_to_chan(bss->freq,
3443 &primary_channel);
3444 if (hw_mode == NUM_HOSTAPD_MODES)
3445 goto edmg_fail;
3446
3447 hostapd_encode_edmg_chan(ssid->enable_edmg,
3448 ssid->edmg_channel,
3449 primary_channel,
3450 &configured_edmg);
3451
3452 if (ieee802_edmg_is_allowed(params.freq.edmg,
3453 configured_edmg)) {
3454 params.freq.edmg = configured_edmg;
3455 wpa_printf(MSG_DEBUG,
3456 "Use EDMG channel %d for connection",
3457 ssid->edmg_channel);
3458 } else {
3459 edmg_fail:
3460 params.freq.edmg.channels = 0;
3461 params.freq.edmg.bw_config = 0;
3462 wpa_printf(MSG_WARNING,
3463 "EDMG channel %d not supported by AP, fallback to DMG",
3464 ssid->edmg_channel);
3465 }
3466 }
3467
3468 if (params.freq.edmg.channels) {
3469 wpa_printf(MSG_DEBUG,
3470 "EDMG before: channels 0x%x, bw_config %d",
3471 params.freq.edmg.channels,
3472 params.freq.edmg.bw_config);
3473 params.freq.edmg = get_supported_edmg(wpa_s,
3474 &params.freq,
3475 params.freq.edmg);
3476 wpa_printf(MSG_DEBUG,
3477 "EDMG after: channels 0x%x, bw_config %d",
3478 params.freq.edmg.channels,
3479 params.freq.edmg.bw_config);
3480 }
3481 }
3482
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003483 params.pairwise_suite = cipher_pairwise;
3484 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003485 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003486 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003487 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003488 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003490 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491 for (i = 0; i < NUM_WEP_KEYS; i++) {
3492 if (ssid->wep_key_len[i])
3493 params.wep_key[i] = ssid->wep_key[i];
3494 params.wep_key_len[i] = ssid->wep_key_len[i];
3495 }
3496 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
3497
Hai Shalom74f70d42019-02-11 14:42:39 -08003498 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003499 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3500 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003501 params.passphrase = ssid->passphrase;
3502 if (ssid->psk_set)
3503 params.psk = ssid->psk;
3504 }
3505
Hai Shalom74f70d42019-02-11 14:42:39 -08003506 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3507 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3508 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3509 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3510 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003511 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003512
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003513 if (wpa_s->conf->key_mgmt_offload) {
3514 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3515 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003516 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3517 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003518 params.req_key_mgmt_offload =
3519 ssid->proactive_key_caching < 0 ?
3520 wpa_s->conf->okc : ssid->proactive_key_caching;
3521 else
3522 params.req_key_mgmt_offload = 1;
3523
3524 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3525 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3526 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3527 ssid->psk_set)
3528 params.psk = ssid->psk;
3529 }
3530
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003531 params.drop_unencrypted = use_crypt;
3532
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003533 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003534 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003535 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3536 struct wpa_ie_data ie;
3537 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3538 ie.capabilities &
3539 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3540 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3541 "MFP: require MFP");
3542 params.mgmt_frame_protection =
3543 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003544#ifdef CONFIG_OWE
3545 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3546 !ssid->owe_only) {
3547 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3548#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003549 }
3550 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003551
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003552 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003553
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003554 if (wpa_s->p2pdev->set_sta_uapsd)
3555 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003556 else
3557 params.uapsd = -1;
3558
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003559#ifdef CONFIG_HT_OVERRIDES
3560 os_memset(&htcaps, 0, sizeof(htcaps));
3561 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3562 params.htcaps = (u8 *) &htcaps;
3563 params.htcaps_mask = (u8 *) &htcaps_mask;
3564 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3565#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003566#ifdef CONFIG_VHT_OVERRIDES
3567 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3568 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3569 params.vhtcaps = &vhtcaps;
3570 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003571 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003572#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003573
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003574#ifdef CONFIG_P2P
3575 /*
3576 * If multi-channel concurrency is not supported, check for any
3577 * frequency conflict. In case of any frequency conflict, remove the
3578 * least prioritized connection.
3579 */
3580 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003581 int freq, num;
3582 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003583 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003584 wpa_printf(MSG_DEBUG,
3585 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003586 freq, params.freq.freq);
3587 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003588 wpa_s, params.freq.freq, ssid) < 0) {
3589 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003590 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003591 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003592 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003593 }
3594 }
3595#endif /* CONFIG_P2P */
3596
Dmitry Shmidte4663042016-04-04 10:07:49 -07003597 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3598 wpa_s->current_ssid)
3599 params.prev_bssid = prev_bssid;
3600
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003601 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003602 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003603 if (ret < 0) {
3604 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3605 "failed");
3606 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3607 /*
3608 * The driver is known to mean what is saying, so we
3609 * can stop right here; the association will not
3610 * succeed.
3611 */
3612 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003613 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003614 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3615 return;
3616 }
3617 /* try to continue anyway; new association will be tried again
3618 * after timeout */
3619 assoc_failed = 1;
3620 }
3621
3622 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3623 /* Set the key after the association just in case association
3624 * cleared the previously configured key. */
3625 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3626 /* No need to timeout authentication since there is no key
3627 * management. */
3628 wpa_supplicant_cancel_auth_timeout(wpa_s);
3629 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3630#ifdef CONFIG_IBSS_RSN
3631 } else if (ssid->mode == WPAS_MODE_IBSS &&
3632 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3633 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3634 /*
3635 * RSN IBSS authentication is per-STA and we can disable the
3636 * per-BSSID authentication.
3637 */
3638 wpa_supplicant_cancel_auth_timeout(wpa_s);
3639#endif /* CONFIG_IBSS_RSN */
3640 } else {
3641 /* Timeout for IEEE 802.11 authentication and association */
3642 int timeout = 60;
3643
3644 if (assoc_failed) {
3645 /* give IBSS a bit more time */
3646 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3647 } else if (wpa_s->conf->ap_scan == 1) {
3648 /* give IBSS a bit more time */
3649 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3650 }
3651 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3652 }
3653
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003654 if (wep_keys_set &&
3655 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003656 /* Set static WEP keys again */
3657 wpa_set_wep_keys(wpa_s, ssid);
3658 }
3659
3660 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3661 /*
3662 * Do not allow EAP session resumption between different
3663 * network configurations.
3664 */
3665 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3666 }
3667 old_ssid = wpa_s->current_ssid;
3668 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003669
3670 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003671 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003672#ifdef CONFIG_HS20
3673 hs20_configure_frame_filters(wpa_s);
3674#endif /* CONFIG_HS20 */
3675 }
3676
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003677 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3678 wpa_supplicant_initiate_eapol(wpa_s);
3679 if (old_ssid != wpa_s->current_ssid)
3680 wpas_notify_network_changed(wpa_s);
3681}
3682
3683
3684static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3685 const u8 *addr)
3686{
3687 struct wpa_ssid *old_ssid;
3688
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003689 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003690 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003691 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003692 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003693 wpa_sm_set_config(wpa_s->wpa, NULL);
3694 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3695 if (old_ssid != wpa_s->current_ssid)
3696 wpas_notify_network_changed(wpa_s);
3697 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3698}
3699
3700
3701/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003702 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3703 * @wpa_s: Pointer to wpa_supplicant data
3704 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3705 *
3706 * This function is used to request %wpa_supplicant to deauthenticate from the
3707 * current AP.
3708 */
3709void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003710 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003711{
3712 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003713 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003714 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003715
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003716 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003717 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003718 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003719 reason_code, reason2str(reason_code),
3720 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003721
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003722 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3723 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3724 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003725 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003726 else if (!is_zero_ether_addr(wpa_s->bssid))
3727 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003728 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3729 /*
3730 * When using driver-based BSS selection, we may not know the
3731 * BSSID with which we are currently trying to associate. We
3732 * need to notify the driver of this disconnection even in such
3733 * a case, so use the all zeros address here.
3734 */
3735 addr = wpa_s->bssid;
3736 zero_addr = 1;
3737 }
3738
Hai Shalom74f70d42019-02-11 14:42:39 -08003739 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3740 wpa_s->enabled_4addr_mode = 0;
3741
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003742#ifdef CONFIG_TDLS
3743 wpa_tdls_teardown_peers(wpa_s->wpa);
3744#endif /* CONFIG_TDLS */
3745
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003746#ifdef CONFIG_MESH
3747 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003748 struct mesh_conf *mconf;
3749
3750 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003751 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3752 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003753 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3754 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003755 wpa_supplicant_leave_mesh(wpa_s);
3756 }
3757#endif /* CONFIG_MESH */
3758
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003759 if (addr) {
3760 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003761 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07003762 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003763 event.deauth_info.locally_generated = 1;
3764 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003765 if (zero_addr)
3766 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767 }
3768
3769 wpa_supplicant_clear_connection(wpa_s, addr);
3770}
3771
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003772static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3773 struct wpa_ssid *ssid)
3774{
3775 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3776 return;
3777
3778 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003779 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003780 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3781 wpas_notify_network_enabled_changed(wpa_s, ssid);
3782
3783 /*
3784 * Try to reassociate since there is no current configuration and a new
3785 * network was made available.
3786 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003787 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003788 wpa_s->reassociate = 1;
3789}
3790
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003791
Roshan Pius950bec92016-07-19 09:49:24 -07003792/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003793 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003794 * @wpa_s: wpa_supplicant structure for a network interface
3795 * Returns: The new network configuration or %NULL if operation failed
3796 *
3797 * This function performs the following operations:
3798 * 1. Adds a new network.
3799 * 2. Send network addition notification.
3800 * 3. Marks the network disabled.
3801 * 4. Set network default parameters.
3802 */
3803struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3804{
3805 struct wpa_ssid *ssid;
3806
3807 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003808 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003809 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003810 wpas_notify_network_added(wpa_s, ssid);
3811 ssid->disabled = 1;
3812 wpa_config_set_network_defaults(ssid);
3813
3814 return ssid;
3815}
3816
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003817
Roshan Pius950bec92016-07-19 09:49:24 -07003818/**
3819 * wpa_supplicant_remove_network - Remove a configured network based on id
3820 * @wpa_s: wpa_supplicant structure for a network interface
3821 * @id: Unique network id to search for
3822 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3823 * could not be removed
3824 *
3825 * This function performs the following operations:
3826 * 1. Removes the network.
3827 * 2. Send network removal notification.
3828 * 3. Update internal state machines.
3829 * 4. Stop any running sched scans.
3830 */
3831int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
3832{
3833 struct wpa_ssid *ssid;
3834 int was_disabled;
3835
3836 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003837 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003838 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003839 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07003840
3841 if (wpa_s->last_ssid == ssid)
3842 wpa_s->last_ssid = NULL;
3843
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003844 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07003845#ifdef CONFIG_SME
3846 wpa_s->sme.prev_bssid_set = 0;
3847#endif /* CONFIG_SME */
3848 /*
3849 * Invalidate the EAP session cache if the current or
3850 * previously used network is removed.
3851 */
3852 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3853 }
3854
3855 if (ssid == wpa_s->current_ssid) {
3856 wpa_sm_set_config(wpa_s->wpa, NULL);
3857 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3858
3859 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3860 wpa_s->own_disconnect_req = 1;
3861 wpa_supplicant_deauthenticate(wpa_s,
3862 WLAN_REASON_DEAUTH_LEAVING);
3863 }
3864
3865 was_disabled = ssid->disabled;
3866
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003867 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07003868 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07003869
3870 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003871 wpa_printf(MSG_DEBUG,
3872 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07003873 wpa_supplicant_cancel_sched_scan(wpa_s);
3874 wpa_supplicant_req_scan(wpa_s, 0, 0);
3875 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003876
Roshan Pius950bec92016-07-19 09:49:24 -07003877 return 0;
3878}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003879
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003880
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003881/**
3882 * wpa_supplicant_enable_network - Mark a configured network as enabled
3883 * @wpa_s: wpa_supplicant structure for a network interface
3884 * @ssid: wpa_ssid structure for a configured network or %NULL
3885 *
3886 * Enables the specified network or all networks if no network specified.
3887 */
3888void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
3889 struct wpa_ssid *ssid)
3890{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003891 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003892 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3893 wpa_supplicant_enable_one_network(wpa_s, ssid);
3894 } else
3895 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003896
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003897 if (wpa_s->reassociate && !wpa_s->disconnected &&
3898 (!wpa_s->current_ssid ||
3899 wpa_s->wpa_state == WPA_DISCONNECTED ||
3900 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003901 if (wpa_s->sched_scanning) {
3902 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
3903 "new network to scan filters");
3904 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003905 }
3906
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003907 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3908 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003909 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003910 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003911 }
3912}
3913
3914
3915/**
3916 * wpa_supplicant_disable_network - Mark a configured network as disabled
3917 * @wpa_s: wpa_supplicant structure for a network interface
3918 * @ssid: wpa_ssid structure for a configured network or %NULL
3919 *
3920 * Disables the specified network or all networks if no network specified.
3921 */
3922void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
3923 struct wpa_ssid *ssid)
3924{
3925 struct wpa_ssid *other_ssid;
3926 int was_disabled;
3927
3928 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003929 if (wpa_s->sched_scanning)
3930 wpa_supplicant_cancel_sched_scan(wpa_s);
3931
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003932 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3933 other_ssid = other_ssid->next) {
3934 was_disabled = other_ssid->disabled;
3935 if (was_disabled == 2)
3936 continue; /* do not change persistent P2P group
3937 * data */
3938
3939 other_ssid->disabled = 1;
3940
3941 if (was_disabled != other_ssid->disabled)
3942 wpas_notify_network_enabled_changed(
3943 wpa_s, other_ssid);
3944 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003945 if (wpa_s->current_ssid) {
3946 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3947 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003948 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003949 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003950 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003951 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003952 if (ssid == wpa_s->current_ssid) {
3953 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3954 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003955 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003956 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003957 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958
3959 was_disabled = ssid->disabled;
3960
3961 ssid->disabled = 1;
3962
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003963 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003964 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003965 if (wpa_s->sched_scanning) {
3966 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3967 "to remove network from filters");
3968 wpa_supplicant_cancel_sched_scan(wpa_s);
3969 wpa_supplicant_req_scan(wpa_s, 0, 0);
3970 }
3971 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003972 }
3973}
3974
3975
3976/**
3977 * wpa_supplicant_select_network - Attempt association with a network
3978 * @wpa_s: wpa_supplicant structure for a network interface
3979 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3980 */
3981void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3982 struct wpa_ssid *ssid)
3983{
3984
3985 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003986 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003987
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003988 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003989 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3990 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003991 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003992 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003993 disconnected = 1;
3994 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003995
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003996 if (ssid)
3997 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3998
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003999 /*
4000 * Mark all other networks disabled or mark all networks enabled if no
4001 * network specified.
4002 */
4003 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4004 other_ssid = other_ssid->next) {
4005 int was_disabled = other_ssid->disabled;
4006 if (was_disabled == 2)
4007 continue; /* do not change persistent P2P group data */
4008
4009 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004010 if (was_disabled && !other_ssid->disabled)
4011 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004012
4013 if (was_disabled != other_ssid->disabled)
4014 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4015 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004016
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004017 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4018 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004019 /* We are already associated with the selected network */
4020 wpa_printf(MSG_DEBUG, "Already associated with the "
4021 "selected network - do nothing");
4022 return;
4023 }
4024
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004025 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004026 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004027 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004028 wpa_s->connect_without_scan =
4029 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004030
4031 /*
4032 * Don't optimize next scan freqs since a new ESS has been
4033 * selected.
4034 */
4035 os_free(wpa_s->next_scan_freqs);
4036 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004037 } else {
4038 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004039 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004040
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004041 wpa_s->disconnected = 0;
4042 wpa_s->reassociate = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07004043#if defined(CONFIG_SAE) && defined(CONFIG_SME)
4044 os_free(wpa_s->sme.sae_rejected_groups);
4045 wpa_s->sme.sae_rejected_groups = NULL;
4046#endif /* CONFIG_SAE && CONFIG_SME */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004047 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004048 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004049 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004050 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4051 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004052
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004053 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004054 wpa_supplicant_fast_associate(wpa_s) != 1) {
4055 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004056 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004057 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004058 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004059
4060 if (ssid)
4061 wpas_notify_network_selected(wpa_s, ssid);
4062}
4063
4064
4065/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004066 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4067 * @wpa_s: wpa_supplicant structure for a network interface
4068 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4069 * @pkcs11_module_path: PKCS #11 module path or NULL
4070 * Returns: 0 on success; -1 on failure
4071 *
4072 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4073 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4074 * module path fails the paths will be reset to the default value (NULL).
4075 */
4076int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4077 const char *pkcs11_engine_path,
4078 const char *pkcs11_module_path)
4079{
4080 char *pkcs11_engine_path_copy = NULL;
4081 char *pkcs11_module_path_copy = NULL;
4082
4083 if (pkcs11_engine_path != NULL) {
4084 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4085 if (pkcs11_engine_path_copy == NULL)
4086 return -1;
4087 }
4088 if (pkcs11_module_path != NULL) {
4089 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004090 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004091 os_free(pkcs11_engine_path_copy);
4092 return -1;
4093 }
4094 }
4095
4096 os_free(wpa_s->conf->pkcs11_engine_path);
4097 os_free(wpa_s->conf->pkcs11_module_path);
4098 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4099 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4100
4101 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4102 eapol_sm_deinit(wpa_s->eapol);
4103 wpa_s->eapol = NULL;
4104 if (wpa_supplicant_init_eapol(wpa_s)) {
4105 /* Error -> Reset paths to the default value (NULL) once. */
4106 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4107 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4108 NULL);
4109
4110 return -1;
4111 }
4112 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4113
4114 return 0;
4115}
4116
4117
4118/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004119 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4120 * @wpa_s: wpa_supplicant structure for a network interface
4121 * @ap_scan: AP scan mode
4122 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4123 *
4124 */
4125int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4126{
4127
4128 int old_ap_scan;
4129
4130 if (ap_scan < 0 || ap_scan > 2)
4131 return -1;
4132
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004133 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4134 wpa_printf(MSG_INFO,
4135 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4136 }
4137
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004138#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004139 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4140 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4141 wpa_s->wpa_state < WPA_COMPLETED) {
4142 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4143 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004144 return 0;
4145 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004146#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004147
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004148 old_ap_scan = wpa_s->conf->ap_scan;
4149 wpa_s->conf->ap_scan = ap_scan;
4150
4151 if (old_ap_scan != wpa_s->conf->ap_scan)
4152 wpas_notify_ap_scan_changed(wpa_s);
4153
4154 return 0;
4155}
4156
4157
4158/**
4159 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4160 * @wpa_s: wpa_supplicant structure for a network interface
4161 * @expire_age: Expiration age in seconds
4162 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4163 *
4164 */
4165int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4166 unsigned int bss_expire_age)
4167{
4168 if (bss_expire_age < 10) {
4169 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4170 bss_expire_age);
4171 return -1;
4172 }
4173 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4174 bss_expire_age);
4175 wpa_s->conf->bss_expiration_age = bss_expire_age;
4176
4177 return 0;
4178}
4179
4180
4181/**
4182 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4183 * @wpa_s: wpa_supplicant structure for a network interface
4184 * @expire_count: number of scans after which an unseen BSS is reclaimed
4185 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4186 *
4187 */
4188int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4189 unsigned int bss_expire_count)
4190{
4191 if (bss_expire_count < 1) {
4192 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4193 bss_expire_count);
4194 return -1;
4195 }
4196 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4197 bss_expire_count);
4198 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4199
4200 return 0;
4201}
4202
4203
4204/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004205 * wpa_supplicant_set_scan_interval - Set scan interval
4206 * @wpa_s: wpa_supplicant structure for a network interface
4207 * @scan_interval: scan interval in seconds
4208 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4209 *
4210 */
4211int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4212 int scan_interval)
4213{
4214 if (scan_interval < 0) {
4215 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4216 scan_interval);
4217 return -1;
4218 }
4219 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4220 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004221 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004222
4223 return 0;
4224}
4225
4226
4227/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004228 * wpa_supplicant_set_debug_params - Set global debug params
4229 * @global: wpa_global structure
4230 * @debug_level: debug level
4231 * @debug_timestamp: determines if show timestamp in debug data
4232 * @debug_show_keys: determines if show keys in debug data
4233 * Returns: 0 if succeed or -1 if debug_level has wrong value
4234 */
4235int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4236 int debug_timestamp, int debug_show_keys)
4237{
4238
4239 int old_level, old_timestamp, old_show_keys;
4240
4241 /* check for allowed debuglevels */
4242 if (debug_level != MSG_EXCESSIVE &&
4243 debug_level != MSG_MSGDUMP &&
4244 debug_level != MSG_DEBUG &&
4245 debug_level != MSG_INFO &&
4246 debug_level != MSG_WARNING &&
4247 debug_level != MSG_ERROR)
4248 return -1;
4249
4250 old_level = wpa_debug_level;
4251 old_timestamp = wpa_debug_timestamp;
4252 old_show_keys = wpa_debug_show_keys;
4253
4254 wpa_debug_level = debug_level;
4255 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4256 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4257
4258 if (wpa_debug_level != old_level)
4259 wpas_notify_debug_level_changed(global);
4260 if (wpa_debug_timestamp != old_timestamp)
4261 wpas_notify_debug_timestamp_changed(global);
4262 if (wpa_debug_show_keys != old_show_keys)
4263 wpas_notify_debug_show_keys_changed(global);
4264
4265 return 0;
4266}
4267
4268
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004269#ifdef CONFIG_OWE
4270static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4271 const u8 *entry_ssid, size_t entry_ssid_len)
4272{
4273 const u8 *owe, *pos, *end;
4274 u8 ssid_len;
4275 struct wpa_bss *bss;
4276
4277 /* Check network profile SSID aganst the SSID in the
4278 * OWE Transition Mode element. */
4279
4280 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4281 if (!bss)
4282 return 0;
4283
4284 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4285 if (!owe)
4286 return 0;
4287
4288 pos = owe + 6;
4289 end = owe + 2 + owe[1];
4290
4291 if (end - pos < ETH_ALEN + 1)
4292 return 0;
4293 pos += ETH_ALEN;
4294 ssid_len = *pos++;
4295 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4296 return 0;
4297
4298 return entry_ssid_len == ssid_len &&
4299 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4300}
4301#endif /* CONFIG_OWE */
4302
4303
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004304/**
4305 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4306 * @wpa_s: Pointer to wpa_supplicant data
4307 * Returns: A pointer to the current network structure or %NULL on failure
4308 */
4309struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4310{
4311 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004312 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004313 int res;
4314 size_t ssid_len;
4315 u8 bssid[ETH_ALEN];
4316 int wired;
4317
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004318 res = wpa_drv_get_ssid(wpa_s, ssid);
4319 if (res < 0) {
4320 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4321 "driver");
4322 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004323 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004324 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004325
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004326 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004327 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4328 "driver");
4329 return NULL;
4330 }
4331
4332 wired = wpa_s->conf->ap_scan == 0 &&
4333 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4334
4335 entry = wpa_s->conf->ssid;
4336 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004337 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004338 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004339 (!entry->ssid ||
4340 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4341 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004342 (!entry->bssid_set ||
4343 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4344 return entry;
4345#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004346 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4348 (entry->ssid == NULL || entry->ssid_len == 0) &&
4349 (!entry->bssid_set ||
4350 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4351 return entry;
4352#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004353
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004354#ifdef CONFIG_OWE
4355 if (!wpas_network_disabled(wpa_s, entry) &&
4356 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4357 entry->ssid_len) &&
4358 (!entry->bssid_set ||
4359 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4360 return entry;
4361#endif /* CONFIG_OWE */
4362
Dmitry Shmidt04949592012-07-19 12:16:46 -07004363 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004364 entry->ssid_len == 0 &&
4365 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4366 return entry;
4367
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004368 entry = entry->next;
4369 }
4370
4371 return NULL;
4372}
4373
4374
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004375static int select_driver(struct wpa_supplicant *wpa_s, int i)
4376{
4377 struct wpa_global *global = wpa_s->global;
4378
4379 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004380 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004381 if (global->drv_priv[i] == NULL) {
4382 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4383 "'%s'", wpa_drivers[i]->name);
4384 return -1;
4385 }
4386 }
4387
4388 wpa_s->driver = wpa_drivers[i];
4389 wpa_s->global_drv_priv = global->drv_priv[i];
4390
4391 return 0;
4392}
4393
4394
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004395static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4396 const char *name)
4397{
4398 int i;
4399 size_t len;
4400 const char *pos, *driver = name;
4401
4402 if (wpa_s == NULL)
4403 return -1;
4404
4405 if (wpa_drivers[0] == NULL) {
4406 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4407 "wpa_supplicant");
4408 return -1;
4409 }
4410
4411 if (name == NULL) {
4412 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004413 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004414 }
4415
4416 do {
4417 pos = os_strchr(driver, ',');
4418 if (pos)
4419 len = pos - driver;
4420 else
4421 len = os_strlen(driver);
4422
4423 for (i = 0; wpa_drivers[i]; i++) {
4424 if (os_strlen(wpa_drivers[i]->name) == len &&
4425 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004426 0) {
4427 /* First driver that succeeds wins */
4428 if (select_driver(wpa_s, i) == 0)
4429 return 0;
4430 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004431 }
4432
4433 driver = pos + 1;
4434 } while (pos);
4435
4436 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4437 return -1;
4438}
4439
4440
4441/**
4442 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4443 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4444 * with struct wpa_driver_ops::init()
4445 * @src_addr: Source address of the EAPOL frame
4446 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4447 * @len: Length of the EAPOL data
4448 *
4449 * This function is called for each received EAPOL frame. Most driver
4450 * interfaces rely on more generic OS mechanism for receiving frames through
4451 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4452 * take care of received EAPOL frames and deliver them to the core supplicant
4453 * code by calling this function.
4454 */
4455void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4456 const u8 *buf, size_t len)
4457{
4458 struct wpa_supplicant *wpa_s = ctx;
4459
4460 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4461 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4462
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004463#ifdef CONFIG_TESTING_OPTIONS
4464 if (wpa_s->ignore_auth_resp) {
4465 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4466 return;
4467 }
4468#endif /* CONFIG_TESTING_OPTIONS */
4469
Jouni Malinena05074c2012-12-21 21:35:35 +02004470 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4471 (wpa_s->last_eapol_matches_bssid &&
4472#ifdef CONFIG_AP
4473 !wpa_s->ap_iface &&
4474#endif /* CONFIG_AP */
4475 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004476 /*
4477 * There is possible race condition between receiving the
4478 * association event and the EAPOL frame since they are coming
4479 * through different paths from the driver. In order to avoid
4480 * issues in trying to process the EAPOL frame before receiving
4481 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004482 * the association event is received. This may also be needed in
4483 * driver-based roaming case, so also use src_addr != BSSID as a
4484 * trigger if we have previously confirmed that the
4485 * Authenticator uses BSSID as the src_addr (which is not the
4486 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004487 */
4488 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004489 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4490 wpa_supplicant_state_txt(wpa_s->wpa_state),
4491 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004492 wpabuf_free(wpa_s->pending_eapol_rx);
4493 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4494 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004495 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004496 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4497 ETH_ALEN);
4498 }
4499 return;
4500 }
4501
Jouni Malinena05074c2012-12-21 21:35:35 +02004502 wpa_s->last_eapol_matches_bssid =
4503 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4504
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004505#ifdef CONFIG_AP
4506 if (wpa_s->ap_iface) {
4507 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4508 return;
4509 }
4510#endif /* CONFIG_AP */
4511
4512 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4513 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4514 "no key management is configured");
4515 return;
4516 }
4517
4518 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004519 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004520 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4521 wpa_s->wpa_state != WPA_COMPLETED) &&
4522 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004523 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004524 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004525 int timeout = 10;
4526
4527 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4528 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4529 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4530 /* Use longer timeout for IEEE 802.1X/EAP */
4531 timeout = 70;
4532 }
4533
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004534#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004535 if (wpa_s->current_ssid && wpa_s->current_bss &&
4536 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4537 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4538 /*
4539 * Use shorter timeout if going through WPS AP iteration
4540 * for PIN config method with an AP that does not
4541 * advertise Selected Registrar.
4542 */
4543 struct wpabuf *wps_ie;
4544
4545 wps_ie = wpa_bss_get_vendor_ie_multi(
4546 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4547 if (wps_ie &&
4548 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4549 timeout = 10;
4550 wpabuf_free(wps_ie);
4551 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004552#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004553
4554 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004555 }
4556 wpa_s->eapol_received++;
4557
4558 if (wpa_s->countermeasures) {
4559 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4560 "EAPOL packet");
4561 return;
4562 }
4563
4564#ifdef CONFIG_IBSS_RSN
4565 if (wpa_s->current_ssid &&
4566 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4567 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4568 return;
4569 }
4570#endif /* CONFIG_IBSS_RSN */
4571
4572 /* Source address of the incoming EAPOL frame could be compared to the
4573 * current BSSID. However, it is possible that a centralized
4574 * Authenticator could be using another MAC address than the BSSID of
4575 * an AP, so just allow any address to be used for now. The replies are
4576 * still sent to the current BSSID (if available), though. */
4577
4578 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4579 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004580 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4581 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004582 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4583 return;
4584 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004585 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004586 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4587 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4588 /*
4589 * Set portValid = TRUE here since we are going to skip 4-way
4590 * handshake processing which would normally set portValid. We
4591 * need this to allow the EAPOL state machines to be completed
4592 * without going through EAPOL-Key handshake.
4593 */
4594 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
4595 }
4596}
4597
4598
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004599int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004600{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004601 if ((!wpa_s->p2p_mgmt ||
4602 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4603 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004604 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004605 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4606 wpa_drv_get_mac_addr(wpa_s),
4607 ETH_P_EAPOL,
4608 wpa_supplicant_rx_eapol, wpa_s, 0);
4609 if (wpa_s->l2 == NULL)
4610 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004611
4612 if (l2_packet_set_packet_filter(wpa_s->l2,
4613 L2_PACKET_FILTER_PKTTYPE))
4614 wpa_dbg(wpa_s, MSG_DEBUG,
4615 "Failed to attach pkt_type filter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004616 } else {
4617 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4618 if (addr)
4619 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4620 }
4621
4622 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4623 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
4624 return -1;
4625 }
4626
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004627 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004628 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004629
Hai Shalomc3565922019-10-28 11:58:20 -07004630#ifdef CONFIG_FST
4631 if (wpa_s->fst)
4632 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4633#endif /* CONFIG_FST */
4634
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004635 return 0;
4636}
4637
4638
Dmitry Shmidt04949592012-07-19 12:16:46 -07004639static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4640 const u8 *buf, size_t len)
4641{
4642 struct wpa_supplicant *wpa_s = ctx;
4643 const struct l2_ethhdr *eth;
4644
4645 if (len < sizeof(*eth))
4646 return;
4647 eth = (const struct l2_ethhdr *) buf;
4648
4649 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4650 !(eth->h_dest[0] & 0x01)) {
4651 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4652 " (bridge - not for this interface - ignore)",
4653 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4654 return;
4655 }
4656
4657 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4658 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4659 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4660 len - sizeof(*eth));
4661}
4662
4663
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004664/**
4665 * wpa_supplicant_driver_init - Initialize driver interface parameters
4666 * @wpa_s: Pointer to wpa_supplicant data
4667 * Returns: 0 on success, -1 on failure
4668 *
4669 * This function is called to initialize driver interface parameters.
4670 * wpa_drv_init() must have been called before this function to initialize the
4671 * driver interface.
4672 */
4673int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4674{
4675 static int interface_count = 0;
4676
4677 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4678 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004679
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004680 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4681 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004682 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004683 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4684
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004685 if (wpa_s->bridge_ifname[0]) {
4686 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4687 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004688 wpa_s->l2_br = l2_packet_init_bridge(
4689 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4690 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004691 if (wpa_s->l2_br == NULL) {
4692 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4693 "connection for the bridge interface '%s'",
4694 wpa_s->bridge_ifname);
4695 return -1;
4696 }
4697 }
4698
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004699 if (wpa_s->conf->ap_scan == 2 &&
4700 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4701 wpa_printf(MSG_INFO,
4702 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4703 }
4704
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004705 wpa_clear_keys(wpa_s, NULL);
4706
4707 /* Make sure that TKIP countermeasures are not left enabled (could
4708 * happen if wpa_supplicant is killed during countermeasures. */
4709 wpa_drv_set_countermeasures(wpa_s, 0);
4710
4711 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4712 wpa_drv_flush_pmkid(wpa_s);
4713
4714 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004715 wpa_s->prev_scan_wildcard = 0;
4716
Dmitry Shmidt04949592012-07-19 12:16:46 -07004717 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004718 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4719 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4720 interface_count = 0;
4721 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004722#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004723 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004724 wpa_supplicant_delayed_sched_scan(wpa_s,
4725 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004726 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004727 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004728 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004729#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004730 interface_count++;
4731 } else
4732 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4733
4734 return 0;
4735}
4736
4737
4738static int wpa_supplicant_daemon(const char *pid_file)
4739{
4740 wpa_printf(MSG_DEBUG, "Daemonize..");
4741 return os_daemonize(pid_file);
4742}
4743
4744
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004745static struct wpa_supplicant *
4746wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004747{
4748 struct wpa_supplicant *wpa_s;
4749
4750 wpa_s = os_zalloc(sizeof(*wpa_s));
4751 if (wpa_s == NULL)
4752 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004753 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004754 wpa_s->scan_interval = 5;
4755 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004756 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004757 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004758 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004759
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004760 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004761 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004762
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004763 return wpa_s;
4764}
4765
4766
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004767#ifdef CONFIG_HT_OVERRIDES
4768
4769static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4770 struct ieee80211_ht_capabilities *htcaps,
4771 struct ieee80211_ht_capabilities *htcaps_mask,
4772 const char *ht_mcs)
4773{
4774 /* parse ht_mcs into hex array */
4775 int i;
4776 const char *tmp = ht_mcs;
4777 char *end = NULL;
4778
4779 /* If ht_mcs is null, do not set anything */
4780 if (!ht_mcs)
4781 return 0;
4782
4783 /* This is what we are setting in the kernel */
4784 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4785
4786 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4787
4788 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004789 long v;
4790
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004791 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004792 v = strtol(tmp, &end, 16);
4793
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004794 if (errno == 0) {
4795 wpa_msg(wpa_s, MSG_DEBUG,
4796 "htcap value[%i]: %ld end: %p tmp: %p",
4797 i, v, end, tmp);
4798 if (end == tmp)
4799 break;
4800
4801 htcaps->supported_mcs_set[i] = v;
4802 tmp = end;
4803 } else {
4804 wpa_msg(wpa_s, MSG_ERROR,
4805 "Failed to parse ht-mcs: %s, error: %s\n",
4806 ht_mcs, strerror(errno));
4807 return -1;
4808 }
4809 }
4810
4811 /*
4812 * If we were able to parse any values, then set mask for the MCS set.
4813 */
4814 if (i) {
4815 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4816 IEEE80211_HT_MCS_MASK_LEN - 1);
4817 /* skip the 3 reserved bits */
4818 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4819 0x1f;
4820 }
4821
4822 return 0;
4823}
4824
4825
4826static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4827 struct ieee80211_ht_capabilities *htcaps,
4828 struct ieee80211_ht_capabilities *htcaps_mask,
4829 int disabled)
4830{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004831 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004832
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004833 if (disabled == -1)
4834 return 0;
4835
Hai Shalom74f70d42019-02-11 14:42:39 -08004836 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
4837
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004838 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
4839 htcaps_mask->ht_capabilities_info |= msk;
4840 if (disabled)
4841 htcaps->ht_capabilities_info &= msk;
4842 else
4843 htcaps->ht_capabilities_info |= msk;
4844
4845 return 0;
4846}
4847
4848
4849static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
4850 struct ieee80211_ht_capabilities *htcaps,
4851 struct ieee80211_ht_capabilities *htcaps_mask,
4852 int factor)
4853{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004854 if (factor == -1)
4855 return 0;
4856
Hai Shalom74f70d42019-02-11 14:42:39 -08004857 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
4858
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004859 if (factor < 0 || factor > 3) {
4860 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
4861 "Must be 0-3 or -1", factor);
4862 return -EINVAL;
4863 }
4864
4865 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
4866 htcaps->a_mpdu_params &= ~0x3;
4867 htcaps->a_mpdu_params |= factor & 0x3;
4868
4869 return 0;
4870}
4871
4872
4873static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
4874 struct ieee80211_ht_capabilities *htcaps,
4875 struct ieee80211_ht_capabilities *htcaps_mask,
4876 int density)
4877{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004878 if (density == -1)
4879 return 0;
4880
Hai Shalom74f70d42019-02-11 14:42:39 -08004881 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
4882
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004883 if (density < 0 || density > 7) {
4884 wpa_msg(wpa_s, MSG_ERROR,
4885 "ampdu_density: %d out of range. Must be 0-7 or -1.",
4886 density);
4887 return -EINVAL;
4888 }
4889
4890 htcaps_mask->a_mpdu_params |= 0x1C;
4891 htcaps->a_mpdu_params &= ~(0x1C);
4892 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
4893
4894 return 0;
4895}
4896
4897
4898static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
4899 struct ieee80211_ht_capabilities *htcaps,
4900 struct ieee80211_ht_capabilities *htcaps_mask,
4901 int disabled)
4902{
Hai Shalom74f70d42019-02-11 14:42:39 -08004903 if (disabled)
4904 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004905
Paul Stewart092955c2017-02-06 09:13:09 -08004906 set_disable_ht40(htcaps, disabled);
4907 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004908
4909 return 0;
4910}
4911
4912
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004913static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
4914 struct ieee80211_ht_capabilities *htcaps,
4915 struct ieee80211_ht_capabilities *htcaps_mask,
4916 int disabled)
4917{
4918 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004919 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
4920 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004921
Hai Shalom74f70d42019-02-11 14:42:39 -08004922 if (disabled)
4923 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004924
4925 if (disabled)
4926 htcaps->ht_capabilities_info &= ~msk;
4927 else
4928 htcaps->ht_capabilities_info |= msk;
4929
4930 htcaps_mask->ht_capabilities_info |= msk;
4931
4932 return 0;
4933}
4934
4935
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004936static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
4937 struct ieee80211_ht_capabilities *htcaps,
4938 struct ieee80211_ht_capabilities *htcaps_mask,
4939 int disabled)
4940{
4941 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004942 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004943
Hai Shalom74f70d42019-02-11 14:42:39 -08004944 if (disabled)
4945 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004946
4947 if (disabled)
4948 htcaps->ht_capabilities_info &= ~msk;
4949 else
4950 htcaps->ht_capabilities_info |= msk;
4951
4952 htcaps_mask->ht_capabilities_info |= msk;
4953
4954 return 0;
4955}
4956
4957
Hai Shalom74f70d42019-02-11 14:42:39 -08004958static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
4959 struct ieee80211_ht_capabilities *htcaps,
4960 struct ieee80211_ht_capabilities *htcaps_mask,
4961 int tx_stbc)
4962{
4963 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
4964
4965 if (tx_stbc == -1)
4966 return 0;
4967
4968 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
4969
4970 if (tx_stbc < 0 || tx_stbc > 1) {
4971 wpa_msg(wpa_s, MSG_ERROR,
4972 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
4973 return -EINVAL;
4974 }
4975
4976 htcaps_mask->ht_capabilities_info |= msk;
4977 htcaps->ht_capabilities_info &= ~msk;
4978 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
4979
4980 return 0;
4981}
4982
4983
4984static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
4985 struct ieee80211_ht_capabilities *htcaps,
4986 struct ieee80211_ht_capabilities *htcaps_mask,
4987 int rx_stbc)
4988{
4989 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
4990
4991 if (rx_stbc == -1)
4992 return 0;
4993
4994 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
4995
4996 if (rx_stbc < 0 || rx_stbc > 3) {
4997 wpa_msg(wpa_s, MSG_ERROR,
4998 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
4999 return -EINVAL;
5000 }
5001
5002 htcaps_mask->ht_capabilities_info |= msk;
5003 htcaps->ht_capabilities_info &= ~msk;
5004 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5005
5006 return 0;
5007}
5008
5009
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005010void wpa_supplicant_apply_ht_overrides(
5011 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5012 struct wpa_driver_associate_params *params)
5013{
5014 struct ieee80211_ht_capabilities *htcaps;
5015 struct ieee80211_ht_capabilities *htcaps_mask;
5016
5017 if (!ssid)
5018 return;
5019
5020 params->disable_ht = ssid->disable_ht;
5021 if (!params->htcaps || !params->htcaps_mask)
5022 return;
5023
5024 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5025 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5026 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5027 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5028 ssid->disable_max_amsdu);
5029 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5030 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5031 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005032 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005033 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005034 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5035 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005036
5037 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005038 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005039 htcaps->ht_capabilities_info |= bit;
5040 htcaps_mask->ht_capabilities_info |= bit;
5041 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005042}
5043
5044#endif /* CONFIG_HT_OVERRIDES */
5045
5046
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005047#ifdef CONFIG_VHT_OVERRIDES
5048void wpa_supplicant_apply_vht_overrides(
5049 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5050 struct wpa_driver_associate_params *params)
5051{
5052 struct ieee80211_vht_capabilities *vhtcaps;
5053 struct ieee80211_vht_capabilities *vhtcaps_mask;
5054
5055 if (!ssid)
5056 return;
5057
5058 params->disable_vht = ssid->disable_vht;
5059
5060 vhtcaps = (void *) params->vhtcaps;
5061 vhtcaps_mask = (void *) params->vhtcaps_mask;
5062
5063 if (!vhtcaps || !vhtcaps_mask)
5064 return;
5065
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005066 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5067 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005068
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005069#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005070 if (ssid->disable_sgi) {
5071 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5072 VHT_CAP_SHORT_GI_160);
5073 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5074 VHT_CAP_SHORT_GI_160);
5075 wpa_msg(wpa_s, MSG_DEBUG,
5076 "disable-sgi override specified, vht-caps: 0x%x",
5077 vhtcaps->vht_capabilities_info);
5078 }
5079
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005080 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005081 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5082 int max_ampdu;
5083
5084 max_ampdu = (ssid->vht_capa &
5085 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5086 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005087
5088 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5089 wpa_set_ampdu_factor(wpa_s,
5090 (void *) params->htcaps,
5091 (void *) params->htcaps_mask,
5092 max_ampdu);
5093 }
5094#endif /* CONFIG_HT_OVERRIDES */
5095
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005096#define OVERRIDE_MCS(i) \
5097 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5098 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005099 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005100 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005101 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5102 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005103 } \
5104 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5105 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005106 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005107 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005108 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5109 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005110 }
5111
5112 OVERRIDE_MCS(1);
5113 OVERRIDE_MCS(2);
5114 OVERRIDE_MCS(3);
5115 OVERRIDE_MCS(4);
5116 OVERRIDE_MCS(5);
5117 OVERRIDE_MCS(6);
5118 OVERRIDE_MCS(7);
5119 OVERRIDE_MCS(8);
5120}
5121#endif /* CONFIG_VHT_OVERRIDES */
5122
5123
Dmitry Shmidt04949592012-07-19 12:16:46 -07005124static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5125{
5126#ifdef PCSC_FUNCS
5127 size_t len;
5128
5129 if (!wpa_s->conf->pcsc_reader)
5130 return 0;
5131
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005132 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005133 if (!wpa_s->scard)
5134 return 1;
5135
5136 if (wpa_s->conf->pcsc_pin &&
5137 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5138 scard_deinit(wpa_s->scard);
5139 wpa_s->scard = NULL;
5140 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5141 return -1;
5142 }
5143
5144 len = sizeof(wpa_s->imsi) - 1;
5145 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5146 scard_deinit(wpa_s->scard);
5147 wpa_s->scard = NULL;
5148 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5149 return -1;
5150 }
5151 wpa_s->imsi[len] = '\0';
5152
5153 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5154
5155 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5156 wpa_s->imsi, wpa_s->mnc_len);
5157
5158 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5159 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5160#endif /* PCSC_FUNCS */
5161
5162 return 0;
5163}
5164
5165
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005166int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5167{
5168 char *val, *pos;
5169
5170 ext_password_deinit(wpa_s->ext_pw);
5171 wpa_s->ext_pw = NULL;
5172 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5173
5174 if (!wpa_s->conf->ext_password_backend)
5175 return 0;
5176
5177 val = os_strdup(wpa_s->conf->ext_password_backend);
5178 if (val == NULL)
5179 return -1;
5180 pos = os_strchr(val, ':');
5181 if (pos)
5182 *pos++ = '\0';
5183
5184 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5185
5186 wpa_s->ext_pw = ext_password_init(val, pos);
5187 os_free(val);
5188 if (wpa_s->ext_pw == NULL) {
5189 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5190 return -1;
5191 }
5192 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5193
5194 return 0;
5195}
5196
5197
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005198#ifdef CONFIG_FST
5199
5200static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5201{
5202 struct wpa_supplicant *wpa_s = ctx;
5203
5204 return (is_zero_ether_addr(wpa_s->bssid) ||
5205 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5206}
5207
5208
5209static void wpas_fst_get_channel_info_cb(void *ctx,
5210 enum hostapd_hw_mode *hw_mode,
5211 u8 *channel)
5212{
5213 struct wpa_supplicant *wpa_s = ctx;
5214
5215 if (wpa_s->current_bss) {
5216 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5217 channel);
5218 } else if (wpa_s->hw.num_modes) {
5219 *hw_mode = wpa_s->hw.modes[0].mode;
5220 } else {
5221 WPA_ASSERT(0);
5222 *hw_mode = 0;
5223 }
5224}
5225
5226
5227static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5228{
5229 struct wpa_supplicant *wpa_s = ctx;
5230
5231 *modes = wpa_s->hw.modes;
5232 return wpa_s->hw.num_modes;
5233}
5234
5235
5236static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5237{
5238 struct wpa_supplicant *wpa_s = ctx;
5239
5240 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5241 wpa_s->fst_ies = fst_ies;
5242}
5243
5244
5245static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5246{
5247 struct wpa_supplicant *wpa_s = ctx;
5248
Paul Stewart092955c2017-02-06 09:13:09 -08005249 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5250 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5251 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5252 return -1;
5253 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005254 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005255 wpa_s->own_addr, wpa_s->bssid,
5256 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005257 0);
5258}
5259
5260
5261static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5262{
5263 struct wpa_supplicant *wpa_s = ctx;
5264
5265 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5266 return wpa_s->received_mb_ies;
5267}
5268
5269
5270static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5271 const u8 *buf, size_t size)
5272{
5273 struct wpa_supplicant *wpa_s = ctx;
5274 struct mb_ies_info info;
5275
5276 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5277
5278 if (!mb_ies_info_by_ies(&info, buf, size)) {
5279 wpabuf_free(wpa_s->received_mb_ies);
5280 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5281 }
5282}
5283
5284
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005285static const u8 * wpas_fst_get_peer_first(void *ctx,
5286 struct fst_get_peer_ctx **get_ctx,
5287 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005288{
5289 struct wpa_supplicant *wpa_s = ctx;
5290
5291 *get_ctx = NULL;
5292 if (!is_zero_ether_addr(wpa_s->bssid))
5293 return (wpa_s->received_mb_ies || !mb_only) ?
5294 wpa_s->bssid : NULL;
5295 return NULL;
5296}
5297
5298
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005299static const u8 * wpas_fst_get_peer_next(void *ctx,
5300 struct fst_get_peer_ctx **get_ctx,
5301 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005302{
5303 return NULL;
5304}
5305
5306void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5307 struct fst_wpa_obj *iface_obj)
5308{
5309 iface_obj->ctx = wpa_s;
5310 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5311 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5312 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5313 iface_obj->set_ies = wpas_fst_set_ies_cb;
5314 iface_obj->send_action = wpas_fst_send_action_cb;
5315 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5316 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5317 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5318 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5319}
5320#endif /* CONFIG_FST */
5321
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005322static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005323 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005324{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005325 struct wowlan_triggers *triggers;
5326 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005327
5328 if (!wpa_s->conf->wowlan_triggers)
5329 return 0;
5330
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005331 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5332 if (triggers) {
5333 ret = wpa_drv_wowlan(wpa_s, triggers);
5334 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005335 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005336 return ret;
5337}
5338
5339
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005340enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005341{
5342 if (freq < 3000)
5343 return BAND_2_4_GHZ;
5344 if (freq > 50000)
5345 return BAND_60_GHZ;
5346 return BAND_5_GHZ;
5347}
5348
5349
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005350unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005351{
5352 int i;
5353 unsigned int band = 0;
5354
5355 if (freqs) {
5356 /* freqs are specified for the radio work */
5357 for (i = 0; freqs[i]; i++)
5358 band |= wpas_freq_to_band(freqs[i]);
5359 } else {
5360 /*
5361 * freqs are not specified, implies all
5362 * the supported freqs by HW
5363 */
5364 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5365 if (wpa_s->hw.modes[i].num_channels != 0) {
5366 if (wpa_s->hw.modes[i].mode ==
5367 HOSTAPD_MODE_IEEE80211B ||
5368 wpa_s->hw.modes[i].mode ==
5369 HOSTAPD_MODE_IEEE80211G)
5370 band |= BAND_2_4_GHZ;
5371 else if (wpa_s->hw.modes[i].mode ==
5372 HOSTAPD_MODE_IEEE80211A)
5373 band |= BAND_5_GHZ;
5374 else if (wpa_s->hw.modes[i].mode ==
5375 HOSTAPD_MODE_IEEE80211AD)
5376 band |= BAND_60_GHZ;
5377 else if (wpa_s->hw.modes[i].mode ==
5378 HOSTAPD_MODE_IEEE80211ANY)
5379 band = BAND_2_4_GHZ | BAND_5_GHZ |
5380 BAND_60_GHZ;
5381 }
5382 }
5383 }
5384
5385 return band;
5386}
5387
5388
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005389static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5390 const char *rn)
5391{
5392 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5393 struct wpa_radio *radio;
5394
5395 while (rn && iface) {
5396 radio = iface->radio;
5397 if (radio && os_strcmp(rn, radio->name) == 0) {
5398 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5399 wpa_s->ifname, rn);
5400 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5401 return radio;
5402 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005403
5404 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005405 }
5406
5407 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5408 wpa_s->ifname, rn ? rn : "N/A");
5409 radio = os_zalloc(sizeof(*radio));
5410 if (radio == NULL)
5411 return NULL;
5412
5413 if (rn)
5414 os_strlcpy(radio->name, rn, sizeof(radio->name));
5415 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005416 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005417 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5418
5419 return radio;
5420}
5421
5422
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005423static void radio_work_free(struct wpa_radio_work *work)
5424{
5425 if (work->wpa_s->scan_work == work) {
5426 /* This should not really happen. */
5427 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5428 work->type, work, work->started);
5429 work->wpa_s->scan_work = NULL;
5430 }
5431
5432#ifdef CONFIG_P2P
5433 if (work->wpa_s->p2p_scan_work == work) {
5434 /* This should not really happen. */
5435 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5436 work->type, work, work->started);
5437 work->wpa_s->p2p_scan_work = NULL;
5438 }
5439#endif /* CONFIG_P2P */
5440
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005441 if (work->started) {
5442 work->wpa_s->radio->num_active_works--;
5443 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005444 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005445 work->type, work,
5446 work->wpa_s->radio->num_active_works);
5447 }
5448
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005449 dl_list_del(&work->list);
5450 os_free(work);
5451}
5452
5453
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005454static int radio_work_is_connect(struct wpa_radio_work *work)
5455{
5456 return os_strcmp(work->type, "sme-connect") == 0 ||
5457 os_strcmp(work->type, "connect") == 0;
5458}
5459
5460
5461static int radio_work_is_scan(struct wpa_radio_work *work)
5462{
5463 return os_strcmp(work->type, "scan") == 0 ||
5464 os_strcmp(work->type, "p2p-scan") == 0;
5465}
5466
5467
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005468static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5469{
5470 struct wpa_radio_work *active_work = NULL;
5471 struct wpa_radio_work *tmp;
5472
5473 /* Get the active work to know the type and band. */
5474 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5475 if (tmp->started) {
5476 active_work = tmp;
5477 break;
5478 }
5479 }
5480
5481 if (!active_work) {
5482 /* No active work, start one */
5483 radio->num_active_works = 0;
5484 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5485 list) {
5486 if (os_strcmp(tmp->type, "scan") == 0 &&
5487 radio->external_scan_running &&
5488 (((struct wpa_driver_scan_params *)
5489 tmp->ctx)->only_new_results ||
5490 tmp->wpa_s->clear_driver_scan_cache))
5491 continue;
5492 return tmp;
5493 }
5494 return NULL;
5495 }
5496
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005497 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005498 /*
5499 * If the active work is either connect or sme-connect,
5500 * do not parallelize them with other radio works.
5501 */
5502 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5503 "Do not parallelize radio work with %s",
5504 active_work->type);
5505 return NULL;
5506 }
5507
5508 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5509 if (tmp->started)
5510 continue;
5511
5512 /*
5513 * If connect or sme-connect are enqueued, parallelize only
5514 * those operations ahead of them in the queue.
5515 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005516 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005517 break;
5518
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005519 /* Serialize parallel scan and p2p_scan operations on the same
5520 * interface since the driver_nl80211 mechanism for tracking
5521 * scan cookies does not yet have support for this. */
5522 if (active_work->wpa_s == tmp->wpa_s &&
5523 radio_work_is_scan(active_work) &&
5524 radio_work_is_scan(tmp)) {
5525 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5526 "Do not start work '%s' when another work '%s' is already scheduled",
5527 tmp->type, active_work->type);
5528 continue;
5529 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005530 /*
5531 * Check that the radio works are distinct and
5532 * on different bands.
5533 */
5534 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5535 (active_work->bands != tmp->bands)) {
5536 /*
5537 * If a scan has to be scheduled through nl80211 scan
5538 * interface and if an external scan is already running,
5539 * do not schedule the scan since it is likely to get
5540 * rejected by kernel.
5541 */
5542 if (os_strcmp(tmp->type, "scan") == 0 &&
5543 radio->external_scan_running &&
5544 (((struct wpa_driver_scan_params *)
5545 tmp->ctx)->only_new_results ||
5546 tmp->wpa_s->clear_driver_scan_cache))
5547 continue;
5548
5549 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5550 "active_work:%s new_work:%s",
5551 active_work->type, tmp->type);
5552 return tmp;
5553 }
5554 }
5555
5556 /* Did not find a radio work to schedule in parallel. */
5557 return NULL;
5558}
5559
5560
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005561static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5562{
5563 struct wpa_radio *radio = eloop_ctx;
5564 struct wpa_radio_work *work;
5565 struct os_reltime now, diff;
5566 struct wpa_supplicant *wpa_s;
5567
5568 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005569 if (work == NULL) {
5570 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005571 return;
5572 }
5573
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005574 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5575 radio_list);
5576
5577 if (!(wpa_s &&
5578 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5579 if (work->started)
5580 return; /* already started and still in progress */
5581
5582 if (wpa_s && wpa_s->radio->external_scan_running) {
5583 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5584 return;
5585 }
5586 } else {
5587 work = NULL;
5588 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5589 /* get the work to schedule next */
5590 work = radio_work_get_next_work(radio);
5591 }
5592 if (!work)
5593 return;
5594 }
5595
5596 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005597 os_get_reltime(&now);
5598 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005599 wpa_dbg(wpa_s, MSG_DEBUG,
5600 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005601 work->type, work, diff.sec, diff.usec);
5602 work->started = 1;
5603 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005604 radio->num_active_works++;
5605
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005606 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005607
5608 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5609 radio->num_active_works < MAX_ACTIVE_WORKS)
5610 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005611}
5612
5613
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005614/*
5615 * This function removes both started and pending radio works running on
5616 * the provided interface's radio.
5617 * Prior to the removal of the radio work, its callback (cb) is called with
5618 * deinit set to be 1. Each work's callback is responsible for clearing its
5619 * internal data and restoring to a correct state.
5620 * @wpa_s: wpa_supplicant data
5621 * @type: type of works to be removed
5622 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5623 * this interface's works.
5624 */
5625void radio_remove_works(struct wpa_supplicant *wpa_s,
5626 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005627{
5628 struct wpa_radio_work *work, *tmp;
5629 struct wpa_radio *radio = wpa_s->radio;
5630
5631 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5632 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005633 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005634 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005635
5636 /* skip other ifaces' works */
5637 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005638 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005639
5640 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5641 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005642 work->cb(work, 1);
5643 radio_work_free(work);
5644 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005645
5646 /* in case we removed the started work */
5647 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005648}
5649
5650
Roshan Pius3a1667e2018-07-03 15:17:14 -07005651void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5652{
5653 struct wpa_radio_work *work;
5654 struct wpa_radio *radio = wpa_s->radio;
5655
5656 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5657 if (work->ctx != ctx)
5658 continue;
5659 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5660 work->type, work, work->started ? " (started)" : "");
5661 radio_work_free(work);
5662 break;
5663 }
5664}
5665
5666
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005667static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5668{
5669 struct wpa_radio *radio = wpa_s->radio;
5670
5671 if (!radio)
5672 return;
5673
5674 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5675 wpa_s->ifname, radio->name);
5676 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005677 radio_remove_works(wpa_s, NULL, 0);
5678 wpa_s->radio = NULL;
5679 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005680 return; /* Interfaces remain for this radio */
5681
5682 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005683 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005684 os_free(radio);
5685}
5686
5687
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005688void radio_work_check_next(struct wpa_supplicant *wpa_s)
5689{
5690 struct wpa_radio *radio = wpa_s->radio;
5691
5692 if (dl_list_empty(&radio->work))
5693 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005694 if (wpa_s->ext_work_in_progress) {
5695 wpa_printf(MSG_DEBUG,
5696 "External radio work in progress - delay start of pending item");
5697 return;
5698 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005699 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5700 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5701}
5702
5703
5704/**
5705 * radio_add_work - Add a radio work item
5706 * @wpa_s: Pointer to wpa_supplicant data
5707 * @freq: Frequency of the offchannel operation in MHz or 0
5708 * @type: Unique identifier for each type of work
5709 * @next: Force as the next work to be executed
5710 * @cb: Callback function for indicating when radio is available
5711 * @ctx: Context pointer for the work (work->ctx in cb())
5712 * Returns: 0 on success, -1 on failure
5713 *
5714 * This function is used to request time for an operation that requires
5715 * exclusive radio control. Once the radio is available, the registered callback
5716 * function will be called. radio_work_done() must be called once the exclusive
5717 * radio operation has been completed, so that the radio is freed for other
5718 * operations. The special case of deinit=1 is used to free the context data
5719 * during interface removal. That does not allow the callback function to start
5720 * the radio operation, i.e., it must free any resources allocated for the radio
5721 * work and return.
5722 *
5723 * The @freq parameter can be used to indicate a single channel on which the
5724 * offchannel operation will occur. This may allow multiple radio work
5725 * operations to be performed in parallel if they apply for the same channel.
5726 * Setting this to 0 indicates that the work item may use multiple channels or
5727 * requires exclusive control of the radio.
5728 */
5729int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5730 const char *type, int next,
5731 void (*cb)(struct wpa_radio_work *work, int deinit),
5732 void *ctx)
5733{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005734 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005735 struct wpa_radio_work *work;
5736 int was_empty;
5737
5738 work = os_zalloc(sizeof(*work));
5739 if (work == NULL)
5740 return -1;
5741 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5742 os_get_reltime(&work->time);
5743 work->freq = freq;
5744 work->type = type;
5745 work->wpa_s = wpa_s;
5746 work->cb = cb;
5747 work->ctx = ctx;
5748
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005749 if (freq)
5750 work->bands = wpas_freq_to_band(freq);
5751 else if (os_strcmp(type, "scan") == 0 ||
5752 os_strcmp(type, "p2p-scan") == 0)
5753 work->bands = wpas_get_bands(wpa_s,
5754 ((struct wpa_driver_scan_params *)
5755 ctx)->freqs);
5756 else
5757 work->bands = wpas_get_bands(wpa_s, NULL);
5758
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005759 was_empty = dl_list_empty(&wpa_s->radio->work);
5760 if (next)
5761 dl_list_add(&wpa_s->radio->work, &work->list);
5762 else
5763 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5764 if (was_empty) {
5765 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5766 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005767 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5768 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5769 wpa_dbg(wpa_s, MSG_DEBUG,
5770 "Try to schedule a radio work (num_active_works=%u)",
5771 radio->num_active_works);
5772 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005773 }
5774
5775 return 0;
5776}
5777
5778
5779/**
5780 * radio_work_done - Indicate that a radio work item has been completed
5781 * @work: Completed work
5782 *
5783 * This function is called once the callback function registered with
5784 * radio_add_work() has completed its work.
5785 */
5786void radio_work_done(struct wpa_radio_work *work)
5787{
5788 struct wpa_supplicant *wpa_s = work->wpa_s;
5789 struct os_reltime now, diff;
5790 unsigned int started = work->started;
5791
5792 os_get_reltime(&now);
5793 os_reltime_sub(&now, &work->time, &diff);
5794 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5795 work->type, work, started ? "done" : "canceled",
5796 diff.sec, diff.usec);
5797 radio_work_free(work);
5798 if (started)
5799 radio_work_check_next(wpa_s);
5800}
5801
5802
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005803struct wpa_radio_work *
5804radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005805{
5806 struct wpa_radio_work *work;
5807 struct wpa_radio *radio = wpa_s->radio;
5808
5809 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5810 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005811 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005812 }
5813
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005814 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005815}
5816
5817
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005818static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005819 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005820{
5821 const char *ifname, *driver, *rn;
5822
5823 driver = iface->driver;
5824next_driver:
5825 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
5826 return -1;
5827
5828 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
5829 if (wpa_s->drv_priv == NULL) {
5830 const char *pos;
5831 pos = driver ? os_strchr(driver, ',') : NULL;
5832 if (pos) {
5833 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
5834 "driver interface - try next driver wrapper");
5835 driver = pos + 1;
5836 goto next_driver;
5837 }
5838 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
5839 "interface");
5840 return -1;
5841 }
5842 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
5843 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
5844 "driver_param '%s'", wpa_s->conf->driver_param);
5845 return -1;
5846 }
5847
5848 ifname = wpa_drv_get_ifname(wpa_s);
5849 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
5850 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
5851 "interface name with '%s'", ifname);
5852 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
5853 }
5854
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005855 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005856 if (rn && rn[0] == '\0')
5857 rn = NULL;
5858
5859 wpa_s->radio = radio_add_interface(wpa_s, rn);
5860 if (wpa_s->radio == NULL)
5861 return -1;
5862
5863 return 0;
5864}
5865
5866
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005867#ifdef CONFIG_GAS_SERVER
5868
5869static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
5870 unsigned int freq, const u8 *dst,
5871 const u8 *src, const u8 *bssid,
5872 const u8 *data, size_t data_len,
5873 enum offchannel_send_action_result result)
5874{
5875 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
5876 " result=%s",
5877 freq, MAC2STR(dst),
5878 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
5879 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
5880 "FAILED"));
5881 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
5882 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
5883}
5884
5885
5886static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
5887 struct wpabuf *buf, unsigned int wait_time)
5888{
5889 struct wpa_supplicant *wpa_s = ctx;
5890 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
5891
5892 if (wait_time > wpa_s->max_remain_on_chan)
5893 wait_time = wpa_s->max_remain_on_chan;
5894
5895 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
5896 wpabuf_head(buf), wpabuf_len(buf),
5897 wait_time, wpas_gas_server_tx_status, 0);
5898}
5899
5900#endif /* CONFIG_GAS_SERVER */
5901
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005902static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005903 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005904{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005905 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005906 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005907 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005908
5909 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
5910 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
5911 iface->confname ? iface->confname : "N/A",
5912 iface->driver ? iface->driver : "default",
5913 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
5914 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
5915
5916 if (iface->confname) {
5917#ifdef CONFIG_BACKEND_FILE
5918 wpa_s->confname = os_rel2abs_path(iface->confname);
5919 if (wpa_s->confname == NULL) {
5920 wpa_printf(MSG_ERROR, "Failed to get absolute path "
5921 "for configuration file '%s'.",
5922 iface->confname);
5923 return -1;
5924 }
5925 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
5926 iface->confname, wpa_s->confname);
5927#else /* CONFIG_BACKEND_FILE */
5928 wpa_s->confname = os_strdup(iface->confname);
5929#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005930 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005931 if (wpa_s->conf == NULL) {
5932 wpa_printf(MSG_ERROR, "Failed to read or parse "
5933 "configuration '%s'.", wpa_s->confname);
5934 return -1;
5935 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005936 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005937 if (wpa_s->confanother &&
5938 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
5939 wpa_printf(MSG_ERROR,
5940 "Failed to read or parse configuration '%s'.",
5941 wpa_s->confanother);
5942 return -1;
5943 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005944
5945 /*
5946 * Override ctrl_interface and driver_param if set on command
5947 * line.
5948 */
5949 if (iface->ctrl_interface) {
5950 os_free(wpa_s->conf->ctrl_interface);
5951 wpa_s->conf->ctrl_interface =
5952 os_strdup(iface->ctrl_interface);
5953 }
5954
5955 if (iface->driver_param) {
5956 os_free(wpa_s->conf->driver_param);
5957 wpa_s->conf->driver_param =
5958 os_strdup(iface->driver_param);
5959 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005960
5961 if (iface->p2p_mgmt && !iface->ctrl_interface) {
5962 os_free(wpa_s->conf->ctrl_interface);
5963 wpa_s->conf->ctrl_interface = NULL;
5964 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005965 } else
5966 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
5967 iface->driver_param);
5968
5969 if (wpa_s->conf == NULL) {
5970 wpa_printf(MSG_ERROR, "\nNo configuration found.");
5971 return -1;
5972 }
5973
5974 if (iface->ifname == NULL) {
5975 wpa_printf(MSG_ERROR, "\nInterface name is required.");
5976 return -1;
5977 }
5978 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
5979 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
5980 iface->ifname);
5981 return -1;
5982 }
5983 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
5984
5985 if (iface->bridge_ifname) {
5986 if (os_strlen(iface->bridge_ifname) >=
5987 sizeof(wpa_s->bridge_ifname)) {
5988 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
5989 "name '%s'.", iface->bridge_ifname);
5990 return -1;
5991 }
5992 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
5993 sizeof(wpa_s->bridge_ifname));
5994 }
5995
5996 /* RSNA Supplicant Key Management - INITIALIZE */
5997 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
5998 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
5999
6000 /* Initialize driver interface and register driver event handler before
6001 * L2 receive handler so that association events are processed before
6002 * EAPOL-Key packets if both become available for the same select()
6003 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006004 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006005 return -1;
6006
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006007 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6008 return -1;
6009
6010 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6011 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6012 NULL);
6013 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6014
6015 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6016 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6017 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6018 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6019 "dot11RSNAConfigPMKLifetime");
6020 return -1;
6021 }
6022
6023 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6024 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6025 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6026 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6027 "dot11RSNAConfigPMKReauthThreshold");
6028 return -1;
6029 }
6030
6031 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6032 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6033 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6034 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6035 "dot11RSNAConfigSATimeout");
6036 return -1;
6037 }
6038
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006039 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6040 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006041 &wpa_s->hw.flags,
6042 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006043 if (wpa_s->hw.modes) {
6044 u16 i;
6045
6046 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6047 if (wpa_s->hw.modes[i].vht_capab) {
6048 wpa_s->hw_capab = CAPAB_VHT;
6049 break;
6050 }
6051
6052 if (wpa_s->hw.modes[i].ht_capab &
6053 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6054 wpa_s->hw_capab = CAPAB_HT40;
6055 else if (wpa_s->hw.modes[i].ht_capab &&
6056 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6057 wpa_s->hw_capab = CAPAB_HT;
6058 }
6059 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006060
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006061 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6062 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006063 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006064 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006065 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006066 wpa_s->drv_smps_modes = capa.smps_modes;
6067 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006068 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006069 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006070 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006071 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6072 wpa_s->max_sched_scan_plan_interval =
6073 capa.max_sched_scan_plan_interval;
6074 wpa_s->max_sched_scan_plan_iterations =
6075 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006076 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6077 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006078 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6079 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006080 wpa_s->extended_capa = capa.extended_capa;
6081 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6082 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006083 wpa_s->num_multichan_concurrent =
6084 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006085 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6086
6087 if (capa.mac_addr_rand_scan_supported)
6088 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6089 if (wpa_s->sched_scan_supported &&
6090 capa.mac_addr_rand_sched_scan_supported)
6091 wpa_s->mac_addr_rand_supported |=
6092 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006093
6094 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6095 if (wpa_s->extended_capa &&
6096 wpa_s->extended_capa_len >= 3 &&
6097 wpa_s->extended_capa[2] & 0x40)
6098 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006099 }
6100 if (wpa_s->max_remain_on_chan == 0)
6101 wpa_s->max_remain_on_chan = 1000;
6102
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006103 /*
6104 * Only take p2p_mgmt parameters when P2P Device is supported.
6105 * Doing it here as it determines whether l2_packet_init() will be done
6106 * during wpa_supplicant_driver_init().
6107 */
6108 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6109 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006110
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006111 if (wpa_s->num_multichan_concurrent == 0)
6112 wpa_s->num_multichan_concurrent = 1;
6113
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006114 if (wpa_supplicant_driver_init(wpa_s) < 0)
6115 return -1;
6116
6117#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006118 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006119 return -1;
6120#endif /* CONFIG_TDLS */
6121
6122 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6123 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6124 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6125 return -1;
6126 }
6127
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006128#ifdef CONFIG_FST
6129 if (wpa_s->conf->fst_group_id) {
6130 struct fst_iface_cfg cfg;
6131 struct fst_wpa_obj iface_obj;
6132
6133 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6134 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6135 sizeof(cfg.group_id));
6136 cfg.priority = wpa_s->conf->fst_priority;
6137 cfg.llt = wpa_s->conf->fst_llt;
6138
6139 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6140 &iface_obj, &cfg);
6141 if (!wpa_s->fst) {
6142 wpa_msg(wpa_s, MSG_ERROR,
6143 "FST: Cannot attach iface %s to group %s",
6144 wpa_s->ifname, cfg.group_id);
6145 return -1;
6146 }
6147 }
6148#endif /* CONFIG_FST */
6149
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006150 if (wpas_wps_init(wpa_s))
6151 return -1;
6152
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006153#ifdef CONFIG_GAS_SERVER
6154 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6155 if (!wpa_s->gas_server) {
6156 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6157 return -1;
6158 }
6159#endif /* CONFIG_GAS_SERVER */
6160
6161#ifdef CONFIG_DPP
6162 if (wpas_dpp_init(wpa_s) < 0)
6163 return -1;
6164#endif /* CONFIG_DPP */
6165
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006166 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6167 return -1;
6168 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6169
6170 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6171 if (wpa_s->ctrl_iface == NULL) {
6172 wpa_printf(MSG_ERROR,
6173 "Failed to initialize control interface '%s'.\n"
6174 "You may have another wpa_supplicant process "
6175 "already running or the file was\n"
6176 "left by an unclean termination of wpa_supplicant "
6177 "in which case you will need\n"
6178 "to manually remove this file before starting "
6179 "wpa_supplicant again.\n",
6180 wpa_s->conf->ctrl_interface);
6181 return -1;
6182 }
6183
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006184 wpa_s->gas = gas_query_init(wpa_s);
6185 if (wpa_s->gas == NULL) {
6186 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6187 return -1;
6188 }
6189
Roshan Pius3a1667e2018-07-03 15:17:14 -07006190 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6191 wpa_s->p2p_mgmt) &&
6192 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006193 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6194 return -1;
6195 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006196
6197 if (wpa_bss_init(wpa_s) < 0)
6198 return -1;
6199
Paul Stewart092955c2017-02-06 09:13:09 -08006200#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6201#ifdef CONFIG_MESH
6202 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6203#endif /* CONFIG_MESH */
6204#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6205
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006206 /*
6207 * Set Wake-on-WLAN triggers, if configured.
6208 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6209 * have effect anyway when the interface is down).
6210 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006211 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006212 return -1;
6213
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006214#ifdef CONFIG_EAP_PROXY
6215{
6216 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006217 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6218 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006219 if (wpa_s->mnc_len > 0) {
6220 wpa_s->imsi[len] = '\0';
6221 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6222 wpa_s->imsi, wpa_s->mnc_len);
6223 } else {
6224 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6225 }
6226}
6227#endif /* CONFIG_EAP_PROXY */
6228
Dmitry Shmidt04949592012-07-19 12:16:46 -07006229 if (pcsc_reader_init(wpa_s) < 0)
6230 return -1;
6231
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006232 if (wpas_init_ext_pw(wpa_s) < 0)
6233 return -1;
6234
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006235 wpas_rrm_reset(wpa_s);
6236
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006237 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6238
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006239#ifdef CONFIG_HS20
6240 hs20_init(wpa_s);
6241#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006242#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006243 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006244 if ((wpa_s->conf->oce & OCE_STA) &&
6245 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6246 wpa_s->enable_oce = OCE_STA;
6247 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6248 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6249 /* TODO: Need to add STA-CFON support */
6250 wpa_printf(MSG_ERROR,
6251 "OCE STA-CFON feature is not yet supported");
6252 }
6253 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006254 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6255#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006256
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006257 wpa_supplicant_set_default_scan_ies(wpa_s);
6258
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006259 return 0;
6260}
6261
6262
6263static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006264 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006265{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006266 struct wpa_global *global = wpa_s->global;
6267 struct wpa_supplicant *iface, *prev;
6268
6269 if (wpa_s == wpa_s->parent)
6270 wpas_p2p_group_remove(wpa_s, "*");
6271
6272 iface = global->ifaces;
6273 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006274 if (iface->p2pdev == wpa_s)
6275 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006276 if (iface == wpa_s || iface->parent != wpa_s) {
6277 iface = iface->next;
6278 continue;
6279 }
6280 wpa_printf(MSG_DEBUG,
6281 "Remove remaining child interface %s from parent %s",
6282 iface->ifname, wpa_s->ifname);
6283 prev = iface;
6284 iface = iface->next;
6285 wpa_supplicant_remove_iface(global, prev, terminate);
6286 }
6287
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006288 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006289 if (wpa_s->drv_priv) {
6290 wpa_supplicant_deauthenticate(wpa_s,
6291 WLAN_REASON_DEAUTH_LEAVING);
6292
6293 wpa_drv_set_countermeasures(wpa_s, 0);
6294 wpa_clear_keys(wpa_s, NULL);
6295 }
6296
6297 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006298 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006299
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006300 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006301 radio_remove_interface(wpa_s);
6302
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006303#ifdef CONFIG_FST
6304 if (wpa_s->fst) {
6305 fst_detach(wpa_s->fst);
6306 wpa_s->fst = NULL;
6307 }
6308 if (wpa_s->received_mb_ies) {
6309 wpabuf_free(wpa_s->received_mb_ies);
6310 wpa_s->received_mb_ies = NULL;
6311 }
6312#endif /* CONFIG_FST */
6313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006314 if (wpa_s->drv_priv)
6315 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006316
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006317 if (notify)
6318 wpas_notify_iface_removed(wpa_s);
6319
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006320 if (terminate)
6321 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006322
6323 if (wpa_s->ctrl_iface) {
6324 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6325 wpa_s->ctrl_iface = NULL;
6326 }
6327
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006328#ifdef CONFIG_MESH
6329 if (wpa_s->ifmsh) {
6330 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6331 wpa_s->ifmsh = NULL;
6332 }
6333#endif /* CONFIG_MESH */
6334
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006335 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006336 wpa_config_free(wpa_s->conf);
6337 wpa_s->conf = NULL;
6338 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006339
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006340 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006341 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006342
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006343 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006344}
6345
6346
Dmitry Shmidte4663042016-04-04 10:07:49 -07006347#ifdef CONFIG_MATCH_IFACE
6348
6349/**
6350 * wpa_supplicant_match_iface - Match an interface description to a name
6351 * @global: Pointer to global data from wpa_supplicant_init()
6352 * @ifname: Name of the interface to match
6353 * Returns: Pointer to the created interface description or %NULL on failure
6354 */
6355struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6356 const char *ifname)
6357{
6358 int i;
6359 struct wpa_interface *iface, *miface;
6360
6361 for (i = 0; i < global->params.match_iface_count; i++) {
6362 miface = &global->params.match_ifaces[i];
6363 if (!miface->ifname ||
6364 fnmatch(miface->ifname, ifname, 0) == 0) {
6365 iface = os_zalloc(sizeof(*iface));
6366 if (!iface)
6367 return NULL;
6368 *iface = *miface;
6369 iface->ifname = ifname;
6370 return iface;
6371 }
6372 }
6373
6374 return NULL;
6375}
6376
6377
6378/**
6379 * wpa_supplicant_match_existing - Match existing interfaces
6380 * @global: Pointer to global data from wpa_supplicant_init()
6381 * Returns: 0 on success, -1 on failure
6382 */
6383static int wpa_supplicant_match_existing(struct wpa_global *global)
6384{
6385 struct if_nameindex *ifi, *ifp;
6386 struct wpa_supplicant *wpa_s;
6387 struct wpa_interface *iface;
6388
6389 ifp = if_nameindex();
6390 if (!ifp) {
6391 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6392 return -1;
6393 }
6394
6395 for (ifi = ifp; ifi->if_name; ifi++) {
6396 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6397 if (wpa_s)
6398 continue;
6399 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6400 if (iface) {
6401 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6402 os_free(iface);
6403 if (wpa_s)
6404 wpa_s->matched = 1;
6405 }
6406 }
6407
6408 if_freenameindex(ifp);
6409 return 0;
6410}
6411
6412#endif /* CONFIG_MATCH_IFACE */
6413
6414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006415/**
6416 * wpa_supplicant_add_iface - Add a new network interface
6417 * @global: Pointer to global data from wpa_supplicant_init()
6418 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006419 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006420 * Returns: Pointer to the created interface or %NULL on failure
6421 *
6422 * This function is used to add new network interfaces for %wpa_supplicant.
6423 * This can be called before wpa_supplicant_run() to add interfaces before the
6424 * main event loop has been started. In addition, new interfaces can be added
6425 * dynamically while %wpa_supplicant is already running. This could happen,
6426 * e.g., when a hotplug network adapter is inserted.
6427 */
6428struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006429 struct wpa_interface *iface,
6430 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006431{
6432 struct wpa_supplicant *wpa_s;
6433 struct wpa_interface t_iface;
6434 struct wpa_ssid *ssid;
6435
6436 if (global == NULL || iface == NULL)
6437 return NULL;
6438
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006439 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006440 if (wpa_s == NULL)
6441 return NULL;
6442
6443 wpa_s->global = global;
6444
6445 t_iface = *iface;
6446 if (global->params.override_driver) {
6447 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6448 "('%s' -> '%s')",
6449 iface->driver, global->params.override_driver);
6450 t_iface.driver = global->params.override_driver;
6451 }
6452 if (global->params.override_ctrl_interface) {
6453 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6454 "ctrl_interface ('%s' -> '%s')",
6455 iface->ctrl_interface,
6456 global->params.override_ctrl_interface);
6457 t_iface.ctrl_interface =
6458 global->params.override_ctrl_interface;
6459 }
6460 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6461 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6462 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006463 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006464 return NULL;
6465 }
6466
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006467 /* Notify the control interfaces about new iface */
6468 if (wpas_notify_iface_added(wpa_s)) {
6469 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6470 return NULL;
6471 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006472
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006473 /* Notify the control interfaces about new networks for non p2p mgmt
6474 * ifaces. */
6475 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006476 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6477 wpas_notify_network_added(wpa_s, ssid);
6478 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006479
6480 wpa_s->next = global->ifaces;
6481 global->ifaces = wpa_s;
6482
6483 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006484 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006485
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006486#ifdef CONFIG_P2P
6487 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006488 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006489 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006490 wpas_p2p_add_p2pdev_interface(
6491 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006492 wpa_printf(MSG_INFO,
6493 "P2P: Failed to enable P2P Device interface");
6494 /* Try to continue without. P2P will be disabled. */
6495 }
6496#endif /* CONFIG_P2P */
6497
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006498 return wpa_s;
6499}
6500
6501
6502/**
6503 * wpa_supplicant_remove_iface - Remove a network interface
6504 * @global: Pointer to global data from wpa_supplicant_init()
6505 * @wpa_s: Pointer to the network interface to be removed
6506 * Returns: 0 if interface was removed, -1 if interface was not found
6507 *
6508 * This function can be used to dynamically remove network interfaces from
6509 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6510 * addition, this function is used to remove all remaining interfaces when
6511 * %wpa_supplicant is terminated.
6512 */
6513int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006514 struct wpa_supplicant *wpa_s,
6515 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006516{
6517 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006518#ifdef CONFIG_MESH
6519 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6520 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006521 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006522#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006523
6524 /* Remove interface from the global list of interfaces */
6525 prev = global->ifaces;
6526 if (prev == wpa_s) {
6527 global->ifaces = wpa_s->next;
6528 } else {
6529 while (prev && prev->next != wpa_s)
6530 prev = prev->next;
6531 if (prev == NULL)
6532 return -1;
6533 prev->next = wpa_s->next;
6534 }
6535
6536 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6537
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006538#ifdef CONFIG_MESH
6539 if (mesh_if_created) {
6540 ifname = os_strdup(wpa_s->ifname);
6541 if (ifname == NULL) {
6542 wpa_dbg(wpa_s, MSG_ERROR,
6543 "mesh: Failed to malloc ifname");
6544 return -1;
6545 }
6546 }
6547#endif /* CONFIG_MESH */
6548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006549 if (global->p2p_group_formation == wpa_s)
6550 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006551 if (global->p2p_invite_group == wpa_s)
6552 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006553 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006554
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006555#ifdef CONFIG_MESH
6556 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006557 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006558 os_free(ifname);
6559 }
6560#endif /* CONFIG_MESH */
6561
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006562 return 0;
6563}
6564
6565
6566/**
6567 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6568 * @wpa_s: Pointer to the network interface
6569 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6570 */
6571const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6572{
6573 const char *eapol_method;
6574
6575 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6576 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6577 return "NO-EAP";
6578 }
6579
6580 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6581 if (eapol_method == NULL)
6582 return "UNKNOWN-EAP";
6583
6584 return eapol_method;
6585}
6586
6587
6588/**
6589 * wpa_supplicant_get_iface - Get a new network interface
6590 * @global: Pointer to global data from wpa_supplicant_init()
6591 * @ifname: Interface name
6592 * Returns: Pointer to the interface or %NULL if not found
6593 */
6594struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6595 const char *ifname)
6596{
6597 struct wpa_supplicant *wpa_s;
6598
6599 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6600 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6601 return wpa_s;
6602 }
6603 return NULL;
6604}
6605
6606
6607#ifndef CONFIG_NO_WPA_MSG
6608static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6609{
6610 struct wpa_supplicant *wpa_s = ctx;
6611 if (wpa_s == NULL)
6612 return NULL;
6613 return wpa_s->ifname;
6614}
6615#endif /* CONFIG_NO_WPA_MSG */
6616
6617
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006618#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6619#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6620#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6621
6622/* Periodic cleanup tasks */
6623static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6624{
6625 struct wpa_global *global = eloop_ctx;
6626 struct wpa_supplicant *wpa_s;
6627
6628 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6629 wpas_periodic, global, NULL);
6630
6631#ifdef CONFIG_P2P
6632 if (global->p2p)
6633 p2p_expire_peers(global->p2p);
6634#endif /* CONFIG_P2P */
6635
6636 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6637 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6638#ifdef CONFIG_AP
6639 ap_periodic(wpa_s);
6640#endif /* CONFIG_AP */
6641 }
6642}
6643
6644
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006645/**
6646 * wpa_supplicant_init - Initialize %wpa_supplicant
6647 * @params: Parameters for %wpa_supplicant
6648 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6649 *
6650 * This function is used to initialize %wpa_supplicant. After successful
6651 * initialization, the returned data pointer can be used to add and remove
6652 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6653 */
6654struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6655{
6656 struct wpa_global *global;
6657 int ret, i;
6658
6659 if (params == NULL)
6660 return NULL;
6661
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006662#ifdef CONFIG_DRIVER_NDIS
6663 {
6664 void driver_ndis_init_ops(void);
6665 driver_ndis_init_ops();
6666 }
6667#endif /* CONFIG_DRIVER_NDIS */
6668
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006669#ifndef CONFIG_NO_WPA_MSG
6670 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6671#endif /* CONFIG_NO_WPA_MSG */
6672
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006673 if (params->wpa_debug_file_path)
6674 wpa_debug_open_file(params->wpa_debug_file_path);
6675 else
6676 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006677 if (params->wpa_debug_syslog)
6678 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006679 if (params->wpa_debug_tracing) {
6680 ret = wpa_debug_open_linux_tracing();
6681 if (ret) {
6682 wpa_printf(MSG_ERROR,
6683 "Failed to enable trace logging");
6684 return NULL;
6685 }
6686 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006687
6688 ret = eap_register_methods();
6689 if (ret) {
6690 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6691 if (ret == -2)
6692 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6693 "the same EAP type.");
6694 return NULL;
6695 }
6696
6697 global = os_zalloc(sizeof(*global));
6698 if (global == NULL)
6699 return NULL;
6700 dl_list_init(&global->p2p_srv_bonjour);
6701 dl_list_init(&global->p2p_srv_upnp);
6702 global->params.daemonize = params->daemonize;
6703 global->params.wait_for_monitor = params->wait_for_monitor;
6704 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6705 if (params->pid_file)
6706 global->params.pid_file = os_strdup(params->pid_file);
6707 if (params->ctrl_interface)
6708 global->params.ctrl_interface =
6709 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006710 if (params->ctrl_interface_group)
6711 global->params.ctrl_interface_group =
6712 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006713 if (params->override_driver)
6714 global->params.override_driver =
6715 os_strdup(params->override_driver);
6716 if (params->override_ctrl_interface)
6717 global->params.override_ctrl_interface =
6718 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006719#ifdef CONFIG_MATCH_IFACE
6720 global->params.match_iface_count = params->match_iface_count;
6721 if (params->match_iface_count) {
6722 global->params.match_ifaces =
6723 os_calloc(params->match_iface_count,
6724 sizeof(struct wpa_interface));
6725 os_memcpy(global->params.match_ifaces,
6726 params->match_ifaces,
6727 params->match_iface_count *
6728 sizeof(struct wpa_interface));
6729 }
6730#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006731#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006732 if (params->conf_p2p_dev)
6733 global->params.conf_p2p_dev =
6734 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006735#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006736 wpa_debug_level = global->params.wpa_debug_level =
6737 params->wpa_debug_level;
6738 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6739 params->wpa_debug_show_keys;
6740 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6741 params->wpa_debug_timestamp;
6742
6743 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
6744
6745 if (eloop_init()) {
6746 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6747 wpa_supplicant_deinit(global);
6748 return NULL;
6749 }
6750
Jouni Malinen75ecf522011-06-27 15:19:46 -07006751 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006752
6753 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6754 if (global->ctrl_iface == NULL) {
6755 wpa_supplicant_deinit(global);
6756 return NULL;
6757 }
6758
6759 if (wpas_notify_supplicant_initialized(global)) {
6760 wpa_supplicant_deinit(global);
6761 return NULL;
6762 }
6763
6764 for (i = 0; wpa_drivers[i]; i++)
6765 global->drv_count++;
6766 if (global->drv_count == 0) {
6767 wpa_printf(MSG_ERROR, "No drivers enabled");
6768 wpa_supplicant_deinit(global);
6769 return NULL;
6770 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006771 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006772 if (global->drv_priv == NULL) {
6773 wpa_supplicant_deinit(global);
6774 return NULL;
6775 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006776
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006777#ifdef CONFIG_WIFI_DISPLAY
6778 if (wifi_display_init(global) < 0) {
6779 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6780 wpa_supplicant_deinit(global);
6781 return NULL;
6782 }
6783#endif /* CONFIG_WIFI_DISPLAY */
6784
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006785 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6786 wpas_periodic, global, NULL);
6787
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006788 return global;
6789}
6790
6791
6792/**
6793 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6794 * @global: Pointer to global data from wpa_supplicant_init()
6795 * Returns: 0 after successful event loop run, -1 on failure
6796 *
6797 * This function starts the main event loop and continues running as long as
6798 * there are any remaining events. In most cases, this function is running as
6799 * long as the %wpa_supplicant process in still in use.
6800 */
6801int wpa_supplicant_run(struct wpa_global *global)
6802{
6803 struct wpa_supplicant *wpa_s;
6804
6805 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006806 (wpa_supplicant_daemon(global->params.pid_file) ||
6807 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006808 return -1;
6809
Dmitry Shmidte4663042016-04-04 10:07:49 -07006810#ifdef CONFIG_MATCH_IFACE
6811 if (wpa_supplicant_match_existing(global))
6812 return -1;
6813#endif
6814
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006815 if (global->params.wait_for_monitor) {
6816 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08006817 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006818 wpa_supplicant_ctrl_iface_wait(
6819 wpa_s->ctrl_iface);
6820 }
6821
6822 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
6823 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
6824
6825 eloop_run();
6826
6827 return 0;
6828}
6829
6830
6831/**
6832 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
6833 * @global: Pointer to global data from wpa_supplicant_init()
6834 *
6835 * This function is called to deinitialize %wpa_supplicant and to free all
6836 * allocated resources. Remaining network interfaces will also be removed.
6837 */
6838void wpa_supplicant_deinit(struct wpa_global *global)
6839{
6840 int i;
6841
6842 if (global == NULL)
6843 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006844
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006845 eloop_cancel_timeout(wpas_periodic, global, NULL);
6846
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006847#ifdef CONFIG_WIFI_DISPLAY
6848 wifi_display_deinit(global);
6849#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006850
6851 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006852 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006853
6854 if (global->ctrl_iface)
6855 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
6856
6857 wpas_notify_supplicant_deinitialized(global);
6858
6859 eap_peer_unregister_methods();
6860#ifdef CONFIG_AP
6861 eap_server_unregister_methods();
6862#endif /* CONFIG_AP */
6863
6864 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
6865 if (!global->drv_priv[i])
6866 continue;
6867 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
6868 }
6869 os_free(global->drv_priv);
6870
6871 random_deinit();
6872
6873 eloop_destroy();
6874
6875 if (global->params.pid_file) {
6876 os_daemonize_terminate(global->params.pid_file);
6877 os_free(global->params.pid_file);
6878 }
6879 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006880 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006881 os_free(global->params.override_driver);
6882 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006883#ifdef CONFIG_MATCH_IFACE
6884 os_free(global->params.match_ifaces);
6885#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006886#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006887 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006888#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006889
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07006890 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006891 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006892 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006893
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006894 os_free(global);
6895 wpa_debug_close_syslog();
6896 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006897 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006898}
6899
6900
6901void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
6902{
6903 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
6904 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
6905 char country[3];
6906 country[0] = wpa_s->conf->country[0];
6907 country[1] = wpa_s->conf->country[1];
6908 country[2] = '\0';
6909 if (wpa_drv_set_country(wpa_s, country) < 0) {
6910 wpa_printf(MSG_ERROR, "Failed to set country code "
6911 "'%s'", country);
6912 }
6913 }
6914
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006915 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
6916 wpas_init_ext_pw(wpa_s);
6917
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006918 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
6919 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6920
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006921 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
6922 struct wpa_driver_capa capa;
6923 int res = wpa_drv_get_capa(wpa_s, &capa);
6924
6925 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
6926 wpa_printf(MSG_ERROR,
6927 "Failed to update wowlan_triggers to '%s'",
6928 wpa_s->conf->wowlan_triggers);
6929 }
6930
Hai Shalom81f62d82019-07-22 12:10:00 -07006931 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
6932 wpa_supplicant_set_default_scan_ies(wpa_s);
6933
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006934#ifdef CONFIG_WPS
6935 wpas_wps_update_config(wpa_s);
6936#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006937 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006938 wpa_s->conf->changed_parameters = 0;
6939}
6940
6941
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006942void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006943{
6944 int i;
6945
6946 for (i = 0; i < *num_freqs; i++) {
6947 if (freqs[i] == freq)
6948 return;
6949 }
6950
6951 freqs[*num_freqs] = freq;
6952 (*num_freqs)++;
6953}
6954
6955
6956static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
6957{
6958 struct wpa_bss *bss, *cbss;
6959 const int max_freqs = 10;
6960 int *freqs;
6961 int num_freqs = 0;
6962
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006963 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006964 if (freqs == NULL)
6965 return NULL;
6966
6967 cbss = wpa_s->current_bss;
6968
6969 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
6970 if (bss == cbss)
6971 continue;
6972 if (bss->ssid_len == cbss->ssid_len &&
6973 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
6974 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
6975 add_freq(freqs, &num_freqs, bss->freq);
6976 if (num_freqs == max_freqs)
6977 break;
6978 }
6979 }
6980
6981 if (num_freqs == 0) {
6982 os_free(freqs);
6983 freqs = NULL;
6984 }
6985
6986 return freqs;
6987}
6988
6989
6990void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6991{
6992 int timeout;
6993 int count;
6994 int *freqs = NULL;
6995
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006996 wpas_connect_work_done(wpa_s);
6997
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006998 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006999 * Remove possible authentication timeout since the connection failed.
7000 */
7001 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7002
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007003 /*
7004 * There is no point in blacklisting the AP if this event is
7005 * generated based on local request to disconnect.
7006 */
7007 if (wpa_s->own_disconnect_req) {
7008 wpa_s->own_disconnect_req = 0;
7009 wpa_dbg(wpa_s, MSG_DEBUG,
7010 "Ignore connection failure due to local request to disconnect");
7011 return;
7012 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007013 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007014 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7015 "indication since interface has been put into "
7016 "disconnected state");
7017 return;
7018 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007019 if (wpa_s->auto_reconnect_disabled) {
7020 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7021 "indication since auto connect is disabled");
7022 return;
7023 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007024
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007025 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007026 * Add the failed BSSID into the blacklist and speed up next scan
7027 * attempt if there could be other APs that could accept association.
7028 * The current blacklist count indicates how many times we have tried
7029 * connecting to this AP and multiple attempts mean that other APs are
7030 * either not available or has already been tried, so that we can start
7031 * increasing the delay here to avoid constant scanning.
7032 */
7033 count = wpa_blacklist_add(wpa_s, bssid);
7034 if (count == 1 && wpa_s->current_bss) {
7035 /*
7036 * This BSS was not in the blacklist before. If there is
7037 * another BSS available for the same ESS, we should try that
7038 * next. Otherwise, we may as well try this one once more
7039 * before allowing other, likely worse, ESSes to be considered.
7040 */
7041 freqs = get_bss_freqs_in_ess(wpa_s);
7042 if (freqs) {
7043 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7044 "has been seen; try it next");
7045 wpa_blacklist_add(wpa_s, bssid);
7046 /*
7047 * On the next scan, go through only the known channels
7048 * used in this ESS based on previous scans to speed up
7049 * common load balancing use case.
7050 */
7051 os_free(wpa_s->next_scan_freqs);
7052 wpa_s->next_scan_freqs = freqs;
7053 }
7054 }
7055
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007056 /*
7057 * Add previous failure count in case the temporary blacklist was
7058 * cleared due to no other BSSes being available.
7059 */
7060 count += wpa_s->extra_blacklist_count;
7061
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007062 if (count > 3 && wpa_s->current_ssid) {
7063 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7064 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007065 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007066 }
7067
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007068 switch (count) {
7069 case 1:
7070 timeout = 100;
7071 break;
7072 case 2:
7073 timeout = 500;
7074 break;
7075 case 3:
7076 timeout = 1000;
7077 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007078 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007079 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007080 break;
7081 default:
7082 timeout = 10000;
7083 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007084 }
7085
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007086 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
7087 "ms", count, timeout);
7088
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007089 /*
7090 * TODO: if more than one possible AP is available in scan results,
7091 * could try the other ones before requesting a new scan.
7092 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007093
7094 /* speed up the connection attempt with normal scan */
7095 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007096 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7097 1000 * (timeout % 1000));
7098}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007099
7100
Hai Shalomce48b4a2018-09-05 11:41:35 -07007101#ifdef CONFIG_FILS
7102void fils_connection_failure(struct wpa_supplicant *wpa_s)
7103{
7104 struct wpa_ssid *ssid = wpa_s->current_ssid;
7105 const u8 *realm, *username, *rrk;
7106 size_t realm_len, username_len, rrk_len;
7107 u16 next_seq_num;
7108
7109 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7110 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7111 &username, &username_len,
7112 &realm, &realm_len, &next_seq_num,
7113 &rrk, &rrk_len) != 0 ||
7114 !realm)
7115 return;
7116
7117 wpa_hexdump_ascii(MSG_DEBUG,
7118 "FILS: Store last connection failure realm",
7119 realm, realm_len);
7120 os_free(wpa_s->last_con_fail_realm);
7121 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7122 if (wpa_s->last_con_fail_realm) {
7123 wpa_s->last_con_fail_realm_len = realm_len;
7124 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7125 }
7126}
7127#endif /* CONFIG_FILS */
7128
7129
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007130int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7131{
7132 return wpa_s->conf->ap_scan == 2 ||
7133 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7134}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007135
Dmitry Shmidt04949592012-07-19 12:16:46 -07007136
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007137#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007138int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7139 struct wpa_ssid *ssid,
7140 const char *field,
7141 const char *value)
7142{
7143#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007144 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007145
7146 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7147 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7148 (const u8 *) value, os_strlen(value));
7149
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007150 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007151 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007152#else /* IEEE8021X_EAPOL */
7153 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7154 return -1;
7155#endif /* IEEE8021X_EAPOL */
7156}
7157
7158int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7159 struct wpa_ssid *ssid,
7160 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007161 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007162{
7163#ifdef IEEE8021X_EAPOL
7164 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007165 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007166
7167 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007168 case WPA_CTRL_REQ_EAP_IDENTITY:
7169 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007170 os_free(eap->imsi_identity);
7171 if (value == NULL)
7172 return -1;
7173 identity = os_strchr(value, ':');
7174 if (identity == NULL) {
7175 /* plain identity */
7176 eap->identity = (u8 *)os_strdup(value);
7177 eap->identity_len = os_strlen(value);
7178 } else {
7179 /* have both plain identity and encrypted identity */
7180 imsi_identity = value;
7181 *identity++ = '\0';
7182 /* plain identity */
7183 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7184 eap->imsi_identity_len = strlen(imsi_identity);
7185 /* encrypted identity */
7186 eap->identity = (u8 *)dup_binstr(identity,
7187 value_len - strlen(imsi_identity) - 1);
7188 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7189 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007190 eap->pending_req_identity = 0;
7191 if (ssid == wpa_s->current_ssid)
7192 wpa_s->reassociate = 1;
7193 break;
7194 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007195 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007196 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007197 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007198 eap->pending_req_password = 0;
7199 if (ssid == wpa_s->current_ssid)
7200 wpa_s->reassociate = 1;
7201 break;
7202 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007203 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007204 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007205 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007206 eap->pending_req_new_password = 0;
7207 if (ssid == wpa_s->current_ssid)
7208 wpa_s->reassociate = 1;
7209 break;
7210 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007211 str_clear_free(eap->cert.pin);
7212 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007213 eap->pending_req_pin = 0;
7214 if (ssid == wpa_s->current_ssid)
7215 wpa_s->reassociate = 1;
7216 break;
7217 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007218 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007219 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007220 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007221 os_free(eap->pending_req_otp);
7222 eap->pending_req_otp = NULL;
7223 eap->pending_req_otp_len = 0;
7224 break;
7225 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007226 str_clear_free(eap->cert.private_key_passwd);
7227 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007228 eap->pending_req_passphrase = 0;
7229 if (ssid == wpa_s->current_ssid)
7230 wpa_s->reassociate = 1;
7231 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007232 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007233 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007234 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007235 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007236 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007237 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7238 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7239 return -1;
7240 ssid->mem_only_psk = 1;
7241 if (ssid->passphrase)
7242 wpa_config_update_psk(ssid);
7243 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7244 wpa_supplicant_req_scan(wpa_s, 0, 0);
7245 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007246 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7247 if (eap->pending_ext_cert_check != PENDING_CHECK)
7248 return -1;
7249 if (os_strcmp(value, "good") == 0)
7250 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7251 else if (os_strcmp(value, "bad") == 0)
7252 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7253 else
7254 return -1;
7255 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007256 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007257 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007258 return -1;
7259 }
7260
7261 return 0;
7262#else /* IEEE8021X_EAPOL */
7263 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7264 return -1;
7265#endif /* IEEE8021X_EAPOL */
7266}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007267#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007268
7269
7270int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7271{
7272 int i;
7273 unsigned int drv_enc;
7274
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007275 if (wpa_s->p2p_mgmt)
7276 return 1; /* no normal network profiles on p2p_mgmt interface */
7277
Dmitry Shmidt04949592012-07-19 12:16:46 -07007278 if (ssid == NULL)
7279 return 1;
7280
7281 if (ssid->disabled)
7282 return 1;
7283
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007284 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007285 drv_enc = wpa_s->drv_enc;
7286 else
7287 drv_enc = (unsigned int) -1;
7288
7289 for (i = 0; i < NUM_WEP_KEYS; i++) {
7290 size_t len = ssid->wep_key_len[i];
7291 if (len == 0)
7292 continue;
7293 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7294 continue;
7295 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7296 continue;
7297 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7298 continue;
7299 return 1; /* invalid WEP key */
7300 }
7301
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007302 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007303 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007304 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007305 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007306 return 1;
7307
Dmitry Shmidt04949592012-07-19 12:16:46 -07007308 return 0;
7309}
7310
7311
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007312int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7313{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007314 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7315 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7316 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7317 /*
7318 * Driver does not support BIP -- ignore pmf=1 default
7319 * since the connection with PMF would fail and the
7320 * configuration does not require PMF to be enabled.
7321 */
7322 return NO_MGMT_FRAME_PROTECTION;
7323 }
7324
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007325 if (ssid &&
7326 (ssid->key_mgmt &
7327 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7328 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7329 /*
7330 * Do not use the default PMF value for non-RSN networks
7331 * since PMF is available only with RSN and pmf=2
7332 * configuration would otherwise prevent connections to
7333 * all open networks.
7334 */
7335 return NO_MGMT_FRAME_PROTECTION;
7336 }
7337
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007338 return wpa_s->conf->pmf;
7339 }
7340
7341 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007342}
7343
7344
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007345int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007346{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007347 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007348 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007349 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007350 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007351 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007352}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007353
7354
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007355void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007356{
7357 struct wpa_ssid *ssid = wpa_s->current_ssid;
7358 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007359 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007360
7361 if (ssid == NULL) {
7362 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7363 "SSID block");
7364 return;
7365 }
7366
7367 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7368 return;
7369
7370 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007371
7372#ifdef CONFIG_P2P
7373 if (ssid->p2p_group &&
7374 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7375 /*
7376 * Skip the wait time since there is a short timeout on the
7377 * connection to a P2P group.
7378 */
7379 return;
7380 }
7381#endif /* CONFIG_P2P */
7382
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007383 if (ssid->auth_failures > 50)
7384 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007385 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007386 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007387 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007388 dur = 90;
7389 else if (ssid->auth_failures > 3)
7390 dur = 60;
7391 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007392 dur = 30;
7393 else if (ssid->auth_failures > 1)
7394 dur = 20;
7395 else
7396 dur = 10;
7397
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007398 if (ssid->auth_failures > 1 &&
7399 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7400 dur += os_random() % (ssid->auth_failures * 10);
7401
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007402 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007403 if (now.sec + dur <= ssid->disabled_until.sec)
7404 return;
7405
7406 ssid->disabled_until.sec = now.sec + dur;
7407
7408 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007409 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007410 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007411 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007412}
7413
7414
7415void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7416 struct wpa_ssid *ssid, int clear_failures)
7417{
7418 if (ssid == NULL)
7419 return;
7420
7421 if (ssid->disabled_until.sec) {
7422 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7423 "id=%d ssid=\"%s\"",
7424 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7425 }
7426 ssid->disabled_until.sec = 0;
7427 ssid->disabled_until.usec = 0;
7428 if (clear_failures)
7429 ssid->auth_failures = 0;
7430}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007431
7432
7433int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7434{
7435 size_t i;
7436
7437 if (wpa_s->disallow_aps_bssid == NULL)
7438 return 0;
7439
7440 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7441 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7442 bssid, ETH_ALEN) == 0)
7443 return 1;
7444 }
7445
7446 return 0;
7447}
7448
7449
7450int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7451 size_t ssid_len)
7452{
7453 size_t i;
7454
7455 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7456 return 0;
7457
7458 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7459 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7460 if (ssid_len == s->ssid_len &&
7461 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7462 return 1;
7463 }
7464
7465 return 0;
7466}
7467
7468
7469/**
7470 * wpas_request_connection - Request a new connection
7471 * @wpa_s: Pointer to the network interface
7472 *
7473 * This function is used to request a new connection to be found. It will mark
7474 * the interface to allow reassociation and request a new scan to find a
7475 * suitable network to connect to.
7476 */
7477void wpas_request_connection(struct wpa_supplicant *wpa_s)
7478{
7479 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007480 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007481 wpa_supplicant_reinit_autoscan(wpa_s);
7482 wpa_s->extra_blacklist_count = 0;
7483 wpa_s->disconnected = 0;
7484 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007485 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007486
7487 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7488 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007489 else
7490 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007491}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007492
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007493
Roshan Pius02242d72016-08-09 15:31:48 -07007494/**
7495 * wpas_request_disconnection - Request disconnection
7496 * @wpa_s: Pointer to the network interface
7497 *
7498 * This function is used to request disconnection from the currently connected
7499 * network. This will stop any ongoing scans and initiate deauthentication.
7500 */
7501void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7502{
7503#ifdef CONFIG_SME
7504 wpa_s->sme.prev_bssid_set = 0;
7505#endif /* CONFIG_SME */
7506 wpa_s->reassociate = 0;
7507 wpa_s->disconnected = 1;
7508 wpa_supplicant_cancel_sched_scan(wpa_s);
7509 wpa_supplicant_cancel_scan(wpa_s);
7510 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7511 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007512 radio_remove_works(wpa_s, "connect", 0);
7513 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007514}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007515
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007516
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007517void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7518 struct wpa_used_freq_data *freqs_data,
7519 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007520{
7521 unsigned int i;
7522
7523 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7524 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007525 for (i = 0; i < len; i++) {
7526 struct wpa_used_freq_data *cur = &freqs_data[i];
7527 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7528 i, cur->freq, cur->flags);
7529 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007530}
7531
7532
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007533/*
7534 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007535 * are using the same radio as the current interface, and in addition, get
7536 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007537 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007538int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7539 struct wpa_used_freq_data *freqs_data,
7540 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007541{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007542 struct wpa_supplicant *ifs;
7543 u8 bssid[ETH_ALEN];
7544 int freq;
7545 unsigned int idx = 0, i;
7546
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007547 wpa_dbg(wpa_s, MSG_DEBUG,
7548 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007549 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007550
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007551 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7552 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007553 if (idx == len)
7554 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007555
7556 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7557 continue;
7558
7559 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007560 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7561 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007562 freq = ifs->current_ssid->frequency;
7563 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7564 freq = ifs->assoc_freq;
7565 else
7566 continue;
7567
7568 /* Hold only distinct freqs */
7569 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007570 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007571 break;
7572
7573 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007574 freqs_data[idx++].freq = freq;
7575
7576 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007577 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007578 WPA_FREQ_USED_BY_P2P_CLIENT :
7579 WPA_FREQ_USED_BY_INFRA_STATION;
7580 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007581 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007582
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007583 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007584 return idx;
7585}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007586
7587
7588/*
7589 * Find the operating frequencies of any of the virtual interfaces that
7590 * are using the same radio as the current interface.
7591 */
7592int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7593 int *freq_array, unsigned int len)
7594{
7595 struct wpa_used_freq_data *freqs_data;
7596 int num, i;
7597
7598 os_memset(freq_array, 0, sizeof(int) * len);
7599
7600 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7601 if (!freqs_data)
7602 return -1;
7603
7604 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7605 for (i = 0; i < num; i++)
7606 freq_array[i] = freqs_data[i].freq;
7607
7608 os_free(freqs_data);
7609
7610 return num;
7611}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007612
7613
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007614struct wpa_supplicant *
7615wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7616{
7617 switch (frame) {
7618#ifdef CONFIG_P2P
7619 case VENDOR_ELEM_PROBE_REQ_P2P:
7620 case VENDOR_ELEM_PROBE_RESP_P2P:
7621 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7622 case VENDOR_ELEM_BEACON_P2P_GO:
7623 case VENDOR_ELEM_P2P_PD_REQ:
7624 case VENDOR_ELEM_P2P_PD_RESP:
7625 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7626 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7627 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7628 case VENDOR_ELEM_P2P_INV_REQ:
7629 case VENDOR_ELEM_P2P_INV_RESP:
7630 case VENDOR_ELEM_P2P_ASSOC_REQ:
7631 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007632 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007633#endif /* CONFIG_P2P */
7634 default:
7635 return wpa_s;
7636 }
7637}
7638
7639
7640void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7641{
7642 unsigned int i;
7643 char buf[30];
7644
7645 wpa_printf(MSG_DEBUG, "Update vendor elements");
7646
7647 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7648 if (wpa_s->vendor_elem[i]) {
7649 int res;
7650
7651 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7652 if (!os_snprintf_error(sizeof(buf), res)) {
7653 wpa_hexdump_buf(MSG_DEBUG, buf,
7654 wpa_s->vendor_elem[i]);
7655 }
7656 }
7657 }
7658
7659#ifdef CONFIG_P2P
7660 if (wpa_s->parent == wpa_s &&
7661 wpa_s->global->p2p &&
7662 !wpa_s->global->p2p_disabled)
7663 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7664#endif /* CONFIG_P2P */
7665}
7666
7667
7668int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7669 const u8 *elem, size_t len)
7670{
7671 u8 *ie, *end;
7672
7673 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7674 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7675
7676 for (; ie + 1 < end; ie += 2 + ie[1]) {
7677 if (ie + len > end)
7678 break;
7679 if (os_memcmp(ie, elem, len) != 0)
7680 continue;
7681
7682 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7683 wpabuf_free(wpa_s->vendor_elem[frame]);
7684 wpa_s->vendor_elem[frame] = NULL;
7685 } else {
7686 os_memmove(ie, ie + len, end - (ie + len));
7687 wpa_s->vendor_elem[frame]->used -= len;
7688 }
7689 wpas_vendor_elem_update(wpa_s);
7690 return 0;
7691 }
7692
7693 return -1;
7694}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007695
7696
7697struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
7698 u16 num_modes, enum hostapd_hw_mode mode)
7699{
7700 u16 i;
7701
7702 for (i = 0; i < num_modes; i++) {
7703 if (modes[i].mode == mode)
7704 return &modes[i];
7705 }
7706
7707 return NULL;
7708}
7709
7710
7711static struct
7712wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7713 const u8 *bssid)
7714{
7715 struct wpa_bss_tmp_disallowed *bss;
7716
7717 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7718 struct wpa_bss_tmp_disallowed, list) {
7719 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7720 return bss;
7721 }
7722
7723 return NULL;
7724}
7725
7726
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007727static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7728{
7729 struct wpa_bss_tmp_disallowed *tmp;
7730 unsigned int num_bssid = 0;
7731 u8 *bssids;
7732 int ret;
7733
7734 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7735 if (!bssids)
7736 return -1;
7737 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7738 struct wpa_bss_tmp_disallowed, list) {
7739 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7740 ETH_ALEN);
7741 num_bssid++;
7742 }
7743 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7744 os_free(bssids);
7745 return ret;
7746}
7747
7748
7749static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7750{
7751 struct wpa_supplicant *wpa_s = eloop_ctx;
7752 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7753
7754 /* Make sure the bss is not already freed */
7755 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7756 struct wpa_bss_tmp_disallowed, list) {
7757 if (bss == tmp) {
7758 dl_list_del(&tmp->list);
7759 os_free(tmp);
7760 wpa_set_driver_tmp_disallow_list(wpa_s);
7761 break;
7762 }
7763 }
7764}
7765
7766
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007767void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08007768 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007769{
7770 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007771
7772 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7773 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007774 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08007775 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007776 }
7777
7778 bss = os_malloc(sizeof(*bss));
7779 if (!bss) {
7780 wpa_printf(MSG_DEBUG,
7781 "Failed to allocate memory for temp disallow BSS");
7782 return;
7783 }
7784
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007785 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7786 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007787 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08007788
7789finish:
7790 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007791 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7792 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007793}
7794
7795
Hai Shalom74f70d42019-02-11 14:42:39 -08007796int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
7797 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007798{
Hai Shalom74f70d42019-02-11 14:42:39 -08007799 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007800
7801 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7802 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007803 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
7804 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007805 break;
7806 }
7807 }
Hai Shalom74f70d42019-02-11 14:42:39 -08007808 if (!disallowed)
7809 return 0;
7810
7811 if (disallowed->rssi_threshold != 0 &&
7812 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007813 return 0;
7814
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007815 return 1;
7816}
Hai Shalom81f62d82019-07-22 12:10:00 -07007817
7818
7819int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
7820 unsigned int type, const u8 *addr,
7821 const u8 *mask)
7822{
7823 if ((addr && !mask) || (!addr && mask)) {
7824 wpa_printf(MSG_INFO,
7825 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
7826 return -1;
7827 }
7828
7829 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
7830 wpa_printf(MSG_INFO,
7831 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
7832 return -1;
7833 }
7834
7835 if (type & MAC_ADDR_RAND_SCAN) {
7836 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
7837 addr, mask))
7838 return -1;
7839 }
7840
7841 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
7842 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
7843 addr, mask))
7844 return -1;
7845
7846 if (wpa_s->sched_scanning && !wpa_s->pno)
7847 wpas_scan_restart_sched_scan(wpa_s);
7848 }
7849
7850 if (type & MAC_ADDR_RAND_PNO) {
7851 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
7852 addr, mask))
7853 return -1;
7854
7855 if (wpa_s->pno) {
7856 wpas_stop_pno(wpa_s);
7857 wpas_start_pno(wpa_s);
7858 }
7859 }
7860
7861 return 0;
7862}
7863
7864
7865int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
7866 unsigned int type)
7867{
7868 wpas_mac_addr_rand_scan_clear(wpa_s, type);
7869 if (wpa_s->pno) {
7870 if (type & MAC_ADDR_RAND_PNO) {
7871 wpas_stop_pno(wpa_s);
7872 wpas_start_pno(wpa_s);
7873 }
7874 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
7875 wpas_scan_restart_sched_scan(wpa_s);
7876 }
7877
7878 return 0;
7879}