blob: 73e63ab5901969a2e6be06e10493f01c66a26194 [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;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800503 os_free(wpa_s->extra_sae_rejected_groups);
504 wpa_s->extra_sae_rejected_groups = NULL;
505 wpabuf_free(wpa_s->rsnxe_override_assoc);
506 wpa_s->rsnxe_override_assoc = NULL;
507 wpabuf_free(wpa_s->rsnxe_override_eapol);
508 wpa_s->rsnxe_override_eapol = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800509#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700510
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700511 if (wpa_s->conf != NULL) {
512 struct wpa_ssid *ssid;
513 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
514 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515 }
516
517 os_free(wpa_s->confname);
518 wpa_s->confname = NULL;
519
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700520 os_free(wpa_s->confanother);
521 wpa_s->confanother = NULL;
522
Hai Shalomce48b4a2018-09-05 11:41:35 -0700523 os_free(wpa_s->last_con_fail_realm);
524 wpa_s->last_con_fail_realm = NULL;
525 wpa_s->last_con_fail_realm_len = 0;
526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700527 wpa_sm_set_eapol(wpa_s->wpa, NULL);
528 eapol_sm_deinit(wpa_s->eapol);
529 wpa_s->eapol = NULL;
530
531 rsn_preauth_deinit(wpa_s->wpa);
532
533#ifdef CONFIG_TDLS
534 wpa_tdls_deinit(wpa_s->wpa);
535#endif /* CONFIG_TDLS */
536
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800537 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700538 pmksa_candidate_free(wpa_s->wpa);
539 wpa_sm_deinit(wpa_s->wpa);
540 wpa_s->wpa = NULL;
541 wpa_blacklist_clear(wpa_s);
542
543 wpa_bss_deinit(wpa_s);
544
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700545 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700546 wpa_supplicant_cancel_scan(wpa_s);
547 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800548 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
549#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
550 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
551 wpa_s, NULL);
552#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700553
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700554 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
555
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700556 wpas_wps_deinit(wpa_s);
557
558 wpabuf_free(wpa_s->pending_eapol_rx);
559 wpa_s->pending_eapol_rx = NULL;
560
561#ifdef CONFIG_IBSS_RSN
562 ibss_rsn_deinit(wpa_s->ibss_rsn);
563 wpa_s->ibss_rsn = NULL;
564#endif /* CONFIG_IBSS_RSN */
565
566 sme_deinit(wpa_s);
567
568#ifdef CONFIG_AP
569 wpa_supplicant_ap_deinit(wpa_s);
570#endif /* CONFIG_AP */
571
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700572 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800574#ifdef CONFIG_OFFCHANNEL
575 offchannel_deinit(wpa_s);
576#endif /* CONFIG_OFFCHANNEL */
577
578 wpa_supplicant_cancel_sched_scan(wpa_s);
579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580 os_free(wpa_s->next_scan_freqs);
581 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800582
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800583 os_free(wpa_s->manual_scan_freqs);
584 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700585 os_free(wpa_s->select_network_scan_freqs);
586 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800587
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700588 os_free(wpa_s->manual_sched_scan_freqs);
589 wpa_s->manual_sched_scan_freqs = NULL;
590
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800591 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
592
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700593 /*
594 * Need to remove any pending gas-query radio work before the
595 * gas_query_deinit() call because gas_query::work has not yet been set
596 * for works that have not been started. gas_query_free() will be unable
597 * to cancel such pending radio works and once the pending gas-query
598 * radio work eventually gets removed, the deinit notification call to
599 * gas_query_start_cb() would result in dereferencing freed memory.
600 */
601 if (wpa_s->radio)
602 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800603 gas_query_deinit(wpa_s->gas);
604 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700605 gas_server_deinit(wpa_s->gas_server);
606 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800607
608 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700609
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700610 ieee802_1x_dealloc_kay_sm(wpa_s);
611
Dmitry Shmidt04949592012-07-19 12:16:46 -0700612 os_free(wpa_s->bssid_filter);
613 wpa_s->bssid_filter = NULL;
614
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800615 os_free(wpa_s->disallow_aps_bssid);
616 wpa_s->disallow_aps_bssid = NULL;
617 os_free(wpa_s->disallow_aps_ssid);
618 wpa_s->disallow_aps_ssid = NULL;
619
Dmitry Shmidt04949592012-07-19 12:16:46 -0700620 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700621#ifdef CONFIG_WNM
622 wnm_deallocate_memory(wpa_s);
623#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700624
625 ext_password_deinit(wpa_s->ext_pw);
626 wpa_s->ext_pw = NULL;
627
628 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800629 wpa_s->last_gas_resp = NULL;
630 wpabuf_free(wpa_s->prev_gas_resp);
631 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700632
633 os_free(wpa_s->last_scan_res);
634 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800635
636#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700637 if (wpa_s->drv_priv)
638 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700639 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800640#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700641
642 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
643 wpabuf_free(wpa_s->vendor_elem[i]);
644 wpa_s->vendor_elem[i] = NULL;
645 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800646
647 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800648
649 wpa_s->sched_scan_plans_num = 0;
650 os_free(wpa_s->sched_scan_plans);
651 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800652
653#ifdef CONFIG_MBO
654 wpa_s->non_pref_chan_num = 0;
655 os_free(wpa_s->non_pref_chan);
656 wpa_s->non_pref_chan = NULL;
657#endif /* CONFIG_MBO */
658
659 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700660
661 wpabuf_free(wpa_s->lci);
662 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800663 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800664
665#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
666#ifdef CONFIG_MESH
667 {
668 struct external_pmksa_cache *entry;
669
670 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
671 struct external_pmksa_cache,
672 list)) != NULL) {
673 dl_list_del(&entry->list);
674 os_free(entry->pmksa_cache);
675 os_free(entry);
676 }
677 }
678#endif /* CONFIG_MESH */
679#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
680
681 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800682
683 wpabuf_free(wpa_s->ric_ies);
684 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700685
686#ifdef CONFIG_DPP
687 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700688 dpp_global_deinit(wpa_s->dpp);
689 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700690#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691}
692
693
694/**
695 * wpa_clear_keys - Clear keys configured for the driver
696 * @wpa_s: Pointer to wpa_supplicant data
697 * @addr: Previously used BSSID or %NULL if not available
698 *
699 * This function clears the encryption keys that has been previously configured
700 * for the driver.
701 */
702void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
703{
Hai Shalomc3565922019-10-28 11:58:20 -0700704 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705
706 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800707 for (i = 0; i < max; i++) {
708 if (wpa_s->keys_cleared & BIT(i))
709 continue;
710 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
711 NULL, 0);
712 }
713 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
714 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700715 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
716 0);
717 /* MLME-SETPROTECTION.request(None) */
718 wpa_drv_mlme_setprotection(
719 wpa_s, addr,
720 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
721 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
722 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800723 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700724}
725
726
727/**
728 * wpa_supplicant_state_txt - Get the connection state name as a text string
729 * @state: State (wpa_state; WPA_*)
730 * Returns: The state name as a printable text string
731 */
732const char * wpa_supplicant_state_txt(enum wpa_states state)
733{
734 switch (state) {
735 case WPA_DISCONNECTED:
736 return "DISCONNECTED";
737 case WPA_INACTIVE:
738 return "INACTIVE";
739 case WPA_INTERFACE_DISABLED:
740 return "INTERFACE_DISABLED";
741 case WPA_SCANNING:
742 return "SCANNING";
743 case WPA_AUTHENTICATING:
744 return "AUTHENTICATING";
745 case WPA_ASSOCIATING:
746 return "ASSOCIATING";
747 case WPA_ASSOCIATED:
748 return "ASSOCIATED";
749 case WPA_4WAY_HANDSHAKE:
750 return "4WAY_HANDSHAKE";
751 case WPA_GROUP_HANDSHAKE:
752 return "GROUP_HANDSHAKE";
753 case WPA_COMPLETED:
754 return "COMPLETED";
755 default:
756 return "UNKNOWN";
757 }
758}
759
760
761#ifdef CONFIG_BGSCAN
762
763static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
764{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800765 const char *name;
766
767 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
768 name = wpa_s->current_ssid->bgscan;
769 else
770 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800771 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800772 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800773 if (wpas_driver_bss_selection(wpa_s))
774 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700775 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
776 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800777#ifdef CONFIG_P2P
778 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
779 return;
780#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781
782 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800783 if (wpa_s->current_ssid) {
784 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700785 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
786 "bgscan");
787 /*
788 * Live without bgscan; it is only used as a roaming
789 * optimization, so the initial connection is not
790 * affected.
791 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700792 } else {
793 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700794 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700795 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
796 0);
797 if (scan_res) {
798 bgscan_notify_scan(wpa_s, scan_res);
799 wpa_scan_results_free(scan_res);
800 }
801 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700802 } else
803 wpa_s->bgscan_ssid = NULL;
804}
805
806
807static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
808{
809 if (wpa_s->bgscan_ssid != NULL) {
810 bgscan_deinit(wpa_s);
811 wpa_s->bgscan_ssid = NULL;
812 }
813}
814
815#endif /* CONFIG_BGSCAN */
816
817
Dmitry Shmidt04949592012-07-19 12:16:46 -0700818static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
819{
820 if (autoscan_init(wpa_s, 0))
821 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
822}
823
824
825static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
826{
827 autoscan_deinit(wpa_s);
828}
829
830
831void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
832{
833 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
834 wpa_s->wpa_state == WPA_SCANNING) {
835 autoscan_deinit(wpa_s);
836 wpa_supplicant_start_autoscan(wpa_s);
837 }
838}
839
840
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700841/**
842 * wpa_supplicant_set_state - Set current connection state
843 * @wpa_s: Pointer to wpa_supplicant data
844 * @state: The new connection state
845 *
846 * This function is called whenever the connection state changes, e.g.,
847 * association is completed for WPA/WPA2 4-Way Handshake is started.
848 */
849void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
850 enum wpa_states state)
851{
852 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700853#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
854 Boolean update_fils_connect_params = FALSE;
855#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700856
857 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
858 wpa_supplicant_state_txt(wpa_s->wpa_state),
859 wpa_supplicant_state_txt(state));
860
Hai Shalom74f70d42019-02-11 14:42:39 -0800861 if (state == WPA_COMPLETED &&
862 os_reltime_initialized(&wpa_s->roam_start)) {
863 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
864 wpa_s->roam_start.sec = 0;
865 wpa_s->roam_start.usec = 0;
866 wpas_notify_auth_changed(wpa_s);
867 wpas_notify_roam_time(wpa_s);
868 wpas_notify_roam_complete(wpa_s);
869 } else if (state == WPA_DISCONNECTED &&
870 os_reltime_initialized(&wpa_s->roam_start)) {
871 wpa_s->roam_start.sec = 0;
872 wpa_s->roam_start.usec = 0;
873 wpa_s->roam_time.sec = 0;
874 wpa_s->roam_time.usec = 0;
875 wpas_notify_roam_complete(wpa_s);
876 }
877
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800878 if (state == WPA_INTERFACE_DISABLED) {
879 /* Assure normal scan when interface is restored */
880 wpa_s->normal_scans = 0;
881 }
882
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700883 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800884 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700885 /* Reinitialize normal_scan counter */
886 wpa_s->normal_scans = 0;
887 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800888
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700889#ifdef CONFIG_P2P
890 /*
891 * P2PS client has to reply to Probe Request frames received on the
892 * group operating channel. Enable Probe Request frame reporting for
893 * P2P connected client in case p2p_cli_probe configuration property is
894 * set to 1.
895 */
896 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
897 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
898 wpa_s->current_ssid->p2p_group) {
899 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
900 wpa_dbg(wpa_s, MSG_DEBUG,
901 "P2P: Enable CLI Probe Request RX reporting");
902 wpa_s->p2p_cli_probe =
903 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
904 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
905 wpa_dbg(wpa_s, MSG_DEBUG,
906 "P2P: Disable CLI Probe Request RX reporting");
907 wpa_s->p2p_cli_probe = 0;
908 wpa_drv_probe_req_report(wpa_s, 0);
909 }
910 }
911#endif /* CONFIG_P2P */
912
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700913 if (state != WPA_SCANNING)
914 wpa_supplicant_notify_scanning(wpa_s, 0);
915
916 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700917 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700918 int fils_hlp_sent = 0;
919
920#ifdef CONFIG_SME
921 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
922 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
923 fils_hlp_sent = 1;
924#endif /* CONFIG_SME */
925 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
926 wpa_auth_alg_fils(wpa_s->auth_alg))
927 fils_hlp_sent = 1;
928
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700929#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700931 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800932 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700933 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700934 ssid && ssid->id_str ? ssid->id_str : "",
935 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700936#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700937 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700938 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800939 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700940 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700941 wpa_drv_set_operstate(wpa_s, 1);
942#ifndef IEEE8021X_EAPOL
943 wpa_drv_set_supp_port(wpa_s, 1);
944#endif /* IEEE8021X_EAPOL */
945 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700946 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700947 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700948
949 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700950
951#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
952 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalomc3565922019-10-28 11:58:20 -0700953 update_fils_connect_params = TRUE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700954#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700955#ifdef CONFIG_OWE
956 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
957 wpas_update_owe_connect_params(wpa_s);
958#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700959 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
960 state == WPA_ASSOCIATED) {
961 wpa_s->new_connection = 1;
962 wpa_drv_set_operstate(wpa_s, 0);
963#ifndef IEEE8021X_EAPOL
964 wpa_drv_set_supp_port(wpa_s, 0);
965#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700966 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700967 }
968 wpa_s->wpa_state = state;
969
970#ifdef CONFIG_BGSCAN
971 if (state == WPA_COMPLETED)
972 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800973 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974 wpa_supplicant_stop_bgscan(wpa_s);
975#endif /* CONFIG_BGSCAN */
976
Hai Shalom5f92bc92019-04-18 11:54:11 -0700977 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700978 wpa_supplicant_stop_autoscan(wpa_s);
979
980 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
981 wpa_supplicant_start_autoscan(wpa_s);
982
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800983 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
984 wmm_ac_notify_disassoc(wpa_s);
985
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700986 if (wpa_s->wpa_state != old_state) {
987 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
988
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700989 /*
990 * Notify the P2P Device interface about a state change in one
991 * of the interfaces.
992 */
993 wpas_p2p_indicate_state_change(wpa_s);
994
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700995 if (wpa_s->wpa_state == WPA_COMPLETED ||
996 old_state == WPA_COMPLETED)
997 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700998#ifdef CONFIG_DPP2
999 if (wpa_s->wpa_state == WPA_COMPLETED)
1000 wpas_dpp_connected(wpa_s);
1001#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002 }
Hai Shalomc3565922019-10-28 11:58:20 -07001003#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1004 if (update_fils_connect_params)
1005 wpas_update_fils_connect_params(wpa_s);
1006#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007}
1008
1009
1010void wpa_supplicant_terminate_proc(struct wpa_global *global)
1011{
1012 int pending = 0;
1013#ifdef CONFIG_WPS
1014 struct wpa_supplicant *wpa_s = global->ifaces;
1015 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001016 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001017 if (wpas_wps_terminate_pending(wpa_s) == 1)
1018 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001019#ifdef CONFIG_P2P
1020 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1021 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1022 wpas_p2p_disconnect(wpa_s);
1023#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001024 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 }
1026#endif /* CONFIG_WPS */
1027 if (pending)
1028 return;
1029 eloop_terminate();
1030}
1031
1032
1033static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1034{
1035 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001036 wpa_supplicant_terminate_proc(global);
1037}
1038
1039
1040void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1041{
1042 enum wpa_states old_state = wpa_s->wpa_state;
1043
1044 wpa_s->pairwise_cipher = 0;
1045 wpa_s->group_cipher = 0;
1046 wpa_s->mgmt_group_cipher = 0;
1047 wpa_s->key_mgmt = 0;
1048 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001049 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001050
1051 if (wpa_s->wpa_state != old_state)
1052 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1053}
1054
1055
1056/**
1057 * wpa_supplicant_reload_configuration - Reload configuration data
1058 * @wpa_s: Pointer to wpa_supplicant data
1059 * Returns: 0 on success or -1 if configuration parsing failed
1060 *
1061 * This function can be used to request that the configuration data is reloaded
1062 * (e.g., after configuration file change). This function is reloading
1063 * configuration only for one interface, so this may need to be called multiple
1064 * times if %wpa_supplicant is controlling multiple interfaces and all
1065 * interfaces need reconfiguration.
1066 */
1067int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1068{
1069 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070 int reconf_ctrl;
1071 int old_ap_scan;
1072
1073 if (wpa_s->confname == NULL)
1074 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001075 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001076 if (conf == NULL) {
1077 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1078 "file '%s' - exiting", wpa_s->confname);
1079 return -1;
1080 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001081 if (wpa_s->confanother &&
1082 !wpa_config_read(wpa_s->confanother, conf)) {
1083 wpa_msg(wpa_s, MSG_ERROR,
1084 "Failed to parse the configuration file '%s' - exiting",
1085 wpa_s->confanother);
1086 return -1;
1087 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001088
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089 conf->changed_parameters = (unsigned int) -1;
1090
1091 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1092 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1093 os_strcmp(conf->ctrl_interface,
1094 wpa_s->conf->ctrl_interface) != 0);
1095
1096 if (reconf_ctrl && wpa_s->ctrl_iface) {
1097 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1098 wpa_s->ctrl_iface = NULL;
1099 }
1100
1101 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001102 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001103 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1104 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001105 wpa_supplicant_deauthenticate(wpa_s,
1106 WLAN_REASON_DEAUTH_LEAVING);
1107 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108
1109 /*
1110 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001111 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001112 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001113 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1114 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1115 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001116 /*
1117 * Clear forced success to clear EAP state for next
1118 * authentication.
1119 */
1120 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1121 }
1122 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1123 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001124 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1126 rsn_preauth_deinit(wpa_s->wpa);
1127
1128 old_ap_scan = wpa_s->conf->ap_scan;
1129 wpa_config_free(wpa_s->conf);
1130 wpa_s->conf = conf;
1131 if (old_ap_scan != wpa_s->conf->ap_scan)
1132 wpas_notify_ap_scan_changed(wpa_s);
1133
1134 if (reconf_ctrl)
1135 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1136
1137 wpa_supplicant_update_config(wpa_s);
1138
1139 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001140 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001141 wpa_s->reassociate = 1;
1142 wpa_supplicant_req_scan(wpa_s, 0, 0);
1143 }
1144 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1145 return 0;
1146}
1147
1148
1149static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1150{
1151 struct wpa_global *global = signal_ctx;
1152 struct wpa_supplicant *wpa_s;
1153 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1154 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1155 sig);
1156 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1157 wpa_supplicant_terminate_proc(global);
1158 }
1159 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001160
1161 if (wpa_debug_reopen_file() < 0) {
1162 /* Ignore errors since we cannot really do much to fix this */
1163 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1164 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165}
1166
1167
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001168static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1169 struct wpa_ssid *ssid,
1170 struct wpa_ie_data *ie)
1171{
1172 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1173 if (ret) {
1174 if (ret == -2) {
1175 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1176 "from association info");
1177 }
1178 return -1;
1179 }
1180
1181 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1182 "cipher suites");
1183 if (!(ie->group_cipher & ssid->group_cipher)) {
1184 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1185 "cipher 0x%x (mask 0x%x) - reject",
1186 ie->group_cipher, ssid->group_cipher);
1187 return -1;
1188 }
1189 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1190 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1191 "cipher 0x%x (mask 0x%x) - reject",
1192 ie->pairwise_cipher, ssid->pairwise_cipher);
1193 return -1;
1194 }
1195 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1196 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1197 "management 0x%x (mask 0x%x) - reject",
1198 ie->key_mgmt, ssid->key_mgmt);
1199 return -1;
1200 }
1201
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001202 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001203 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001204 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1205 "that does not support management frame protection - "
1206 "reject");
1207 return -1;
1208 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209
1210 return 0;
1211}
1212
1213
Hai Shalom021b0b52019-04-10 11:17:58 -07001214static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1215 int freq)
1216{
1217 if (!ie->has_group)
1218 ie->group_cipher = wpa_default_rsn_cipher(freq);
1219 if (!ie->has_pairwise)
1220 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1221 return (ie->group_cipher & ssid->group_cipher) &&
1222 (ie->pairwise_cipher & ssid->pairwise_cipher);
1223}
1224
1225
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001226/**
1227 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1228 * @wpa_s: Pointer to wpa_supplicant data
1229 * @bss: Scan results for the selected BSS, or %NULL if not available
1230 * @ssid: Configuration data for the selected network
1231 * @wpa_ie: Buffer for the WPA/RSN IE
1232 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1233 * used buffer length in case the functions returns success.
1234 * Returns: 0 on success or -1 on failure
1235 *
1236 * This function is used to configure authentication and encryption parameters
1237 * based on the network configuration and scan result for the selected BSS (if
1238 * available).
1239 */
1240int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1241 struct wpa_bss *bss, struct wpa_ssid *ssid,
1242 u8 *wpa_ie, size_t *wpa_ie_len)
1243{
1244 struct wpa_ie_data ie;
1245 int sel, proto;
Hai Shalomc3565922019-10-28 11:58:20 -07001246 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001247
1248 if (bss) {
1249 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1250 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001251 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001252 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001253 } else {
1254 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1255 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001256
1257 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1258 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001259 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001260 (ie.key_mgmt & ssid->key_mgmt)) {
1261 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1262 proto = WPA_PROTO_RSN;
1263 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001264 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001265 (ie.group_cipher & ssid->group_cipher) &&
1266 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1267 (ie.key_mgmt & ssid->key_mgmt)) {
1268 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1269 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001270#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001271 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1272 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1273 (ie.group_cipher & ssid->group_cipher) &&
1274 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1275 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001276 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001277 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001278 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1279 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1280 (ie.group_cipher & ssid->group_cipher) &&
1281 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1282 (ie.key_mgmt & ssid->key_mgmt)) {
1283 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1284 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001285#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001286 } else if (bss) {
1287 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001288 wpa_dbg(wpa_s, MSG_DEBUG,
1289 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1290 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1291 ssid->key_mgmt);
1292 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1293 MAC2STR(bss->bssid),
1294 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1295 bss_wpa ? " WPA" : "",
1296 bss_rsn ? " RSN" : "",
1297 bss_osen ? " OSEN" : "");
1298 if (bss_rsn) {
1299 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1300 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1301 wpa_dbg(wpa_s, MSG_DEBUG,
1302 "Could not parse RSN element");
1303 } else {
1304 wpa_dbg(wpa_s, MSG_DEBUG,
1305 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1306 ie.pairwise_cipher, ie.group_cipher,
1307 ie.key_mgmt);
1308 }
1309 }
1310 if (bss_wpa) {
1311 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1312 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1313 wpa_dbg(wpa_s, MSG_DEBUG,
1314 "Could not parse WPA element");
1315 } else {
1316 wpa_dbg(wpa_s, MSG_DEBUG,
1317 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1318 ie.pairwise_cipher, ie.group_cipher,
1319 ie.key_mgmt);
1320 }
1321 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001322 return -1;
1323 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001324 if (ssid->proto & WPA_PROTO_OSEN)
1325 proto = WPA_PROTO_OSEN;
1326 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001327 proto = WPA_PROTO_RSN;
1328 else
1329 proto = WPA_PROTO_WPA;
1330 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1331 os_memset(&ie, 0, sizeof(ie));
1332 ie.group_cipher = ssid->group_cipher;
1333 ie.pairwise_cipher = ssid->pairwise_cipher;
1334 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001335 ie.mgmt_group_cipher = 0;
1336 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1337 if (ssid->group_mgmt_cipher &
1338 WPA_CIPHER_BIP_GMAC_256)
1339 ie.mgmt_group_cipher =
1340 WPA_CIPHER_BIP_GMAC_256;
1341 else if (ssid->group_mgmt_cipher &
1342 WPA_CIPHER_BIP_CMAC_256)
1343 ie.mgmt_group_cipher =
1344 WPA_CIPHER_BIP_CMAC_256;
1345 else if (ssid->group_mgmt_cipher &
1346 WPA_CIPHER_BIP_GMAC_128)
1347 ie.mgmt_group_cipher =
1348 WPA_CIPHER_BIP_GMAC_128;
1349 else
1350 ie.mgmt_group_cipher =
1351 WPA_CIPHER_AES_128_CMAC;
1352 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001353#ifdef CONFIG_OWE
1354 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1355 !ssid->owe_only &&
1356 !bss_wpa && !bss_rsn && !bss_osen) {
1357 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1358 wpa_s->wpa_proto = 0;
1359 *wpa_ie_len = 0;
1360 return 0;
1361 }
1362#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1364 "based on configuration");
1365 } else
1366 proto = ie.proto;
1367 }
1368
1369 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1370 "pairwise %d key_mgmt %d proto %d",
1371 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001372 if (ssid->ieee80211w) {
1373 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1374 ie.mgmt_group_cipher);
1375 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001376
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001377 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001378 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1379 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001380 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001381
1382 if (bss || !wpa_s->ap_ies_from_associnfo) {
1383 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1384 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1385 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001386 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1387 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1388 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389 return -1;
1390 }
1391
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001392#ifdef CONFIG_NO_WPA
1393 wpa_s->group_cipher = WPA_CIPHER_NONE;
1394 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1395#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001396 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001397 wpa_dbg(wpa_s, MSG_DEBUG,
1398 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1399 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001400 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1401 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001402 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1403 "cipher");
1404 return -1;
1405 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001406 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1407 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001408
1409 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001410 wpa_dbg(wpa_s, MSG_DEBUG,
1411 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1412 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001413 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1414 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001415 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1416 "cipher");
1417 return -1;
1418 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001419 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1420 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001421#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001422
1423 sel = ie.key_mgmt & ssid->key_mgmt;
Hai Shalom021b0b52019-04-10 11:17:58 -07001424 wpa_dbg(wpa_s, MSG_DEBUG,
1425 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1426 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001427#ifdef CONFIG_SAE
1428 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1429 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1430#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001431 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001432#ifdef CONFIG_IEEE80211R
1433#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001434 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1435 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001436 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1437 wpa_dbg(wpa_s, MSG_DEBUG,
1438 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001439 if (!ssid->ft_eap_pmksa_caching &&
1440 pmksa_cache_get_current(wpa_s->wpa)) {
1441 /* PMKSA caching with FT may have interoperability
1442 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001443 wpa_dbg(wpa_s, MSG_DEBUG,
1444 "WPA: Disable PMKSA caching for FT/802.1X connection");
1445 pmksa_cache_clear_current(wpa_s->wpa);
1446 }
1447#endif /* CONFIG_SHA384 */
1448#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001449#ifdef CONFIG_SUITEB192
1450 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1451 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1452 wpa_dbg(wpa_s, MSG_DEBUG,
1453 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1454#endif /* CONFIG_SUITEB192 */
1455#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001456 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1457 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1458 wpa_dbg(wpa_s, MSG_DEBUG,
1459 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001460#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001461#ifdef CONFIG_FILS
1462#ifdef CONFIG_IEEE80211R
1463 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1464 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1465 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1466 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1467 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1468 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1469#endif /* CONFIG_IEEE80211R */
1470 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1471 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1472 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1473 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1474 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1475 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1476#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001477#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001478 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1479 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001480 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1481 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001482 if (!ssid->ft_eap_pmksa_caching &&
1483 pmksa_cache_get_current(wpa_s->wpa)) {
1484 /* PMKSA caching with FT may have interoperability
1485 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001486 wpa_dbg(wpa_s, MSG_DEBUG,
1487 "WPA: Disable PMKSA caching for FT/802.1X connection");
1488 pmksa_cache_clear_current(wpa_s->wpa);
1489 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001490#endif /* CONFIG_IEEE80211R */
1491#ifdef CONFIG_DPP
1492 } else if (sel & WPA_KEY_MGMT_DPP) {
1493 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1494 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1495#endif /* CONFIG_DPP */
1496#ifdef CONFIG_SAE
1497 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1498 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1499 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1500 } else if (sel & WPA_KEY_MGMT_SAE) {
1501 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1502 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1503#endif /* CONFIG_SAE */
1504#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1506 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1507 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1508#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001509 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1510 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1511 wpa_dbg(wpa_s, MSG_DEBUG,
1512 "WPA: using KEY_MGMT 802.1X with SHA256");
1513 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1514 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1515 wpa_dbg(wpa_s, MSG_DEBUG,
1516 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001517 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1518 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1519 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1520 } else if (sel & WPA_KEY_MGMT_PSK) {
1521 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1522 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1523 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1524 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1525 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001526#ifdef CONFIG_HS20
1527 } else if (sel & WPA_KEY_MGMT_OSEN) {
1528 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1529 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1530#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001531#ifdef CONFIG_OWE
1532 } else if (sel & WPA_KEY_MGMT_OWE) {
1533 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1534 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1535#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001536 } else {
1537 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1538 "authenticated key management type");
1539 return -1;
1540 }
1541
1542 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1543 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1544 wpa_s->pairwise_cipher);
1545 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1546
Hai Shalomc3565922019-10-28 11:58:20 -07001547 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1548 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1549 wpa_msg(wpa_s, MSG_INFO,
1550 "RSN: Management frame protection required but the selected AP does not enable it");
1551 return -1;
1552 }
1553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001554 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001555 if (ssid->group_mgmt_cipher)
1556 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001557 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1559 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001560 wpa_dbg(wpa_s, MSG_DEBUG,
1561 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1562 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001563 if (sel & WPA_CIPHER_AES_128_CMAC) {
1564 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1565 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1566 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001567 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1568 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1569 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1570 "BIP-GMAC-128");
1571 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1572 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1573 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1574 "BIP-GMAC-256");
1575 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1576 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1577 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1578 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001579 } else {
1580 wpa_s->mgmt_group_cipher = 0;
1581 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1582 }
1583 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1584 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001585 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001586 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001587#ifdef CONFIG_OCV
1588 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
1589#endif /* CONFIG_OCV */
Hai Shalomc3565922019-10-28 11:58:20 -07001590 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, wpa_s->conf->sae_pwe);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001591
1592 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1593 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1594 return -1;
1595 }
1596
Hai Shalomc3565922019-10-28 11:58:20 -07001597 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1598 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1599 &wpa_s->rsnxe_len)) {
1600 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1601 return -1;
1602 }
1603
Hai Shalom021b0b52019-04-10 11:17:58 -07001604 if (0) {
1605#ifdef CONFIG_DPP
1606 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1607 /* Use PMK from DPP network introduction (PMKSA entry) */
1608 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1609#endif /* CONFIG_DPP */
1610 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001611 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001612 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001613
Roshan Pius3a1667e2018-07-03 15:17:14 -07001614 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1615 WPA_KEY_MGMT_FT_PSK |
1616 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1617
1618 if (ssid->psk_set && !sae_only) {
1619 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1620 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001621 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1622 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001623 psk_set = 1;
1624 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001625
Roshan Pius3a1667e2018-07-03 15:17:14 -07001626 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1627 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001628 psk_set = 1;
1629
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001630#ifndef CONFIG_NO_PBKDF2
1631 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001632 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001633 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001634 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1635 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001636 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1637 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001638 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001639 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001640 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001641 }
1642#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001643#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001644 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001645 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1646 ssid->ext_psk);
1647 char pw_str[64 + 1];
1648 u8 psk[PMK_LEN];
1649
1650 if (pw == NULL) {
1651 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1652 "found from external storage");
1653 return -1;
1654 }
1655
1656 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1657 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1658 "PSK length %d in external storage",
1659 (int) wpabuf_len(pw));
1660 ext_password_free(pw);
1661 return -1;
1662 }
1663
1664 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1665 pw_str[wpabuf_len(pw)] = '\0';
1666
1667#ifndef CONFIG_NO_PBKDF2
1668 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1669 {
1670 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1671 4096, psk, PMK_LEN);
1672 os_memset(pw_str, 0, sizeof(pw_str));
1673 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1674 "external passphrase)",
1675 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001676 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1677 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001678 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001679 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001680 } else
1681#endif /* CONFIG_NO_PBKDF2 */
1682 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1683 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1684 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1685 "Invalid PSK hex string");
1686 os_memset(pw_str, 0, sizeof(pw_str));
1687 ext_password_free(pw);
1688 return -1;
1689 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001690 wpa_hexdump_key(MSG_MSGDUMP,
1691 "PSK (from external PSK)",
1692 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001693 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1694 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001695 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001696 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001697 } else {
1698 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1699 "PSK available");
1700 os_memset(pw_str, 0, sizeof(pw_str));
1701 ext_password_free(pw);
1702 return -1;
1703 }
1704
1705 os_memset(pw_str, 0, sizeof(pw_str));
1706 ext_password_free(pw);
1707 }
1708#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001709
1710 if (!psk_set) {
1711 wpa_msg(wpa_s, MSG_INFO,
1712 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001713 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001714 return -1;
1715 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001716#ifdef CONFIG_OWE
1717 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1718 /* OWE Diffie-Hellman exchange in (Re)Association
1719 * Request/Response frames set the PMK, so do not override it
1720 * here. */
1721#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001722 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1724
1725 return 0;
1726}
1727
1728
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001729static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1730{
1731 *pos = 0x00;
1732
1733 switch (idx) {
1734 case 0: /* Bits 0-7 */
1735 break;
1736 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001737 if (wpa_s->conf->coloc_intf_reporting) {
1738 /* Bit 13 - Collocated Interference Reporting */
1739 *pos |= 0x20;
1740 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001741 break;
1742 case 2: /* Bits 16-23 */
1743#ifdef CONFIG_WNM
1744 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001745 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001746 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001747#endif /* CONFIG_WNM */
1748 break;
1749 case 3: /* Bits 24-31 */
1750#ifdef CONFIG_WNM
1751 *pos |= 0x02; /* Bit 25 - SSID List */
1752#endif /* CONFIG_WNM */
1753#ifdef CONFIG_INTERWORKING
1754 if (wpa_s->conf->interworking)
1755 *pos |= 0x80; /* Bit 31 - Interworking */
1756#endif /* CONFIG_INTERWORKING */
1757 break;
1758 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001759#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001760 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001761 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001762#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001763 break;
1764 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001765#ifdef CONFIG_HS20
1766 if (wpa_s->conf->hs20)
1767 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1768#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001769#ifdef CONFIG_MBO
1770 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1771#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001772 break;
1773 case 6: /* Bits 48-55 */
1774 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001775 case 7: /* Bits 56-63 */
1776 break;
1777 case 8: /* Bits 64-71 */
1778 if (wpa_s->conf->ftm_responder)
1779 *pos |= 0x40; /* Bit 70 - FTM responder */
1780 if (wpa_s->conf->ftm_initiator)
1781 *pos |= 0x80; /* Bit 71 - FTM initiator */
1782 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001783 case 9: /* Bits 72-79 */
1784#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001785 if (!wpa_s->disable_fils)
1786 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001787#endif /* CONFIG_FILS */
1788 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001789 }
1790}
1791
1792
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001793int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001794{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001795 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001796 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001797
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001798 if (len < wpa_s->extended_capa_len)
1799 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001800 if (buflen < (size_t) len + 2) {
1801 wpa_printf(MSG_INFO,
1802 "Not enough room for building extended capabilities element");
1803 return -1;
1804 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001805
1806 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001807 *pos++ = len;
1808 for (i = 0; i < len; i++, pos++) {
1809 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001810
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001811 if (i < wpa_s->extended_capa_len) {
1812 *pos &= ~wpa_s->extended_capa_mask[i];
1813 *pos |= wpa_s->extended_capa[i];
1814 }
1815 }
1816
1817 while (len > 0 && buf[1 + len] == 0) {
1818 len--;
1819 buf[1] = len;
1820 }
1821 if (len == 0)
1822 return 0;
1823
1824 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001825}
1826
1827
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001828static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1829 struct wpa_bss *test_bss)
1830{
1831 struct wpa_bss *bss;
1832
1833 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1834 if (bss == test_bss)
1835 return 1;
1836 }
1837
1838 return 0;
1839}
1840
1841
1842static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1843 struct wpa_ssid *test_ssid)
1844{
1845 struct wpa_ssid *ssid;
1846
1847 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1848 if (ssid == test_ssid)
1849 return 1;
1850 }
1851
1852 return 0;
1853}
1854
1855
1856int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1857 struct wpa_ssid *test_ssid)
1858{
1859 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1860 return 0;
1861
1862 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1863}
1864
1865
1866void wpas_connect_work_free(struct wpa_connect_work *cwork)
1867{
1868 if (cwork == NULL)
1869 return;
1870 os_free(cwork);
1871}
1872
1873
1874void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1875{
1876 struct wpa_connect_work *cwork;
1877 struct wpa_radio_work *work = wpa_s->connect_work;
1878
1879 if (!work)
1880 return;
1881
1882 wpa_s->connect_work = NULL;
1883 cwork = work->ctx;
1884 work->ctx = NULL;
1885 wpas_connect_work_free(cwork);
1886 radio_work_done(work);
1887}
1888
1889
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001890int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1891{
1892 struct os_reltime now;
1893 u8 addr[ETH_ALEN];
1894
1895 os_get_reltime(&now);
1896 if (wpa_s->last_mac_addr_style == style &&
1897 wpa_s->last_mac_addr_change.sec != 0 &&
1898 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1899 wpa_s->conf->rand_addr_lifetime)) {
1900 wpa_msg(wpa_s, MSG_DEBUG,
1901 "Previously selected random MAC address has not yet expired");
1902 return 0;
1903 }
1904
1905 switch (style) {
1906 case 1:
1907 if (random_mac_addr(addr) < 0)
1908 return -1;
1909 break;
1910 case 2:
1911 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1912 if (random_mac_addr_keep_oui(addr) < 0)
1913 return -1;
1914 break;
1915 default:
1916 return -1;
1917 }
1918
1919 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1920 wpa_msg(wpa_s, MSG_INFO,
1921 "Failed to set random MAC address");
1922 return -1;
1923 }
1924
1925 os_get_reltime(&wpa_s->last_mac_addr_change);
1926 wpa_s->mac_addr_changed = 1;
1927 wpa_s->last_mac_addr_style = style;
1928
1929 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1930 wpa_msg(wpa_s, MSG_INFO,
1931 "Could not update MAC address information");
1932 return -1;
1933 }
1934
1935 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1936 MAC2STR(addr));
1937
1938 return 0;
1939}
1940
1941
1942int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1943{
1944 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1945 !wpa_s->conf->preassoc_mac_addr)
1946 return 0;
1947
1948 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1949}
1950
1951
Hai Shalomc3565922019-10-28 11:58:20 -07001952static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
1953{
1954#ifdef CONFIG_SAE
1955 int *groups = conf->sae_groups;
1956 int default_groups[] = { 19, 20, 21, 0 };
1957 const char *password;
1958
1959 if (!groups || groups[0] <= 0)
1960 groups = default_groups;
1961
1962 password = ssid->sae_password;
1963 if (!password)
1964 password = ssid->passphrase;
1965
1966 if (conf->sae_pwe == 0 || !password) {
1967 /* PT derivation not needed */
1968 sae_deinit_pt(ssid->pt);
1969 ssid->pt = NULL;
1970 return;
1971 }
1972
1973 if (ssid->pt)
1974 return; /* PT already derived */
1975 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
1976 (const u8 *) password, os_strlen(password),
1977 ssid->sae_password_id);
1978#endif /* CONFIG_SAE */
1979}
1980
1981
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001982static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
1983{
1984#if defined(CONFIG_SAE) && defined(CONFIG_SME)
1985 os_free(wpa_s->sme.sae_rejected_groups);
1986 wpa_s->sme.sae_rejected_groups = NULL;
1987#ifdef CONFIG_TESTING_OPTIONS
1988 if (wpa_s->extra_sae_rejected_groups) {
1989 int i, *groups = wpa_s->extra_sae_rejected_groups;
1990
1991 for (i = 0; groups[i]; i++) {
1992 wpa_printf(MSG_DEBUG,
1993 "TESTING: Indicate rejection of an extra SAE group %d",
1994 groups[i]);
1995 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1996 groups[i]);
1997 }
1998 }
1999#endif /* CONFIG_TESTING_OPTIONS */
2000#endif /* CONFIG_SAE && CONFIG_SME */
2001}
2002
2003
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002004static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2005
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002006/**
2007 * wpa_supplicant_associate - Request association
2008 * @wpa_s: Pointer to wpa_supplicant data
2009 * @bss: Scan results for the selected BSS, or %NULL if not available
2010 * @ssid: Configuration data for the selected network
2011 *
2012 * This function is used to request %wpa_supplicant to associate with a BSS.
2013 */
2014void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2015 struct wpa_bss *bss, struct wpa_ssid *ssid)
2016{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002017 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002018 int rand_style;
2019
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002020 wpa_s->own_disconnect_req = 0;
2021
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002022 /*
2023 * If we are starting a new connection, any previously pending EAPOL
2024 * RX cannot be valid anymore.
2025 */
2026 wpabuf_free(wpa_s->pending_eapol_rx);
2027 wpa_s->pending_eapol_rx = NULL;
2028
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002029 if (ssid->mac_addr == -1)
2030 rand_style = wpa_s->conf->mac_addr;
2031 else
2032 rand_style = ssid->mac_addr;
2033
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002034 wmm_ac_clear_saved_tspecs(wpa_s);
2035 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002036 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002037#ifdef CONFIG_TESTING_OPTIONS
2038 wpa_s->testing_resend_assoc = 0;
2039#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002040
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002041 if (wpa_s->last_ssid == ssid) {
2042 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002043 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002044 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2045 wmm_ac_save_tspecs(wpa_s);
2046 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002047 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2048 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002049 }
Hai Shalomc3565922019-10-28 11:58:20 -07002050 } else {
2051#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002052 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002053 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2054#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002055 }
2056
2057 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002058 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2059 return;
2060 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002061 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002062 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2063 wpa_msg(wpa_s, MSG_INFO,
2064 "Could not restore permanent MAC address");
2065 return;
2066 }
2067 wpa_s->mac_addr_changed = 0;
2068 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2069 wpa_msg(wpa_s, MSG_INFO,
2070 "Could not update MAC address information");
2071 return;
2072 }
2073 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2074 }
2075 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002076
2077#ifdef CONFIG_IBSS_RSN
2078 ibss_rsn_deinit(wpa_s->ibss_rsn);
2079 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002080#else /* CONFIG_IBSS_RSN */
2081 if (ssid->mode == WPAS_MODE_IBSS &&
2082 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2083 wpa_msg(wpa_s, MSG_INFO,
2084 "IBSS RSN not supported in the build");
2085 return;
2086 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002087#endif /* CONFIG_IBSS_RSN */
2088
2089 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2090 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2091#ifdef CONFIG_AP
2092 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2093 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2094 "mode");
2095 return;
2096 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002097 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2098 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002099 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2100 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002101 return;
2102 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002103 wpa_s->current_bss = bss;
2104#else /* CONFIG_AP */
2105 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2106 "the build");
2107#endif /* CONFIG_AP */
2108 return;
2109 }
2110
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002111 if (ssid->mode == WPAS_MODE_MESH) {
2112#ifdef CONFIG_MESH
2113 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2114 wpa_msg(wpa_s, MSG_INFO,
2115 "Driver does not support mesh mode");
2116 return;
2117 }
2118 if (bss)
2119 ssid->frequency = bss->freq;
2120 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2121 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2122 return;
2123 }
2124 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002125 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
2126 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
2127 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002128 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002129#else /* CONFIG_MESH */
2130 wpa_msg(wpa_s, MSG_ERROR,
2131 "mesh mode support not included in the build");
2132#endif /* CONFIG_MESH */
2133 return;
2134 }
2135
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002136 /*
2137 * Set WPA state machine configuration to match the selected network now
2138 * so that the information is available before wpas_start_assoc_cb()
2139 * gets called. This is needed at least for RSN pre-authentication where
2140 * candidate APs are added to a list based on scan result processing
2141 * before completion of the first association.
2142 */
2143 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2144
2145#ifdef CONFIG_DPP
2146 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2147 return;
2148#endif /* CONFIG_DPP */
2149
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002150#ifdef CONFIG_TDLS
2151 if (bss)
2152 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2153 bss->ie_len);
2154#endif /* CONFIG_TDLS */
2155
Hai Shalomc3565922019-10-28 11:58:20 -07002156#ifdef CONFIG_MBO
2157 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2158#endif /* CONFIG_MBO */
2159
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002160 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002161 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002162 sme_authenticate(wpa_s, bss, ssid);
2163 return;
2164 }
2165
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002166 if (wpa_s->connect_work) {
2167 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2168 return;
2169 }
2170
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002171 if (radio_work_pending(wpa_s, "connect")) {
2172 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2173 return;
2174 }
2175
Dmitry Shmidt29333592017-01-09 12:27:11 -08002176#ifdef CONFIG_SME
2177 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2178 /* Clear possibly set auth_alg, if any, from last attempt. */
2179 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2180 }
2181#endif /* CONFIG_SME */
2182
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002183 wpas_abort_ongoing_scan(wpa_s);
2184
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002185 cwork = os_zalloc(sizeof(*cwork));
2186 if (cwork == NULL)
2187 return;
2188
2189 cwork->bss = bss;
2190 cwork->ssid = ssid;
2191
2192 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2193 wpas_start_assoc_cb, cwork) < 0) {
2194 os_free(cwork);
2195 }
2196}
2197
2198
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002199static int bss_is_ibss(struct wpa_bss *bss)
2200{
2201 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2202 IEEE80211_CAP_IBSS;
2203}
2204
2205
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002206static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2207 const struct wpa_ssid *ssid)
2208{
2209 enum hostapd_hw_mode hw_mode;
2210 struct hostapd_hw_modes *mode = NULL;
2211 u8 channel;
2212 int i;
2213
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002214 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2215 if (hw_mode == NUM_HOSTAPD_MODES)
2216 return 0;
2217 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2218 if (wpa_s->hw.modes[i].mode == hw_mode) {
2219 mode = &wpa_s->hw.modes[i];
2220 break;
2221 }
2222 }
2223
2224 if (!mode)
2225 return 0;
2226
2227 return mode->vht_capab != 0;
2228}
2229
2230
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002231void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2232 const struct wpa_ssid *ssid,
2233 struct hostapd_freq_params *freq)
2234{
Hai Shalom81f62d82019-07-22 12:10:00 -07002235 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002236 enum hostapd_hw_mode hw_mode;
2237 struct hostapd_hw_modes *mode = NULL;
2238 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2239 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002240 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002241 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2242 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002243 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002244 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002245 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002246 int chwidth, seg0, seg1;
2247 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002248 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002249
2250 freq->freq = ssid->frequency;
2251
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002252 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2253 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2254
2255 if (ssid->mode != WPAS_MODE_IBSS)
2256 break;
2257
2258 /* Don't adjust control freq in case of fixed_freq */
2259 if (ssid->fixed_freq)
2260 break;
2261
2262 if (!bss_is_ibss(bss))
2263 continue;
2264
2265 if (ssid->ssid_len == bss->ssid_len &&
2266 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2267 wpa_printf(MSG_DEBUG,
2268 "IBSS already found in scan results, adjust control freq: %d",
2269 bss->freq);
2270 freq->freq = bss->freq;
2271 obss_scan = 0;
2272 break;
2273 }
2274 }
2275
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002276 /* For IBSS check HT_IBSS flag */
2277 if (ssid->mode == WPAS_MODE_IBSS &&
2278 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2279 return;
2280
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002281 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2282 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2283 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2284 wpa_printf(MSG_DEBUG,
2285 "IBSS: WEP/TKIP detected, do not try to enable HT");
2286 return;
2287 }
2288
2289 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002290 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2291 if (wpa_s->hw.modes[i].mode == hw_mode) {
2292 mode = &wpa_s->hw.modes[i];
2293 break;
2294 }
2295 }
2296
2297 if (!mode)
2298 return;
2299
Hai Shalomc3565922019-10-28 11:58:20 -07002300 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2301 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002302
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002303#ifdef CONFIG_HT_OVERRIDES
2304 if (ssid->disable_ht) {
2305 freq->ht_enabled = 0;
2306 return;
2307 }
2308#endif /* CONFIG_HT_OVERRIDES */
2309
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002310 freq->ht_enabled = ht_supported(mode);
2311 if (!freq->ht_enabled)
2312 return;
2313
Hai Shalomc3565922019-10-28 11:58:20 -07002314 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2315 if (is_24ghz)
2316 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
2317
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002318 /* Setup higher BW only for 5 GHz */
2319 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2320 return;
2321
2322 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2323 pri_chan = &mode->channels[chan_idx];
2324 if (pri_chan->chan == channel)
2325 break;
2326 pri_chan = NULL;
2327 }
2328 if (!pri_chan)
2329 return;
2330
2331 /* Check primary channel flags */
2332 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2333 return;
2334
Hai Shalom74f70d42019-02-11 14:42:39 -08002335 freq->channel = pri_chan->chan;
2336
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002337#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002338 if (ssid->disable_ht40) {
2339 if (ssid->disable_vht)
2340 return;
2341 goto skip_ht40;
2342 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002343#endif /* CONFIG_HT_OVERRIDES */
2344
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002345 /* Check/setup HT40+/HT40- */
2346 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2347 if (ht40plus[j] == channel) {
2348 ht40 = 1;
2349 break;
2350 }
2351 }
2352
2353 /* Find secondary channel */
2354 for (i = 0; i < mode->num_channels; i++) {
2355 sec_chan = &mode->channels[i];
2356 if (sec_chan->chan == channel + ht40 * 4)
2357 break;
2358 sec_chan = NULL;
2359 }
2360 if (!sec_chan)
2361 return;
2362
2363 /* Check secondary channel flags */
2364 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2365 return;
2366
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002367 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002368 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2369 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002370 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002371 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2372 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002373 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002374 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002375
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002376 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002377 struct wpa_scan_results *scan_res;
2378
2379 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2380 if (scan_res == NULL) {
2381 /* Back to HT20 */
2382 freq->sec_channel_offset = 0;
2383 return;
2384 }
2385
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002386 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002387 switch (res) {
2388 case 0:
2389 /* Back to HT20 */
2390 freq->sec_channel_offset = 0;
2391 break;
2392 case 1:
2393 /* Configuration allowed */
2394 break;
2395 case 2:
2396 /* Switch pri/sec channels */
2397 freq->freq = hw_get_freq(mode, sec_chan->chan);
2398 freq->sec_channel_offset = -freq->sec_channel_offset;
2399 freq->channel = sec_chan->chan;
2400 break;
2401 default:
2402 freq->sec_channel_offset = 0;
2403 break;
2404 }
2405
2406 wpa_scan_results_free(scan_res);
2407 }
2408
Hai Shalom74f70d42019-02-11 14:42:39 -08002409#ifdef CONFIG_HT_OVERRIDES
2410skip_ht40:
2411#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002412 wpa_printf(MSG_DEBUG,
2413 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2414 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002415
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002416 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002417 return;
2418
2419 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002420 if (ssid->mode == WPAS_MODE_IBSS &&
2421 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002422 return;
2423
2424 vht_freq = *freq;
2425
Paul Stewart092955c2017-02-06 09:13:09 -08002426#ifdef CONFIG_VHT_OVERRIDES
2427 if (ssid->disable_vht) {
2428 freq->vht_enabled = 0;
2429 return;
2430 }
2431#endif /* CONFIG_VHT_OVERRIDES */
2432
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002433 vht_freq.vht_enabled = vht_supported(mode);
2434 if (!vht_freq.vht_enabled)
2435 return;
2436
Hai Shalomc3565922019-10-28 11:58:20 -07002437 /* Enable HE for VHT */
2438 vht_freq.he_enabled = mode->he_capab[ieee80211_mode].he_supported;
2439
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002440 /* setup center_freq1, bandwidth */
2441 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2442 if (freq->channel >= vht80[j] &&
2443 freq->channel < vht80[j] + 16)
2444 break;
2445 }
2446
2447 if (j == ARRAY_SIZE(vht80))
2448 return;
2449
2450 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2451 struct hostapd_channel_data *chan;
2452
2453 chan = hw_get_channel_chan(mode, i, NULL);
2454 if (!chan)
2455 return;
2456
2457 /* Back to HT configuration if channel not usable */
2458 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2459 return;
2460 }
2461
Hai Shalom81f62d82019-07-22 12:10:00 -07002462 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002463 seg0 = vht80[j] + 6;
2464 seg1 = 0;
2465
Hai Shalom81f62d82019-07-22 12:10:00 -07002466 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002467 /* setup center_freq2, bandwidth */
2468 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2469 /* Only accept 80 MHz segments separated by a gap */
2470 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2471 continue;
2472 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2473 struct hostapd_channel_data *chan;
2474
2475 chan = hw_get_channel_chan(mode, i, NULL);
2476 if (!chan)
2477 continue;
2478
2479 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2480 HOSTAPD_CHAN_NO_IR |
2481 HOSTAPD_CHAN_RADAR))
2482 continue;
2483
2484 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002485 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002486 vht_caps |=
2487 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2488 seg1 = vht80[k] + 6;
2489 }
2490
Hai Shalom81f62d82019-07-22 12:10:00 -07002491 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002492 break;
2493 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002494 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002495 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002496 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002497 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2498 seg0 = 50;
2499 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002500 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002501 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2502 seg0 = 114;
2503 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002504 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2505 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002506 seg0 = vht80[j] + 2;
2507#ifdef CONFIG_HT_OVERRIDES
2508 if (ssid->disable_ht40)
2509 seg0 = 0;
2510#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002511 }
2512
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002513 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002514 freq->channel, ssid->enable_edmg,
2515 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002516 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002517 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002518 chwidth, seg0, seg1, vht_caps,
2519 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002520 return;
2521
2522 *freq = vht_freq;
2523
2524 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2525 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002526}
2527
2528
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002529#ifdef CONFIG_FILS
2530static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2531 size_t ie_buf_len)
2532{
2533 struct fils_hlp_req *req;
2534 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2535 const u8 *pos;
2536 u8 *buf = ie_buf;
2537
2538 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2539 list) {
2540 rem_len = ie_buf_len - ie_len;
2541 pos = wpabuf_head(req->pkt);
2542 hdr_len = 1 + 2 * ETH_ALEN + 6;
2543 hlp_len = wpabuf_len(req->pkt);
2544
2545 if (rem_len < 2 + hdr_len + hlp_len) {
2546 wpa_printf(MSG_ERROR,
2547 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2548 (unsigned long) rem_len,
2549 (unsigned long) (2 + hdr_len + hlp_len));
2550 break;
2551 }
2552
2553 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2554 /* Element ID */
2555 *buf++ = WLAN_EID_EXTENSION;
2556 /* Length */
2557 *buf++ = len;
2558 /* Element ID Extension */
2559 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2560 /* Destination MAC address */
2561 os_memcpy(buf, req->dst, ETH_ALEN);
2562 buf += ETH_ALEN;
2563 /* Source MAC address */
2564 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2565 buf += ETH_ALEN;
2566 /* LLC/SNAP Header */
2567 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2568 buf += 6;
2569 /* HLP Packet */
2570 os_memcpy(buf, pos, len - hdr_len);
2571 buf += len - hdr_len;
2572 pos += len - hdr_len;
2573
2574 hlp_len -= len - hdr_len;
2575 ie_len += 2 + len;
2576 rem_len -= 2 + len;
2577
2578 while (hlp_len) {
2579 len = (hlp_len > 255) ? 255 : hlp_len;
2580 if (rem_len < 2 + len)
2581 break;
2582 *buf++ = WLAN_EID_FRAGMENT;
2583 *buf++ = len;
2584 os_memcpy(buf, pos, len);
2585 buf += len;
2586 pos += len;
2587
2588 hlp_len -= len;
2589 ie_len += 2 + len;
2590 rem_len -= 2 + len;
2591 }
2592 }
2593
2594 return ie_len;
2595}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002596
2597
2598int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2599{
2600 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2601 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2602 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2603 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2604}
2605
2606
2607int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2608{
2609#ifdef CONFIG_FILS_SK_PFS
2610 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2611 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2612#else /* CONFIG_FILS_SK_PFS */
2613 return 0;
2614#endif /* CONFIG_FILS_SK_PFS */
2615}
2616
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002617#endif /* CONFIG_FILS */
2618
2619
2620static u8 * wpas_populate_assoc_ies(
2621 struct wpa_supplicant *wpa_s,
2622 struct wpa_bss *bss, struct wpa_ssid *ssid,
2623 struct wpa_driver_associate_params *params,
2624 enum wpa_drv_update_connect_params_mask *mask)
2625{
2626 u8 *wpa_ie;
2627 size_t max_wpa_ie_len = 500;
2628 size_t wpa_ie_len;
2629 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002630#ifdef CONFIG_MBO
2631 const u8 *mbo_ie;
2632#endif
Hai Shalom5f92bc92019-04-18 11:54:11 -07002633#ifdef CONFIG_SAE
2634 int sae_pmksa_cached = 0;
2635#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002636#ifdef CONFIG_FILS
2637 const u8 *realm, *username, *rrk;
2638 size_t realm_len, username_len, rrk_len;
2639 u16 next_seq_num;
2640 struct fils_hlp_req *req;
2641
2642 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2643 list) {
2644 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2645 2 + 2 * wpabuf_len(req->pkt) / 255;
2646 }
2647#endif /* CONFIG_FILS */
2648
2649 wpa_ie = os_malloc(max_wpa_ie_len);
2650 if (!wpa_ie) {
2651 wpa_printf(MSG_ERROR,
2652 "Failed to allocate connect IE buffer for %lu bytes",
2653 (unsigned long) max_wpa_ie_len);
2654 return NULL;
2655 }
2656
2657 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2658 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2659 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2660 int try_opportunistic;
2661 const u8 *cache_id = NULL;
2662
2663 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2664 wpa_s->conf->okc :
2665 ssid->proactive_key_caching) &&
2666 (ssid->proto & WPA_PROTO_RSN);
2667#ifdef CONFIG_FILS
2668 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2669 cache_id = wpa_bss_get_fils_cache_id(bss);
2670#endif /* CONFIG_FILS */
2671 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2672 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002673 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002674 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Hai Shalom5f92bc92019-04-18 11:54:11 -07002675#ifdef CONFIG_SAE
2676 sae_pmksa_cached = 1;
2677#endif /* CONFIG_SAE */
2678 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002679 wpa_ie_len = max_wpa_ie_len;
2680 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2681 wpa_ie, &wpa_ie_len)) {
2682 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2683 "key management and encryption suites");
2684 os_free(wpa_ie);
2685 return NULL;
2686 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002687#ifdef CONFIG_HS20
2688 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2689 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2690 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2691 wpa_ie_len = max_wpa_ie_len;
2692 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2693 wpa_ie, &wpa_ie_len)) {
2694 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2695 "key management and encryption suites");
2696 os_free(wpa_ie);
2697 return NULL;
2698 }
2699#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002700 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2701 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2702 /*
2703 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2704 * use non-WPA since the scan results did not indicate that the
2705 * AP is using WPA or WPA2.
2706 */
2707 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2708 wpa_ie_len = 0;
2709 wpa_s->wpa_proto = 0;
2710 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2711 wpa_ie_len = max_wpa_ie_len;
2712 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2713 wpa_ie, &wpa_ie_len)) {
2714 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2715 "key management and encryption suites (no "
2716 "scan results)");
2717 os_free(wpa_ie);
2718 return NULL;
2719 }
2720#ifdef CONFIG_WPS
2721 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2722 struct wpabuf *wps_ie;
2723 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2724 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2725 wpa_ie_len = wpabuf_len(wps_ie);
2726 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2727 } else
2728 wpa_ie_len = 0;
2729 wpabuf_free(wps_ie);
2730 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2731 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2732 params->wps = WPS_MODE_PRIVACY;
2733 else
2734 params->wps = WPS_MODE_OPEN;
2735 wpa_s->wpa_proto = 0;
2736#endif /* CONFIG_WPS */
2737 } else {
2738 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2739 wpa_ie_len = 0;
2740 wpa_s->wpa_proto = 0;
2741 }
2742
2743#ifdef IEEE8021X_EAPOL
2744 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2745 if (ssid->leap) {
2746 if (ssid->non_leap == 0)
2747 algs = WPA_AUTH_ALG_LEAP;
2748 else
2749 algs |= WPA_AUTH_ALG_LEAP;
2750 }
2751 }
2752
2753#ifdef CONFIG_FILS
2754 /* Clear FILS association */
2755 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2756
2757 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2758 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2759 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2760 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002761 &next_seq_num, &rrk, &rrk_len) == 0 &&
2762 (!wpa_s->last_con_fail_realm ||
2763 wpa_s->last_con_fail_realm_len != realm_len ||
2764 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002765 algs = WPA_AUTH_ALG_FILS;
2766 params->fils_erp_username = username;
2767 params->fils_erp_username_len = username_len;
2768 params->fils_erp_realm = realm;
2769 params->fils_erp_realm_len = realm_len;
2770 params->fils_erp_next_seq_num = next_seq_num;
2771 params->fils_erp_rrk = rrk;
2772 params->fils_erp_rrk_len = rrk_len;
2773
2774 if (mask)
2775 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2776 }
2777#endif /* CONFIG_FILS */
2778#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002779#ifdef CONFIG_SAE
2780 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2781 algs = WPA_AUTH_ALG_SAE;
2782#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002783
2784 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2785 if (ssid->auth_alg) {
2786 algs = ssid->auth_alg;
2787 wpa_dbg(wpa_s, MSG_DEBUG,
2788 "Overriding auth_alg selection: 0x%x", algs);
2789 }
2790
Hai Shalom5f92bc92019-04-18 11:54:11 -07002791#ifdef CONFIG_SAE
2792 if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
2793 wpa_dbg(wpa_s, MSG_DEBUG,
2794 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2795 algs = WPA_AUTH_ALG_OPEN;
2796 }
2797#endif /* CONFIG_SAE */
2798
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002799#ifdef CONFIG_P2P
2800 if (wpa_s->global->p2p) {
2801 u8 *pos;
2802 size_t len;
2803 int res;
2804 pos = wpa_ie + wpa_ie_len;
2805 len = max_wpa_ie_len - wpa_ie_len;
2806 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2807 ssid->p2p_group);
2808 if (res >= 0)
2809 wpa_ie_len += res;
2810 }
2811
2812 wpa_s->cross_connect_disallowed = 0;
2813 if (bss) {
2814 struct wpabuf *p2p;
2815 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2816 if (p2p) {
2817 wpa_s->cross_connect_disallowed =
2818 p2p_get_cross_connect_disallowed(p2p);
2819 wpabuf_free(p2p);
2820 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2821 "connection",
2822 wpa_s->cross_connect_disallowed ?
2823 "disallows" : "allows");
2824 }
2825 }
2826
2827 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2828#endif /* CONFIG_P2P */
2829
2830 if (bss) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002831 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002832 wpa_ie + wpa_ie_len,
2833 max_wpa_ie_len -
2834 wpa_ie_len);
2835 }
2836
2837 /*
2838 * Workaround: Add Extended Capabilities element only if the AP
2839 * included this element in Beacon/Probe Response frames. Some older
2840 * APs seem to have interoperability issues if this element is
2841 * included, so while the standard may require us to include the
2842 * element in all cases, it is justifiable to skip it to avoid
2843 * interoperability issues.
2844 */
2845 if (ssid->p2p_group)
2846 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2847 else
2848 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2849
2850 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2851 u8 ext_capab[18];
2852 int ext_capab_len;
2853 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2854 sizeof(ext_capab));
2855 if (ext_capab_len > 0 &&
2856 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2857 u8 *pos = wpa_ie;
2858 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2859 pos += 2 + pos[1];
2860 os_memmove(pos + ext_capab_len, pos,
2861 wpa_ie_len - (pos - wpa_ie));
2862 wpa_ie_len += ext_capab_len;
2863 os_memcpy(pos, ext_capab, ext_capab_len);
2864 }
2865 }
2866
2867#ifdef CONFIG_HS20
2868 if (is_hs20_network(wpa_s, ssid, bss)) {
2869 struct wpabuf *hs20;
2870
Roshan Pius3a1667e2018-07-03 15:17:14 -07002871 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002872 if (hs20) {
2873 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2874 size_t len;
2875
Hai Shalom74f70d42019-02-11 14:42:39 -08002876 wpas_hs20_add_indication(hs20, pps_mo_id,
2877 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002878 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002879 len = max_wpa_ie_len - wpa_ie_len;
2880 if (wpabuf_len(hs20) <= len) {
2881 os_memcpy(wpa_ie + wpa_ie_len,
2882 wpabuf_head(hs20), wpabuf_len(hs20));
2883 wpa_ie_len += wpabuf_len(hs20);
2884 }
2885 wpabuf_free(hs20);
2886
2887 hs20_configure_frame_filters(wpa_s);
2888 }
2889 }
2890#endif /* CONFIG_HS20 */
2891
2892 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2893 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2894 size_t len;
2895
2896 len = max_wpa_ie_len - wpa_ie_len;
2897 if (wpabuf_len(buf) <= len) {
2898 os_memcpy(wpa_ie + wpa_ie_len,
2899 wpabuf_head(buf), wpabuf_len(buf));
2900 wpa_ie_len += wpabuf_len(buf);
2901 }
2902 }
2903
2904#ifdef CONFIG_FST
2905 if (wpa_s->fst_ies) {
2906 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2907
2908 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
2909 os_memcpy(wpa_ie + wpa_ie_len,
2910 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2911 wpa_ie_len += fst_ies_len;
2912 }
2913 }
2914#endif /* CONFIG_FST */
2915
2916#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07002917 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07002918 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002919 int len;
2920
2921 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002922 max_wpa_ie_len - wpa_ie_len,
2923 !!mbo_attr_from_mbo_ie(mbo_ie,
2924 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002925 if (len >= 0)
2926 wpa_ie_len += len;
2927 }
2928#endif /* CONFIG_MBO */
2929
2930#ifdef CONFIG_FILS
2931 if (algs == WPA_AUTH_ALG_FILS) {
2932 size_t len;
2933
2934 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
2935 max_wpa_ie_len - wpa_ie_len);
2936 wpa_ie_len += len;
2937 }
2938#endif /* CONFIG_FILS */
2939
2940#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002941#ifdef CONFIG_TESTING_OPTIONS
2942 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
2943 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2944 } else
2945#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002946 if (algs == WPA_AUTH_ALG_OPEN &&
2947 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
2948 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002949 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002950
Roshan Pius3a1667e2018-07-03 15:17:14 -07002951 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002952 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08002953 } else if (wpa_s->assoc_status_code ==
2954 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002955 if (wpa_s->last_owe_group == 19)
2956 group = 20;
2957 else if (wpa_s->last_owe_group == 20)
2958 group = 21;
2959 else
2960 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002961 } else {
2962 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002963 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002964
Roshan Pius3a1667e2018-07-03 15:17:14 -07002965 wpa_s->last_owe_group = group;
2966 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002967 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2968 if (owe_ie &&
2969 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
2970 os_memcpy(wpa_ie + wpa_ie_len,
2971 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2972 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002973 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002974 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002975 }
2976#endif /* CONFIG_OWE */
2977
Hai Shalom021b0b52019-04-10 11:17:58 -07002978#ifdef CONFIG_DPP2
2979 if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
2980 ssid->dpp_netaccesskey) {
2981 dpp_pfs_free(wpa_s->dpp_pfs);
2982 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
2983 ssid->dpp_netaccesskey_len);
2984 if (!wpa_s->dpp_pfs) {
2985 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
2986 /* Try to continue without PFS */
2987 goto pfs_fail;
2988 }
2989 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
2990 max_wpa_ie_len - wpa_ie_len) {
2991 os_memcpy(wpa_ie + wpa_ie_len,
2992 wpabuf_head(wpa_s->dpp_pfs->ie),
2993 wpabuf_len(wpa_s->dpp_pfs->ie));
2994 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
2995 }
2996 }
2997pfs_fail:
2998#endif /* CONFIG_DPP2 */
2999
Roshan Pius3a1667e2018-07-03 15:17:14 -07003000#ifdef CONFIG_IEEE80211R
3001 /*
3002 * Add MDIE under these conditions: the network profile allows FT,
3003 * the AP supports FT, and the mobility domain ID matches.
3004 */
3005 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3006 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3007
3008 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3009 size_t len = 0;
3010 const u8 *md = mdie + 2;
3011 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3012
3013 if (os_memcmp(md, wpa_md,
3014 MOBILITY_DOMAIN_ID_LEN) == 0) {
3015 /* Add mobility domain IE */
3016 len = wpa_ft_add_mdie(
3017 wpa_s->wpa, wpa_ie + wpa_ie_len,
3018 max_wpa_ie_len - wpa_ie_len, mdie);
3019 wpa_ie_len += len;
3020 }
3021#ifdef CONFIG_SME
3022 if (len > 0 && wpa_s->sme.ft_used &&
3023 wpa_sm_has_ptk(wpa_s->wpa)) {
3024 wpa_dbg(wpa_s, MSG_DEBUG,
3025 "SME: Trying to use FT over-the-air");
3026 algs |= WPA_AUTH_ALG_FT;
3027 }
3028#endif /* CONFIG_SME */
3029 }
3030 }
3031#endif /* CONFIG_IEEE80211R */
3032
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003033#ifdef CONFIG_TESTING_OPTIONS
3034 if (wpa_s->rsnxe_override_assoc &&
3035 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3036 max_wpa_ie_len - wpa_ie_len) {
3037 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3038 os_memcpy(wpa_ie + wpa_ie_len,
3039 wpabuf_head(wpa_s->rsnxe_override_assoc),
3040 wpabuf_len(wpa_s->rsnxe_override_assoc));
3041 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3042 } else
3043#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003044 if (wpa_s->rsnxe_len > 0 &&
3045 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3046 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3047 wpa_ie_len += wpa_s->rsnxe_len;
3048 }
3049
Hai Shalom74f70d42019-02-11 14:42:39 -08003050 if (ssid->multi_ap_backhaul_sta) {
3051 size_t multi_ap_ie_len;
3052
3053 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3054 max_wpa_ie_len - wpa_ie_len,
3055 MULTI_AP_BACKHAUL_STA);
3056 if (multi_ap_ie_len == 0) {
3057 wpa_printf(MSG_ERROR,
3058 "Multi-AP: Failed to build Multi-AP IE");
3059 os_free(wpa_ie);
3060 return NULL;
3061 }
3062 wpa_ie_len += multi_ap_ie_len;
3063 }
3064
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003065 params->wpa_ie = wpa_ie;
3066 params->wpa_ie_len = wpa_ie_len;
3067 params->auth_alg = algs;
3068 if (mask)
3069 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3070
3071 return wpa_ie;
3072}
3073
3074
Hai Shalomc3565922019-10-28 11:58:20 -07003075#ifdef CONFIG_OWE
3076static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3077{
3078 struct wpa_driver_associate_params params;
3079 u8 *wpa_ie;
3080
3081 os_memset(&params, 0, sizeof(params));
3082 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3083 wpa_s->current_ssid, &params, NULL);
3084 if (!wpa_ie)
3085 return;
3086
3087 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3088 os_free(wpa_ie);
3089}
3090#endif /* CONFIG_OWE */
3091
3092
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003093#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3094static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3095{
3096 struct wpa_driver_associate_params params;
3097 enum wpa_drv_update_connect_params_mask mask = 0;
3098 u8 *wpa_ie;
3099
3100 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3101 return; /* nothing to do */
3102
3103 os_memset(&params, 0, sizeof(params));
3104 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3105 wpa_s->current_ssid, &params, &mask);
3106 if (!wpa_ie)
3107 return;
3108
3109 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3110 os_free(wpa_ie);
3111 return;
3112 }
3113
3114 wpa_s->auth_alg = params.auth_alg;
3115 wpa_drv_update_connect_params(wpa_s, &params, mask);
3116 os_free(wpa_ie);
3117}
3118#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3119
3120
Hai Shalomc3565922019-10-28 11:58:20 -07003121static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3122{
3123 if (!edmg_ie || edmg_ie[1] < 6)
3124 return 0;
3125 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3126}
3127
3128
3129static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3130{
3131 if (!edmg_ie || edmg_ie[1] < 6)
3132 return 0;
3133 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3134}
3135
3136
3137/* Returns the intersection of two EDMG configurations.
3138 * Note: The current implementation is limited to CB2 only (CB1 included),
3139 * i.e., the implementation supports up to 2 contiguous channels.
3140 * For supporting non-contiguous (aggregated) channels and for supporting
3141 * CB3 and above, this function will need to be extended.
3142 */
3143static struct ieee80211_edmg_config
3144get_edmg_intersection(struct ieee80211_edmg_config a,
3145 struct ieee80211_edmg_config b,
3146 u8 primary_channel)
3147{
3148 struct ieee80211_edmg_config result;
3149 int i, contiguous = 0;
3150 int max_contiguous = 0;
3151
3152 result.channels = b.channels & a.channels;
3153 if (!result.channels) {
3154 wpa_printf(MSG_DEBUG,
3155 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3156 a.channels, b.channels);
3157 goto fail;
3158 }
3159
3160 if (!(result.channels & BIT(primary_channel - 1))) {
3161 wpa_printf(MSG_DEBUG,
3162 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3163 primary_channel, result.channels);
3164 goto fail;
3165 }
3166
3167 /* Find max contiguous channels */
3168 for (i = 0; i < 6; i++) {
3169 if (result.channels & BIT(i))
3170 contiguous++;
3171 else
3172 contiguous = 0;
3173
3174 if (contiguous > max_contiguous)
3175 max_contiguous = contiguous;
3176 }
3177
3178 /* Assuming AP and STA supports ONLY contiguous channels,
3179 * bw configuration can have value between 4-7.
3180 */
3181 if ((b.bw_config < a.bw_config))
3182 result.bw_config = b.bw_config;
3183 else
3184 result.bw_config = a.bw_config;
3185
3186 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3187 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3188 wpa_printf(MSG_DEBUG,
3189 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3190 max_contiguous);
3191 goto fail;
3192 }
3193
3194 return result;
3195
3196fail:
3197 result.channels = 0;
3198 result.bw_config = 0;
3199 return result;
3200}
3201
3202
3203static struct ieee80211_edmg_config
3204get_supported_edmg(struct wpa_supplicant *wpa_s,
3205 struct hostapd_freq_params *freq,
3206 struct ieee80211_edmg_config request_edmg)
3207{
3208 enum hostapd_hw_mode hw_mode;
3209 struct hostapd_hw_modes *mode = NULL;
3210 u8 primary_channel;
3211
3212 if (!wpa_s->hw.modes)
3213 goto fail;
3214
3215 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3216 if (hw_mode == NUM_HOSTAPD_MODES)
3217 goto fail;
3218
3219 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode);
3220 if (!mode)
3221 goto fail;
3222
3223 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3224
3225fail:
3226 request_edmg.channels = 0;
3227 request_edmg.bw_config = 0;
3228 return request_edmg;
3229}
3230
3231
Hai Shalom021b0b52019-04-10 11:17:58 -07003232#ifdef CONFIG_MBO
3233void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3234{
3235 struct wpa_driver_associate_params params;
3236 u8 *wpa_ie;
3237
3238 /*
3239 * Update MBO connect params only in case of change of MBO attributes
3240 * when connected, if the AP support MBO.
3241 */
3242
3243 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3244 !wpa_s->current_bss ||
3245 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3246 return;
3247
3248 os_memset(&params, 0, sizeof(params));
3249 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3250 wpa_s->current_ssid, &params, NULL);
3251 if (!wpa_ie)
3252 return;
3253
3254 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3255 os_free(wpa_ie);
3256}
3257#endif /* CONFIG_MBO */
3258
3259
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003260static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3261{
3262 struct wpa_connect_work *cwork = work->ctx;
3263 struct wpa_bss *bss = cwork->bss;
3264 struct wpa_ssid *ssid = cwork->ssid;
3265 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003266 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003267 const u8 *edmg_ie_oper;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003268 int use_crypt, ret, i, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003269 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003270 struct wpa_driver_associate_params params;
3271 int wep_keys_set = 0;
3272 int assoc_failed = 0;
3273 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003274 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003275#ifdef CONFIG_HT_OVERRIDES
3276 struct ieee80211_ht_capabilities htcaps;
3277 struct ieee80211_ht_capabilities htcaps_mask;
3278#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003279#ifdef CONFIG_VHT_OVERRIDES
3280 struct ieee80211_vht_capabilities vhtcaps;
3281 struct ieee80211_vht_capabilities vhtcaps_mask;
3282#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003283
3284 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003285 if (work->started) {
3286 wpa_s->connect_work = NULL;
3287
3288 /* cancel possible auth. timeout */
3289 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3290 NULL);
3291 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003292 wpas_connect_work_free(cwork);
3293 return;
3294 }
3295
3296 wpa_s->connect_work = work;
3297
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003298 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3299 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003300 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3301 wpas_connect_work_done(wpa_s);
3302 return;
3303 }
3304
Dmitry Shmidte4663042016-04-04 10:07:49 -07003305 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003306 os_memset(&params, 0, sizeof(params));
3307 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003308 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003309 if (bss &&
3310 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311#ifdef CONFIG_IEEE80211R
3312 const u8 *ie, *md = NULL;
3313#endif /* CONFIG_IEEE80211R */
3314 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3315 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3316 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3317 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3318 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3319 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3320 if (bssid_changed)
3321 wpas_notify_bssid_changed(wpa_s);
3322#ifdef CONFIG_IEEE80211R
3323 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3324 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3325 md = ie + 2;
3326 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3327 if (md) {
3328 /* Prepare for the next transition */
3329 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3330 }
3331#endif /* CONFIG_IEEE80211R */
3332#ifdef CONFIG_WPS
3333 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3334 wpa_s->conf->ap_scan == 2 &&
3335 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3336 /* Use ap_scan==1 style network selection to find the network
3337 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003338 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003339 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003340 wpa_s->reassociate = 1;
3341 wpa_supplicant_req_scan(wpa_s, 0, 0);
3342 return;
3343#endif /* CONFIG_WPS */
3344 } else {
3345 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3346 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003347 if (bss)
3348 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3349 else
3350 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003351 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003352 if (!wpa_s->pno)
3353 wpa_supplicant_cancel_sched_scan(wpa_s);
3354
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003355 wpa_supplicant_cancel_scan(wpa_s);
3356
3357 /* Starting new association, so clear the possibly used WPA IE from the
3358 * previous association. */
3359 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003360 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3361 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003362
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003363 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3364 if (!wpa_ie) {
3365 wpas_connect_work_done(wpa_s);
3366 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003367 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003368
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003369 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3370 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003371 cipher_pairwise = wpa_s->pairwise_cipher;
3372 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003373 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003374 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3375 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3376 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3377 use_crypt = 0;
3378 if (wpa_set_wep_keys(wpa_s, ssid)) {
3379 use_crypt = 1;
3380 wep_keys_set = 1;
3381 }
3382 }
3383 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3384 use_crypt = 0;
3385
3386#ifdef IEEE8021X_EAPOL
3387 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3388 if ((ssid->eapol_flags &
3389 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3390 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3391 !wep_keys_set) {
3392 use_crypt = 0;
3393 } else {
3394 /* Assume that dynamic WEP-104 keys will be used and
3395 * set cipher suites in order for drivers to expect
3396 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003397 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003398 }
3399 }
3400#endif /* IEEE8021X_EAPOL */
3401
3402 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3403 /* Set the key before (and later after) association */
3404 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3405 }
3406
3407 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3408 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003409 params.ssid = bss->ssid;
3410 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003411 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3412 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003413 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3414 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003415 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003416 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003417 ssid->bssid_set,
3418 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003419 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003420 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003421 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003422 params.bssid_hint = bss->bssid;
3423 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003424 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003425 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003426 if (ssid->bssid_hint_set)
3427 params.bssid_hint = ssid->bssid_hint;
3428
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003429 params.ssid = ssid->ssid;
3430 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003431 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003432 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003433
3434 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3435 wpa_s->conf->ap_scan == 2) {
3436 params.bssid = ssid->bssid;
3437 params.fixed_bssid = 1;
3438 }
3439
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003440 /* Initial frequency for IBSS/mesh */
3441 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003442 ssid->frequency > 0 && params.freq.freq == 0)
3443 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003444
3445 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003446 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003447 if (ssid->beacon_int)
3448 params.beacon_int = ssid->beacon_int;
3449 else
3450 params.beacon_int = wpa_s->conf->beacon_int;
3451 }
3452
Hai Shalomc3565922019-10-28 11:58:20 -07003453 if (bss && ssid->enable_edmg)
3454 edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len,
3455 WLAN_EID_EXT_EDMG_OPERATION);
3456 else
3457 edmg_ie_oper = NULL;
3458
3459 if (edmg_ie_oper) {
3460 params.freq.edmg.channels =
3461 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3462 params.freq.edmg.bw_config =
3463 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3464 wpa_printf(MSG_DEBUG,
3465 "AP supports EDMG channels 0x%x, bw_config %d",
3466 params.freq.edmg.channels,
3467 params.freq.edmg.bw_config);
3468
3469 /* User may ask for specific EDMG channel for EDMG connection
3470 * (must be supported by AP)
3471 */
3472 if (ssid->edmg_channel) {
3473 struct ieee80211_edmg_config configured_edmg;
3474 enum hostapd_hw_mode hw_mode;
3475 u8 primary_channel;
3476
3477 hw_mode = ieee80211_freq_to_chan(bss->freq,
3478 &primary_channel);
3479 if (hw_mode == NUM_HOSTAPD_MODES)
3480 goto edmg_fail;
3481
3482 hostapd_encode_edmg_chan(ssid->enable_edmg,
3483 ssid->edmg_channel,
3484 primary_channel,
3485 &configured_edmg);
3486
3487 if (ieee802_edmg_is_allowed(params.freq.edmg,
3488 configured_edmg)) {
3489 params.freq.edmg = configured_edmg;
3490 wpa_printf(MSG_DEBUG,
3491 "Use EDMG channel %d for connection",
3492 ssid->edmg_channel);
3493 } else {
3494 edmg_fail:
3495 params.freq.edmg.channels = 0;
3496 params.freq.edmg.bw_config = 0;
3497 wpa_printf(MSG_WARNING,
3498 "EDMG channel %d not supported by AP, fallback to DMG",
3499 ssid->edmg_channel);
3500 }
3501 }
3502
3503 if (params.freq.edmg.channels) {
3504 wpa_printf(MSG_DEBUG,
3505 "EDMG before: channels 0x%x, bw_config %d",
3506 params.freq.edmg.channels,
3507 params.freq.edmg.bw_config);
3508 params.freq.edmg = get_supported_edmg(wpa_s,
3509 &params.freq,
3510 params.freq.edmg);
3511 wpa_printf(MSG_DEBUG,
3512 "EDMG after: channels 0x%x, bw_config %d",
3513 params.freq.edmg.channels,
3514 params.freq.edmg.bw_config);
3515 }
3516 }
3517
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518 params.pairwise_suite = cipher_pairwise;
3519 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003520 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003521 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003522 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003523 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003524 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003525 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003526 for (i = 0; i < NUM_WEP_KEYS; i++) {
3527 if (ssid->wep_key_len[i])
3528 params.wep_key[i] = ssid->wep_key[i];
3529 params.wep_key_len[i] = ssid->wep_key_len[i];
3530 }
3531 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
3532
Hai Shalom74f70d42019-02-11 14:42:39 -08003533 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003534 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3535 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003536 params.passphrase = ssid->passphrase;
3537 if (ssid->psk_set)
3538 params.psk = ssid->psk;
3539 }
3540
Hai Shalom74f70d42019-02-11 14:42:39 -08003541 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3542 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3543 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3544 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3545 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003546 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003547
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003548 if (wpa_s->conf->key_mgmt_offload) {
3549 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3550 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003551 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3552 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003553 params.req_key_mgmt_offload =
3554 ssid->proactive_key_caching < 0 ?
3555 wpa_s->conf->okc : ssid->proactive_key_caching;
3556 else
3557 params.req_key_mgmt_offload = 1;
3558
3559 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3560 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3561 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3562 ssid->psk_set)
3563 params.psk = ssid->psk;
3564 }
3565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003566 params.drop_unencrypted = use_crypt;
3567
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003568 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003569 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003570 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3571 struct wpa_ie_data ie;
3572 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3573 ie.capabilities &
3574 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3575 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3576 "MFP: require MFP");
3577 params.mgmt_frame_protection =
3578 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003579#ifdef CONFIG_OWE
3580 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3581 !ssid->owe_only) {
3582 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3583#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003584 }
3585 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003586
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003587 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003588
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003589 if (wpa_s->p2pdev->set_sta_uapsd)
3590 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003591 else
3592 params.uapsd = -1;
3593
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003594#ifdef CONFIG_HT_OVERRIDES
3595 os_memset(&htcaps, 0, sizeof(htcaps));
3596 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3597 params.htcaps = (u8 *) &htcaps;
3598 params.htcaps_mask = (u8 *) &htcaps_mask;
3599 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3600#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003601#ifdef CONFIG_VHT_OVERRIDES
3602 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3603 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3604 params.vhtcaps = &vhtcaps;
3605 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003606 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003607#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003608
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003609#ifdef CONFIG_P2P
3610 /*
3611 * If multi-channel concurrency is not supported, check for any
3612 * frequency conflict. In case of any frequency conflict, remove the
3613 * least prioritized connection.
3614 */
3615 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003616 int freq, num;
3617 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003618 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003619 wpa_printf(MSG_DEBUG,
3620 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003621 freq, params.freq.freq);
3622 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003623 wpa_s, params.freq.freq, ssid) < 0) {
3624 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003625 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003626 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003627 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003628 }
3629 }
3630#endif /* CONFIG_P2P */
3631
Dmitry Shmidte4663042016-04-04 10:07:49 -07003632 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3633 wpa_s->current_ssid)
3634 params.prev_bssid = prev_bssid;
3635
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003636 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003637 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003638 if (ret < 0) {
3639 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3640 "failed");
3641 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3642 /*
3643 * The driver is known to mean what is saying, so we
3644 * can stop right here; the association will not
3645 * succeed.
3646 */
3647 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003648 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003649 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3650 return;
3651 }
3652 /* try to continue anyway; new association will be tried again
3653 * after timeout */
3654 assoc_failed = 1;
3655 }
3656
3657 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3658 /* Set the key after the association just in case association
3659 * cleared the previously configured key. */
3660 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3661 /* No need to timeout authentication since there is no key
3662 * management. */
3663 wpa_supplicant_cancel_auth_timeout(wpa_s);
3664 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3665#ifdef CONFIG_IBSS_RSN
3666 } else if (ssid->mode == WPAS_MODE_IBSS &&
3667 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3668 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3669 /*
3670 * RSN IBSS authentication is per-STA and we can disable the
3671 * per-BSSID authentication.
3672 */
3673 wpa_supplicant_cancel_auth_timeout(wpa_s);
3674#endif /* CONFIG_IBSS_RSN */
3675 } else {
3676 /* Timeout for IEEE 802.11 authentication and association */
3677 int timeout = 60;
3678
3679 if (assoc_failed) {
3680 /* give IBSS a bit more time */
3681 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3682 } else if (wpa_s->conf->ap_scan == 1) {
3683 /* give IBSS a bit more time */
3684 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3685 }
3686 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3687 }
3688
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003689 if (wep_keys_set &&
3690 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003691 /* Set static WEP keys again */
3692 wpa_set_wep_keys(wpa_s, ssid);
3693 }
3694
3695 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3696 /*
3697 * Do not allow EAP session resumption between different
3698 * network configurations.
3699 */
3700 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3701 }
3702 old_ssid = wpa_s->current_ssid;
3703 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003704
3705 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003706 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003707#ifdef CONFIG_HS20
3708 hs20_configure_frame_filters(wpa_s);
3709#endif /* CONFIG_HS20 */
3710 }
3711
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003712 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3713 wpa_supplicant_initiate_eapol(wpa_s);
3714 if (old_ssid != wpa_s->current_ssid)
3715 wpas_notify_network_changed(wpa_s);
3716}
3717
3718
3719static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3720 const u8 *addr)
3721{
3722 struct wpa_ssid *old_ssid;
3723
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003724 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003725 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003726 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003727 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003728 wpa_sm_set_config(wpa_s->wpa, NULL);
3729 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3730 if (old_ssid != wpa_s->current_ssid)
3731 wpas_notify_network_changed(wpa_s);
3732 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3733}
3734
3735
3736/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003737 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3738 * @wpa_s: Pointer to wpa_supplicant data
3739 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3740 *
3741 * This function is used to request %wpa_supplicant to deauthenticate from the
3742 * current AP.
3743 */
3744void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003745 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003746{
3747 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003748 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003749 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003750
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003751 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003752 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003753 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003754 reason_code, reason2str(reason_code),
3755 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003756
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003757 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3758 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3759 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003760 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003761 else if (!is_zero_ether_addr(wpa_s->bssid))
3762 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003763 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3764 /*
3765 * When using driver-based BSS selection, we may not know the
3766 * BSSID with which we are currently trying to associate. We
3767 * need to notify the driver of this disconnection even in such
3768 * a case, so use the all zeros address here.
3769 */
3770 addr = wpa_s->bssid;
3771 zero_addr = 1;
3772 }
3773
Hai Shalom74f70d42019-02-11 14:42:39 -08003774 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3775 wpa_s->enabled_4addr_mode = 0;
3776
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003777#ifdef CONFIG_TDLS
3778 wpa_tdls_teardown_peers(wpa_s->wpa);
3779#endif /* CONFIG_TDLS */
3780
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003781#ifdef CONFIG_MESH
3782 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003783 struct mesh_conf *mconf;
3784
3785 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003786 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3787 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003788 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3789 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003790 wpa_supplicant_leave_mesh(wpa_s);
3791 }
3792#endif /* CONFIG_MESH */
3793
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003794 if (addr) {
3795 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003796 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07003797 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003798 event.deauth_info.locally_generated = 1;
3799 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003800 if (zero_addr)
3801 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003802 }
3803
3804 wpa_supplicant_clear_connection(wpa_s, addr);
3805}
3806
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003807static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3808 struct wpa_ssid *ssid)
3809{
3810 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3811 return;
3812
3813 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003814 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003815 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3816 wpas_notify_network_enabled_changed(wpa_s, ssid);
3817
3818 /*
3819 * Try to reassociate since there is no current configuration and a new
3820 * network was made available.
3821 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003822 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003823 wpa_s->reassociate = 1;
3824}
3825
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003826
Roshan Pius950bec92016-07-19 09:49:24 -07003827/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003828 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003829 * @wpa_s: wpa_supplicant structure for a network interface
3830 * Returns: The new network configuration or %NULL if operation failed
3831 *
3832 * This function performs the following operations:
3833 * 1. Adds a new network.
3834 * 2. Send network addition notification.
3835 * 3. Marks the network disabled.
3836 * 4. Set network default parameters.
3837 */
3838struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3839{
3840 struct wpa_ssid *ssid;
3841
3842 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003843 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003844 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003845 wpas_notify_network_added(wpa_s, ssid);
3846 ssid->disabled = 1;
3847 wpa_config_set_network_defaults(ssid);
3848
3849 return ssid;
3850}
3851
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003852
Roshan Pius950bec92016-07-19 09:49:24 -07003853/**
3854 * wpa_supplicant_remove_network - Remove a configured network based on id
3855 * @wpa_s: wpa_supplicant structure for a network interface
3856 * @id: Unique network id to search for
3857 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3858 * could not be removed
3859 *
3860 * This function performs the following operations:
3861 * 1. Removes the network.
3862 * 2. Send network removal notification.
3863 * 3. Update internal state machines.
3864 * 4. Stop any running sched scans.
3865 */
3866int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
3867{
3868 struct wpa_ssid *ssid;
3869 int was_disabled;
3870
3871 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003872 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003873 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003874 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07003875
3876 if (wpa_s->last_ssid == ssid)
3877 wpa_s->last_ssid = NULL;
3878
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003879 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07003880#ifdef CONFIG_SME
3881 wpa_s->sme.prev_bssid_set = 0;
3882#endif /* CONFIG_SME */
3883 /*
3884 * Invalidate the EAP session cache if the current or
3885 * previously used network is removed.
3886 */
3887 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3888 }
3889
3890 if (ssid == wpa_s->current_ssid) {
3891 wpa_sm_set_config(wpa_s->wpa, NULL);
3892 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3893
3894 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3895 wpa_s->own_disconnect_req = 1;
3896 wpa_supplicant_deauthenticate(wpa_s,
3897 WLAN_REASON_DEAUTH_LEAVING);
3898 }
3899
3900 was_disabled = ssid->disabled;
3901
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003902 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07003903 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07003904
3905 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003906 wpa_printf(MSG_DEBUG,
3907 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07003908 wpa_supplicant_cancel_sched_scan(wpa_s);
3909 wpa_supplicant_req_scan(wpa_s, 0, 0);
3910 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003911
Roshan Pius950bec92016-07-19 09:49:24 -07003912 return 0;
3913}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003914
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003915
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003916/**
3917 * wpa_supplicant_enable_network - Mark a configured network as enabled
3918 * @wpa_s: wpa_supplicant structure for a network interface
3919 * @ssid: wpa_ssid structure for a configured network or %NULL
3920 *
3921 * Enables the specified network or all networks if no network specified.
3922 */
3923void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
3924 struct wpa_ssid *ssid)
3925{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003926 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003927 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3928 wpa_supplicant_enable_one_network(wpa_s, ssid);
3929 } else
3930 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003931
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003932 if (wpa_s->reassociate && !wpa_s->disconnected &&
3933 (!wpa_s->current_ssid ||
3934 wpa_s->wpa_state == WPA_DISCONNECTED ||
3935 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003936 if (wpa_s->sched_scanning) {
3937 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
3938 "new network to scan filters");
3939 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003940 }
3941
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003942 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3943 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003944 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003945 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946 }
3947}
3948
3949
3950/**
3951 * wpa_supplicant_disable_network - Mark a configured network as disabled
3952 * @wpa_s: wpa_supplicant structure for a network interface
3953 * @ssid: wpa_ssid structure for a configured network or %NULL
3954 *
3955 * Disables the specified network or all networks if no network specified.
3956 */
3957void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
3958 struct wpa_ssid *ssid)
3959{
3960 struct wpa_ssid *other_ssid;
3961 int was_disabled;
3962
3963 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003964 if (wpa_s->sched_scanning)
3965 wpa_supplicant_cancel_sched_scan(wpa_s);
3966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003967 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3968 other_ssid = other_ssid->next) {
3969 was_disabled = other_ssid->disabled;
3970 if (was_disabled == 2)
3971 continue; /* do not change persistent P2P group
3972 * data */
3973
3974 other_ssid->disabled = 1;
3975
3976 if (was_disabled != other_ssid->disabled)
3977 wpas_notify_network_enabled_changed(
3978 wpa_s, other_ssid);
3979 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003980 if (wpa_s->current_ssid) {
3981 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3982 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003983 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003984 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003985 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003986 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003987 if (ssid == wpa_s->current_ssid) {
3988 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3989 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003990 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003991 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003992 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003993
3994 was_disabled = ssid->disabled;
3995
3996 ssid->disabled = 1;
3997
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003998 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003999 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004000 if (wpa_s->sched_scanning) {
4001 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4002 "to remove network from filters");
4003 wpa_supplicant_cancel_sched_scan(wpa_s);
4004 wpa_supplicant_req_scan(wpa_s, 0, 0);
4005 }
4006 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004007 }
4008}
4009
4010
4011/**
4012 * wpa_supplicant_select_network - Attempt association with a network
4013 * @wpa_s: wpa_supplicant structure for a network interface
4014 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4015 */
4016void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4017 struct wpa_ssid *ssid)
4018{
4019
4020 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004021 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004022
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004023 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004024 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4025 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004026 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004027 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004028 disconnected = 1;
4029 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004030
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004031 if (ssid)
4032 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4033
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004034 /*
4035 * Mark all other networks disabled or mark all networks enabled if no
4036 * network specified.
4037 */
4038 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4039 other_ssid = other_ssid->next) {
4040 int was_disabled = other_ssid->disabled;
4041 if (was_disabled == 2)
4042 continue; /* do not change persistent P2P group data */
4043
4044 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004045 if (was_disabled && !other_ssid->disabled)
4046 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004047
4048 if (was_disabled != other_ssid->disabled)
4049 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4050 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004051
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004052 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4053 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004054 /* We are already associated with the selected network */
4055 wpa_printf(MSG_DEBUG, "Already associated with the "
4056 "selected network - do nothing");
4057 return;
4058 }
4059
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004060 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004061 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004062 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004063 wpa_s->connect_without_scan =
4064 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004065
4066 /*
4067 * Don't optimize next scan freqs since a new ESS has been
4068 * selected.
4069 */
4070 os_free(wpa_s->next_scan_freqs);
4071 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004072 } else {
4073 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004074 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004075
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004076 wpa_s->disconnected = 0;
4077 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004078 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004079 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004080 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004081 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004082 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4083 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004084
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004085 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004086 wpa_supplicant_fast_associate(wpa_s) != 1) {
4087 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004088 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004089 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004090 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004091
4092 if (ssid)
4093 wpas_notify_network_selected(wpa_s, ssid);
4094}
4095
4096
4097/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004098 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4099 * @wpa_s: wpa_supplicant structure for a network interface
4100 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4101 * @pkcs11_module_path: PKCS #11 module path or NULL
4102 * Returns: 0 on success; -1 on failure
4103 *
4104 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4105 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4106 * module path fails the paths will be reset to the default value (NULL).
4107 */
4108int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4109 const char *pkcs11_engine_path,
4110 const char *pkcs11_module_path)
4111{
4112 char *pkcs11_engine_path_copy = NULL;
4113 char *pkcs11_module_path_copy = NULL;
4114
4115 if (pkcs11_engine_path != NULL) {
4116 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4117 if (pkcs11_engine_path_copy == NULL)
4118 return -1;
4119 }
4120 if (pkcs11_module_path != NULL) {
4121 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004122 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004123 os_free(pkcs11_engine_path_copy);
4124 return -1;
4125 }
4126 }
4127
4128 os_free(wpa_s->conf->pkcs11_engine_path);
4129 os_free(wpa_s->conf->pkcs11_module_path);
4130 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4131 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4132
4133 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4134 eapol_sm_deinit(wpa_s->eapol);
4135 wpa_s->eapol = NULL;
4136 if (wpa_supplicant_init_eapol(wpa_s)) {
4137 /* Error -> Reset paths to the default value (NULL) once. */
4138 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4139 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4140 NULL);
4141
4142 return -1;
4143 }
4144 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4145
4146 return 0;
4147}
4148
4149
4150/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004151 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4152 * @wpa_s: wpa_supplicant structure for a network interface
4153 * @ap_scan: AP scan mode
4154 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4155 *
4156 */
4157int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4158{
4159
4160 int old_ap_scan;
4161
4162 if (ap_scan < 0 || ap_scan > 2)
4163 return -1;
4164
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004165 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4166 wpa_printf(MSG_INFO,
4167 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4168 }
4169
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004170#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004171 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4172 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4173 wpa_s->wpa_state < WPA_COMPLETED) {
4174 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4175 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004176 return 0;
4177 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004178#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004179
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004180 old_ap_scan = wpa_s->conf->ap_scan;
4181 wpa_s->conf->ap_scan = ap_scan;
4182
4183 if (old_ap_scan != wpa_s->conf->ap_scan)
4184 wpas_notify_ap_scan_changed(wpa_s);
4185
4186 return 0;
4187}
4188
4189
4190/**
4191 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4192 * @wpa_s: wpa_supplicant structure for a network interface
4193 * @expire_age: Expiration age in seconds
4194 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4195 *
4196 */
4197int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4198 unsigned int bss_expire_age)
4199{
4200 if (bss_expire_age < 10) {
4201 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4202 bss_expire_age);
4203 return -1;
4204 }
4205 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4206 bss_expire_age);
4207 wpa_s->conf->bss_expiration_age = bss_expire_age;
4208
4209 return 0;
4210}
4211
4212
4213/**
4214 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4215 * @wpa_s: wpa_supplicant structure for a network interface
4216 * @expire_count: number of scans after which an unseen BSS is reclaimed
4217 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4218 *
4219 */
4220int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4221 unsigned int bss_expire_count)
4222{
4223 if (bss_expire_count < 1) {
4224 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4225 bss_expire_count);
4226 return -1;
4227 }
4228 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4229 bss_expire_count);
4230 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4231
4232 return 0;
4233}
4234
4235
4236/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004237 * wpa_supplicant_set_scan_interval - Set scan interval
4238 * @wpa_s: wpa_supplicant structure for a network interface
4239 * @scan_interval: scan interval in seconds
4240 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4241 *
4242 */
4243int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4244 int scan_interval)
4245{
4246 if (scan_interval < 0) {
4247 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4248 scan_interval);
4249 return -1;
4250 }
4251 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4252 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004253 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004254
4255 return 0;
4256}
4257
4258
4259/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004260 * wpa_supplicant_set_debug_params - Set global debug params
4261 * @global: wpa_global structure
4262 * @debug_level: debug level
4263 * @debug_timestamp: determines if show timestamp in debug data
4264 * @debug_show_keys: determines if show keys in debug data
4265 * Returns: 0 if succeed or -1 if debug_level has wrong value
4266 */
4267int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4268 int debug_timestamp, int debug_show_keys)
4269{
4270
4271 int old_level, old_timestamp, old_show_keys;
4272
4273 /* check for allowed debuglevels */
4274 if (debug_level != MSG_EXCESSIVE &&
4275 debug_level != MSG_MSGDUMP &&
4276 debug_level != MSG_DEBUG &&
4277 debug_level != MSG_INFO &&
4278 debug_level != MSG_WARNING &&
4279 debug_level != MSG_ERROR)
4280 return -1;
4281
4282 old_level = wpa_debug_level;
4283 old_timestamp = wpa_debug_timestamp;
4284 old_show_keys = wpa_debug_show_keys;
4285
4286 wpa_debug_level = debug_level;
4287 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4288 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4289
4290 if (wpa_debug_level != old_level)
4291 wpas_notify_debug_level_changed(global);
4292 if (wpa_debug_timestamp != old_timestamp)
4293 wpas_notify_debug_timestamp_changed(global);
4294 if (wpa_debug_show_keys != old_show_keys)
4295 wpas_notify_debug_show_keys_changed(global);
4296
4297 return 0;
4298}
4299
4300
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004301#ifdef CONFIG_OWE
4302static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4303 const u8 *entry_ssid, size_t entry_ssid_len)
4304{
4305 const u8 *owe, *pos, *end;
4306 u8 ssid_len;
4307 struct wpa_bss *bss;
4308
4309 /* Check network profile SSID aganst the SSID in the
4310 * OWE Transition Mode element. */
4311
4312 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4313 if (!bss)
4314 return 0;
4315
4316 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4317 if (!owe)
4318 return 0;
4319
4320 pos = owe + 6;
4321 end = owe + 2 + owe[1];
4322
4323 if (end - pos < ETH_ALEN + 1)
4324 return 0;
4325 pos += ETH_ALEN;
4326 ssid_len = *pos++;
4327 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4328 return 0;
4329
4330 return entry_ssid_len == ssid_len &&
4331 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4332}
4333#endif /* CONFIG_OWE */
4334
4335
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004336/**
4337 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4338 * @wpa_s: Pointer to wpa_supplicant data
4339 * Returns: A pointer to the current network structure or %NULL on failure
4340 */
4341struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4342{
4343 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004344 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004345 int res;
4346 size_t ssid_len;
4347 u8 bssid[ETH_ALEN];
4348 int wired;
4349
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004350 res = wpa_drv_get_ssid(wpa_s, ssid);
4351 if (res < 0) {
4352 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4353 "driver");
4354 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004355 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004356 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004357
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004358 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004359 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4360 "driver");
4361 return NULL;
4362 }
4363
4364 wired = wpa_s->conf->ap_scan == 0 &&
4365 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4366
4367 entry = wpa_s->conf->ssid;
4368 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004369 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004370 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004371 (!entry->ssid ||
4372 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4373 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004374 (!entry->bssid_set ||
4375 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4376 return entry;
4377#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004378 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004379 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4380 (entry->ssid == NULL || entry->ssid_len == 0) &&
4381 (!entry->bssid_set ||
4382 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4383 return entry;
4384#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004385
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004386#ifdef CONFIG_OWE
4387 if (!wpas_network_disabled(wpa_s, entry) &&
4388 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4389 entry->ssid_len) &&
4390 (!entry->bssid_set ||
4391 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4392 return entry;
4393#endif /* CONFIG_OWE */
4394
Dmitry Shmidt04949592012-07-19 12:16:46 -07004395 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004396 entry->ssid_len == 0 &&
4397 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4398 return entry;
4399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004400 entry = entry->next;
4401 }
4402
4403 return NULL;
4404}
4405
4406
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004407static int select_driver(struct wpa_supplicant *wpa_s, int i)
4408{
4409 struct wpa_global *global = wpa_s->global;
4410
4411 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004412 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004413 if (global->drv_priv[i] == NULL) {
4414 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4415 "'%s'", wpa_drivers[i]->name);
4416 return -1;
4417 }
4418 }
4419
4420 wpa_s->driver = wpa_drivers[i];
4421 wpa_s->global_drv_priv = global->drv_priv[i];
4422
4423 return 0;
4424}
4425
4426
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004427static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4428 const char *name)
4429{
4430 int i;
4431 size_t len;
4432 const char *pos, *driver = name;
4433
4434 if (wpa_s == NULL)
4435 return -1;
4436
4437 if (wpa_drivers[0] == NULL) {
4438 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4439 "wpa_supplicant");
4440 return -1;
4441 }
4442
4443 if (name == NULL) {
4444 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004445 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004446 }
4447
4448 do {
4449 pos = os_strchr(driver, ',');
4450 if (pos)
4451 len = pos - driver;
4452 else
4453 len = os_strlen(driver);
4454
4455 for (i = 0; wpa_drivers[i]; i++) {
4456 if (os_strlen(wpa_drivers[i]->name) == len &&
4457 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004458 0) {
4459 /* First driver that succeeds wins */
4460 if (select_driver(wpa_s, i) == 0)
4461 return 0;
4462 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004463 }
4464
4465 driver = pos + 1;
4466 } while (pos);
4467
4468 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4469 return -1;
4470}
4471
4472
4473/**
4474 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4475 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4476 * with struct wpa_driver_ops::init()
4477 * @src_addr: Source address of the EAPOL frame
4478 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4479 * @len: Length of the EAPOL data
4480 *
4481 * This function is called for each received EAPOL frame. Most driver
4482 * interfaces rely on more generic OS mechanism for receiving frames through
4483 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4484 * take care of received EAPOL frames and deliver them to the core supplicant
4485 * code by calling this function.
4486 */
4487void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4488 const u8 *buf, size_t len)
4489{
4490 struct wpa_supplicant *wpa_s = ctx;
4491
4492 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4493 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4494
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004495#ifdef CONFIG_TESTING_OPTIONS
4496 if (wpa_s->ignore_auth_resp) {
4497 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4498 return;
4499 }
4500#endif /* CONFIG_TESTING_OPTIONS */
4501
Jouni Malinena05074c2012-12-21 21:35:35 +02004502 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4503 (wpa_s->last_eapol_matches_bssid &&
4504#ifdef CONFIG_AP
4505 !wpa_s->ap_iface &&
4506#endif /* CONFIG_AP */
4507 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004508 /*
4509 * There is possible race condition between receiving the
4510 * association event and the EAPOL frame since they are coming
4511 * through different paths from the driver. In order to avoid
4512 * issues in trying to process the EAPOL frame before receiving
4513 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004514 * the association event is received. This may also be needed in
4515 * driver-based roaming case, so also use src_addr != BSSID as a
4516 * trigger if we have previously confirmed that the
4517 * Authenticator uses BSSID as the src_addr (which is not the
4518 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004519 */
4520 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004521 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4522 wpa_supplicant_state_txt(wpa_s->wpa_state),
4523 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004524 wpabuf_free(wpa_s->pending_eapol_rx);
4525 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4526 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004527 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004528 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4529 ETH_ALEN);
4530 }
4531 return;
4532 }
4533
Jouni Malinena05074c2012-12-21 21:35:35 +02004534 wpa_s->last_eapol_matches_bssid =
4535 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4536
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004537#ifdef CONFIG_AP
4538 if (wpa_s->ap_iface) {
4539 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4540 return;
4541 }
4542#endif /* CONFIG_AP */
4543
4544 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4545 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4546 "no key management is configured");
4547 return;
4548 }
4549
4550 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004551 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004552 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4553 wpa_s->wpa_state != WPA_COMPLETED) &&
4554 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004555 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004556 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004557 int timeout = 10;
4558
4559 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4560 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4561 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4562 /* Use longer timeout for IEEE 802.1X/EAP */
4563 timeout = 70;
4564 }
4565
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004566#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004567 if (wpa_s->current_ssid && wpa_s->current_bss &&
4568 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4569 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4570 /*
4571 * Use shorter timeout if going through WPS AP iteration
4572 * for PIN config method with an AP that does not
4573 * advertise Selected Registrar.
4574 */
4575 struct wpabuf *wps_ie;
4576
4577 wps_ie = wpa_bss_get_vendor_ie_multi(
4578 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4579 if (wps_ie &&
4580 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4581 timeout = 10;
4582 wpabuf_free(wps_ie);
4583 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004584#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004585
4586 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004587 }
4588 wpa_s->eapol_received++;
4589
4590 if (wpa_s->countermeasures) {
4591 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4592 "EAPOL packet");
4593 return;
4594 }
4595
4596#ifdef CONFIG_IBSS_RSN
4597 if (wpa_s->current_ssid &&
4598 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4599 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4600 return;
4601 }
4602#endif /* CONFIG_IBSS_RSN */
4603
4604 /* Source address of the incoming EAPOL frame could be compared to the
4605 * current BSSID. However, it is possible that a centralized
4606 * Authenticator could be using another MAC address than the BSSID of
4607 * an AP, so just allow any address to be used for now. The replies are
4608 * still sent to the current BSSID (if available), though. */
4609
4610 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4611 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004612 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4613 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004614 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4615 return;
4616 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004617 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004618 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4619 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4620 /*
4621 * Set portValid = TRUE here since we are going to skip 4-way
4622 * handshake processing which would normally set portValid. We
4623 * need this to allow the EAPOL state machines to be completed
4624 * without going through EAPOL-Key handshake.
4625 */
4626 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
4627 }
4628}
4629
4630
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004631int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004632{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004633 if ((!wpa_s->p2p_mgmt ||
4634 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4635 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004636 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004637 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4638 wpa_drv_get_mac_addr(wpa_s),
4639 ETH_P_EAPOL,
4640 wpa_supplicant_rx_eapol, wpa_s, 0);
4641 if (wpa_s->l2 == NULL)
4642 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004643
4644 if (l2_packet_set_packet_filter(wpa_s->l2,
4645 L2_PACKET_FILTER_PKTTYPE))
4646 wpa_dbg(wpa_s, MSG_DEBUG,
4647 "Failed to attach pkt_type filter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004648 } else {
4649 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4650 if (addr)
4651 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4652 }
4653
4654 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4655 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
4656 return -1;
4657 }
4658
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004659 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004660 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004661
Hai Shalomc3565922019-10-28 11:58:20 -07004662#ifdef CONFIG_FST
4663 if (wpa_s->fst)
4664 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4665#endif /* CONFIG_FST */
4666
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004667 return 0;
4668}
4669
4670
Dmitry Shmidt04949592012-07-19 12:16:46 -07004671static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4672 const u8 *buf, size_t len)
4673{
4674 struct wpa_supplicant *wpa_s = ctx;
4675 const struct l2_ethhdr *eth;
4676
4677 if (len < sizeof(*eth))
4678 return;
4679 eth = (const struct l2_ethhdr *) buf;
4680
4681 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4682 !(eth->h_dest[0] & 0x01)) {
4683 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4684 " (bridge - not for this interface - ignore)",
4685 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4686 return;
4687 }
4688
4689 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4690 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4691 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4692 len - sizeof(*eth));
4693}
4694
4695
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004696/**
4697 * wpa_supplicant_driver_init - Initialize driver interface parameters
4698 * @wpa_s: Pointer to wpa_supplicant data
4699 * Returns: 0 on success, -1 on failure
4700 *
4701 * This function is called to initialize driver interface parameters.
4702 * wpa_drv_init() must have been called before this function to initialize the
4703 * driver interface.
4704 */
4705int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4706{
4707 static int interface_count = 0;
4708
4709 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4710 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004711
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004712 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4713 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004714 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004715 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4716
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004717 if (wpa_s->bridge_ifname[0]) {
4718 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4719 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004720 wpa_s->l2_br = l2_packet_init_bridge(
4721 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4722 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004723 if (wpa_s->l2_br == NULL) {
4724 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4725 "connection for the bridge interface '%s'",
4726 wpa_s->bridge_ifname);
4727 return -1;
4728 }
4729 }
4730
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004731 if (wpa_s->conf->ap_scan == 2 &&
4732 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4733 wpa_printf(MSG_INFO,
4734 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4735 }
4736
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004737 wpa_clear_keys(wpa_s, NULL);
4738
4739 /* Make sure that TKIP countermeasures are not left enabled (could
4740 * happen if wpa_supplicant is killed during countermeasures. */
4741 wpa_drv_set_countermeasures(wpa_s, 0);
4742
4743 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4744 wpa_drv_flush_pmkid(wpa_s);
4745
4746 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004747 wpa_s->prev_scan_wildcard = 0;
4748
Dmitry Shmidt04949592012-07-19 12:16:46 -07004749 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004750 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4751 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4752 interface_count = 0;
4753 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004754#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004755 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004756 wpa_supplicant_delayed_sched_scan(wpa_s,
4757 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004758 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004759 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004760 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004761#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004762 interface_count++;
4763 } else
4764 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4765
4766 return 0;
4767}
4768
4769
4770static int wpa_supplicant_daemon(const char *pid_file)
4771{
4772 wpa_printf(MSG_DEBUG, "Daemonize..");
4773 return os_daemonize(pid_file);
4774}
4775
4776
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004777static struct wpa_supplicant *
4778wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004779{
4780 struct wpa_supplicant *wpa_s;
4781
4782 wpa_s = os_zalloc(sizeof(*wpa_s));
4783 if (wpa_s == NULL)
4784 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004785 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004786 wpa_s->scan_interval = 5;
4787 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004788 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004789 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004790 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004791
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004792 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004793 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004794
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004795 return wpa_s;
4796}
4797
4798
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004799#ifdef CONFIG_HT_OVERRIDES
4800
4801static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4802 struct ieee80211_ht_capabilities *htcaps,
4803 struct ieee80211_ht_capabilities *htcaps_mask,
4804 const char *ht_mcs)
4805{
4806 /* parse ht_mcs into hex array */
4807 int i;
4808 const char *tmp = ht_mcs;
4809 char *end = NULL;
4810
4811 /* If ht_mcs is null, do not set anything */
4812 if (!ht_mcs)
4813 return 0;
4814
4815 /* This is what we are setting in the kernel */
4816 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4817
4818 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4819
4820 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004821 long v;
4822
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004823 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004824 v = strtol(tmp, &end, 16);
4825
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004826 if (errno == 0) {
4827 wpa_msg(wpa_s, MSG_DEBUG,
4828 "htcap value[%i]: %ld end: %p tmp: %p",
4829 i, v, end, tmp);
4830 if (end == tmp)
4831 break;
4832
4833 htcaps->supported_mcs_set[i] = v;
4834 tmp = end;
4835 } else {
4836 wpa_msg(wpa_s, MSG_ERROR,
4837 "Failed to parse ht-mcs: %s, error: %s\n",
4838 ht_mcs, strerror(errno));
4839 return -1;
4840 }
4841 }
4842
4843 /*
4844 * If we were able to parse any values, then set mask for the MCS set.
4845 */
4846 if (i) {
4847 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4848 IEEE80211_HT_MCS_MASK_LEN - 1);
4849 /* skip the 3 reserved bits */
4850 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4851 0x1f;
4852 }
4853
4854 return 0;
4855}
4856
4857
4858static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4859 struct ieee80211_ht_capabilities *htcaps,
4860 struct ieee80211_ht_capabilities *htcaps_mask,
4861 int disabled)
4862{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004863 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004864
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004865 if (disabled == -1)
4866 return 0;
4867
Hai Shalom74f70d42019-02-11 14:42:39 -08004868 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
4869
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004870 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
4871 htcaps_mask->ht_capabilities_info |= msk;
4872 if (disabled)
4873 htcaps->ht_capabilities_info &= msk;
4874 else
4875 htcaps->ht_capabilities_info |= msk;
4876
4877 return 0;
4878}
4879
4880
4881static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
4882 struct ieee80211_ht_capabilities *htcaps,
4883 struct ieee80211_ht_capabilities *htcaps_mask,
4884 int factor)
4885{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004886 if (factor == -1)
4887 return 0;
4888
Hai Shalom74f70d42019-02-11 14:42:39 -08004889 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
4890
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004891 if (factor < 0 || factor > 3) {
4892 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
4893 "Must be 0-3 or -1", factor);
4894 return -EINVAL;
4895 }
4896
4897 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
4898 htcaps->a_mpdu_params &= ~0x3;
4899 htcaps->a_mpdu_params |= factor & 0x3;
4900
4901 return 0;
4902}
4903
4904
4905static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
4906 struct ieee80211_ht_capabilities *htcaps,
4907 struct ieee80211_ht_capabilities *htcaps_mask,
4908 int density)
4909{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004910 if (density == -1)
4911 return 0;
4912
Hai Shalom74f70d42019-02-11 14:42:39 -08004913 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
4914
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004915 if (density < 0 || density > 7) {
4916 wpa_msg(wpa_s, MSG_ERROR,
4917 "ampdu_density: %d out of range. Must be 0-7 or -1.",
4918 density);
4919 return -EINVAL;
4920 }
4921
4922 htcaps_mask->a_mpdu_params |= 0x1C;
4923 htcaps->a_mpdu_params &= ~(0x1C);
4924 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
4925
4926 return 0;
4927}
4928
4929
4930static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
4931 struct ieee80211_ht_capabilities *htcaps,
4932 struct ieee80211_ht_capabilities *htcaps_mask,
4933 int disabled)
4934{
Hai Shalom74f70d42019-02-11 14:42:39 -08004935 if (disabled)
4936 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004937
Paul Stewart092955c2017-02-06 09:13:09 -08004938 set_disable_ht40(htcaps, disabled);
4939 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004940
4941 return 0;
4942}
4943
4944
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004945static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
4946 struct ieee80211_ht_capabilities *htcaps,
4947 struct ieee80211_ht_capabilities *htcaps_mask,
4948 int disabled)
4949{
4950 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004951 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
4952 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004953
Hai Shalom74f70d42019-02-11 14:42:39 -08004954 if (disabled)
4955 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004956
4957 if (disabled)
4958 htcaps->ht_capabilities_info &= ~msk;
4959 else
4960 htcaps->ht_capabilities_info |= msk;
4961
4962 htcaps_mask->ht_capabilities_info |= msk;
4963
4964 return 0;
4965}
4966
4967
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004968static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
4969 struct ieee80211_ht_capabilities *htcaps,
4970 struct ieee80211_ht_capabilities *htcaps_mask,
4971 int disabled)
4972{
4973 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004974 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004975
Hai Shalom74f70d42019-02-11 14:42:39 -08004976 if (disabled)
4977 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004978
4979 if (disabled)
4980 htcaps->ht_capabilities_info &= ~msk;
4981 else
4982 htcaps->ht_capabilities_info |= msk;
4983
4984 htcaps_mask->ht_capabilities_info |= msk;
4985
4986 return 0;
4987}
4988
4989
Hai Shalom74f70d42019-02-11 14:42:39 -08004990static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
4991 struct ieee80211_ht_capabilities *htcaps,
4992 struct ieee80211_ht_capabilities *htcaps_mask,
4993 int tx_stbc)
4994{
4995 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
4996
4997 if (tx_stbc == -1)
4998 return 0;
4999
5000 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5001
5002 if (tx_stbc < 0 || tx_stbc > 1) {
5003 wpa_msg(wpa_s, MSG_ERROR,
5004 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5005 return -EINVAL;
5006 }
5007
5008 htcaps_mask->ht_capabilities_info |= msk;
5009 htcaps->ht_capabilities_info &= ~msk;
5010 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5011
5012 return 0;
5013}
5014
5015
5016static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5017 struct ieee80211_ht_capabilities *htcaps,
5018 struct ieee80211_ht_capabilities *htcaps_mask,
5019 int rx_stbc)
5020{
5021 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5022
5023 if (rx_stbc == -1)
5024 return 0;
5025
5026 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5027
5028 if (rx_stbc < 0 || rx_stbc > 3) {
5029 wpa_msg(wpa_s, MSG_ERROR,
5030 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5031 return -EINVAL;
5032 }
5033
5034 htcaps_mask->ht_capabilities_info |= msk;
5035 htcaps->ht_capabilities_info &= ~msk;
5036 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5037
5038 return 0;
5039}
5040
5041
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005042void wpa_supplicant_apply_ht_overrides(
5043 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5044 struct wpa_driver_associate_params *params)
5045{
5046 struct ieee80211_ht_capabilities *htcaps;
5047 struct ieee80211_ht_capabilities *htcaps_mask;
5048
5049 if (!ssid)
5050 return;
5051
5052 params->disable_ht = ssid->disable_ht;
5053 if (!params->htcaps || !params->htcaps_mask)
5054 return;
5055
5056 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5057 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5058 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5059 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5060 ssid->disable_max_amsdu);
5061 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5062 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5063 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005064 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005065 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005066 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5067 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005068
5069 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005070 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005071 htcaps->ht_capabilities_info |= bit;
5072 htcaps_mask->ht_capabilities_info |= bit;
5073 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005074}
5075
5076#endif /* CONFIG_HT_OVERRIDES */
5077
5078
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005079#ifdef CONFIG_VHT_OVERRIDES
5080void wpa_supplicant_apply_vht_overrides(
5081 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5082 struct wpa_driver_associate_params *params)
5083{
5084 struct ieee80211_vht_capabilities *vhtcaps;
5085 struct ieee80211_vht_capabilities *vhtcaps_mask;
5086
5087 if (!ssid)
5088 return;
5089
5090 params->disable_vht = ssid->disable_vht;
5091
5092 vhtcaps = (void *) params->vhtcaps;
5093 vhtcaps_mask = (void *) params->vhtcaps_mask;
5094
5095 if (!vhtcaps || !vhtcaps_mask)
5096 return;
5097
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005098 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5099 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005100
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005101#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005102 if (ssid->disable_sgi) {
5103 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5104 VHT_CAP_SHORT_GI_160);
5105 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5106 VHT_CAP_SHORT_GI_160);
5107 wpa_msg(wpa_s, MSG_DEBUG,
5108 "disable-sgi override specified, vht-caps: 0x%x",
5109 vhtcaps->vht_capabilities_info);
5110 }
5111
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005112 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005113 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5114 int max_ampdu;
5115
5116 max_ampdu = (ssid->vht_capa &
5117 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5118 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005119
5120 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5121 wpa_set_ampdu_factor(wpa_s,
5122 (void *) params->htcaps,
5123 (void *) params->htcaps_mask,
5124 max_ampdu);
5125 }
5126#endif /* CONFIG_HT_OVERRIDES */
5127
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005128#define OVERRIDE_MCS(i) \
5129 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5130 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005131 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005132 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005133 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5134 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005135 } \
5136 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5137 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005138 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005139 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005140 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5141 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005142 }
5143
5144 OVERRIDE_MCS(1);
5145 OVERRIDE_MCS(2);
5146 OVERRIDE_MCS(3);
5147 OVERRIDE_MCS(4);
5148 OVERRIDE_MCS(5);
5149 OVERRIDE_MCS(6);
5150 OVERRIDE_MCS(7);
5151 OVERRIDE_MCS(8);
5152}
5153#endif /* CONFIG_VHT_OVERRIDES */
5154
5155
Dmitry Shmidt04949592012-07-19 12:16:46 -07005156static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5157{
5158#ifdef PCSC_FUNCS
5159 size_t len;
5160
5161 if (!wpa_s->conf->pcsc_reader)
5162 return 0;
5163
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005164 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005165 if (!wpa_s->scard)
5166 return 1;
5167
5168 if (wpa_s->conf->pcsc_pin &&
5169 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5170 scard_deinit(wpa_s->scard);
5171 wpa_s->scard = NULL;
5172 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5173 return -1;
5174 }
5175
5176 len = sizeof(wpa_s->imsi) - 1;
5177 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5178 scard_deinit(wpa_s->scard);
5179 wpa_s->scard = NULL;
5180 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5181 return -1;
5182 }
5183 wpa_s->imsi[len] = '\0';
5184
5185 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5186
5187 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5188 wpa_s->imsi, wpa_s->mnc_len);
5189
5190 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5191 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5192#endif /* PCSC_FUNCS */
5193
5194 return 0;
5195}
5196
5197
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005198int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5199{
5200 char *val, *pos;
5201
5202 ext_password_deinit(wpa_s->ext_pw);
5203 wpa_s->ext_pw = NULL;
5204 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5205
5206 if (!wpa_s->conf->ext_password_backend)
5207 return 0;
5208
5209 val = os_strdup(wpa_s->conf->ext_password_backend);
5210 if (val == NULL)
5211 return -1;
5212 pos = os_strchr(val, ':');
5213 if (pos)
5214 *pos++ = '\0';
5215
5216 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5217
5218 wpa_s->ext_pw = ext_password_init(val, pos);
5219 os_free(val);
5220 if (wpa_s->ext_pw == NULL) {
5221 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5222 return -1;
5223 }
5224 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5225
5226 return 0;
5227}
5228
5229
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005230#ifdef CONFIG_FST
5231
5232static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5233{
5234 struct wpa_supplicant *wpa_s = ctx;
5235
5236 return (is_zero_ether_addr(wpa_s->bssid) ||
5237 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5238}
5239
5240
5241static void wpas_fst_get_channel_info_cb(void *ctx,
5242 enum hostapd_hw_mode *hw_mode,
5243 u8 *channel)
5244{
5245 struct wpa_supplicant *wpa_s = ctx;
5246
5247 if (wpa_s->current_bss) {
5248 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5249 channel);
5250 } else if (wpa_s->hw.num_modes) {
5251 *hw_mode = wpa_s->hw.modes[0].mode;
5252 } else {
5253 WPA_ASSERT(0);
5254 *hw_mode = 0;
5255 }
5256}
5257
5258
5259static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5260{
5261 struct wpa_supplicant *wpa_s = ctx;
5262
5263 *modes = wpa_s->hw.modes;
5264 return wpa_s->hw.num_modes;
5265}
5266
5267
5268static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5269{
5270 struct wpa_supplicant *wpa_s = ctx;
5271
5272 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5273 wpa_s->fst_ies = fst_ies;
5274}
5275
5276
5277static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5278{
5279 struct wpa_supplicant *wpa_s = ctx;
5280
Paul Stewart092955c2017-02-06 09:13:09 -08005281 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5282 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5283 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5284 return -1;
5285 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005286 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005287 wpa_s->own_addr, wpa_s->bssid,
5288 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005289 0);
5290}
5291
5292
5293static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5294{
5295 struct wpa_supplicant *wpa_s = ctx;
5296
5297 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5298 return wpa_s->received_mb_ies;
5299}
5300
5301
5302static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5303 const u8 *buf, size_t size)
5304{
5305 struct wpa_supplicant *wpa_s = ctx;
5306 struct mb_ies_info info;
5307
5308 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5309
5310 if (!mb_ies_info_by_ies(&info, buf, size)) {
5311 wpabuf_free(wpa_s->received_mb_ies);
5312 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5313 }
5314}
5315
5316
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005317static const u8 * wpas_fst_get_peer_first(void *ctx,
5318 struct fst_get_peer_ctx **get_ctx,
5319 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005320{
5321 struct wpa_supplicant *wpa_s = ctx;
5322
5323 *get_ctx = NULL;
5324 if (!is_zero_ether_addr(wpa_s->bssid))
5325 return (wpa_s->received_mb_ies || !mb_only) ?
5326 wpa_s->bssid : NULL;
5327 return NULL;
5328}
5329
5330
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005331static const u8 * wpas_fst_get_peer_next(void *ctx,
5332 struct fst_get_peer_ctx **get_ctx,
5333 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005334{
5335 return NULL;
5336}
5337
5338void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5339 struct fst_wpa_obj *iface_obj)
5340{
5341 iface_obj->ctx = wpa_s;
5342 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5343 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5344 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5345 iface_obj->set_ies = wpas_fst_set_ies_cb;
5346 iface_obj->send_action = wpas_fst_send_action_cb;
5347 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5348 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5349 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5350 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5351}
5352#endif /* CONFIG_FST */
5353
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005354static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005355 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005356{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005357 struct wowlan_triggers *triggers;
5358 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005359
5360 if (!wpa_s->conf->wowlan_triggers)
5361 return 0;
5362
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005363 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5364 if (triggers) {
5365 ret = wpa_drv_wowlan(wpa_s, triggers);
5366 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005367 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005368 return ret;
5369}
5370
5371
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005372enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005373{
5374 if (freq < 3000)
5375 return BAND_2_4_GHZ;
5376 if (freq > 50000)
5377 return BAND_60_GHZ;
5378 return BAND_5_GHZ;
5379}
5380
5381
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005382unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005383{
5384 int i;
5385 unsigned int band = 0;
5386
5387 if (freqs) {
5388 /* freqs are specified for the radio work */
5389 for (i = 0; freqs[i]; i++)
5390 band |= wpas_freq_to_band(freqs[i]);
5391 } else {
5392 /*
5393 * freqs are not specified, implies all
5394 * the supported freqs by HW
5395 */
5396 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5397 if (wpa_s->hw.modes[i].num_channels != 0) {
5398 if (wpa_s->hw.modes[i].mode ==
5399 HOSTAPD_MODE_IEEE80211B ||
5400 wpa_s->hw.modes[i].mode ==
5401 HOSTAPD_MODE_IEEE80211G)
5402 band |= BAND_2_4_GHZ;
5403 else if (wpa_s->hw.modes[i].mode ==
5404 HOSTAPD_MODE_IEEE80211A)
5405 band |= BAND_5_GHZ;
5406 else if (wpa_s->hw.modes[i].mode ==
5407 HOSTAPD_MODE_IEEE80211AD)
5408 band |= BAND_60_GHZ;
5409 else if (wpa_s->hw.modes[i].mode ==
5410 HOSTAPD_MODE_IEEE80211ANY)
5411 band = BAND_2_4_GHZ | BAND_5_GHZ |
5412 BAND_60_GHZ;
5413 }
5414 }
5415 }
5416
5417 return band;
5418}
5419
5420
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005421static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5422 const char *rn)
5423{
5424 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5425 struct wpa_radio *radio;
5426
5427 while (rn && iface) {
5428 radio = iface->radio;
5429 if (radio && os_strcmp(rn, radio->name) == 0) {
5430 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5431 wpa_s->ifname, rn);
5432 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5433 return radio;
5434 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005435
5436 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005437 }
5438
5439 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5440 wpa_s->ifname, rn ? rn : "N/A");
5441 radio = os_zalloc(sizeof(*radio));
5442 if (radio == NULL)
5443 return NULL;
5444
5445 if (rn)
5446 os_strlcpy(radio->name, rn, sizeof(radio->name));
5447 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005448 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005449 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5450
5451 return radio;
5452}
5453
5454
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005455static void radio_work_free(struct wpa_radio_work *work)
5456{
5457 if (work->wpa_s->scan_work == work) {
5458 /* This should not really happen. */
5459 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5460 work->type, work, work->started);
5461 work->wpa_s->scan_work = NULL;
5462 }
5463
5464#ifdef CONFIG_P2P
5465 if (work->wpa_s->p2p_scan_work == work) {
5466 /* This should not really happen. */
5467 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5468 work->type, work, work->started);
5469 work->wpa_s->p2p_scan_work = NULL;
5470 }
5471#endif /* CONFIG_P2P */
5472
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005473 if (work->started) {
5474 work->wpa_s->radio->num_active_works--;
5475 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005476 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005477 work->type, work,
5478 work->wpa_s->radio->num_active_works);
5479 }
5480
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005481 dl_list_del(&work->list);
5482 os_free(work);
5483}
5484
5485
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005486static int radio_work_is_connect(struct wpa_radio_work *work)
5487{
5488 return os_strcmp(work->type, "sme-connect") == 0 ||
5489 os_strcmp(work->type, "connect") == 0;
5490}
5491
5492
5493static int radio_work_is_scan(struct wpa_radio_work *work)
5494{
5495 return os_strcmp(work->type, "scan") == 0 ||
5496 os_strcmp(work->type, "p2p-scan") == 0;
5497}
5498
5499
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005500static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5501{
5502 struct wpa_radio_work *active_work = NULL;
5503 struct wpa_radio_work *tmp;
5504
5505 /* Get the active work to know the type and band. */
5506 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5507 if (tmp->started) {
5508 active_work = tmp;
5509 break;
5510 }
5511 }
5512
5513 if (!active_work) {
5514 /* No active work, start one */
5515 radio->num_active_works = 0;
5516 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5517 list) {
5518 if (os_strcmp(tmp->type, "scan") == 0 &&
5519 radio->external_scan_running &&
5520 (((struct wpa_driver_scan_params *)
5521 tmp->ctx)->only_new_results ||
5522 tmp->wpa_s->clear_driver_scan_cache))
5523 continue;
5524 return tmp;
5525 }
5526 return NULL;
5527 }
5528
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005529 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005530 /*
5531 * If the active work is either connect or sme-connect,
5532 * do not parallelize them with other radio works.
5533 */
5534 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5535 "Do not parallelize radio work with %s",
5536 active_work->type);
5537 return NULL;
5538 }
5539
5540 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5541 if (tmp->started)
5542 continue;
5543
5544 /*
5545 * If connect or sme-connect are enqueued, parallelize only
5546 * those operations ahead of them in the queue.
5547 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005548 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005549 break;
5550
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005551 /* Serialize parallel scan and p2p_scan operations on the same
5552 * interface since the driver_nl80211 mechanism for tracking
5553 * scan cookies does not yet have support for this. */
5554 if (active_work->wpa_s == tmp->wpa_s &&
5555 radio_work_is_scan(active_work) &&
5556 radio_work_is_scan(tmp)) {
5557 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5558 "Do not start work '%s' when another work '%s' is already scheduled",
5559 tmp->type, active_work->type);
5560 continue;
5561 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005562 /*
5563 * Check that the radio works are distinct and
5564 * on different bands.
5565 */
5566 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5567 (active_work->bands != tmp->bands)) {
5568 /*
5569 * If a scan has to be scheduled through nl80211 scan
5570 * interface and if an external scan is already running,
5571 * do not schedule the scan since it is likely to get
5572 * rejected by kernel.
5573 */
5574 if (os_strcmp(tmp->type, "scan") == 0 &&
5575 radio->external_scan_running &&
5576 (((struct wpa_driver_scan_params *)
5577 tmp->ctx)->only_new_results ||
5578 tmp->wpa_s->clear_driver_scan_cache))
5579 continue;
5580
5581 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5582 "active_work:%s new_work:%s",
5583 active_work->type, tmp->type);
5584 return tmp;
5585 }
5586 }
5587
5588 /* Did not find a radio work to schedule in parallel. */
5589 return NULL;
5590}
5591
5592
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005593static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5594{
5595 struct wpa_radio *radio = eloop_ctx;
5596 struct wpa_radio_work *work;
5597 struct os_reltime now, diff;
5598 struct wpa_supplicant *wpa_s;
5599
5600 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005601 if (work == NULL) {
5602 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005603 return;
5604 }
5605
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005606 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5607 radio_list);
5608
5609 if (!(wpa_s &&
5610 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5611 if (work->started)
5612 return; /* already started and still in progress */
5613
5614 if (wpa_s && wpa_s->radio->external_scan_running) {
5615 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5616 return;
5617 }
5618 } else {
5619 work = NULL;
5620 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5621 /* get the work to schedule next */
5622 work = radio_work_get_next_work(radio);
5623 }
5624 if (!work)
5625 return;
5626 }
5627
5628 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005629 os_get_reltime(&now);
5630 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005631 wpa_dbg(wpa_s, MSG_DEBUG,
5632 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005633 work->type, work, diff.sec, diff.usec);
5634 work->started = 1;
5635 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005636 radio->num_active_works++;
5637
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005638 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005639
5640 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5641 radio->num_active_works < MAX_ACTIVE_WORKS)
5642 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005643}
5644
5645
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005646/*
5647 * This function removes both started and pending radio works running on
5648 * the provided interface's radio.
5649 * Prior to the removal of the radio work, its callback (cb) is called with
5650 * deinit set to be 1. Each work's callback is responsible for clearing its
5651 * internal data and restoring to a correct state.
5652 * @wpa_s: wpa_supplicant data
5653 * @type: type of works to be removed
5654 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5655 * this interface's works.
5656 */
5657void radio_remove_works(struct wpa_supplicant *wpa_s,
5658 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005659{
5660 struct wpa_radio_work *work, *tmp;
5661 struct wpa_radio *radio = wpa_s->radio;
5662
5663 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5664 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005665 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005666 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005667
5668 /* skip other ifaces' works */
5669 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005670 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005671
5672 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5673 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005674 work->cb(work, 1);
5675 radio_work_free(work);
5676 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005677
5678 /* in case we removed the started work */
5679 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005680}
5681
5682
Roshan Pius3a1667e2018-07-03 15:17:14 -07005683void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5684{
5685 struct wpa_radio_work *work;
5686 struct wpa_radio *radio = wpa_s->radio;
5687
5688 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5689 if (work->ctx != ctx)
5690 continue;
5691 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5692 work->type, work, work->started ? " (started)" : "");
5693 radio_work_free(work);
5694 break;
5695 }
5696}
5697
5698
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005699static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5700{
5701 struct wpa_radio *radio = wpa_s->radio;
5702
5703 if (!radio)
5704 return;
5705
5706 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5707 wpa_s->ifname, radio->name);
5708 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005709 radio_remove_works(wpa_s, NULL, 0);
5710 wpa_s->radio = NULL;
5711 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005712 return; /* Interfaces remain for this radio */
5713
5714 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005715 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005716 os_free(radio);
5717}
5718
5719
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005720void radio_work_check_next(struct wpa_supplicant *wpa_s)
5721{
5722 struct wpa_radio *radio = wpa_s->radio;
5723
5724 if (dl_list_empty(&radio->work))
5725 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005726 if (wpa_s->ext_work_in_progress) {
5727 wpa_printf(MSG_DEBUG,
5728 "External radio work in progress - delay start of pending item");
5729 return;
5730 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005731 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5732 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5733}
5734
5735
5736/**
5737 * radio_add_work - Add a radio work item
5738 * @wpa_s: Pointer to wpa_supplicant data
5739 * @freq: Frequency of the offchannel operation in MHz or 0
5740 * @type: Unique identifier for each type of work
5741 * @next: Force as the next work to be executed
5742 * @cb: Callback function for indicating when radio is available
5743 * @ctx: Context pointer for the work (work->ctx in cb())
5744 * Returns: 0 on success, -1 on failure
5745 *
5746 * This function is used to request time for an operation that requires
5747 * exclusive radio control. Once the radio is available, the registered callback
5748 * function will be called. radio_work_done() must be called once the exclusive
5749 * radio operation has been completed, so that the radio is freed for other
5750 * operations. The special case of deinit=1 is used to free the context data
5751 * during interface removal. That does not allow the callback function to start
5752 * the radio operation, i.e., it must free any resources allocated for the radio
5753 * work and return.
5754 *
5755 * The @freq parameter can be used to indicate a single channel on which the
5756 * offchannel operation will occur. This may allow multiple radio work
5757 * operations to be performed in parallel if they apply for the same channel.
5758 * Setting this to 0 indicates that the work item may use multiple channels or
5759 * requires exclusive control of the radio.
5760 */
5761int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5762 const char *type, int next,
5763 void (*cb)(struct wpa_radio_work *work, int deinit),
5764 void *ctx)
5765{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005766 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005767 struct wpa_radio_work *work;
5768 int was_empty;
5769
5770 work = os_zalloc(sizeof(*work));
5771 if (work == NULL)
5772 return -1;
5773 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5774 os_get_reltime(&work->time);
5775 work->freq = freq;
5776 work->type = type;
5777 work->wpa_s = wpa_s;
5778 work->cb = cb;
5779 work->ctx = ctx;
5780
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005781 if (freq)
5782 work->bands = wpas_freq_to_band(freq);
5783 else if (os_strcmp(type, "scan") == 0 ||
5784 os_strcmp(type, "p2p-scan") == 0)
5785 work->bands = wpas_get_bands(wpa_s,
5786 ((struct wpa_driver_scan_params *)
5787 ctx)->freqs);
5788 else
5789 work->bands = wpas_get_bands(wpa_s, NULL);
5790
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005791 was_empty = dl_list_empty(&wpa_s->radio->work);
5792 if (next)
5793 dl_list_add(&wpa_s->radio->work, &work->list);
5794 else
5795 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5796 if (was_empty) {
5797 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5798 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005799 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5800 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5801 wpa_dbg(wpa_s, MSG_DEBUG,
5802 "Try to schedule a radio work (num_active_works=%u)",
5803 radio->num_active_works);
5804 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005805 }
5806
5807 return 0;
5808}
5809
5810
5811/**
5812 * radio_work_done - Indicate that a radio work item has been completed
5813 * @work: Completed work
5814 *
5815 * This function is called once the callback function registered with
5816 * radio_add_work() has completed its work.
5817 */
5818void radio_work_done(struct wpa_radio_work *work)
5819{
5820 struct wpa_supplicant *wpa_s = work->wpa_s;
5821 struct os_reltime now, diff;
5822 unsigned int started = work->started;
5823
5824 os_get_reltime(&now);
5825 os_reltime_sub(&now, &work->time, &diff);
5826 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5827 work->type, work, started ? "done" : "canceled",
5828 diff.sec, diff.usec);
5829 radio_work_free(work);
5830 if (started)
5831 radio_work_check_next(wpa_s);
5832}
5833
5834
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005835struct wpa_radio_work *
5836radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005837{
5838 struct wpa_radio_work *work;
5839 struct wpa_radio *radio = wpa_s->radio;
5840
5841 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5842 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005843 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005844 }
5845
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005846 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005847}
5848
5849
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005850static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005851 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005852{
5853 const char *ifname, *driver, *rn;
5854
5855 driver = iface->driver;
5856next_driver:
5857 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
5858 return -1;
5859
5860 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
5861 if (wpa_s->drv_priv == NULL) {
5862 const char *pos;
5863 pos = driver ? os_strchr(driver, ',') : NULL;
5864 if (pos) {
5865 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
5866 "driver interface - try next driver wrapper");
5867 driver = pos + 1;
5868 goto next_driver;
5869 }
5870 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
5871 "interface");
5872 return -1;
5873 }
5874 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
5875 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
5876 "driver_param '%s'", wpa_s->conf->driver_param);
5877 return -1;
5878 }
5879
5880 ifname = wpa_drv_get_ifname(wpa_s);
5881 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
5882 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
5883 "interface name with '%s'", ifname);
5884 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
5885 }
5886
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005887 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005888 if (rn && rn[0] == '\0')
5889 rn = NULL;
5890
5891 wpa_s->radio = radio_add_interface(wpa_s, rn);
5892 if (wpa_s->radio == NULL)
5893 return -1;
5894
5895 return 0;
5896}
5897
5898
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005899#ifdef CONFIG_GAS_SERVER
5900
5901static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
5902 unsigned int freq, const u8 *dst,
5903 const u8 *src, const u8 *bssid,
5904 const u8 *data, size_t data_len,
5905 enum offchannel_send_action_result result)
5906{
5907 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
5908 " result=%s",
5909 freq, MAC2STR(dst),
5910 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
5911 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
5912 "FAILED"));
5913 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
5914 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
5915}
5916
5917
5918static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
5919 struct wpabuf *buf, unsigned int wait_time)
5920{
5921 struct wpa_supplicant *wpa_s = ctx;
5922 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
5923
5924 if (wait_time > wpa_s->max_remain_on_chan)
5925 wait_time = wpa_s->max_remain_on_chan;
5926
5927 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
5928 wpabuf_head(buf), wpabuf_len(buf),
5929 wait_time, wpas_gas_server_tx_status, 0);
5930}
5931
5932#endif /* CONFIG_GAS_SERVER */
5933
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005934static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005935 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005936{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005937 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005938 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005939 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005940
5941 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
5942 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
5943 iface->confname ? iface->confname : "N/A",
5944 iface->driver ? iface->driver : "default",
5945 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
5946 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
5947
5948 if (iface->confname) {
5949#ifdef CONFIG_BACKEND_FILE
5950 wpa_s->confname = os_rel2abs_path(iface->confname);
5951 if (wpa_s->confname == NULL) {
5952 wpa_printf(MSG_ERROR, "Failed to get absolute path "
5953 "for configuration file '%s'.",
5954 iface->confname);
5955 return -1;
5956 }
5957 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
5958 iface->confname, wpa_s->confname);
5959#else /* CONFIG_BACKEND_FILE */
5960 wpa_s->confname = os_strdup(iface->confname);
5961#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005962 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005963 if (wpa_s->conf == NULL) {
5964 wpa_printf(MSG_ERROR, "Failed to read or parse "
5965 "configuration '%s'.", wpa_s->confname);
5966 return -1;
5967 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005968 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005969 if (wpa_s->confanother &&
5970 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
5971 wpa_printf(MSG_ERROR,
5972 "Failed to read or parse configuration '%s'.",
5973 wpa_s->confanother);
5974 return -1;
5975 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005976
5977 /*
5978 * Override ctrl_interface and driver_param if set on command
5979 * line.
5980 */
5981 if (iface->ctrl_interface) {
5982 os_free(wpa_s->conf->ctrl_interface);
5983 wpa_s->conf->ctrl_interface =
5984 os_strdup(iface->ctrl_interface);
5985 }
5986
5987 if (iface->driver_param) {
5988 os_free(wpa_s->conf->driver_param);
5989 wpa_s->conf->driver_param =
5990 os_strdup(iface->driver_param);
5991 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005992
5993 if (iface->p2p_mgmt && !iface->ctrl_interface) {
5994 os_free(wpa_s->conf->ctrl_interface);
5995 wpa_s->conf->ctrl_interface = NULL;
5996 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005997 } else
5998 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
5999 iface->driver_param);
6000
6001 if (wpa_s->conf == NULL) {
6002 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6003 return -1;
6004 }
6005
6006 if (iface->ifname == NULL) {
6007 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6008 return -1;
6009 }
6010 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6011 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6012 iface->ifname);
6013 return -1;
6014 }
6015 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
6016
6017 if (iface->bridge_ifname) {
6018 if (os_strlen(iface->bridge_ifname) >=
6019 sizeof(wpa_s->bridge_ifname)) {
6020 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6021 "name '%s'.", iface->bridge_ifname);
6022 return -1;
6023 }
6024 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6025 sizeof(wpa_s->bridge_ifname));
6026 }
6027
6028 /* RSNA Supplicant Key Management - INITIALIZE */
6029 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
6030 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
6031
6032 /* Initialize driver interface and register driver event handler before
6033 * L2 receive handler so that association events are processed before
6034 * EAPOL-Key packets if both become available for the same select()
6035 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006036 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006037 return -1;
6038
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006039 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6040 return -1;
6041
6042 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6043 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6044 NULL);
6045 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6046
6047 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6048 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6049 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6050 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6051 "dot11RSNAConfigPMKLifetime");
6052 return -1;
6053 }
6054
6055 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6056 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6057 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6058 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6059 "dot11RSNAConfigPMKReauthThreshold");
6060 return -1;
6061 }
6062
6063 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6064 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6065 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6066 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6067 "dot11RSNAConfigSATimeout");
6068 return -1;
6069 }
6070
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006071 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6072 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006073 &wpa_s->hw.flags,
6074 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006075 if (wpa_s->hw.modes) {
6076 u16 i;
6077
6078 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6079 if (wpa_s->hw.modes[i].vht_capab) {
6080 wpa_s->hw_capab = CAPAB_VHT;
6081 break;
6082 }
6083
6084 if (wpa_s->hw.modes[i].ht_capab &
6085 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6086 wpa_s->hw_capab = CAPAB_HT40;
6087 else if (wpa_s->hw.modes[i].ht_capab &&
6088 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6089 wpa_s->hw_capab = CAPAB_HT;
6090 }
6091 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006092
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006093 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6094 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006095 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006096 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006097 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006098 wpa_s->drv_smps_modes = capa.smps_modes;
6099 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006100 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006101 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006102 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006103 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6104 wpa_s->max_sched_scan_plan_interval =
6105 capa.max_sched_scan_plan_interval;
6106 wpa_s->max_sched_scan_plan_iterations =
6107 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006108 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6109 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006110 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6111 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006112 wpa_s->extended_capa = capa.extended_capa;
6113 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6114 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006115 wpa_s->num_multichan_concurrent =
6116 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006117 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6118
6119 if (capa.mac_addr_rand_scan_supported)
6120 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6121 if (wpa_s->sched_scan_supported &&
6122 capa.mac_addr_rand_sched_scan_supported)
6123 wpa_s->mac_addr_rand_supported |=
6124 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006125
6126 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6127 if (wpa_s->extended_capa &&
6128 wpa_s->extended_capa_len >= 3 &&
6129 wpa_s->extended_capa[2] & 0x40)
6130 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006131 }
6132 if (wpa_s->max_remain_on_chan == 0)
6133 wpa_s->max_remain_on_chan = 1000;
6134
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006135 /*
6136 * Only take p2p_mgmt parameters when P2P Device is supported.
6137 * Doing it here as it determines whether l2_packet_init() will be done
6138 * during wpa_supplicant_driver_init().
6139 */
6140 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6141 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006142
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006143 if (wpa_s->num_multichan_concurrent == 0)
6144 wpa_s->num_multichan_concurrent = 1;
6145
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006146 if (wpa_supplicant_driver_init(wpa_s) < 0)
6147 return -1;
6148
6149#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006150 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006151 return -1;
6152#endif /* CONFIG_TDLS */
6153
6154 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6155 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6156 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6157 return -1;
6158 }
6159
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006160#ifdef CONFIG_FST
6161 if (wpa_s->conf->fst_group_id) {
6162 struct fst_iface_cfg cfg;
6163 struct fst_wpa_obj iface_obj;
6164
6165 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6166 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6167 sizeof(cfg.group_id));
6168 cfg.priority = wpa_s->conf->fst_priority;
6169 cfg.llt = wpa_s->conf->fst_llt;
6170
6171 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6172 &iface_obj, &cfg);
6173 if (!wpa_s->fst) {
6174 wpa_msg(wpa_s, MSG_ERROR,
6175 "FST: Cannot attach iface %s to group %s",
6176 wpa_s->ifname, cfg.group_id);
6177 return -1;
6178 }
6179 }
6180#endif /* CONFIG_FST */
6181
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006182 if (wpas_wps_init(wpa_s))
6183 return -1;
6184
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006185#ifdef CONFIG_GAS_SERVER
6186 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6187 if (!wpa_s->gas_server) {
6188 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6189 return -1;
6190 }
6191#endif /* CONFIG_GAS_SERVER */
6192
6193#ifdef CONFIG_DPP
6194 if (wpas_dpp_init(wpa_s) < 0)
6195 return -1;
6196#endif /* CONFIG_DPP */
6197
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006198 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6199 return -1;
6200 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6201
6202 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6203 if (wpa_s->ctrl_iface == NULL) {
6204 wpa_printf(MSG_ERROR,
6205 "Failed to initialize control interface '%s'.\n"
6206 "You may have another wpa_supplicant process "
6207 "already running or the file was\n"
6208 "left by an unclean termination of wpa_supplicant "
6209 "in which case you will need\n"
6210 "to manually remove this file before starting "
6211 "wpa_supplicant again.\n",
6212 wpa_s->conf->ctrl_interface);
6213 return -1;
6214 }
6215
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006216 wpa_s->gas = gas_query_init(wpa_s);
6217 if (wpa_s->gas == NULL) {
6218 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6219 return -1;
6220 }
6221
Roshan Pius3a1667e2018-07-03 15:17:14 -07006222 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6223 wpa_s->p2p_mgmt) &&
6224 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006225 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6226 return -1;
6227 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006228
6229 if (wpa_bss_init(wpa_s) < 0)
6230 return -1;
6231
Paul Stewart092955c2017-02-06 09:13:09 -08006232#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6233#ifdef CONFIG_MESH
6234 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6235#endif /* CONFIG_MESH */
6236#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6237
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006238 /*
6239 * Set Wake-on-WLAN triggers, if configured.
6240 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6241 * have effect anyway when the interface is down).
6242 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006243 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006244 return -1;
6245
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006246#ifdef CONFIG_EAP_PROXY
6247{
6248 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006249 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6250 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006251 if (wpa_s->mnc_len > 0) {
6252 wpa_s->imsi[len] = '\0';
6253 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6254 wpa_s->imsi, wpa_s->mnc_len);
6255 } else {
6256 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6257 }
6258}
6259#endif /* CONFIG_EAP_PROXY */
6260
Dmitry Shmidt04949592012-07-19 12:16:46 -07006261 if (pcsc_reader_init(wpa_s) < 0)
6262 return -1;
6263
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006264 if (wpas_init_ext_pw(wpa_s) < 0)
6265 return -1;
6266
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006267 wpas_rrm_reset(wpa_s);
6268
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006269 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6270
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006271#ifdef CONFIG_HS20
6272 hs20_init(wpa_s);
6273#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006274#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006275 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006276 if ((wpa_s->conf->oce & OCE_STA) &&
6277 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6278 wpa_s->enable_oce = OCE_STA;
6279 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6280 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6281 /* TODO: Need to add STA-CFON support */
6282 wpa_printf(MSG_ERROR,
6283 "OCE STA-CFON feature is not yet supported");
6284 }
6285 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006286 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6287#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006288
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006289 wpa_supplicant_set_default_scan_ies(wpa_s);
6290
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006291 return 0;
6292}
6293
6294
6295static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006296 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006297{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006298 struct wpa_global *global = wpa_s->global;
6299 struct wpa_supplicant *iface, *prev;
6300
6301 if (wpa_s == wpa_s->parent)
6302 wpas_p2p_group_remove(wpa_s, "*");
6303
6304 iface = global->ifaces;
6305 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006306 if (iface->p2pdev == wpa_s)
6307 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006308 if (iface == wpa_s || iface->parent != wpa_s) {
6309 iface = iface->next;
6310 continue;
6311 }
6312 wpa_printf(MSG_DEBUG,
6313 "Remove remaining child interface %s from parent %s",
6314 iface->ifname, wpa_s->ifname);
6315 prev = iface;
6316 iface = iface->next;
6317 wpa_supplicant_remove_iface(global, prev, terminate);
6318 }
6319
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006320 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006321 if (wpa_s->drv_priv) {
6322 wpa_supplicant_deauthenticate(wpa_s,
6323 WLAN_REASON_DEAUTH_LEAVING);
6324
6325 wpa_drv_set_countermeasures(wpa_s, 0);
6326 wpa_clear_keys(wpa_s, NULL);
6327 }
6328
6329 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006330 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006331
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006332 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006333 radio_remove_interface(wpa_s);
6334
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006335#ifdef CONFIG_FST
6336 if (wpa_s->fst) {
6337 fst_detach(wpa_s->fst);
6338 wpa_s->fst = NULL;
6339 }
6340 if (wpa_s->received_mb_ies) {
6341 wpabuf_free(wpa_s->received_mb_ies);
6342 wpa_s->received_mb_ies = NULL;
6343 }
6344#endif /* CONFIG_FST */
6345
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006346 if (wpa_s->drv_priv)
6347 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006348
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006349 if (notify)
6350 wpas_notify_iface_removed(wpa_s);
6351
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006352 if (terminate)
6353 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006354
6355 if (wpa_s->ctrl_iface) {
6356 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6357 wpa_s->ctrl_iface = NULL;
6358 }
6359
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006360#ifdef CONFIG_MESH
6361 if (wpa_s->ifmsh) {
6362 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6363 wpa_s->ifmsh = NULL;
6364 }
6365#endif /* CONFIG_MESH */
6366
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006367 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006368 wpa_config_free(wpa_s->conf);
6369 wpa_s->conf = NULL;
6370 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006371
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006372 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006373 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006374
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006375 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006376}
6377
6378
Dmitry Shmidte4663042016-04-04 10:07:49 -07006379#ifdef CONFIG_MATCH_IFACE
6380
6381/**
6382 * wpa_supplicant_match_iface - Match an interface description to a name
6383 * @global: Pointer to global data from wpa_supplicant_init()
6384 * @ifname: Name of the interface to match
6385 * Returns: Pointer to the created interface description or %NULL on failure
6386 */
6387struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6388 const char *ifname)
6389{
6390 int i;
6391 struct wpa_interface *iface, *miface;
6392
6393 for (i = 0; i < global->params.match_iface_count; i++) {
6394 miface = &global->params.match_ifaces[i];
6395 if (!miface->ifname ||
6396 fnmatch(miface->ifname, ifname, 0) == 0) {
6397 iface = os_zalloc(sizeof(*iface));
6398 if (!iface)
6399 return NULL;
6400 *iface = *miface;
6401 iface->ifname = ifname;
6402 return iface;
6403 }
6404 }
6405
6406 return NULL;
6407}
6408
6409
6410/**
6411 * wpa_supplicant_match_existing - Match existing interfaces
6412 * @global: Pointer to global data from wpa_supplicant_init()
6413 * Returns: 0 on success, -1 on failure
6414 */
6415static int wpa_supplicant_match_existing(struct wpa_global *global)
6416{
6417 struct if_nameindex *ifi, *ifp;
6418 struct wpa_supplicant *wpa_s;
6419 struct wpa_interface *iface;
6420
6421 ifp = if_nameindex();
6422 if (!ifp) {
6423 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6424 return -1;
6425 }
6426
6427 for (ifi = ifp; ifi->if_name; ifi++) {
6428 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6429 if (wpa_s)
6430 continue;
6431 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6432 if (iface) {
6433 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6434 os_free(iface);
6435 if (wpa_s)
6436 wpa_s->matched = 1;
6437 }
6438 }
6439
6440 if_freenameindex(ifp);
6441 return 0;
6442}
6443
6444#endif /* CONFIG_MATCH_IFACE */
6445
6446
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006447/**
6448 * wpa_supplicant_add_iface - Add a new network interface
6449 * @global: Pointer to global data from wpa_supplicant_init()
6450 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006451 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006452 * Returns: Pointer to the created interface or %NULL on failure
6453 *
6454 * This function is used to add new network interfaces for %wpa_supplicant.
6455 * This can be called before wpa_supplicant_run() to add interfaces before the
6456 * main event loop has been started. In addition, new interfaces can be added
6457 * dynamically while %wpa_supplicant is already running. This could happen,
6458 * e.g., when a hotplug network adapter is inserted.
6459 */
6460struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006461 struct wpa_interface *iface,
6462 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006463{
6464 struct wpa_supplicant *wpa_s;
6465 struct wpa_interface t_iface;
6466 struct wpa_ssid *ssid;
6467
6468 if (global == NULL || iface == NULL)
6469 return NULL;
6470
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006471 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006472 if (wpa_s == NULL)
6473 return NULL;
6474
6475 wpa_s->global = global;
6476
6477 t_iface = *iface;
6478 if (global->params.override_driver) {
6479 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6480 "('%s' -> '%s')",
6481 iface->driver, global->params.override_driver);
6482 t_iface.driver = global->params.override_driver;
6483 }
6484 if (global->params.override_ctrl_interface) {
6485 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6486 "ctrl_interface ('%s' -> '%s')",
6487 iface->ctrl_interface,
6488 global->params.override_ctrl_interface);
6489 t_iface.ctrl_interface =
6490 global->params.override_ctrl_interface;
6491 }
6492 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6493 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6494 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006495 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006496 return NULL;
6497 }
6498
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006499 /* Notify the control interfaces about new iface */
6500 if (wpas_notify_iface_added(wpa_s)) {
6501 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6502 return NULL;
6503 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006504
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006505 /* Notify the control interfaces about new networks for non p2p mgmt
6506 * ifaces. */
6507 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006508 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6509 wpas_notify_network_added(wpa_s, ssid);
6510 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006511
6512 wpa_s->next = global->ifaces;
6513 global->ifaces = wpa_s;
6514
6515 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006516 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006517
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006518#ifdef CONFIG_P2P
6519 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006520 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006521 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006522 wpas_p2p_add_p2pdev_interface(
6523 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006524 wpa_printf(MSG_INFO,
6525 "P2P: Failed to enable P2P Device interface");
6526 /* Try to continue without. P2P will be disabled. */
6527 }
6528#endif /* CONFIG_P2P */
6529
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006530 return wpa_s;
6531}
6532
6533
6534/**
6535 * wpa_supplicant_remove_iface - Remove a network interface
6536 * @global: Pointer to global data from wpa_supplicant_init()
6537 * @wpa_s: Pointer to the network interface to be removed
6538 * Returns: 0 if interface was removed, -1 if interface was not found
6539 *
6540 * This function can be used to dynamically remove network interfaces from
6541 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6542 * addition, this function is used to remove all remaining interfaces when
6543 * %wpa_supplicant is terminated.
6544 */
6545int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006546 struct wpa_supplicant *wpa_s,
6547 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006548{
6549 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006550#ifdef CONFIG_MESH
6551 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6552 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006553 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006554#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006555
6556 /* Remove interface from the global list of interfaces */
6557 prev = global->ifaces;
6558 if (prev == wpa_s) {
6559 global->ifaces = wpa_s->next;
6560 } else {
6561 while (prev && prev->next != wpa_s)
6562 prev = prev->next;
6563 if (prev == NULL)
6564 return -1;
6565 prev->next = wpa_s->next;
6566 }
6567
6568 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6569
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006570#ifdef CONFIG_MESH
6571 if (mesh_if_created) {
6572 ifname = os_strdup(wpa_s->ifname);
6573 if (ifname == NULL) {
6574 wpa_dbg(wpa_s, MSG_ERROR,
6575 "mesh: Failed to malloc ifname");
6576 return -1;
6577 }
6578 }
6579#endif /* CONFIG_MESH */
6580
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006581 if (global->p2p_group_formation == wpa_s)
6582 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006583 if (global->p2p_invite_group == wpa_s)
6584 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006585 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006586
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006587#ifdef CONFIG_MESH
6588 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006589 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006590 os_free(ifname);
6591 }
6592#endif /* CONFIG_MESH */
6593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006594 return 0;
6595}
6596
6597
6598/**
6599 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6600 * @wpa_s: Pointer to the network interface
6601 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6602 */
6603const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6604{
6605 const char *eapol_method;
6606
6607 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6608 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6609 return "NO-EAP";
6610 }
6611
6612 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6613 if (eapol_method == NULL)
6614 return "UNKNOWN-EAP";
6615
6616 return eapol_method;
6617}
6618
6619
6620/**
6621 * wpa_supplicant_get_iface - Get a new network interface
6622 * @global: Pointer to global data from wpa_supplicant_init()
6623 * @ifname: Interface name
6624 * Returns: Pointer to the interface or %NULL if not found
6625 */
6626struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6627 const char *ifname)
6628{
6629 struct wpa_supplicant *wpa_s;
6630
6631 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6632 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6633 return wpa_s;
6634 }
6635 return NULL;
6636}
6637
6638
6639#ifndef CONFIG_NO_WPA_MSG
6640static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6641{
6642 struct wpa_supplicant *wpa_s = ctx;
6643 if (wpa_s == NULL)
6644 return NULL;
6645 return wpa_s->ifname;
6646}
6647#endif /* CONFIG_NO_WPA_MSG */
6648
6649
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006650#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6651#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6652#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6653
6654/* Periodic cleanup tasks */
6655static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6656{
6657 struct wpa_global *global = eloop_ctx;
6658 struct wpa_supplicant *wpa_s;
6659
6660 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6661 wpas_periodic, global, NULL);
6662
6663#ifdef CONFIG_P2P
6664 if (global->p2p)
6665 p2p_expire_peers(global->p2p);
6666#endif /* CONFIG_P2P */
6667
6668 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6669 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6670#ifdef CONFIG_AP
6671 ap_periodic(wpa_s);
6672#endif /* CONFIG_AP */
6673 }
6674}
6675
6676
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006677/**
6678 * wpa_supplicant_init - Initialize %wpa_supplicant
6679 * @params: Parameters for %wpa_supplicant
6680 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6681 *
6682 * This function is used to initialize %wpa_supplicant. After successful
6683 * initialization, the returned data pointer can be used to add and remove
6684 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6685 */
6686struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6687{
6688 struct wpa_global *global;
6689 int ret, i;
6690
6691 if (params == NULL)
6692 return NULL;
6693
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006694#ifdef CONFIG_DRIVER_NDIS
6695 {
6696 void driver_ndis_init_ops(void);
6697 driver_ndis_init_ops();
6698 }
6699#endif /* CONFIG_DRIVER_NDIS */
6700
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006701#ifndef CONFIG_NO_WPA_MSG
6702 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6703#endif /* CONFIG_NO_WPA_MSG */
6704
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006705 if (params->wpa_debug_file_path)
6706 wpa_debug_open_file(params->wpa_debug_file_path);
6707 else
6708 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006709 if (params->wpa_debug_syslog)
6710 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006711 if (params->wpa_debug_tracing) {
6712 ret = wpa_debug_open_linux_tracing();
6713 if (ret) {
6714 wpa_printf(MSG_ERROR,
6715 "Failed to enable trace logging");
6716 return NULL;
6717 }
6718 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006719
6720 ret = eap_register_methods();
6721 if (ret) {
6722 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6723 if (ret == -2)
6724 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6725 "the same EAP type.");
6726 return NULL;
6727 }
6728
6729 global = os_zalloc(sizeof(*global));
6730 if (global == NULL)
6731 return NULL;
6732 dl_list_init(&global->p2p_srv_bonjour);
6733 dl_list_init(&global->p2p_srv_upnp);
6734 global->params.daemonize = params->daemonize;
6735 global->params.wait_for_monitor = params->wait_for_monitor;
6736 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6737 if (params->pid_file)
6738 global->params.pid_file = os_strdup(params->pid_file);
6739 if (params->ctrl_interface)
6740 global->params.ctrl_interface =
6741 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006742 if (params->ctrl_interface_group)
6743 global->params.ctrl_interface_group =
6744 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006745 if (params->override_driver)
6746 global->params.override_driver =
6747 os_strdup(params->override_driver);
6748 if (params->override_ctrl_interface)
6749 global->params.override_ctrl_interface =
6750 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006751#ifdef CONFIG_MATCH_IFACE
6752 global->params.match_iface_count = params->match_iface_count;
6753 if (params->match_iface_count) {
6754 global->params.match_ifaces =
6755 os_calloc(params->match_iface_count,
6756 sizeof(struct wpa_interface));
6757 os_memcpy(global->params.match_ifaces,
6758 params->match_ifaces,
6759 params->match_iface_count *
6760 sizeof(struct wpa_interface));
6761 }
6762#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006763#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006764 if (params->conf_p2p_dev)
6765 global->params.conf_p2p_dev =
6766 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006767#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006768 wpa_debug_level = global->params.wpa_debug_level =
6769 params->wpa_debug_level;
6770 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6771 params->wpa_debug_show_keys;
6772 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6773 params->wpa_debug_timestamp;
6774
6775 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
6776
6777 if (eloop_init()) {
6778 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6779 wpa_supplicant_deinit(global);
6780 return NULL;
6781 }
6782
Jouni Malinen75ecf522011-06-27 15:19:46 -07006783 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006784
6785 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6786 if (global->ctrl_iface == NULL) {
6787 wpa_supplicant_deinit(global);
6788 return NULL;
6789 }
6790
6791 if (wpas_notify_supplicant_initialized(global)) {
6792 wpa_supplicant_deinit(global);
6793 return NULL;
6794 }
6795
6796 for (i = 0; wpa_drivers[i]; i++)
6797 global->drv_count++;
6798 if (global->drv_count == 0) {
6799 wpa_printf(MSG_ERROR, "No drivers enabled");
6800 wpa_supplicant_deinit(global);
6801 return NULL;
6802 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006803 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006804 if (global->drv_priv == NULL) {
6805 wpa_supplicant_deinit(global);
6806 return NULL;
6807 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006808
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006809#ifdef CONFIG_WIFI_DISPLAY
6810 if (wifi_display_init(global) < 0) {
6811 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6812 wpa_supplicant_deinit(global);
6813 return NULL;
6814 }
6815#endif /* CONFIG_WIFI_DISPLAY */
6816
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006817 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6818 wpas_periodic, global, NULL);
6819
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006820 return global;
6821}
6822
6823
6824/**
6825 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6826 * @global: Pointer to global data from wpa_supplicant_init()
6827 * Returns: 0 after successful event loop run, -1 on failure
6828 *
6829 * This function starts the main event loop and continues running as long as
6830 * there are any remaining events. In most cases, this function is running as
6831 * long as the %wpa_supplicant process in still in use.
6832 */
6833int wpa_supplicant_run(struct wpa_global *global)
6834{
6835 struct wpa_supplicant *wpa_s;
6836
6837 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006838 (wpa_supplicant_daemon(global->params.pid_file) ||
6839 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006840 return -1;
6841
Dmitry Shmidte4663042016-04-04 10:07:49 -07006842#ifdef CONFIG_MATCH_IFACE
6843 if (wpa_supplicant_match_existing(global))
6844 return -1;
6845#endif
6846
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006847 if (global->params.wait_for_monitor) {
6848 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08006849 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006850 wpa_supplicant_ctrl_iface_wait(
6851 wpa_s->ctrl_iface);
6852 }
6853
6854 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
6855 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
6856
6857 eloop_run();
6858
6859 return 0;
6860}
6861
6862
6863/**
6864 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
6865 * @global: Pointer to global data from wpa_supplicant_init()
6866 *
6867 * This function is called to deinitialize %wpa_supplicant and to free all
6868 * allocated resources. Remaining network interfaces will also be removed.
6869 */
6870void wpa_supplicant_deinit(struct wpa_global *global)
6871{
6872 int i;
6873
6874 if (global == NULL)
6875 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006876
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006877 eloop_cancel_timeout(wpas_periodic, global, NULL);
6878
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006879#ifdef CONFIG_WIFI_DISPLAY
6880 wifi_display_deinit(global);
6881#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006882
6883 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006884 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006885
6886 if (global->ctrl_iface)
6887 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
6888
6889 wpas_notify_supplicant_deinitialized(global);
6890
6891 eap_peer_unregister_methods();
6892#ifdef CONFIG_AP
6893 eap_server_unregister_methods();
6894#endif /* CONFIG_AP */
6895
6896 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
6897 if (!global->drv_priv[i])
6898 continue;
6899 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
6900 }
6901 os_free(global->drv_priv);
6902
6903 random_deinit();
6904
6905 eloop_destroy();
6906
6907 if (global->params.pid_file) {
6908 os_daemonize_terminate(global->params.pid_file);
6909 os_free(global->params.pid_file);
6910 }
6911 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006912 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006913 os_free(global->params.override_driver);
6914 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006915#ifdef CONFIG_MATCH_IFACE
6916 os_free(global->params.match_ifaces);
6917#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006918#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006919 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006920#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006921
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07006922 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006923 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006924 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006925
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006926 os_free(global);
6927 wpa_debug_close_syslog();
6928 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006929 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006930}
6931
6932
6933void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
6934{
6935 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
6936 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
6937 char country[3];
6938 country[0] = wpa_s->conf->country[0];
6939 country[1] = wpa_s->conf->country[1];
6940 country[2] = '\0';
6941 if (wpa_drv_set_country(wpa_s, country) < 0) {
6942 wpa_printf(MSG_ERROR, "Failed to set country code "
6943 "'%s'", country);
6944 }
6945 }
6946
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006947 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
6948 wpas_init_ext_pw(wpa_s);
6949
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006950 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
6951 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6952
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006953 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
6954 struct wpa_driver_capa capa;
6955 int res = wpa_drv_get_capa(wpa_s, &capa);
6956
6957 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
6958 wpa_printf(MSG_ERROR,
6959 "Failed to update wowlan_triggers to '%s'",
6960 wpa_s->conf->wowlan_triggers);
6961 }
6962
Hai Shalom81f62d82019-07-22 12:10:00 -07006963 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
6964 wpa_supplicant_set_default_scan_ies(wpa_s);
6965
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006966#ifdef CONFIG_WPS
6967 wpas_wps_update_config(wpa_s);
6968#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006969 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006970 wpa_s->conf->changed_parameters = 0;
6971}
6972
6973
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006974void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006975{
6976 int i;
6977
6978 for (i = 0; i < *num_freqs; i++) {
6979 if (freqs[i] == freq)
6980 return;
6981 }
6982
6983 freqs[*num_freqs] = freq;
6984 (*num_freqs)++;
6985}
6986
6987
6988static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
6989{
6990 struct wpa_bss *bss, *cbss;
6991 const int max_freqs = 10;
6992 int *freqs;
6993 int num_freqs = 0;
6994
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006995 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006996 if (freqs == NULL)
6997 return NULL;
6998
6999 cbss = wpa_s->current_bss;
7000
7001 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7002 if (bss == cbss)
7003 continue;
7004 if (bss->ssid_len == cbss->ssid_len &&
7005 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
7006 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
7007 add_freq(freqs, &num_freqs, bss->freq);
7008 if (num_freqs == max_freqs)
7009 break;
7010 }
7011 }
7012
7013 if (num_freqs == 0) {
7014 os_free(freqs);
7015 freqs = NULL;
7016 }
7017
7018 return freqs;
7019}
7020
7021
7022void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7023{
7024 int timeout;
7025 int count;
7026 int *freqs = NULL;
7027
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007028 wpas_connect_work_done(wpa_s);
7029
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007030 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007031 * Remove possible authentication timeout since the connection failed.
7032 */
7033 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7034
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007035 /*
7036 * There is no point in blacklisting the AP if this event is
7037 * generated based on local request to disconnect.
7038 */
7039 if (wpa_s->own_disconnect_req) {
7040 wpa_s->own_disconnect_req = 0;
7041 wpa_dbg(wpa_s, MSG_DEBUG,
7042 "Ignore connection failure due to local request to disconnect");
7043 return;
7044 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007045 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007046 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7047 "indication since interface has been put into "
7048 "disconnected state");
7049 return;
7050 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007051 if (wpa_s->auto_reconnect_disabled) {
7052 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7053 "indication since auto connect is disabled");
7054 return;
7055 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007056
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007057 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007058 * Add the failed BSSID into the blacklist and speed up next scan
7059 * attempt if there could be other APs that could accept association.
7060 * The current blacklist count indicates how many times we have tried
7061 * connecting to this AP and multiple attempts mean that other APs are
7062 * either not available or has already been tried, so that we can start
7063 * increasing the delay here to avoid constant scanning.
7064 */
7065 count = wpa_blacklist_add(wpa_s, bssid);
7066 if (count == 1 && wpa_s->current_bss) {
7067 /*
7068 * This BSS was not in the blacklist before. If there is
7069 * another BSS available for the same ESS, we should try that
7070 * next. Otherwise, we may as well try this one once more
7071 * before allowing other, likely worse, ESSes to be considered.
7072 */
7073 freqs = get_bss_freqs_in_ess(wpa_s);
7074 if (freqs) {
7075 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7076 "has been seen; try it next");
7077 wpa_blacklist_add(wpa_s, bssid);
7078 /*
7079 * On the next scan, go through only the known channels
7080 * used in this ESS based on previous scans to speed up
7081 * common load balancing use case.
7082 */
7083 os_free(wpa_s->next_scan_freqs);
7084 wpa_s->next_scan_freqs = freqs;
7085 }
7086 }
7087
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007088 /*
7089 * Add previous failure count in case the temporary blacklist was
7090 * cleared due to no other BSSes being available.
7091 */
7092 count += wpa_s->extra_blacklist_count;
7093
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007094 if (count > 3 && wpa_s->current_ssid) {
7095 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7096 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007097 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007098 }
7099
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007100 switch (count) {
7101 case 1:
7102 timeout = 100;
7103 break;
7104 case 2:
7105 timeout = 500;
7106 break;
7107 case 3:
7108 timeout = 1000;
7109 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007110 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007111 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007112 break;
7113 default:
7114 timeout = 10000;
7115 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007116 }
7117
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007118 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
7119 "ms", count, timeout);
7120
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007121 /*
7122 * TODO: if more than one possible AP is available in scan results,
7123 * could try the other ones before requesting a new scan.
7124 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007125
7126 /* speed up the connection attempt with normal scan */
7127 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007128 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7129 1000 * (timeout % 1000));
7130}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007131
7132
Hai Shalomce48b4a2018-09-05 11:41:35 -07007133#ifdef CONFIG_FILS
7134void fils_connection_failure(struct wpa_supplicant *wpa_s)
7135{
7136 struct wpa_ssid *ssid = wpa_s->current_ssid;
7137 const u8 *realm, *username, *rrk;
7138 size_t realm_len, username_len, rrk_len;
7139 u16 next_seq_num;
7140
7141 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7142 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7143 &username, &username_len,
7144 &realm, &realm_len, &next_seq_num,
7145 &rrk, &rrk_len) != 0 ||
7146 !realm)
7147 return;
7148
7149 wpa_hexdump_ascii(MSG_DEBUG,
7150 "FILS: Store last connection failure realm",
7151 realm, realm_len);
7152 os_free(wpa_s->last_con_fail_realm);
7153 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7154 if (wpa_s->last_con_fail_realm) {
7155 wpa_s->last_con_fail_realm_len = realm_len;
7156 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7157 }
7158}
7159#endif /* CONFIG_FILS */
7160
7161
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007162int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7163{
7164 return wpa_s->conf->ap_scan == 2 ||
7165 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7166}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007167
Dmitry Shmidt04949592012-07-19 12:16:46 -07007168
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007169#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007170int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7171 struct wpa_ssid *ssid,
7172 const char *field,
7173 const char *value)
7174{
7175#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007176 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007177
7178 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7179 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7180 (const u8 *) value, os_strlen(value));
7181
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007182 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007183 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007184#else /* IEEE8021X_EAPOL */
7185 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7186 return -1;
7187#endif /* IEEE8021X_EAPOL */
7188}
7189
7190int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7191 struct wpa_ssid *ssid,
7192 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007193 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007194{
7195#ifdef IEEE8021X_EAPOL
7196 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007197 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007198
7199 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007200 case WPA_CTRL_REQ_EAP_IDENTITY:
7201 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007202 os_free(eap->imsi_identity);
7203 if (value == NULL)
7204 return -1;
7205 identity = os_strchr(value, ':');
7206 if (identity == NULL) {
7207 /* plain identity */
7208 eap->identity = (u8 *)os_strdup(value);
7209 eap->identity_len = os_strlen(value);
7210 } else {
7211 /* have both plain identity and encrypted identity */
7212 imsi_identity = value;
7213 *identity++ = '\0';
7214 /* plain identity */
7215 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7216 eap->imsi_identity_len = strlen(imsi_identity);
7217 /* encrypted identity */
7218 eap->identity = (u8 *)dup_binstr(identity,
7219 value_len - strlen(imsi_identity) - 1);
7220 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7221 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007222 eap->pending_req_identity = 0;
7223 if (ssid == wpa_s->current_ssid)
7224 wpa_s->reassociate = 1;
7225 break;
7226 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007227 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007228 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007229 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007230 eap->pending_req_password = 0;
7231 if (ssid == wpa_s->current_ssid)
7232 wpa_s->reassociate = 1;
7233 break;
7234 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007235 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007236 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007237 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007238 eap->pending_req_new_password = 0;
7239 if (ssid == wpa_s->current_ssid)
7240 wpa_s->reassociate = 1;
7241 break;
7242 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007243 str_clear_free(eap->cert.pin);
7244 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007245 eap->pending_req_pin = 0;
7246 if (ssid == wpa_s->current_ssid)
7247 wpa_s->reassociate = 1;
7248 break;
7249 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007250 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007251 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007252 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007253 os_free(eap->pending_req_otp);
7254 eap->pending_req_otp = NULL;
7255 eap->pending_req_otp_len = 0;
7256 break;
7257 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007258 str_clear_free(eap->cert.private_key_passwd);
7259 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007260 eap->pending_req_passphrase = 0;
7261 if (ssid == wpa_s->current_ssid)
7262 wpa_s->reassociate = 1;
7263 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007264 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007265 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007266 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007267 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007268 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007269 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7270 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7271 return -1;
7272 ssid->mem_only_psk = 1;
7273 if (ssid->passphrase)
7274 wpa_config_update_psk(ssid);
7275 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7276 wpa_supplicant_req_scan(wpa_s, 0, 0);
7277 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007278 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7279 if (eap->pending_ext_cert_check != PENDING_CHECK)
7280 return -1;
7281 if (os_strcmp(value, "good") == 0)
7282 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7283 else if (os_strcmp(value, "bad") == 0)
7284 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7285 else
7286 return -1;
7287 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007288 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007289 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007290 return -1;
7291 }
7292
7293 return 0;
7294#else /* IEEE8021X_EAPOL */
7295 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7296 return -1;
7297#endif /* IEEE8021X_EAPOL */
7298}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007299#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007300
7301
7302int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7303{
7304 int i;
7305 unsigned int drv_enc;
7306
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007307 if (wpa_s->p2p_mgmt)
7308 return 1; /* no normal network profiles on p2p_mgmt interface */
7309
Dmitry Shmidt04949592012-07-19 12:16:46 -07007310 if (ssid == NULL)
7311 return 1;
7312
7313 if (ssid->disabled)
7314 return 1;
7315
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007316 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007317 drv_enc = wpa_s->drv_enc;
7318 else
7319 drv_enc = (unsigned int) -1;
7320
7321 for (i = 0; i < NUM_WEP_KEYS; i++) {
7322 size_t len = ssid->wep_key_len[i];
7323 if (len == 0)
7324 continue;
7325 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7326 continue;
7327 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7328 continue;
7329 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7330 continue;
7331 return 1; /* invalid WEP key */
7332 }
7333
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007334 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007335 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007336 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007337 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007338 return 1;
7339
Dmitry Shmidt04949592012-07-19 12:16:46 -07007340 return 0;
7341}
7342
7343
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007344int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7345{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007346 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7347 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7348 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7349 /*
7350 * Driver does not support BIP -- ignore pmf=1 default
7351 * since the connection with PMF would fail and the
7352 * configuration does not require PMF to be enabled.
7353 */
7354 return NO_MGMT_FRAME_PROTECTION;
7355 }
7356
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007357 if (ssid &&
7358 (ssid->key_mgmt &
7359 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7360 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7361 /*
7362 * Do not use the default PMF value for non-RSN networks
7363 * since PMF is available only with RSN and pmf=2
7364 * configuration would otherwise prevent connections to
7365 * all open networks.
7366 */
7367 return NO_MGMT_FRAME_PROTECTION;
7368 }
7369
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007370 return wpa_s->conf->pmf;
7371 }
7372
7373 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007374}
7375
7376
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007377int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007378{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007379 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007380 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007381 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007382 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007383 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007384}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007385
7386
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007387void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007388{
7389 struct wpa_ssid *ssid = wpa_s->current_ssid;
7390 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007391 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007392
7393 if (ssid == NULL) {
7394 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7395 "SSID block");
7396 return;
7397 }
7398
7399 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7400 return;
7401
7402 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007403
7404#ifdef CONFIG_P2P
7405 if (ssid->p2p_group &&
7406 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7407 /*
7408 * Skip the wait time since there is a short timeout on the
7409 * connection to a P2P group.
7410 */
7411 return;
7412 }
7413#endif /* CONFIG_P2P */
7414
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007415 if (ssid->auth_failures > 50)
7416 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007417 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007418 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007419 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007420 dur = 90;
7421 else if (ssid->auth_failures > 3)
7422 dur = 60;
7423 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007424 dur = 30;
7425 else if (ssid->auth_failures > 1)
7426 dur = 20;
7427 else
7428 dur = 10;
7429
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007430 if (ssid->auth_failures > 1 &&
7431 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7432 dur += os_random() % (ssid->auth_failures * 10);
7433
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007434 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007435 if (now.sec + dur <= ssid->disabled_until.sec)
7436 return;
7437
7438 ssid->disabled_until.sec = now.sec + dur;
7439
7440 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007441 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007442 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007443 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007444}
7445
7446
7447void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7448 struct wpa_ssid *ssid, int clear_failures)
7449{
7450 if (ssid == NULL)
7451 return;
7452
7453 if (ssid->disabled_until.sec) {
7454 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7455 "id=%d ssid=\"%s\"",
7456 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7457 }
7458 ssid->disabled_until.sec = 0;
7459 ssid->disabled_until.usec = 0;
7460 if (clear_failures)
7461 ssid->auth_failures = 0;
7462}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007463
7464
7465int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7466{
7467 size_t i;
7468
7469 if (wpa_s->disallow_aps_bssid == NULL)
7470 return 0;
7471
7472 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7473 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7474 bssid, ETH_ALEN) == 0)
7475 return 1;
7476 }
7477
7478 return 0;
7479}
7480
7481
7482int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7483 size_t ssid_len)
7484{
7485 size_t i;
7486
7487 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7488 return 0;
7489
7490 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7491 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7492 if (ssid_len == s->ssid_len &&
7493 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7494 return 1;
7495 }
7496
7497 return 0;
7498}
7499
7500
7501/**
7502 * wpas_request_connection - Request a new connection
7503 * @wpa_s: Pointer to the network interface
7504 *
7505 * This function is used to request a new connection to be found. It will mark
7506 * the interface to allow reassociation and request a new scan to find a
7507 * suitable network to connect to.
7508 */
7509void wpas_request_connection(struct wpa_supplicant *wpa_s)
7510{
7511 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007512 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007513 wpa_supplicant_reinit_autoscan(wpa_s);
7514 wpa_s->extra_blacklist_count = 0;
7515 wpa_s->disconnected = 0;
7516 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007517 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007518
7519 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7520 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007521 else
7522 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007523}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007524
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007525
Roshan Pius02242d72016-08-09 15:31:48 -07007526/**
7527 * wpas_request_disconnection - Request disconnection
7528 * @wpa_s: Pointer to the network interface
7529 *
7530 * This function is used to request disconnection from the currently connected
7531 * network. This will stop any ongoing scans and initiate deauthentication.
7532 */
7533void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7534{
7535#ifdef CONFIG_SME
7536 wpa_s->sme.prev_bssid_set = 0;
7537#endif /* CONFIG_SME */
7538 wpa_s->reassociate = 0;
7539 wpa_s->disconnected = 1;
7540 wpa_supplicant_cancel_sched_scan(wpa_s);
7541 wpa_supplicant_cancel_scan(wpa_s);
7542 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7543 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007544 radio_remove_works(wpa_s, "connect", 0);
7545 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007546}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007547
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007548
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007549void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7550 struct wpa_used_freq_data *freqs_data,
7551 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007552{
7553 unsigned int i;
7554
7555 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7556 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007557 for (i = 0; i < len; i++) {
7558 struct wpa_used_freq_data *cur = &freqs_data[i];
7559 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7560 i, cur->freq, cur->flags);
7561 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007562}
7563
7564
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007565/*
7566 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007567 * are using the same radio as the current interface, and in addition, get
7568 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007569 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007570int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7571 struct wpa_used_freq_data *freqs_data,
7572 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007573{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007574 struct wpa_supplicant *ifs;
7575 u8 bssid[ETH_ALEN];
7576 int freq;
7577 unsigned int idx = 0, i;
7578
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007579 wpa_dbg(wpa_s, MSG_DEBUG,
7580 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007581 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007582
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007583 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7584 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007585 if (idx == len)
7586 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007587
7588 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7589 continue;
7590
7591 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007592 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7593 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007594 freq = ifs->current_ssid->frequency;
7595 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7596 freq = ifs->assoc_freq;
7597 else
7598 continue;
7599
7600 /* Hold only distinct freqs */
7601 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007602 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007603 break;
7604
7605 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007606 freqs_data[idx++].freq = freq;
7607
7608 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007609 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007610 WPA_FREQ_USED_BY_P2P_CLIENT :
7611 WPA_FREQ_USED_BY_INFRA_STATION;
7612 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007613 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007614
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007615 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007616 return idx;
7617}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007618
7619
7620/*
7621 * Find the operating frequencies of any of the virtual interfaces that
7622 * are using the same radio as the current interface.
7623 */
7624int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7625 int *freq_array, unsigned int len)
7626{
7627 struct wpa_used_freq_data *freqs_data;
7628 int num, i;
7629
7630 os_memset(freq_array, 0, sizeof(int) * len);
7631
7632 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7633 if (!freqs_data)
7634 return -1;
7635
7636 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7637 for (i = 0; i < num; i++)
7638 freq_array[i] = freqs_data[i].freq;
7639
7640 os_free(freqs_data);
7641
7642 return num;
7643}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007644
7645
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007646struct wpa_supplicant *
7647wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7648{
7649 switch (frame) {
7650#ifdef CONFIG_P2P
7651 case VENDOR_ELEM_PROBE_REQ_P2P:
7652 case VENDOR_ELEM_PROBE_RESP_P2P:
7653 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7654 case VENDOR_ELEM_BEACON_P2P_GO:
7655 case VENDOR_ELEM_P2P_PD_REQ:
7656 case VENDOR_ELEM_P2P_PD_RESP:
7657 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7658 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7659 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7660 case VENDOR_ELEM_P2P_INV_REQ:
7661 case VENDOR_ELEM_P2P_INV_RESP:
7662 case VENDOR_ELEM_P2P_ASSOC_REQ:
7663 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007664 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007665#endif /* CONFIG_P2P */
7666 default:
7667 return wpa_s;
7668 }
7669}
7670
7671
7672void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7673{
7674 unsigned int i;
7675 char buf[30];
7676
7677 wpa_printf(MSG_DEBUG, "Update vendor elements");
7678
7679 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7680 if (wpa_s->vendor_elem[i]) {
7681 int res;
7682
7683 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7684 if (!os_snprintf_error(sizeof(buf), res)) {
7685 wpa_hexdump_buf(MSG_DEBUG, buf,
7686 wpa_s->vendor_elem[i]);
7687 }
7688 }
7689 }
7690
7691#ifdef CONFIG_P2P
7692 if (wpa_s->parent == wpa_s &&
7693 wpa_s->global->p2p &&
7694 !wpa_s->global->p2p_disabled)
7695 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7696#endif /* CONFIG_P2P */
7697}
7698
7699
7700int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7701 const u8 *elem, size_t len)
7702{
7703 u8 *ie, *end;
7704
7705 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7706 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7707
7708 for (; ie + 1 < end; ie += 2 + ie[1]) {
7709 if (ie + len > end)
7710 break;
7711 if (os_memcmp(ie, elem, len) != 0)
7712 continue;
7713
7714 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7715 wpabuf_free(wpa_s->vendor_elem[frame]);
7716 wpa_s->vendor_elem[frame] = NULL;
7717 } else {
7718 os_memmove(ie, ie + len, end - (ie + len));
7719 wpa_s->vendor_elem[frame]->used -= len;
7720 }
7721 wpas_vendor_elem_update(wpa_s);
7722 return 0;
7723 }
7724
7725 return -1;
7726}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007727
7728
7729struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
7730 u16 num_modes, enum hostapd_hw_mode mode)
7731{
7732 u16 i;
7733
7734 for (i = 0; i < num_modes; i++) {
7735 if (modes[i].mode == mode)
7736 return &modes[i];
7737 }
7738
7739 return NULL;
7740}
7741
7742
7743static struct
7744wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7745 const u8 *bssid)
7746{
7747 struct wpa_bss_tmp_disallowed *bss;
7748
7749 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7750 struct wpa_bss_tmp_disallowed, list) {
7751 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7752 return bss;
7753 }
7754
7755 return NULL;
7756}
7757
7758
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007759static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7760{
7761 struct wpa_bss_tmp_disallowed *tmp;
7762 unsigned int num_bssid = 0;
7763 u8 *bssids;
7764 int ret;
7765
7766 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7767 if (!bssids)
7768 return -1;
7769 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7770 struct wpa_bss_tmp_disallowed, list) {
7771 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7772 ETH_ALEN);
7773 num_bssid++;
7774 }
7775 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7776 os_free(bssids);
7777 return ret;
7778}
7779
7780
7781static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7782{
7783 struct wpa_supplicant *wpa_s = eloop_ctx;
7784 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7785
7786 /* Make sure the bss is not already freed */
7787 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7788 struct wpa_bss_tmp_disallowed, list) {
7789 if (bss == tmp) {
7790 dl_list_del(&tmp->list);
7791 os_free(tmp);
7792 wpa_set_driver_tmp_disallow_list(wpa_s);
7793 break;
7794 }
7795 }
7796}
7797
7798
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007799void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08007800 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007801{
7802 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007803
7804 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7805 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007806 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08007807 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007808 }
7809
7810 bss = os_malloc(sizeof(*bss));
7811 if (!bss) {
7812 wpa_printf(MSG_DEBUG,
7813 "Failed to allocate memory for temp disallow BSS");
7814 return;
7815 }
7816
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007817 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7818 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007819 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08007820
7821finish:
7822 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007823 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7824 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007825}
7826
7827
Hai Shalom74f70d42019-02-11 14:42:39 -08007828int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
7829 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007830{
Hai Shalom74f70d42019-02-11 14:42:39 -08007831 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007832
7833 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7834 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007835 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
7836 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007837 break;
7838 }
7839 }
Hai Shalom74f70d42019-02-11 14:42:39 -08007840 if (!disallowed)
7841 return 0;
7842
7843 if (disallowed->rssi_threshold != 0 &&
7844 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007845 return 0;
7846
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007847 return 1;
7848}
Hai Shalom81f62d82019-07-22 12:10:00 -07007849
7850
7851int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
7852 unsigned int type, const u8 *addr,
7853 const u8 *mask)
7854{
7855 if ((addr && !mask) || (!addr && mask)) {
7856 wpa_printf(MSG_INFO,
7857 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
7858 return -1;
7859 }
7860
7861 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
7862 wpa_printf(MSG_INFO,
7863 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
7864 return -1;
7865 }
7866
7867 if (type & MAC_ADDR_RAND_SCAN) {
7868 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
7869 addr, mask))
7870 return -1;
7871 }
7872
7873 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
7874 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
7875 addr, mask))
7876 return -1;
7877
7878 if (wpa_s->sched_scanning && !wpa_s->pno)
7879 wpas_scan_restart_sched_scan(wpa_s);
7880 }
7881
7882 if (type & MAC_ADDR_RAND_PNO) {
7883 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
7884 addr, mask))
7885 return -1;
7886
7887 if (wpa_s->pno) {
7888 wpas_stop_pno(wpa_s);
7889 wpas_start_pno(wpa_s);
7890 }
7891 }
7892
7893 return 0;
7894}
7895
7896
7897int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
7898 unsigned int type)
7899{
7900 wpas_mac_addr_rand_scan_clear(wpa_s, type);
7901 if (wpa_s->pno) {
7902 if (type & MAC_ADDR_RAND_PNO) {
7903 wpas_stop_pno(wpa_s);
7904 wpas_start_pno(wpa_s);
7905 }
7906 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
7907 wpas_scan_restart_sched_scan(wpa_s);
7908 }
7909
7910 return 0;
7911}