blob: d1dd54069728fabca4cf5eca0f7abacf9acd37ec [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 */
128
129
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700130/* Configure default/group WEP keys for static WEP */
131int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
132{
133 int i, set = 0;
134
135 for (i = 0; i < NUM_WEP_KEYS; i++) {
136 if (ssid->wep_key_len[i] == 0)
137 continue;
138
139 set = 1;
140 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
141 i, i == ssid->wep_tx_keyidx, NULL, 0,
142 ssid->wep_key[i], ssid->wep_key_len[i]);
143 }
144
145 return set;
146}
147
148
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700149int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
150 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700151{
152 u8 key[32];
153 size_t keylen;
154 enum wpa_alg alg;
155 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800156 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700157
158 /* IBSS/WPA-None uses only one key (Group) for both receiving and
159 * sending unicast and multicast packets. */
160
161 if (ssid->mode != WPAS_MODE_IBSS) {
162 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
163 "IBSS/ad-hoc) for WPA-None", ssid->mode);
164 return -1;
165 }
166
167 if (!ssid->psk_set) {
168 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
169 "WPA-None");
170 return -1;
171 }
172
173 switch (wpa_s->group_cipher) {
174 case WPA_CIPHER_CCMP:
175 os_memcpy(key, ssid->psk, 16);
176 keylen = 16;
177 alg = WPA_ALG_CCMP;
178 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700179 case WPA_CIPHER_GCMP:
180 os_memcpy(key, ssid->psk, 16);
181 keylen = 16;
182 alg = WPA_ALG_GCMP;
183 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700184 case WPA_CIPHER_TKIP:
185 /* WPA-None uses the same Michael MIC key for both TX and RX */
186 os_memcpy(key, ssid->psk, 16 + 8);
187 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
188 keylen = 32;
189 alg = WPA_ALG_TKIP;
190 break;
191 default:
192 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
193 "WPA-None", wpa_s->group_cipher);
194 return -1;
195 }
196
197 /* TODO: should actually remember the previously used seq#, both for TX
198 * and RX from each STA.. */
199
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800200 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
201 os_memset(key, 0, sizeof(key));
202 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700203}
204
205
206static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
207{
208 struct wpa_supplicant *wpa_s = eloop_ctx;
209 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700210 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
211 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
212 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700213 bssid = wpa_s->pending_bssid;
214 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
215 MAC2STR(bssid));
216 wpa_blacklist_add(wpa_s, bssid);
217 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800218 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700219 wpa_s->reassociate = 1;
Roshan Pius38e96762017-01-23 14:52:00 -0800220 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700221
222 /*
223 * If we timed out, the AP or the local radio may be busy.
224 * So, wait a second until scanning again.
225 */
226 wpa_supplicant_req_scan(wpa_s, 1, 0);
227}
228
229
230/**
231 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
232 * @wpa_s: Pointer to wpa_supplicant data
233 * @sec: Number of seconds after which to time out authentication
234 * @usec: Number of microseconds after which to time out authentication
235 *
236 * This function is used to schedule a timeout for the current authentication
237 * attempt.
238 */
239void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
240 int sec, int usec)
241{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700242 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700243 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
244 return;
245
246 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
247 "%d usec", sec, usec);
248 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700249 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700250 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
251}
252
253
Roshan Pius3a1667e2018-07-03 15:17:14 -0700254/*
255 * wpas_auth_timeout_restart - Restart and change timeout for authentication
256 * @wpa_s: Pointer to wpa_supplicant data
257 * @sec_diff: difference in seconds applied to original timeout value
258 */
259void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
260{
261 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
262
263 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
264 wpa_dbg(wpa_s, MSG_DEBUG,
265 "Authentication timeout restart: %d sec", new_sec);
266 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
267 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
268 wpa_s, NULL);
269 }
270}
271
272
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700273/**
274 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
275 * @wpa_s: Pointer to wpa_supplicant data
276 *
277 * This function is used to cancel authentication timeout scheduled with
278 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
279 * been completed.
280 */
281void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
282{
283 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
284 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
285 wpa_blacklist_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700286 os_free(wpa_s->last_con_fail_realm);
287 wpa_s->last_con_fail_realm = NULL;
288 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700289}
290
291
292/**
293 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
294 * @wpa_s: Pointer to wpa_supplicant data
295 *
296 * This function is used to configure EAPOL state machine based on the selected
297 * authentication mode.
298 */
299void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
300{
301#ifdef IEEE8021X_EAPOL
302 struct eapol_config eapol_conf;
303 struct wpa_ssid *ssid = wpa_s->current_ssid;
304
305#ifdef CONFIG_IBSS_RSN
306 if (ssid->mode == WPAS_MODE_IBSS &&
307 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
308 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
309 /*
310 * RSN IBSS authentication is per-STA and we can disable the
311 * per-BSSID EAPOL authentication.
312 */
313 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
314 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
315 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
316 return;
317 }
318#endif /* CONFIG_IBSS_RSN */
319
320 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
321 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
322
323 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
324 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
325 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
326 else
327 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
328
329 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
330 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
331 eapol_conf.accept_802_1x_keys = 1;
332 eapol_conf.required_keys = 0;
333 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
334 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
335 }
336 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
337 eapol_conf.required_keys |=
338 EAPOL_REQUIRE_KEY_BROADCAST;
339 }
340
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700341 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700342 eapol_conf.required_keys = 0;
343 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700344 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700345 eapol_conf.workaround = ssid->eap_workaround;
346 eapol_conf.eap_disabled =
347 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
348 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
349 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700350 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800351
352#ifdef CONFIG_WPS
353 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
354 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
355 if (wpa_s->current_bss) {
356 struct wpabuf *ie;
357 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
358 WPS_IE_VENDOR_TYPE);
359 if (ie) {
360 if (wps_is_20(ie))
361 eapol_conf.wps |=
362 EAPOL_PEER_IS_WPS20_AP;
363 wpabuf_free(ie);
364 }
365 }
366 }
367#endif /* CONFIG_WPS */
368
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700369 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700370
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800371#ifdef CONFIG_MACSEC
372 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
373 ieee802_1x_create_preshared_mka(wpa_s, ssid);
374 else
375 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
376#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800377#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700378}
379
380
381/**
382 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
383 * @wpa_s: Pointer to wpa_supplicant data
384 * @ssid: Configuration data for the network
385 *
386 * This function is used to configure WPA state machine and related parameters
387 * to a mode where WPA is not enabled. This is called as part of the
388 * authentication configuration when the selected network does not use WPA.
389 */
390void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
391 struct wpa_ssid *ssid)
392{
393 int i;
394
395 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
396 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
397 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
398 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
399 else
400 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
401 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
402 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
403 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
404 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
405 wpa_s->group_cipher = WPA_CIPHER_NONE;
406 wpa_s->mgmt_group_cipher = 0;
407
408 for (i = 0; i < NUM_WEP_KEYS; i++) {
409 if (ssid->wep_key_len[i] > 5) {
410 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
411 wpa_s->group_cipher = WPA_CIPHER_WEP104;
412 break;
413 } else if (ssid->wep_key_len[i] > 0) {
414 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
415 wpa_s->group_cipher = WPA_CIPHER_WEP40;
416 break;
417 }
418 }
419
420 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
421 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
422 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
423 wpa_s->pairwise_cipher);
424 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
425#ifdef CONFIG_IEEE80211W
426 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
427 wpa_s->mgmt_group_cipher);
428#endif /* CONFIG_IEEE80211W */
429
430 pmksa_cache_clear_current(wpa_s->wpa);
431}
432
433
Dmitry Shmidt04949592012-07-19 12:16:46 -0700434void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800435{
436 int i;
437 if (wpa_s->hw.modes == NULL)
438 return;
439
440 for (i = 0; i < wpa_s->hw.num_modes; i++) {
441 os_free(wpa_s->hw.modes[i].channels);
442 os_free(wpa_s->hw.modes[i].rates);
443 }
444
445 os_free(wpa_s->hw.modes);
446 wpa_s->hw.modes = NULL;
447}
448
449
Hai Shalom74f70d42019-02-11 14:42:39 -0800450void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800451{
452 struct wpa_bss_tmp_disallowed *bss, *prev;
453
454 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
455 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700456 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800457 dl_list_del(&bss->list);
458 os_free(bss);
459 }
460}
461
462
Paul Stewart092955c2017-02-06 09:13:09 -0800463void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
464{
465 struct fils_hlp_req *req;
466
467 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
468 list)) != NULL) {
469 dl_list_del(&req->list);
470 wpabuf_free(req->pkt);
471 os_free(req);
472 }
473}
474
475
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700476static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
477{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700478 int i;
479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700480 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700481 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700482 scard_deinit(wpa_s->scard);
483 wpa_s->scard = NULL;
484 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
485 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
486 l2_packet_deinit(wpa_s->l2);
487 wpa_s->l2 = NULL;
488 if (wpa_s->l2_br) {
489 l2_packet_deinit(wpa_s->l2_br);
490 wpa_s->l2_br = NULL;
491 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800492#ifdef CONFIG_TESTING_OPTIONS
493 l2_packet_deinit(wpa_s->l2_test);
494 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800495 os_free(wpa_s->get_pref_freq_list_override);
496 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700497 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
498 wpa_s->last_assoc_req_wpa_ie = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800499#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700501 if (wpa_s->conf != NULL) {
502 struct wpa_ssid *ssid;
503 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
504 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700505 }
506
507 os_free(wpa_s->confname);
508 wpa_s->confname = NULL;
509
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700510 os_free(wpa_s->confanother);
511 wpa_s->confanother = NULL;
512
Hai Shalomce48b4a2018-09-05 11:41:35 -0700513 os_free(wpa_s->last_con_fail_realm);
514 wpa_s->last_con_fail_realm = NULL;
515 wpa_s->last_con_fail_realm_len = 0;
516
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700517 wpa_sm_set_eapol(wpa_s->wpa, NULL);
518 eapol_sm_deinit(wpa_s->eapol);
519 wpa_s->eapol = NULL;
520
521 rsn_preauth_deinit(wpa_s->wpa);
522
523#ifdef CONFIG_TDLS
524 wpa_tdls_deinit(wpa_s->wpa);
525#endif /* CONFIG_TDLS */
526
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800527 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700528 pmksa_candidate_free(wpa_s->wpa);
529 wpa_sm_deinit(wpa_s->wpa);
530 wpa_s->wpa = NULL;
531 wpa_blacklist_clear(wpa_s);
532
533 wpa_bss_deinit(wpa_s);
534
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700535 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700536 wpa_supplicant_cancel_scan(wpa_s);
537 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800538 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
539#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
540 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
541 wpa_s, NULL);
542#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700543
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700544 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
545
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700546 wpas_wps_deinit(wpa_s);
547
548 wpabuf_free(wpa_s->pending_eapol_rx);
549 wpa_s->pending_eapol_rx = NULL;
550
551#ifdef CONFIG_IBSS_RSN
552 ibss_rsn_deinit(wpa_s->ibss_rsn);
553 wpa_s->ibss_rsn = NULL;
554#endif /* CONFIG_IBSS_RSN */
555
556 sme_deinit(wpa_s);
557
558#ifdef CONFIG_AP
559 wpa_supplicant_ap_deinit(wpa_s);
560#endif /* CONFIG_AP */
561
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700562 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700563
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800564#ifdef CONFIG_OFFCHANNEL
565 offchannel_deinit(wpa_s);
566#endif /* CONFIG_OFFCHANNEL */
567
568 wpa_supplicant_cancel_sched_scan(wpa_s);
569
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700570 os_free(wpa_s->next_scan_freqs);
571 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800572
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800573 os_free(wpa_s->manual_scan_freqs);
574 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700575 os_free(wpa_s->select_network_scan_freqs);
576 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800577
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700578 os_free(wpa_s->manual_sched_scan_freqs);
579 wpa_s->manual_sched_scan_freqs = NULL;
580
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800581 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
582
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700583 /*
584 * Need to remove any pending gas-query radio work before the
585 * gas_query_deinit() call because gas_query::work has not yet been set
586 * for works that have not been started. gas_query_free() will be unable
587 * to cancel such pending radio works and once the pending gas-query
588 * radio work eventually gets removed, the deinit notification call to
589 * gas_query_start_cb() would result in dereferencing freed memory.
590 */
591 if (wpa_s->radio)
592 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800593 gas_query_deinit(wpa_s->gas);
594 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700595 gas_server_deinit(wpa_s->gas_server);
596 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800597
598 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700599
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700600 ieee802_1x_dealloc_kay_sm(wpa_s);
601
Dmitry Shmidt04949592012-07-19 12:16:46 -0700602 os_free(wpa_s->bssid_filter);
603 wpa_s->bssid_filter = NULL;
604
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800605 os_free(wpa_s->disallow_aps_bssid);
606 wpa_s->disallow_aps_bssid = NULL;
607 os_free(wpa_s->disallow_aps_ssid);
608 wpa_s->disallow_aps_ssid = NULL;
609
Dmitry Shmidt04949592012-07-19 12:16:46 -0700610 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700611#ifdef CONFIG_WNM
612 wnm_deallocate_memory(wpa_s);
613#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700614
615 ext_password_deinit(wpa_s->ext_pw);
616 wpa_s->ext_pw = NULL;
617
618 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800619 wpa_s->last_gas_resp = NULL;
620 wpabuf_free(wpa_s->prev_gas_resp);
621 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700622
623 os_free(wpa_s->last_scan_res);
624 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800625
626#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700627 if (wpa_s->drv_priv)
628 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700629 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800630#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700631
632 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
633 wpabuf_free(wpa_s->vendor_elem[i]);
634 wpa_s->vendor_elem[i] = NULL;
635 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800636
637 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800638
639 wpa_s->sched_scan_plans_num = 0;
640 os_free(wpa_s->sched_scan_plans);
641 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800642
643#ifdef CONFIG_MBO
644 wpa_s->non_pref_chan_num = 0;
645 os_free(wpa_s->non_pref_chan);
646 wpa_s->non_pref_chan = NULL;
647#endif /* CONFIG_MBO */
648
649 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700650
651 wpabuf_free(wpa_s->lci);
652 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800653 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800654
655#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
656#ifdef CONFIG_MESH
657 {
658 struct external_pmksa_cache *entry;
659
660 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
661 struct external_pmksa_cache,
662 list)) != NULL) {
663 dl_list_del(&entry->list);
664 os_free(entry->pmksa_cache);
665 os_free(entry);
666 }
667 }
668#endif /* CONFIG_MESH */
669#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
670
671 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800672
673 wpabuf_free(wpa_s->ric_ies);
674 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700675
676#ifdef CONFIG_DPP
677 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700678 dpp_global_deinit(wpa_s->dpp);
679 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700680#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700681}
682
683
684/**
685 * wpa_clear_keys - Clear keys configured for the driver
686 * @wpa_s: Pointer to wpa_supplicant data
687 * @addr: Previously used BSSID or %NULL if not available
688 *
689 * This function clears the encryption keys that has been previously configured
690 * for the driver.
691 */
692void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
693{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800694 int i, max;
695
696#ifdef CONFIG_IEEE80211W
697 max = 6;
698#else /* CONFIG_IEEE80211W */
699 max = 4;
700#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700701
702 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800703 for (i = 0; i < max; i++) {
704 if (wpa_s->keys_cleared & BIT(i))
705 continue;
706 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
707 NULL, 0);
708 }
709 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
710 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700711 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
712 0);
713 /* MLME-SETPROTECTION.request(None) */
714 wpa_drv_mlme_setprotection(
715 wpa_s, addr,
716 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
717 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
718 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800719 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700720}
721
722
723/**
724 * wpa_supplicant_state_txt - Get the connection state name as a text string
725 * @state: State (wpa_state; WPA_*)
726 * Returns: The state name as a printable text string
727 */
728const char * wpa_supplicant_state_txt(enum wpa_states state)
729{
730 switch (state) {
731 case WPA_DISCONNECTED:
732 return "DISCONNECTED";
733 case WPA_INACTIVE:
734 return "INACTIVE";
735 case WPA_INTERFACE_DISABLED:
736 return "INTERFACE_DISABLED";
737 case WPA_SCANNING:
738 return "SCANNING";
739 case WPA_AUTHENTICATING:
740 return "AUTHENTICATING";
741 case WPA_ASSOCIATING:
742 return "ASSOCIATING";
743 case WPA_ASSOCIATED:
744 return "ASSOCIATED";
745 case WPA_4WAY_HANDSHAKE:
746 return "4WAY_HANDSHAKE";
747 case WPA_GROUP_HANDSHAKE:
748 return "GROUP_HANDSHAKE";
749 case WPA_COMPLETED:
750 return "COMPLETED";
751 default:
752 return "UNKNOWN";
753 }
754}
755
756
757#ifdef CONFIG_BGSCAN
758
759static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
760{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800761 const char *name;
762
763 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
764 name = wpa_s->current_ssid->bgscan;
765 else
766 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800767 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800768 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800769 if (wpas_driver_bss_selection(wpa_s))
770 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700771 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
772 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800773#ifdef CONFIG_P2P
774 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
775 return;
776#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700777
778 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800779 if (wpa_s->current_ssid) {
780 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
782 "bgscan");
783 /*
784 * Live without bgscan; it is only used as a roaming
785 * optimization, so the initial connection is not
786 * affected.
787 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700788 } else {
789 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700790 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700791 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
792 0);
793 if (scan_res) {
794 bgscan_notify_scan(wpa_s, scan_res);
795 wpa_scan_results_free(scan_res);
796 }
797 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798 } else
799 wpa_s->bgscan_ssid = NULL;
800}
801
802
803static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
804{
805 if (wpa_s->bgscan_ssid != NULL) {
806 bgscan_deinit(wpa_s);
807 wpa_s->bgscan_ssid = NULL;
808 }
809}
810
811#endif /* CONFIG_BGSCAN */
812
813
Dmitry Shmidt04949592012-07-19 12:16:46 -0700814static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
815{
816 if (autoscan_init(wpa_s, 0))
817 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
818}
819
820
821static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
822{
823 autoscan_deinit(wpa_s);
824}
825
826
827void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
828{
829 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
830 wpa_s->wpa_state == WPA_SCANNING) {
831 autoscan_deinit(wpa_s);
832 wpa_supplicant_start_autoscan(wpa_s);
833 }
834}
835
836
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700837/**
838 * wpa_supplicant_set_state - Set current connection state
839 * @wpa_s: Pointer to wpa_supplicant data
840 * @state: The new connection state
841 *
842 * This function is called whenever the connection state changes, e.g.,
843 * association is completed for WPA/WPA2 4-Way Handshake is started.
844 */
845void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
846 enum wpa_states state)
847{
848 enum wpa_states old_state = wpa_s->wpa_state;
849
850 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
851 wpa_supplicant_state_txt(wpa_s->wpa_state),
852 wpa_supplicant_state_txt(state));
853
Hai Shalom74f70d42019-02-11 14:42:39 -0800854 if (state == WPA_COMPLETED &&
855 os_reltime_initialized(&wpa_s->roam_start)) {
856 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
857 wpa_s->roam_start.sec = 0;
858 wpa_s->roam_start.usec = 0;
859 wpas_notify_auth_changed(wpa_s);
860 wpas_notify_roam_time(wpa_s);
861 wpas_notify_roam_complete(wpa_s);
862 } else if (state == WPA_DISCONNECTED &&
863 os_reltime_initialized(&wpa_s->roam_start)) {
864 wpa_s->roam_start.sec = 0;
865 wpa_s->roam_start.usec = 0;
866 wpa_s->roam_time.sec = 0;
867 wpa_s->roam_time.usec = 0;
868 wpas_notify_roam_complete(wpa_s);
869 }
870
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800871 if (state == WPA_INTERFACE_DISABLED) {
872 /* Assure normal scan when interface is restored */
873 wpa_s->normal_scans = 0;
874 }
875
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700876 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800877 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700878 /* Reinitialize normal_scan counter */
879 wpa_s->normal_scans = 0;
880 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800881
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700882#ifdef CONFIG_P2P
883 /*
884 * P2PS client has to reply to Probe Request frames received on the
885 * group operating channel. Enable Probe Request frame reporting for
886 * P2P connected client in case p2p_cli_probe configuration property is
887 * set to 1.
888 */
889 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
890 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
891 wpa_s->current_ssid->p2p_group) {
892 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
893 wpa_dbg(wpa_s, MSG_DEBUG,
894 "P2P: Enable CLI Probe Request RX reporting");
895 wpa_s->p2p_cli_probe =
896 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
897 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
898 wpa_dbg(wpa_s, MSG_DEBUG,
899 "P2P: Disable CLI Probe Request RX reporting");
900 wpa_s->p2p_cli_probe = 0;
901 wpa_drv_probe_req_report(wpa_s, 0);
902 }
903 }
904#endif /* CONFIG_P2P */
905
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700906 if (state != WPA_SCANNING)
907 wpa_supplicant_notify_scanning(wpa_s, 0);
908
909 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700910 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700911 int fils_hlp_sent = 0;
912
913#ifdef CONFIG_SME
914 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
915 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
916 fils_hlp_sent = 1;
917#endif /* CONFIG_SME */
918 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
919 wpa_auth_alg_fils(wpa_s->auth_alg))
920 fils_hlp_sent = 1;
921
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700922#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700923 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700924 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800925 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700926 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700927 ssid && ssid->id_str ? ssid->id_str : "",
928 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700929#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700930 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700931 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800932 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700933 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700934 wpa_drv_set_operstate(wpa_s, 1);
935#ifndef IEEE8021X_EAPOL
936 wpa_drv_set_supp_port(wpa_s, 1);
937#endif /* IEEE8021X_EAPOL */
938 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700939 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700940 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700941
942 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700943
944#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
945 if (!fils_hlp_sent && ssid && ssid->eap.erp)
946 wpas_update_fils_connect_params(wpa_s);
947#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700948 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
949 state == WPA_ASSOCIATED) {
950 wpa_s->new_connection = 1;
951 wpa_drv_set_operstate(wpa_s, 0);
952#ifndef IEEE8021X_EAPOL
953 wpa_drv_set_supp_port(wpa_s, 0);
954#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700955 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956 }
957 wpa_s->wpa_state = state;
958
959#ifdef CONFIG_BGSCAN
960 if (state == WPA_COMPLETED)
961 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800962 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700963 wpa_supplicant_stop_bgscan(wpa_s);
964#endif /* CONFIG_BGSCAN */
965
Hai Shalom5f92bc92019-04-18 11:54:11 -0700966 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700967 wpa_supplicant_stop_autoscan(wpa_s);
968
969 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
970 wpa_supplicant_start_autoscan(wpa_s);
971
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800972 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
973 wmm_ac_notify_disassoc(wpa_s);
974
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700975 if (wpa_s->wpa_state != old_state) {
976 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
977
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700978 /*
979 * Notify the P2P Device interface about a state change in one
980 * of the interfaces.
981 */
982 wpas_p2p_indicate_state_change(wpa_s);
983
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700984 if (wpa_s->wpa_state == WPA_COMPLETED ||
985 old_state == WPA_COMPLETED)
986 wpas_notify_auth_changed(wpa_s);
987 }
988}
989
990
991void wpa_supplicant_terminate_proc(struct wpa_global *global)
992{
993 int pending = 0;
994#ifdef CONFIG_WPS
995 struct wpa_supplicant *wpa_s = global->ifaces;
996 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800997 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700998 if (wpas_wps_terminate_pending(wpa_s) == 1)
999 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001000#ifdef CONFIG_P2P
1001 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1002 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1003 wpas_p2p_disconnect(wpa_s);
1004#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001005 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006 }
1007#endif /* CONFIG_WPS */
1008 if (pending)
1009 return;
1010 eloop_terminate();
1011}
1012
1013
1014static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1015{
1016 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001017 wpa_supplicant_terminate_proc(global);
1018}
1019
1020
1021void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1022{
1023 enum wpa_states old_state = wpa_s->wpa_state;
1024
1025 wpa_s->pairwise_cipher = 0;
1026 wpa_s->group_cipher = 0;
1027 wpa_s->mgmt_group_cipher = 0;
1028 wpa_s->key_mgmt = 0;
1029 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001030 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001031
1032 if (wpa_s->wpa_state != old_state)
1033 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1034}
1035
1036
1037/**
1038 * wpa_supplicant_reload_configuration - Reload configuration data
1039 * @wpa_s: Pointer to wpa_supplicant data
1040 * Returns: 0 on success or -1 if configuration parsing failed
1041 *
1042 * This function can be used to request that the configuration data is reloaded
1043 * (e.g., after configuration file change). This function is reloading
1044 * configuration only for one interface, so this may need to be called multiple
1045 * times if %wpa_supplicant is controlling multiple interfaces and all
1046 * interfaces need reconfiguration.
1047 */
1048int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1049{
1050 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001051 int reconf_ctrl;
1052 int old_ap_scan;
1053
1054 if (wpa_s->confname == NULL)
1055 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001056 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057 if (conf == NULL) {
1058 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1059 "file '%s' - exiting", wpa_s->confname);
1060 return -1;
1061 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001062 if (wpa_s->confanother &&
1063 !wpa_config_read(wpa_s->confanother, conf)) {
1064 wpa_msg(wpa_s, MSG_ERROR,
1065 "Failed to parse the configuration file '%s' - exiting",
1066 wpa_s->confanother);
1067 return -1;
1068 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001069
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070 conf->changed_parameters = (unsigned int) -1;
1071
1072 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1073 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1074 os_strcmp(conf->ctrl_interface,
1075 wpa_s->conf->ctrl_interface) != 0);
1076
1077 if (reconf_ctrl && wpa_s->ctrl_iface) {
1078 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1079 wpa_s->ctrl_iface = NULL;
1080 }
1081
1082 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001083 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001084 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1085 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001086 wpa_supplicant_deauthenticate(wpa_s,
1087 WLAN_REASON_DEAUTH_LEAVING);
1088 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089
1090 /*
1091 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001092 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001093 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001094 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1095 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1096 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001097 /*
1098 * Clear forced success to clear EAP state for next
1099 * authentication.
1100 */
1101 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1102 }
1103 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1104 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001105 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001106 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1107 rsn_preauth_deinit(wpa_s->wpa);
1108
1109 old_ap_scan = wpa_s->conf->ap_scan;
1110 wpa_config_free(wpa_s->conf);
1111 wpa_s->conf = conf;
1112 if (old_ap_scan != wpa_s->conf->ap_scan)
1113 wpas_notify_ap_scan_changed(wpa_s);
1114
1115 if (reconf_ctrl)
1116 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1117
1118 wpa_supplicant_update_config(wpa_s);
1119
1120 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001121 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001122 wpa_s->reassociate = 1;
1123 wpa_supplicant_req_scan(wpa_s, 0, 0);
1124 }
1125 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1126 return 0;
1127}
1128
1129
1130static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1131{
1132 struct wpa_global *global = signal_ctx;
1133 struct wpa_supplicant *wpa_s;
1134 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1135 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1136 sig);
1137 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1138 wpa_supplicant_terminate_proc(global);
1139 }
1140 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001141
1142 if (wpa_debug_reopen_file() < 0) {
1143 /* Ignore errors since we cannot really do much to fix this */
1144 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1145 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146}
1147
1148
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001149static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1150 struct wpa_ssid *ssid,
1151 struct wpa_ie_data *ie)
1152{
1153 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1154 if (ret) {
1155 if (ret == -2) {
1156 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1157 "from association info");
1158 }
1159 return -1;
1160 }
1161
1162 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1163 "cipher suites");
1164 if (!(ie->group_cipher & ssid->group_cipher)) {
1165 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1166 "cipher 0x%x (mask 0x%x) - reject",
1167 ie->group_cipher, ssid->group_cipher);
1168 return -1;
1169 }
1170 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1171 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1172 "cipher 0x%x (mask 0x%x) - reject",
1173 ie->pairwise_cipher, ssid->pairwise_cipher);
1174 return -1;
1175 }
1176 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1177 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1178 "management 0x%x (mask 0x%x) - reject",
1179 ie->key_mgmt, ssid->key_mgmt);
1180 return -1;
1181 }
1182
1183#ifdef CONFIG_IEEE80211W
1184 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001185 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001186 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1187 "that does not support management frame protection - "
1188 "reject");
1189 return -1;
1190 }
1191#endif /* CONFIG_IEEE80211W */
1192
1193 return 0;
1194}
1195
1196
Hai Shalom021b0b52019-04-10 11:17:58 -07001197static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1198 int freq)
1199{
1200 if (!ie->has_group)
1201 ie->group_cipher = wpa_default_rsn_cipher(freq);
1202 if (!ie->has_pairwise)
1203 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1204 return (ie->group_cipher & ssid->group_cipher) &&
1205 (ie->pairwise_cipher & ssid->pairwise_cipher);
1206}
1207
1208
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209/**
1210 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1211 * @wpa_s: Pointer to wpa_supplicant data
1212 * @bss: Scan results for the selected BSS, or %NULL if not available
1213 * @ssid: Configuration data for the selected network
1214 * @wpa_ie: Buffer for the WPA/RSN IE
1215 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1216 * used buffer length in case the functions returns success.
1217 * Returns: 0 on success or -1 on failure
1218 *
1219 * This function is used to configure authentication and encryption parameters
1220 * based on the network configuration and scan result for the selected BSS (if
1221 * available).
1222 */
1223int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1224 struct wpa_bss *bss, struct wpa_ssid *ssid,
1225 u8 *wpa_ie, size_t *wpa_ie_len)
1226{
1227 struct wpa_ie_data ie;
1228 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001229 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001230
1231 if (bss) {
1232 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1233 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001234 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001236 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001237
1238 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1239 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001240 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001241 (ie.key_mgmt & ssid->key_mgmt)) {
1242 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1243 proto = WPA_PROTO_RSN;
1244 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001245 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001246 (ie.group_cipher & ssid->group_cipher) &&
1247 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1248 (ie.key_mgmt & ssid->key_mgmt)) {
1249 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1250 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001251#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001252 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1253 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1254 (ie.group_cipher & ssid->group_cipher) &&
1255 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1256 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001257 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001258 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001259 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1260 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1261 (ie.group_cipher & ssid->group_cipher) &&
1262 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1263 (ie.key_mgmt & ssid->key_mgmt)) {
1264 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1265 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001266#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001267 } else if (bss) {
1268 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001269 wpa_dbg(wpa_s, MSG_DEBUG,
1270 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1271 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1272 ssid->key_mgmt);
1273 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1274 MAC2STR(bss->bssid),
1275 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1276 bss_wpa ? " WPA" : "",
1277 bss_rsn ? " RSN" : "",
1278 bss_osen ? " OSEN" : "");
1279 if (bss_rsn) {
1280 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1281 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1282 wpa_dbg(wpa_s, MSG_DEBUG,
1283 "Could not parse RSN element");
1284 } else {
1285 wpa_dbg(wpa_s, MSG_DEBUG,
1286 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1287 ie.pairwise_cipher, ie.group_cipher,
1288 ie.key_mgmt);
1289 }
1290 }
1291 if (bss_wpa) {
1292 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1293 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1294 wpa_dbg(wpa_s, MSG_DEBUG,
1295 "Could not parse WPA element");
1296 } else {
1297 wpa_dbg(wpa_s, MSG_DEBUG,
1298 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1299 ie.pairwise_cipher, ie.group_cipher,
1300 ie.key_mgmt);
1301 }
1302 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001303 return -1;
1304 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001305 if (ssid->proto & WPA_PROTO_OSEN)
1306 proto = WPA_PROTO_OSEN;
1307 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001308 proto = WPA_PROTO_RSN;
1309 else
1310 proto = WPA_PROTO_WPA;
1311 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1312 os_memset(&ie, 0, sizeof(ie));
1313 ie.group_cipher = ssid->group_cipher;
1314 ie.pairwise_cipher = ssid->pairwise_cipher;
1315 ie.key_mgmt = ssid->key_mgmt;
1316#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001317 ie.mgmt_group_cipher = 0;
1318 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1319 if (ssid->group_mgmt_cipher &
1320 WPA_CIPHER_BIP_GMAC_256)
1321 ie.mgmt_group_cipher =
1322 WPA_CIPHER_BIP_GMAC_256;
1323 else if (ssid->group_mgmt_cipher &
1324 WPA_CIPHER_BIP_CMAC_256)
1325 ie.mgmt_group_cipher =
1326 WPA_CIPHER_BIP_CMAC_256;
1327 else if (ssid->group_mgmt_cipher &
1328 WPA_CIPHER_BIP_GMAC_128)
1329 ie.mgmt_group_cipher =
1330 WPA_CIPHER_BIP_GMAC_128;
1331 else
1332 ie.mgmt_group_cipher =
1333 WPA_CIPHER_AES_128_CMAC;
1334 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001335#endif /* CONFIG_IEEE80211W */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001336#ifdef CONFIG_OWE
1337 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1338 !ssid->owe_only &&
1339 !bss_wpa && !bss_rsn && !bss_osen) {
1340 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1341 wpa_s->wpa_proto = 0;
1342 *wpa_ie_len = 0;
1343 return 0;
1344 }
1345#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1347 "based on configuration");
1348 } else
1349 proto = ie.proto;
1350 }
1351
1352 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1353 "pairwise %d key_mgmt %d proto %d",
1354 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1355#ifdef CONFIG_IEEE80211W
1356 if (ssid->ieee80211w) {
1357 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1358 ie.mgmt_group_cipher);
1359 }
1360#endif /* CONFIG_IEEE80211W */
1361
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001362 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1364 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001365 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366
1367 if (bss || !wpa_s->ap_ies_from_associnfo) {
1368 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1369 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1370 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1371 bss_rsn ? 2 + bss_rsn[1] : 0))
1372 return -1;
1373 }
1374
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001375#ifdef CONFIG_NO_WPA
1376 wpa_s->group_cipher = WPA_CIPHER_NONE;
1377 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1378#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001379 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001380 wpa_dbg(wpa_s, MSG_DEBUG,
1381 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1382 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001383 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1384 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001385 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1386 "cipher");
1387 return -1;
1388 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001389 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1390 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001391
1392 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001393 wpa_dbg(wpa_s, MSG_DEBUG,
1394 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1395 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001396 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1397 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001398 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1399 "cipher");
1400 return -1;
1401 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001402 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1403 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001404#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405
1406 sel = ie.key_mgmt & ssid->key_mgmt;
Hai Shalom021b0b52019-04-10 11:17:58 -07001407 wpa_dbg(wpa_s, MSG_DEBUG,
1408 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1409 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001410#ifdef CONFIG_SAE
1411 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1412 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1413#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001414 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001415#ifdef CONFIG_IEEE80211R
1416#ifdef CONFIG_SHA384
1417 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
1418 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1419 wpa_dbg(wpa_s, MSG_DEBUG,
1420 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001421 if (!ssid->ft_eap_pmksa_caching &&
1422 pmksa_cache_get_current(wpa_s->wpa)) {
1423 /* PMKSA caching with FT may have interoperability
1424 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001425 wpa_dbg(wpa_s, MSG_DEBUG,
1426 "WPA: Disable PMKSA caching for FT/802.1X connection");
1427 pmksa_cache_clear_current(wpa_s->wpa);
1428 }
1429#endif /* CONFIG_SHA384 */
1430#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001431#ifdef CONFIG_SUITEB192
1432 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1433 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1434 wpa_dbg(wpa_s, MSG_DEBUG,
1435 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1436#endif /* CONFIG_SUITEB192 */
1437#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001438 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1439 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1440 wpa_dbg(wpa_s, MSG_DEBUG,
1441 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001442#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001443#ifdef CONFIG_FILS
1444#ifdef CONFIG_IEEE80211R
1445 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1446 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1447 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1448 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1449 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1450 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1451#endif /* CONFIG_IEEE80211R */
1452 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1453 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1454 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1455 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1456 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1457 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1458#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459#ifdef CONFIG_IEEE80211R
1460 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1461 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1462 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001463 if (!ssid->ft_eap_pmksa_caching &&
1464 pmksa_cache_get_current(wpa_s->wpa)) {
1465 /* PMKSA caching with FT may have interoperability
1466 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001467 wpa_dbg(wpa_s, MSG_DEBUG,
1468 "WPA: Disable PMKSA caching for FT/802.1X connection");
1469 pmksa_cache_clear_current(wpa_s->wpa);
1470 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001471#endif /* CONFIG_IEEE80211R */
1472#ifdef CONFIG_DPP
1473 } else if (sel & WPA_KEY_MGMT_DPP) {
1474 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1475 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1476#endif /* CONFIG_DPP */
1477#ifdef CONFIG_SAE
1478 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1479 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1480 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1481 } else if (sel & WPA_KEY_MGMT_SAE) {
1482 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1483 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1484#endif /* CONFIG_SAE */
1485#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001486 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1487 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1488 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1489#endif /* CONFIG_IEEE80211R */
1490#ifdef CONFIG_IEEE80211W
1491 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1492 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1493 wpa_dbg(wpa_s, MSG_DEBUG,
1494 "WPA: using KEY_MGMT 802.1X with SHA256");
1495 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1496 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1497 wpa_dbg(wpa_s, MSG_DEBUG,
1498 "WPA: using KEY_MGMT PSK with SHA256");
1499#endif /* CONFIG_IEEE80211W */
1500 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1501 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1502 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1503 } else if (sel & WPA_KEY_MGMT_PSK) {
1504 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1505 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1506 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1507 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1508 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001509#ifdef CONFIG_HS20
1510 } else if (sel & WPA_KEY_MGMT_OSEN) {
1511 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1512 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1513#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001514#ifdef CONFIG_OWE
1515 } else if (sel & WPA_KEY_MGMT_OWE) {
1516 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1517 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1518#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001519 } else {
1520 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1521 "authenticated key management type");
1522 return -1;
1523 }
1524
1525 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1526 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1527 wpa_s->pairwise_cipher);
1528 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1529
1530#ifdef CONFIG_IEEE80211W
1531 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001532 if (ssid->group_mgmt_cipher)
1533 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001534 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001535 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1536 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001537 wpa_dbg(wpa_s, MSG_DEBUG,
1538 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1539 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001540 if (sel & WPA_CIPHER_AES_128_CMAC) {
1541 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1542 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1543 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001544 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1545 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1546 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1547 "BIP-GMAC-128");
1548 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1549 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1550 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1551 "BIP-GMAC-256");
1552 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1553 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1554 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1555 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001556 } else {
1557 wpa_s->mgmt_group_cipher = 0;
1558 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1559 }
1560 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1561 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001562 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001563 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001564#endif /* CONFIG_IEEE80211W */
Hai Shalom74f70d42019-02-11 14:42:39 -08001565#ifdef CONFIG_OCV
1566 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
1567#endif /* CONFIG_OCV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001568
1569 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1570 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1571 return -1;
1572 }
1573
Hai Shalom021b0b52019-04-10 11:17:58 -07001574 if (0) {
1575#ifdef CONFIG_DPP
1576 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1577 /* Use PMK from DPP network introduction (PMKSA entry) */
1578 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1579#endif /* CONFIG_DPP */
1580 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001581 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001582 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001583
Roshan Pius3a1667e2018-07-03 15:17:14 -07001584 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1585 WPA_KEY_MGMT_FT_PSK |
1586 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1587
1588 if (ssid->psk_set && !sae_only) {
1589 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1590 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001591 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1592 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001593 psk_set = 1;
1594 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001595
Roshan Pius3a1667e2018-07-03 15:17:14 -07001596 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1597 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001598 psk_set = 1;
1599
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001600#ifndef CONFIG_NO_PBKDF2
1601 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001602 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001603 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001604 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1605 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001606 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1607 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001608 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001609 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001610 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001611 }
1612#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001613#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001614 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001615 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1616 ssid->ext_psk);
1617 char pw_str[64 + 1];
1618 u8 psk[PMK_LEN];
1619
1620 if (pw == NULL) {
1621 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1622 "found from external storage");
1623 return -1;
1624 }
1625
1626 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1627 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1628 "PSK length %d in external storage",
1629 (int) wpabuf_len(pw));
1630 ext_password_free(pw);
1631 return -1;
1632 }
1633
1634 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1635 pw_str[wpabuf_len(pw)] = '\0';
1636
1637#ifndef CONFIG_NO_PBKDF2
1638 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1639 {
1640 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1641 4096, psk, PMK_LEN);
1642 os_memset(pw_str, 0, sizeof(pw_str));
1643 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1644 "external passphrase)",
1645 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001646 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1647 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001648 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001649 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001650 } else
1651#endif /* CONFIG_NO_PBKDF2 */
1652 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1653 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1654 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1655 "Invalid PSK hex string");
1656 os_memset(pw_str, 0, sizeof(pw_str));
1657 ext_password_free(pw);
1658 return -1;
1659 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001660 wpa_hexdump_key(MSG_MSGDUMP,
1661 "PSK (from external PSK)",
1662 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001663 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1664 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001665 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001666 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001667 } else {
1668 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1669 "PSK available");
1670 os_memset(pw_str, 0, sizeof(pw_str));
1671 ext_password_free(pw);
1672 return -1;
1673 }
1674
1675 os_memset(pw_str, 0, sizeof(pw_str));
1676 ext_password_free(pw);
1677 }
1678#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001679
1680 if (!psk_set) {
1681 wpa_msg(wpa_s, MSG_INFO,
1682 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001683 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001684 return -1;
1685 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001686#ifdef CONFIG_OWE
1687 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1688 /* OWE Diffie-Hellman exchange in (Re)Association
1689 * Request/Response frames set the PMK, so do not override it
1690 * here. */
1691#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001692 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001693 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1694
1695 return 0;
1696}
1697
1698
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001699static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1700{
1701 *pos = 0x00;
1702
1703 switch (idx) {
1704 case 0: /* Bits 0-7 */
1705 break;
1706 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001707 if (wpa_s->conf->coloc_intf_reporting) {
1708 /* Bit 13 - Collocated Interference Reporting */
1709 *pos |= 0x20;
1710 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001711 break;
1712 case 2: /* Bits 16-23 */
1713#ifdef CONFIG_WNM
1714 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalom81f62d82019-07-22 12:10:00 -07001715 if (!wpa_s->conf->disable_btm)
1716 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001717#endif /* CONFIG_WNM */
1718 break;
1719 case 3: /* Bits 24-31 */
1720#ifdef CONFIG_WNM
1721 *pos |= 0x02; /* Bit 25 - SSID List */
1722#endif /* CONFIG_WNM */
1723#ifdef CONFIG_INTERWORKING
1724 if (wpa_s->conf->interworking)
1725 *pos |= 0x80; /* Bit 31 - Interworking */
1726#endif /* CONFIG_INTERWORKING */
1727 break;
1728 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001729#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001730 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001731 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001732#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001733 break;
1734 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001735#ifdef CONFIG_HS20
1736 if (wpa_s->conf->hs20)
1737 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1738#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001739#ifdef CONFIG_MBO
1740 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1741#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001742 break;
1743 case 6: /* Bits 48-55 */
1744 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001745 case 7: /* Bits 56-63 */
1746 break;
1747 case 8: /* Bits 64-71 */
1748 if (wpa_s->conf->ftm_responder)
1749 *pos |= 0x40; /* Bit 70 - FTM responder */
1750 if (wpa_s->conf->ftm_initiator)
1751 *pos |= 0x80; /* Bit 71 - FTM initiator */
1752 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001753 case 9: /* Bits 72-79 */
1754#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001755 if (!wpa_s->disable_fils)
1756 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001757#endif /* CONFIG_FILS */
1758 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001759 }
1760}
1761
1762
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001763int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001764{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001765 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001766 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001767
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001768 if (len < wpa_s->extended_capa_len)
1769 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001770 if (buflen < (size_t) len + 2) {
1771 wpa_printf(MSG_INFO,
1772 "Not enough room for building extended capabilities element");
1773 return -1;
1774 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001775
1776 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001777 *pos++ = len;
1778 for (i = 0; i < len; i++, pos++) {
1779 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001780
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001781 if (i < wpa_s->extended_capa_len) {
1782 *pos &= ~wpa_s->extended_capa_mask[i];
1783 *pos |= wpa_s->extended_capa[i];
1784 }
1785 }
1786
1787 while (len > 0 && buf[1 + len] == 0) {
1788 len--;
1789 buf[1] = len;
1790 }
1791 if (len == 0)
1792 return 0;
1793
1794 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001795}
1796
1797
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001798static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1799 struct wpa_bss *test_bss)
1800{
1801 struct wpa_bss *bss;
1802
1803 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1804 if (bss == test_bss)
1805 return 1;
1806 }
1807
1808 return 0;
1809}
1810
1811
1812static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1813 struct wpa_ssid *test_ssid)
1814{
1815 struct wpa_ssid *ssid;
1816
1817 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1818 if (ssid == test_ssid)
1819 return 1;
1820 }
1821
1822 return 0;
1823}
1824
1825
1826int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1827 struct wpa_ssid *test_ssid)
1828{
1829 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1830 return 0;
1831
1832 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1833}
1834
1835
1836void wpas_connect_work_free(struct wpa_connect_work *cwork)
1837{
1838 if (cwork == NULL)
1839 return;
1840 os_free(cwork);
1841}
1842
1843
1844void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1845{
1846 struct wpa_connect_work *cwork;
1847 struct wpa_radio_work *work = wpa_s->connect_work;
1848
1849 if (!work)
1850 return;
1851
1852 wpa_s->connect_work = NULL;
1853 cwork = work->ctx;
1854 work->ctx = NULL;
1855 wpas_connect_work_free(cwork);
1856 radio_work_done(work);
1857}
1858
1859
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001860int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1861{
1862 struct os_reltime now;
1863 u8 addr[ETH_ALEN];
1864
1865 os_get_reltime(&now);
1866 if (wpa_s->last_mac_addr_style == style &&
1867 wpa_s->last_mac_addr_change.sec != 0 &&
1868 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1869 wpa_s->conf->rand_addr_lifetime)) {
1870 wpa_msg(wpa_s, MSG_DEBUG,
1871 "Previously selected random MAC address has not yet expired");
1872 return 0;
1873 }
1874
1875 switch (style) {
1876 case 1:
1877 if (random_mac_addr(addr) < 0)
1878 return -1;
1879 break;
1880 case 2:
1881 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1882 if (random_mac_addr_keep_oui(addr) < 0)
1883 return -1;
1884 break;
1885 default:
1886 return -1;
1887 }
1888
1889 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1890 wpa_msg(wpa_s, MSG_INFO,
1891 "Failed to set random MAC address");
1892 return -1;
1893 }
1894
1895 os_get_reltime(&wpa_s->last_mac_addr_change);
1896 wpa_s->mac_addr_changed = 1;
1897 wpa_s->last_mac_addr_style = style;
1898
1899 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1900 wpa_msg(wpa_s, MSG_INFO,
1901 "Could not update MAC address information");
1902 return -1;
1903 }
1904
1905 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1906 MAC2STR(addr));
1907
1908 return 0;
1909}
1910
1911
1912int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1913{
1914 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1915 !wpa_s->conf->preassoc_mac_addr)
1916 return 0;
1917
1918 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1919}
1920
1921
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001922static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1923
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001924/**
1925 * wpa_supplicant_associate - Request association
1926 * @wpa_s: Pointer to wpa_supplicant data
1927 * @bss: Scan results for the selected BSS, or %NULL if not available
1928 * @ssid: Configuration data for the selected network
1929 *
1930 * This function is used to request %wpa_supplicant to associate with a BSS.
1931 */
1932void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1933 struct wpa_bss *bss, struct wpa_ssid *ssid)
1934{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001935 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001936 int rand_style;
1937
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001938 wpa_s->own_disconnect_req = 0;
1939
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001940 /*
1941 * If we are starting a new connection, any previously pending EAPOL
1942 * RX cannot be valid anymore.
1943 */
1944 wpabuf_free(wpa_s->pending_eapol_rx);
1945 wpa_s->pending_eapol_rx = NULL;
1946
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001947 if (ssid->mac_addr == -1)
1948 rand_style = wpa_s->conf->mac_addr;
1949 else
1950 rand_style = ssid->mac_addr;
1951
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001952 wmm_ac_clear_saved_tspecs(wpa_s);
1953 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001954 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001955#ifdef CONFIG_TESTING_OPTIONS
1956 wpa_s->testing_resend_assoc = 0;
1957#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001958
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001959 if (wpa_s->last_ssid == ssid) {
1960 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001961 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001962 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1963 wmm_ac_save_tspecs(wpa_s);
1964 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08001965 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
1966 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001967 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001968 }
1969
1970 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001971 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1972 return;
1973 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001974 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001975 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1976 wpa_msg(wpa_s, MSG_INFO,
1977 "Could not restore permanent MAC address");
1978 return;
1979 }
1980 wpa_s->mac_addr_changed = 0;
1981 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1982 wpa_msg(wpa_s, MSG_INFO,
1983 "Could not update MAC address information");
1984 return;
1985 }
1986 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1987 }
1988 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001989
1990#ifdef CONFIG_IBSS_RSN
1991 ibss_rsn_deinit(wpa_s->ibss_rsn);
1992 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001993#else /* CONFIG_IBSS_RSN */
1994 if (ssid->mode == WPAS_MODE_IBSS &&
1995 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1996 wpa_msg(wpa_s, MSG_INFO,
1997 "IBSS RSN not supported in the build");
1998 return;
1999 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002000#endif /* CONFIG_IBSS_RSN */
2001
2002 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2003 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2004#ifdef CONFIG_AP
2005 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2006 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2007 "mode");
2008 return;
2009 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002010 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2011 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002012 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2013 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002014 return;
2015 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002016 wpa_s->current_bss = bss;
2017#else /* CONFIG_AP */
2018 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2019 "the build");
2020#endif /* CONFIG_AP */
2021 return;
2022 }
2023
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002024 if (ssid->mode == WPAS_MODE_MESH) {
2025#ifdef CONFIG_MESH
2026 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2027 wpa_msg(wpa_s, MSG_INFO,
2028 "Driver does not support mesh mode");
2029 return;
2030 }
2031 if (bss)
2032 ssid->frequency = bss->freq;
2033 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2034 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2035 return;
2036 }
2037 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002038 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
2039 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
2040 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002041 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002042#else /* CONFIG_MESH */
2043 wpa_msg(wpa_s, MSG_ERROR,
2044 "mesh mode support not included in the build");
2045#endif /* CONFIG_MESH */
2046 return;
2047 }
2048
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002049 /*
2050 * Set WPA state machine configuration to match the selected network now
2051 * so that the information is available before wpas_start_assoc_cb()
2052 * gets called. This is needed at least for RSN pre-authentication where
2053 * candidate APs are added to a list based on scan result processing
2054 * before completion of the first association.
2055 */
2056 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2057
2058#ifdef CONFIG_DPP
2059 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2060 return;
2061#endif /* CONFIG_DPP */
2062
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002063#ifdef CONFIG_TDLS
2064 if (bss)
2065 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2066 bss->ie_len);
2067#endif /* CONFIG_TDLS */
2068
2069 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002070 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002071 sme_authenticate(wpa_s, bss, ssid);
2072 return;
2073 }
2074
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002075 if (wpa_s->connect_work) {
2076 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2077 return;
2078 }
2079
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002080 if (radio_work_pending(wpa_s, "connect")) {
2081 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2082 return;
2083 }
2084
Dmitry Shmidt29333592017-01-09 12:27:11 -08002085#ifdef CONFIG_SME
2086 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2087 /* Clear possibly set auth_alg, if any, from last attempt. */
2088 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2089 }
2090#endif /* CONFIG_SME */
2091
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002092 wpas_abort_ongoing_scan(wpa_s);
2093
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002094 cwork = os_zalloc(sizeof(*cwork));
2095 if (cwork == NULL)
2096 return;
2097
2098 cwork->bss = bss;
2099 cwork->ssid = ssid;
2100
2101 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2102 wpas_start_assoc_cb, cwork) < 0) {
2103 os_free(cwork);
2104 }
2105}
2106
2107
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002108static int bss_is_ibss(struct wpa_bss *bss)
2109{
2110 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2111 IEEE80211_CAP_IBSS;
2112}
2113
2114
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002115static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2116 const struct wpa_ssid *ssid)
2117{
2118 enum hostapd_hw_mode hw_mode;
2119 struct hostapd_hw_modes *mode = NULL;
2120 u8 channel;
2121 int i;
2122
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002123 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2124 if (hw_mode == NUM_HOSTAPD_MODES)
2125 return 0;
2126 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2127 if (wpa_s->hw.modes[i].mode == hw_mode) {
2128 mode = &wpa_s->hw.modes[i];
2129 break;
2130 }
2131 }
2132
2133 if (!mode)
2134 return 0;
2135
2136 return mode->vht_capab != 0;
2137}
2138
2139
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002140void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2141 const struct wpa_ssid *ssid,
2142 struct hostapd_freq_params *freq)
2143{
Hai Shalom81f62d82019-07-22 12:10:00 -07002144 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002145 enum hostapd_hw_mode hw_mode;
2146 struct hostapd_hw_modes *mode = NULL;
2147 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2148 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002149 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002150 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2151 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002152 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002153 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002154 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002155 int chwidth, seg0, seg1;
2156 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002157
2158 freq->freq = ssid->frequency;
2159
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002160 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2161 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2162
2163 if (ssid->mode != WPAS_MODE_IBSS)
2164 break;
2165
2166 /* Don't adjust control freq in case of fixed_freq */
2167 if (ssid->fixed_freq)
2168 break;
2169
2170 if (!bss_is_ibss(bss))
2171 continue;
2172
2173 if (ssid->ssid_len == bss->ssid_len &&
2174 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2175 wpa_printf(MSG_DEBUG,
2176 "IBSS already found in scan results, adjust control freq: %d",
2177 bss->freq);
2178 freq->freq = bss->freq;
2179 obss_scan = 0;
2180 break;
2181 }
2182 }
2183
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002184 /* For IBSS check HT_IBSS flag */
2185 if (ssid->mode == WPAS_MODE_IBSS &&
2186 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2187 return;
2188
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002189 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2190 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2191 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2192 wpa_printf(MSG_DEBUG,
2193 "IBSS: WEP/TKIP detected, do not try to enable HT");
2194 return;
2195 }
2196
2197 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002198 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2199 if (wpa_s->hw.modes[i].mode == hw_mode) {
2200 mode = &wpa_s->hw.modes[i];
2201 break;
2202 }
2203 }
2204
2205 if (!mode)
2206 return;
2207
Hai Shalom81f62d82019-07-22 12:10:00 -07002208 /* HE can work without HT + VHT */
2209 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
2210
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002211#ifdef CONFIG_HT_OVERRIDES
2212 if (ssid->disable_ht) {
2213 freq->ht_enabled = 0;
2214 return;
2215 }
2216#endif /* CONFIG_HT_OVERRIDES */
2217
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002218 freq->ht_enabled = ht_supported(mode);
2219 if (!freq->ht_enabled)
2220 return;
2221
2222 /* Setup higher BW only for 5 GHz */
2223 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2224 return;
2225
2226 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2227 pri_chan = &mode->channels[chan_idx];
2228 if (pri_chan->chan == channel)
2229 break;
2230 pri_chan = NULL;
2231 }
2232 if (!pri_chan)
2233 return;
2234
2235 /* Check primary channel flags */
2236 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2237 return;
2238
Hai Shalom74f70d42019-02-11 14:42:39 -08002239 freq->channel = pri_chan->chan;
2240
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002241#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002242 if (ssid->disable_ht40) {
2243 if (ssid->disable_vht)
2244 return;
2245 goto skip_ht40;
2246 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002247#endif /* CONFIG_HT_OVERRIDES */
2248
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002249 /* Check/setup HT40+/HT40- */
2250 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2251 if (ht40plus[j] == channel) {
2252 ht40 = 1;
2253 break;
2254 }
2255 }
2256
2257 /* Find secondary channel */
2258 for (i = 0; i < mode->num_channels; i++) {
2259 sec_chan = &mode->channels[i];
2260 if (sec_chan->chan == channel + ht40 * 4)
2261 break;
2262 sec_chan = NULL;
2263 }
2264 if (!sec_chan)
2265 return;
2266
2267 /* Check secondary channel flags */
2268 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2269 return;
2270
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002271 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002272 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2273 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002274 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002275 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2276 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002277 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002278 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002279
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002280 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002281 struct wpa_scan_results *scan_res;
2282
2283 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2284 if (scan_res == NULL) {
2285 /* Back to HT20 */
2286 freq->sec_channel_offset = 0;
2287 return;
2288 }
2289
2290 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2291 sec_chan->chan);
2292 switch (res) {
2293 case 0:
2294 /* Back to HT20 */
2295 freq->sec_channel_offset = 0;
2296 break;
2297 case 1:
2298 /* Configuration allowed */
2299 break;
2300 case 2:
2301 /* Switch pri/sec channels */
2302 freq->freq = hw_get_freq(mode, sec_chan->chan);
2303 freq->sec_channel_offset = -freq->sec_channel_offset;
2304 freq->channel = sec_chan->chan;
2305 break;
2306 default:
2307 freq->sec_channel_offset = 0;
2308 break;
2309 }
2310
2311 wpa_scan_results_free(scan_res);
2312 }
2313
Hai Shalom74f70d42019-02-11 14:42:39 -08002314#ifdef CONFIG_HT_OVERRIDES
2315skip_ht40:
2316#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002317 wpa_printf(MSG_DEBUG,
2318 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2319 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002320
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002321 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002322 return;
2323
2324 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002325 if (ssid->mode == WPAS_MODE_IBSS &&
2326 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002327 return;
2328
2329 vht_freq = *freq;
2330
Paul Stewart092955c2017-02-06 09:13:09 -08002331#ifdef CONFIG_VHT_OVERRIDES
2332 if (ssid->disable_vht) {
2333 freq->vht_enabled = 0;
2334 return;
2335 }
2336#endif /* CONFIG_VHT_OVERRIDES */
2337
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002338 vht_freq.vht_enabled = vht_supported(mode);
2339 if (!vht_freq.vht_enabled)
2340 return;
2341
2342 /* setup center_freq1, bandwidth */
2343 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2344 if (freq->channel >= vht80[j] &&
2345 freq->channel < vht80[j] + 16)
2346 break;
2347 }
2348
2349 if (j == ARRAY_SIZE(vht80))
2350 return;
2351
2352 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2353 struct hostapd_channel_data *chan;
2354
2355 chan = hw_get_channel_chan(mode, i, NULL);
2356 if (!chan)
2357 return;
2358
2359 /* Back to HT configuration if channel not usable */
2360 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2361 return;
2362 }
2363
Hai Shalom81f62d82019-07-22 12:10:00 -07002364 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002365 seg0 = vht80[j] + 6;
2366 seg1 = 0;
2367
Hai Shalom81f62d82019-07-22 12:10:00 -07002368 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002369 /* setup center_freq2, bandwidth */
2370 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2371 /* Only accept 80 MHz segments separated by a gap */
2372 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2373 continue;
2374 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2375 struct hostapd_channel_data *chan;
2376
2377 chan = hw_get_channel_chan(mode, i, NULL);
2378 if (!chan)
2379 continue;
2380
2381 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2382 HOSTAPD_CHAN_NO_IR |
2383 HOSTAPD_CHAN_RADAR))
2384 continue;
2385
2386 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002387 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002388 vht_caps |=
2389 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2390 seg1 = vht80[k] + 6;
2391 }
2392
Hai Shalom81f62d82019-07-22 12:10:00 -07002393 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002394 break;
2395 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002396 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002397 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002398 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002399 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2400 seg0 = 50;
2401 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002402 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002403 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2404 seg0 = 114;
2405 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002406 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2407 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002408 seg0 = vht80[j] + 2;
2409#ifdef CONFIG_HT_OVERRIDES
2410 if (ssid->disable_ht40)
2411 seg0 = 0;
2412#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002413 }
2414
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002415 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2416 freq->channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002417 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002418 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002419 chwidth, seg0, seg1, vht_caps,
2420 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002421 return;
2422
2423 *freq = vht_freq;
2424
2425 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2426 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002427}
2428
2429
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002430#ifdef CONFIG_FILS
2431static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2432 size_t ie_buf_len)
2433{
2434 struct fils_hlp_req *req;
2435 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2436 const u8 *pos;
2437 u8 *buf = ie_buf;
2438
2439 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2440 list) {
2441 rem_len = ie_buf_len - ie_len;
2442 pos = wpabuf_head(req->pkt);
2443 hdr_len = 1 + 2 * ETH_ALEN + 6;
2444 hlp_len = wpabuf_len(req->pkt);
2445
2446 if (rem_len < 2 + hdr_len + hlp_len) {
2447 wpa_printf(MSG_ERROR,
2448 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2449 (unsigned long) rem_len,
2450 (unsigned long) (2 + hdr_len + hlp_len));
2451 break;
2452 }
2453
2454 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2455 /* Element ID */
2456 *buf++ = WLAN_EID_EXTENSION;
2457 /* Length */
2458 *buf++ = len;
2459 /* Element ID Extension */
2460 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2461 /* Destination MAC address */
2462 os_memcpy(buf, req->dst, ETH_ALEN);
2463 buf += ETH_ALEN;
2464 /* Source MAC address */
2465 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2466 buf += ETH_ALEN;
2467 /* LLC/SNAP Header */
2468 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2469 buf += 6;
2470 /* HLP Packet */
2471 os_memcpy(buf, pos, len - hdr_len);
2472 buf += len - hdr_len;
2473 pos += len - hdr_len;
2474
2475 hlp_len -= len - hdr_len;
2476 ie_len += 2 + len;
2477 rem_len -= 2 + len;
2478
2479 while (hlp_len) {
2480 len = (hlp_len > 255) ? 255 : hlp_len;
2481 if (rem_len < 2 + len)
2482 break;
2483 *buf++ = WLAN_EID_FRAGMENT;
2484 *buf++ = len;
2485 os_memcpy(buf, pos, len);
2486 buf += len;
2487 pos += len;
2488
2489 hlp_len -= len;
2490 ie_len += 2 + len;
2491 rem_len -= 2 + len;
2492 }
2493 }
2494
2495 return ie_len;
2496}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002497
2498
2499int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2500{
2501 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2502 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2503 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2504 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2505}
2506
2507
2508int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2509{
2510#ifdef CONFIG_FILS_SK_PFS
2511 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2512 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2513#else /* CONFIG_FILS_SK_PFS */
2514 return 0;
2515#endif /* CONFIG_FILS_SK_PFS */
2516}
2517
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002518#endif /* CONFIG_FILS */
2519
2520
2521static u8 * wpas_populate_assoc_ies(
2522 struct wpa_supplicant *wpa_s,
2523 struct wpa_bss *bss, struct wpa_ssid *ssid,
2524 struct wpa_driver_associate_params *params,
2525 enum wpa_drv_update_connect_params_mask *mask)
2526{
2527 u8 *wpa_ie;
2528 size_t max_wpa_ie_len = 500;
2529 size_t wpa_ie_len;
2530 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002531#ifdef CONFIG_MBO
2532 const u8 *mbo_ie;
2533#endif
Hai Shalom5f92bc92019-04-18 11:54:11 -07002534#ifdef CONFIG_SAE
2535 int sae_pmksa_cached = 0;
2536#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002537#ifdef CONFIG_FILS
2538 const u8 *realm, *username, *rrk;
2539 size_t realm_len, username_len, rrk_len;
2540 u16 next_seq_num;
2541 struct fils_hlp_req *req;
2542
2543 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2544 list) {
2545 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2546 2 + 2 * wpabuf_len(req->pkt) / 255;
2547 }
2548#endif /* CONFIG_FILS */
2549
2550 wpa_ie = os_malloc(max_wpa_ie_len);
2551 if (!wpa_ie) {
2552 wpa_printf(MSG_ERROR,
2553 "Failed to allocate connect IE buffer for %lu bytes",
2554 (unsigned long) max_wpa_ie_len);
2555 return NULL;
2556 }
2557
2558 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2559 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2560 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2561 int try_opportunistic;
2562 const u8 *cache_id = NULL;
2563
2564 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2565 wpa_s->conf->okc :
2566 ssid->proactive_key_caching) &&
2567 (ssid->proto & WPA_PROTO_RSN);
2568#ifdef CONFIG_FILS
2569 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2570 cache_id = wpa_bss_get_fils_cache_id(bss);
2571#endif /* CONFIG_FILS */
2572 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2573 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002574 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002575 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Hai Shalom5f92bc92019-04-18 11:54:11 -07002576#ifdef CONFIG_SAE
2577 sae_pmksa_cached = 1;
2578#endif /* CONFIG_SAE */
2579 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002580 wpa_ie_len = max_wpa_ie_len;
2581 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2582 wpa_ie, &wpa_ie_len)) {
2583 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2584 "key management and encryption suites");
2585 os_free(wpa_ie);
2586 return NULL;
2587 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002588#ifdef CONFIG_HS20
2589 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2590 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2591 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2592 wpa_ie_len = max_wpa_ie_len;
2593 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2594 wpa_ie, &wpa_ie_len)) {
2595 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2596 "key management and encryption suites");
2597 os_free(wpa_ie);
2598 return NULL;
2599 }
2600#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002601 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2602 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2603 /*
2604 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2605 * use non-WPA since the scan results did not indicate that the
2606 * AP is using WPA or WPA2.
2607 */
2608 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2609 wpa_ie_len = 0;
2610 wpa_s->wpa_proto = 0;
2611 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2612 wpa_ie_len = max_wpa_ie_len;
2613 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2614 wpa_ie, &wpa_ie_len)) {
2615 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2616 "key management and encryption suites (no "
2617 "scan results)");
2618 os_free(wpa_ie);
2619 return NULL;
2620 }
2621#ifdef CONFIG_WPS
2622 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2623 struct wpabuf *wps_ie;
2624 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2625 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2626 wpa_ie_len = wpabuf_len(wps_ie);
2627 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2628 } else
2629 wpa_ie_len = 0;
2630 wpabuf_free(wps_ie);
2631 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2632 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2633 params->wps = WPS_MODE_PRIVACY;
2634 else
2635 params->wps = WPS_MODE_OPEN;
2636 wpa_s->wpa_proto = 0;
2637#endif /* CONFIG_WPS */
2638 } else {
2639 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2640 wpa_ie_len = 0;
2641 wpa_s->wpa_proto = 0;
2642 }
2643
2644#ifdef IEEE8021X_EAPOL
2645 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2646 if (ssid->leap) {
2647 if (ssid->non_leap == 0)
2648 algs = WPA_AUTH_ALG_LEAP;
2649 else
2650 algs |= WPA_AUTH_ALG_LEAP;
2651 }
2652 }
2653
2654#ifdef CONFIG_FILS
2655 /* Clear FILS association */
2656 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2657
2658 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2659 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2660 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2661 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002662 &next_seq_num, &rrk, &rrk_len) == 0 &&
2663 (!wpa_s->last_con_fail_realm ||
2664 wpa_s->last_con_fail_realm_len != realm_len ||
2665 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002666 algs = WPA_AUTH_ALG_FILS;
2667 params->fils_erp_username = username;
2668 params->fils_erp_username_len = username_len;
2669 params->fils_erp_realm = realm;
2670 params->fils_erp_realm_len = realm_len;
2671 params->fils_erp_next_seq_num = next_seq_num;
2672 params->fils_erp_rrk = rrk;
2673 params->fils_erp_rrk_len = rrk_len;
2674
2675 if (mask)
2676 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2677 }
2678#endif /* CONFIG_FILS */
2679#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002680#ifdef CONFIG_SAE
2681 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2682 algs = WPA_AUTH_ALG_SAE;
2683#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002684
2685 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2686 if (ssid->auth_alg) {
2687 algs = ssid->auth_alg;
2688 wpa_dbg(wpa_s, MSG_DEBUG,
2689 "Overriding auth_alg selection: 0x%x", algs);
2690 }
2691
Hai Shalom5f92bc92019-04-18 11:54:11 -07002692#ifdef CONFIG_SAE
2693 if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
2694 wpa_dbg(wpa_s, MSG_DEBUG,
2695 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2696 algs = WPA_AUTH_ALG_OPEN;
2697 }
2698#endif /* CONFIG_SAE */
2699
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002700#ifdef CONFIG_P2P
2701 if (wpa_s->global->p2p) {
2702 u8 *pos;
2703 size_t len;
2704 int res;
2705 pos = wpa_ie + wpa_ie_len;
2706 len = max_wpa_ie_len - wpa_ie_len;
2707 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2708 ssid->p2p_group);
2709 if (res >= 0)
2710 wpa_ie_len += res;
2711 }
2712
2713 wpa_s->cross_connect_disallowed = 0;
2714 if (bss) {
2715 struct wpabuf *p2p;
2716 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2717 if (p2p) {
2718 wpa_s->cross_connect_disallowed =
2719 p2p_get_cross_connect_disallowed(p2p);
2720 wpabuf_free(p2p);
2721 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2722 "connection",
2723 wpa_s->cross_connect_disallowed ?
2724 "disallows" : "allows");
2725 }
2726 }
2727
2728 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2729#endif /* CONFIG_P2P */
2730
2731 if (bss) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002732 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002733 wpa_ie + wpa_ie_len,
2734 max_wpa_ie_len -
2735 wpa_ie_len);
2736 }
2737
2738 /*
2739 * Workaround: Add Extended Capabilities element only if the AP
2740 * included this element in Beacon/Probe Response frames. Some older
2741 * APs seem to have interoperability issues if this element is
2742 * included, so while the standard may require us to include the
2743 * element in all cases, it is justifiable to skip it to avoid
2744 * interoperability issues.
2745 */
2746 if (ssid->p2p_group)
2747 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2748 else
2749 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2750
2751 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2752 u8 ext_capab[18];
2753 int ext_capab_len;
2754 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2755 sizeof(ext_capab));
2756 if (ext_capab_len > 0 &&
2757 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2758 u8 *pos = wpa_ie;
2759 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2760 pos += 2 + pos[1];
2761 os_memmove(pos + ext_capab_len, pos,
2762 wpa_ie_len - (pos - wpa_ie));
2763 wpa_ie_len += ext_capab_len;
2764 os_memcpy(pos, ext_capab, ext_capab_len);
2765 }
2766 }
2767
2768#ifdef CONFIG_HS20
2769 if (is_hs20_network(wpa_s, ssid, bss)) {
2770 struct wpabuf *hs20;
2771
Roshan Pius3a1667e2018-07-03 15:17:14 -07002772 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002773 if (hs20) {
2774 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2775 size_t len;
2776
Hai Shalom74f70d42019-02-11 14:42:39 -08002777 wpas_hs20_add_indication(hs20, pps_mo_id,
2778 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002779 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002780 len = max_wpa_ie_len - wpa_ie_len;
2781 if (wpabuf_len(hs20) <= len) {
2782 os_memcpy(wpa_ie + wpa_ie_len,
2783 wpabuf_head(hs20), wpabuf_len(hs20));
2784 wpa_ie_len += wpabuf_len(hs20);
2785 }
2786 wpabuf_free(hs20);
2787
2788 hs20_configure_frame_filters(wpa_s);
2789 }
2790 }
2791#endif /* CONFIG_HS20 */
2792
2793 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2794 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2795 size_t len;
2796
2797 len = max_wpa_ie_len - wpa_ie_len;
2798 if (wpabuf_len(buf) <= len) {
2799 os_memcpy(wpa_ie + wpa_ie_len,
2800 wpabuf_head(buf), wpabuf_len(buf));
2801 wpa_ie_len += wpabuf_len(buf);
2802 }
2803 }
2804
2805#ifdef CONFIG_FST
2806 if (wpa_s->fst_ies) {
2807 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2808
2809 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
2810 os_memcpy(wpa_ie + wpa_ie_len,
2811 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2812 wpa_ie_len += fst_ies_len;
2813 }
2814 }
2815#endif /* CONFIG_FST */
2816
2817#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07002818 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
2819 if (mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002820 int len;
2821
2822 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002823 max_wpa_ie_len - wpa_ie_len,
2824 !!mbo_attr_from_mbo_ie(mbo_ie,
2825 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002826 if (len >= 0)
2827 wpa_ie_len += len;
2828 }
2829#endif /* CONFIG_MBO */
2830
2831#ifdef CONFIG_FILS
2832 if (algs == WPA_AUTH_ALG_FILS) {
2833 size_t len;
2834
2835 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
2836 max_wpa_ie_len - wpa_ie_len);
2837 wpa_ie_len += len;
2838 }
2839#endif /* CONFIG_FILS */
2840
2841#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002842#ifdef CONFIG_TESTING_OPTIONS
2843 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
2844 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2845 } else
2846#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002847 if (algs == WPA_AUTH_ALG_OPEN &&
2848 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
2849 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002850 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002851
Roshan Pius3a1667e2018-07-03 15:17:14 -07002852 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002853 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08002854 } else if (wpa_s->assoc_status_code ==
2855 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002856 if (wpa_s->last_owe_group == 19)
2857 group = 20;
2858 else if (wpa_s->last_owe_group == 20)
2859 group = 21;
2860 else
2861 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002862 } else {
2863 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002864 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002865
Roshan Pius3a1667e2018-07-03 15:17:14 -07002866 wpa_s->last_owe_group = group;
2867 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002868 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2869 if (owe_ie &&
2870 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
2871 os_memcpy(wpa_ie + wpa_ie_len,
2872 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2873 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002874 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002875 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002876 }
2877#endif /* CONFIG_OWE */
2878
Hai Shalom021b0b52019-04-10 11:17:58 -07002879#ifdef CONFIG_DPP2
2880 if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
2881 ssid->dpp_netaccesskey) {
2882 dpp_pfs_free(wpa_s->dpp_pfs);
2883 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
2884 ssid->dpp_netaccesskey_len);
2885 if (!wpa_s->dpp_pfs) {
2886 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
2887 /* Try to continue without PFS */
2888 goto pfs_fail;
2889 }
2890 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
2891 max_wpa_ie_len - wpa_ie_len) {
2892 os_memcpy(wpa_ie + wpa_ie_len,
2893 wpabuf_head(wpa_s->dpp_pfs->ie),
2894 wpabuf_len(wpa_s->dpp_pfs->ie));
2895 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
2896 }
2897 }
2898pfs_fail:
2899#endif /* CONFIG_DPP2 */
2900
Roshan Pius3a1667e2018-07-03 15:17:14 -07002901#ifdef CONFIG_IEEE80211R
2902 /*
2903 * Add MDIE under these conditions: the network profile allows FT,
2904 * the AP supports FT, and the mobility domain ID matches.
2905 */
2906 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
2907 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2908
2909 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
2910 size_t len = 0;
2911 const u8 *md = mdie + 2;
2912 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
2913
2914 if (os_memcmp(md, wpa_md,
2915 MOBILITY_DOMAIN_ID_LEN) == 0) {
2916 /* Add mobility domain IE */
2917 len = wpa_ft_add_mdie(
2918 wpa_s->wpa, wpa_ie + wpa_ie_len,
2919 max_wpa_ie_len - wpa_ie_len, mdie);
2920 wpa_ie_len += len;
2921 }
2922#ifdef CONFIG_SME
2923 if (len > 0 && wpa_s->sme.ft_used &&
2924 wpa_sm_has_ptk(wpa_s->wpa)) {
2925 wpa_dbg(wpa_s, MSG_DEBUG,
2926 "SME: Trying to use FT over-the-air");
2927 algs |= WPA_AUTH_ALG_FT;
2928 }
2929#endif /* CONFIG_SME */
2930 }
2931 }
2932#endif /* CONFIG_IEEE80211R */
2933
Hai Shalom74f70d42019-02-11 14:42:39 -08002934 if (ssid->multi_ap_backhaul_sta) {
2935 size_t multi_ap_ie_len;
2936
2937 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
2938 max_wpa_ie_len - wpa_ie_len,
2939 MULTI_AP_BACKHAUL_STA);
2940 if (multi_ap_ie_len == 0) {
2941 wpa_printf(MSG_ERROR,
2942 "Multi-AP: Failed to build Multi-AP IE");
2943 os_free(wpa_ie);
2944 return NULL;
2945 }
2946 wpa_ie_len += multi_ap_ie_len;
2947 }
2948
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002949 params->wpa_ie = wpa_ie;
2950 params->wpa_ie_len = wpa_ie_len;
2951 params->auth_alg = algs;
2952 if (mask)
2953 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
2954
2955 return wpa_ie;
2956}
2957
2958
2959#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
2960static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
2961{
2962 struct wpa_driver_associate_params params;
2963 enum wpa_drv_update_connect_params_mask mask = 0;
2964 u8 *wpa_ie;
2965
2966 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
2967 return; /* nothing to do */
2968
2969 os_memset(&params, 0, sizeof(params));
2970 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
2971 wpa_s->current_ssid, &params, &mask);
2972 if (!wpa_ie)
2973 return;
2974
2975 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
2976 os_free(wpa_ie);
2977 return;
2978 }
2979
2980 wpa_s->auth_alg = params.auth_alg;
2981 wpa_drv_update_connect_params(wpa_s, &params, mask);
2982 os_free(wpa_ie);
2983}
2984#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
2985
2986
Hai Shalom021b0b52019-04-10 11:17:58 -07002987#ifdef CONFIG_MBO
2988void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
2989{
2990 struct wpa_driver_associate_params params;
2991 u8 *wpa_ie;
2992
2993 /*
2994 * Update MBO connect params only in case of change of MBO attributes
2995 * when connected, if the AP support MBO.
2996 */
2997
2998 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
2999 !wpa_s->current_bss ||
3000 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3001 return;
3002
3003 os_memset(&params, 0, sizeof(params));
3004 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3005 wpa_s->current_ssid, &params, NULL);
3006 if (!wpa_ie)
3007 return;
3008
3009 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3010 os_free(wpa_ie);
3011}
3012#endif /* CONFIG_MBO */
3013
3014
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003015static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3016{
3017 struct wpa_connect_work *cwork = work->ctx;
3018 struct wpa_bss *bss = cwork->bss;
3019 struct wpa_ssid *ssid = cwork->ssid;
3020 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003021 u8 *wpa_ie;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003022 int use_crypt, ret, i, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003023 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003024 struct wpa_driver_associate_params params;
3025 int wep_keys_set = 0;
3026 int assoc_failed = 0;
3027 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003028 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003029#ifdef CONFIG_HT_OVERRIDES
3030 struct ieee80211_ht_capabilities htcaps;
3031 struct ieee80211_ht_capabilities htcaps_mask;
3032#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003033#ifdef CONFIG_VHT_OVERRIDES
3034 struct ieee80211_vht_capabilities vhtcaps;
3035 struct ieee80211_vht_capabilities vhtcaps_mask;
3036#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003037
3038 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003039 if (work->started) {
3040 wpa_s->connect_work = NULL;
3041
3042 /* cancel possible auth. timeout */
3043 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3044 NULL);
3045 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003046 wpas_connect_work_free(cwork);
3047 return;
3048 }
3049
3050 wpa_s->connect_work = work;
3051
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003052 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3053 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003054 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3055 wpas_connect_work_done(wpa_s);
3056 return;
3057 }
3058
Dmitry Shmidte4663042016-04-04 10:07:49 -07003059 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003060 os_memset(&params, 0, sizeof(params));
3061 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003062 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003063 if (bss &&
3064 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003065#ifdef CONFIG_IEEE80211R
3066 const u8 *ie, *md = NULL;
3067#endif /* CONFIG_IEEE80211R */
3068 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3069 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3070 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3071 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3072 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3073 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3074 if (bssid_changed)
3075 wpas_notify_bssid_changed(wpa_s);
3076#ifdef CONFIG_IEEE80211R
3077 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3078 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3079 md = ie + 2;
3080 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3081 if (md) {
3082 /* Prepare for the next transition */
3083 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3084 }
3085#endif /* CONFIG_IEEE80211R */
3086#ifdef CONFIG_WPS
3087 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3088 wpa_s->conf->ap_scan == 2 &&
3089 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3090 /* Use ap_scan==1 style network selection to find the network
3091 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003092 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003093 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003094 wpa_s->reassociate = 1;
3095 wpa_supplicant_req_scan(wpa_s, 0, 0);
3096 return;
3097#endif /* CONFIG_WPS */
3098 } else {
3099 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3100 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003101 if (bss)
3102 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3103 else
3104 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003105 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003106 if (!wpa_s->pno)
3107 wpa_supplicant_cancel_sched_scan(wpa_s);
3108
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003109 wpa_supplicant_cancel_scan(wpa_s);
3110
3111 /* Starting new association, so clear the possibly used WPA IE from the
3112 * previous association. */
3113 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
3114
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003115 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3116 if (!wpa_ie) {
3117 wpas_connect_work_done(wpa_s);
3118 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003119 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003120
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003121 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3122 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003123 cipher_pairwise = wpa_s->pairwise_cipher;
3124 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003125 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003126 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3127 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3128 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3129 use_crypt = 0;
3130 if (wpa_set_wep_keys(wpa_s, ssid)) {
3131 use_crypt = 1;
3132 wep_keys_set = 1;
3133 }
3134 }
3135 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3136 use_crypt = 0;
3137
3138#ifdef IEEE8021X_EAPOL
3139 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3140 if ((ssid->eapol_flags &
3141 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3142 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3143 !wep_keys_set) {
3144 use_crypt = 0;
3145 } else {
3146 /* Assume that dynamic WEP-104 keys will be used and
3147 * set cipher suites in order for drivers to expect
3148 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003149 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003150 }
3151 }
3152#endif /* IEEE8021X_EAPOL */
3153
3154 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3155 /* Set the key before (and later after) association */
3156 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3157 }
3158
3159 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3160 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003161 params.ssid = bss->ssid;
3162 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003163 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3164 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003165 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3166 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003167 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003168 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003169 ssid->bssid_set,
3170 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003171 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003172 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003173 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003174 params.bssid_hint = bss->bssid;
3175 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003176 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003177 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003178 if (ssid->bssid_hint_set)
3179 params.bssid_hint = ssid->bssid_hint;
3180
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003181 params.ssid = ssid->ssid;
3182 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003183 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003184 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003185
3186 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3187 wpa_s->conf->ap_scan == 2) {
3188 params.bssid = ssid->bssid;
3189 params.fixed_bssid = 1;
3190 }
3191
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003192 /* Initial frequency for IBSS/mesh */
3193 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003194 ssid->frequency > 0 && params.freq.freq == 0)
3195 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003196
3197 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003198 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003199 if (ssid->beacon_int)
3200 params.beacon_int = ssid->beacon_int;
3201 else
3202 params.beacon_int = wpa_s->conf->beacon_int;
3203 }
3204
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003205 params.pairwise_suite = cipher_pairwise;
3206 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003207 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003208 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003209 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003210 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003211 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003212 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003213 for (i = 0; i < NUM_WEP_KEYS; i++) {
3214 if (ssid->wep_key_len[i])
3215 params.wep_key[i] = ssid->wep_key[i];
3216 params.wep_key_len[i] = ssid->wep_key_len[i];
3217 }
3218 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
3219
Hai Shalom74f70d42019-02-11 14:42:39 -08003220 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003221 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3222 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003223 params.passphrase = ssid->passphrase;
3224 if (ssid->psk_set)
3225 params.psk = ssid->psk;
3226 }
3227
Hai Shalom74f70d42019-02-11 14:42:39 -08003228 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3229 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3230 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3231 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3232 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
3233 params.req_key_mgmt_offload = 1;
3234
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003235 if (wpa_s->conf->key_mgmt_offload) {
3236 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3237 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003238 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3239 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003240 params.req_key_mgmt_offload =
3241 ssid->proactive_key_caching < 0 ?
3242 wpa_s->conf->okc : ssid->proactive_key_caching;
3243 else
3244 params.req_key_mgmt_offload = 1;
3245
3246 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3247 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3248 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3249 ssid->psk_set)
3250 params.psk = ssid->psk;
3251 }
3252
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003253 params.drop_unencrypted = use_crypt;
3254
3255#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003256 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003257 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003258 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3259 struct wpa_ie_data ie;
3260 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3261 ie.capabilities &
3262 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3263 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3264 "MFP: require MFP");
3265 params.mgmt_frame_protection =
3266 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003267#ifdef CONFIG_OWE
3268 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3269 !ssid->owe_only) {
3270 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3271#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003272 }
3273 }
3274#endif /* CONFIG_IEEE80211W */
3275
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003276 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003277
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003278 if (wpa_s->p2pdev->set_sta_uapsd)
3279 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003280 else
3281 params.uapsd = -1;
3282
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003283#ifdef CONFIG_HT_OVERRIDES
3284 os_memset(&htcaps, 0, sizeof(htcaps));
3285 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3286 params.htcaps = (u8 *) &htcaps;
3287 params.htcaps_mask = (u8 *) &htcaps_mask;
3288 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3289#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003290#ifdef CONFIG_VHT_OVERRIDES
3291 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3292 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3293 params.vhtcaps = &vhtcaps;
3294 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003295 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003296#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003297
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003298#ifdef CONFIG_P2P
3299 /*
3300 * If multi-channel concurrency is not supported, check for any
3301 * frequency conflict. In case of any frequency conflict, remove the
3302 * least prioritized connection.
3303 */
3304 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003305 int freq, num;
3306 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003307 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003308 wpa_printf(MSG_DEBUG,
3309 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003310 freq, params.freq.freq);
3311 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003312 wpa_s, params.freq.freq, ssid) < 0) {
3313 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003314 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003315 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003316 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003317 }
3318 }
3319#endif /* CONFIG_P2P */
3320
Dmitry Shmidte4663042016-04-04 10:07:49 -07003321 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3322 wpa_s->current_ssid)
3323 params.prev_bssid = prev_bssid;
3324
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003325 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003326 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327 if (ret < 0) {
3328 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3329 "failed");
3330 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3331 /*
3332 * The driver is known to mean what is saying, so we
3333 * can stop right here; the association will not
3334 * succeed.
3335 */
3336 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003337 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003338 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3339 return;
3340 }
3341 /* try to continue anyway; new association will be tried again
3342 * after timeout */
3343 assoc_failed = 1;
3344 }
3345
3346 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3347 /* Set the key after the association just in case association
3348 * cleared the previously configured key. */
3349 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3350 /* No need to timeout authentication since there is no key
3351 * management. */
3352 wpa_supplicant_cancel_auth_timeout(wpa_s);
3353 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3354#ifdef CONFIG_IBSS_RSN
3355 } else if (ssid->mode == WPAS_MODE_IBSS &&
3356 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3357 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3358 /*
3359 * RSN IBSS authentication is per-STA and we can disable the
3360 * per-BSSID authentication.
3361 */
3362 wpa_supplicant_cancel_auth_timeout(wpa_s);
3363#endif /* CONFIG_IBSS_RSN */
3364 } else {
3365 /* Timeout for IEEE 802.11 authentication and association */
3366 int timeout = 60;
3367
3368 if (assoc_failed) {
3369 /* give IBSS a bit more time */
3370 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3371 } else if (wpa_s->conf->ap_scan == 1) {
3372 /* give IBSS a bit more time */
3373 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3374 }
3375 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3376 }
3377
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003378 if (wep_keys_set &&
3379 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003380 /* Set static WEP keys again */
3381 wpa_set_wep_keys(wpa_s, ssid);
3382 }
3383
3384 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3385 /*
3386 * Do not allow EAP session resumption between different
3387 * network configurations.
3388 */
3389 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3390 }
3391 old_ssid = wpa_s->current_ssid;
3392 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003393
3394 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003395 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003396#ifdef CONFIG_HS20
3397 hs20_configure_frame_filters(wpa_s);
3398#endif /* CONFIG_HS20 */
3399 }
3400
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3402 wpa_supplicant_initiate_eapol(wpa_s);
3403 if (old_ssid != wpa_s->current_ssid)
3404 wpas_notify_network_changed(wpa_s);
3405}
3406
3407
3408static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3409 const u8 *addr)
3410{
3411 struct wpa_ssid *old_ssid;
3412
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003413 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003414 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003415 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003416 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003417 wpa_sm_set_config(wpa_s->wpa, NULL);
3418 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3419 if (old_ssid != wpa_s->current_ssid)
3420 wpas_notify_network_changed(wpa_s);
3421 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3422}
3423
3424
3425/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003426 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3427 * @wpa_s: Pointer to wpa_supplicant data
3428 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3429 *
3430 * This function is used to request %wpa_supplicant to deauthenticate from the
3431 * current AP.
3432 */
3433void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003434 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003435{
3436 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003437 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003438 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003439
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003440 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003441 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003442 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003443 reason_code, reason2str(reason_code),
3444 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003445
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003446 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3447 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3448 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003449 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003450 else if (!is_zero_ether_addr(wpa_s->bssid))
3451 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003452 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3453 /*
3454 * When using driver-based BSS selection, we may not know the
3455 * BSSID with which we are currently trying to associate. We
3456 * need to notify the driver of this disconnection even in such
3457 * a case, so use the all zeros address here.
3458 */
3459 addr = wpa_s->bssid;
3460 zero_addr = 1;
3461 }
3462
Hai Shalom74f70d42019-02-11 14:42:39 -08003463 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3464 wpa_s->enabled_4addr_mode = 0;
3465
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003466#ifdef CONFIG_TDLS
3467 wpa_tdls_teardown_peers(wpa_s->wpa);
3468#endif /* CONFIG_TDLS */
3469
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003470#ifdef CONFIG_MESH
3471 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003472 struct mesh_conf *mconf;
3473
3474 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003475 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3476 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003477 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3478 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003479 wpa_supplicant_leave_mesh(wpa_s);
3480 }
3481#endif /* CONFIG_MESH */
3482
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003483 if (addr) {
3484 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003485 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07003486 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003487 event.deauth_info.locally_generated = 1;
3488 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003489 if (zero_addr)
3490 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491 }
3492
3493 wpa_supplicant_clear_connection(wpa_s, addr);
3494}
3495
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003496static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3497 struct wpa_ssid *ssid)
3498{
3499 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3500 return;
3501
3502 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003503 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003504 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3505 wpas_notify_network_enabled_changed(wpa_s, ssid);
3506
3507 /*
3508 * Try to reassociate since there is no current configuration and a new
3509 * network was made available.
3510 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003511 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003512 wpa_s->reassociate = 1;
3513}
3514
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003515
Roshan Pius950bec92016-07-19 09:49:24 -07003516/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003517 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003518 * @wpa_s: wpa_supplicant structure for a network interface
3519 * Returns: The new network configuration or %NULL if operation failed
3520 *
3521 * This function performs the following operations:
3522 * 1. Adds a new network.
3523 * 2. Send network addition notification.
3524 * 3. Marks the network disabled.
3525 * 4. Set network default parameters.
3526 */
3527struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3528{
3529 struct wpa_ssid *ssid;
3530
3531 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003532 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003533 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003534 wpas_notify_network_added(wpa_s, ssid);
3535 ssid->disabled = 1;
3536 wpa_config_set_network_defaults(ssid);
3537
3538 return ssid;
3539}
3540
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003541
Roshan Pius950bec92016-07-19 09:49:24 -07003542/**
3543 * wpa_supplicant_remove_network - Remove a configured network based on id
3544 * @wpa_s: wpa_supplicant structure for a network interface
3545 * @id: Unique network id to search for
3546 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3547 * could not be removed
3548 *
3549 * This function performs the following operations:
3550 * 1. Removes the network.
3551 * 2. Send network removal notification.
3552 * 3. Update internal state machines.
3553 * 4. Stop any running sched scans.
3554 */
3555int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
3556{
3557 struct wpa_ssid *ssid;
3558 int was_disabled;
3559
3560 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003561 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003562 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003563 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07003564
3565 if (wpa_s->last_ssid == ssid)
3566 wpa_s->last_ssid = NULL;
3567
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003568 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07003569#ifdef CONFIG_SME
3570 wpa_s->sme.prev_bssid_set = 0;
3571#endif /* CONFIG_SME */
3572 /*
3573 * Invalidate the EAP session cache if the current or
3574 * previously used network is removed.
3575 */
3576 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3577 }
3578
3579 if (ssid == wpa_s->current_ssid) {
3580 wpa_sm_set_config(wpa_s->wpa, NULL);
3581 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3582
3583 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3584 wpa_s->own_disconnect_req = 1;
3585 wpa_supplicant_deauthenticate(wpa_s,
3586 WLAN_REASON_DEAUTH_LEAVING);
3587 }
3588
3589 was_disabled = ssid->disabled;
3590
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003591 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07003592 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07003593
3594 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003595 wpa_printf(MSG_DEBUG,
3596 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07003597 wpa_supplicant_cancel_sched_scan(wpa_s);
3598 wpa_supplicant_req_scan(wpa_s, 0, 0);
3599 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003600
Roshan Pius950bec92016-07-19 09:49:24 -07003601 return 0;
3602}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003603
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003604
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003605/**
3606 * wpa_supplicant_enable_network - Mark a configured network as enabled
3607 * @wpa_s: wpa_supplicant structure for a network interface
3608 * @ssid: wpa_ssid structure for a configured network or %NULL
3609 *
3610 * Enables the specified network or all networks if no network specified.
3611 */
3612void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
3613 struct wpa_ssid *ssid)
3614{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003615 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003616 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3617 wpa_supplicant_enable_one_network(wpa_s, ssid);
3618 } else
3619 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003620
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003621 if (wpa_s->reassociate && !wpa_s->disconnected &&
3622 (!wpa_s->current_ssid ||
3623 wpa_s->wpa_state == WPA_DISCONNECTED ||
3624 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003625 if (wpa_s->sched_scanning) {
3626 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
3627 "new network to scan filters");
3628 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629 }
3630
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003631 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3632 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003633 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003634 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003635 }
3636}
3637
3638
3639/**
3640 * wpa_supplicant_disable_network - Mark a configured network as disabled
3641 * @wpa_s: wpa_supplicant structure for a network interface
3642 * @ssid: wpa_ssid structure for a configured network or %NULL
3643 *
3644 * Disables the specified network or all networks if no network specified.
3645 */
3646void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
3647 struct wpa_ssid *ssid)
3648{
3649 struct wpa_ssid *other_ssid;
3650 int was_disabled;
3651
3652 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003653 if (wpa_s->sched_scanning)
3654 wpa_supplicant_cancel_sched_scan(wpa_s);
3655
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003656 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3657 other_ssid = other_ssid->next) {
3658 was_disabled = other_ssid->disabled;
3659 if (was_disabled == 2)
3660 continue; /* do not change persistent P2P group
3661 * data */
3662
3663 other_ssid->disabled = 1;
3664
3665 if (was_disabled != other_ssid->disabled)
3666 wpas_notify_network_enabled_changed(
3667 wpa_s, other_ssid);
3668 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003669 if (wpa_s->current_ssid) {
3670 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3671 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003672 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003673 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003674 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003676 if (ssid == wpa_s->current_ssid) {
3677 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3678 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003679 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003680 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003681 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003682
3683 was_disabled = ssid->disabled;
3684
3685 ssid->disabled = 1;
3686
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003687 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003688 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003689 if (wpa_s->sched_scanning) {
3690 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3691 "to remove network from filters");
3692 wpa_supplicant_cancel_sched_scan(wpa_s);
3693 wpa_supplicant_req_scan(wpa_s, 0, 0);
3694 }
3695 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003696 }
3697}
3698
3699
3700/**
3701 * wpa_supplicant_select_network - Attempt association with a network
3702 * @wpa_s: wpa_supplicant structure for a network interface
3703 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3704 */
3705void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3706 struct wpa_ssid *ssid)
3707{
3708
3709 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003710 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003711
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003712 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003713 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3714 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003715 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003716 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003717 disconnected = 1;
3718 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003719
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003720 if (ssid)
3721 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3722
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003723 /*
3724 * Mark all other networks disabled or mark all networks enabled if no
3725 * network specified.
3726 */
3727 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3728 other_ssid = other_ssid->next) {
3729 int was_disabled = other_ssid->disabled;
3730 if (was_disabled == 2)
3731 continue; /* do not change persistent P2P group data */
3732
3733 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003734 if (was_disabled && !other_ssid->disabled)
3735 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003736
3737 if (was_disabled != other_ssid->disabled)
3738 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3739 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003740
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003741 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3742 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003743 /* We are already associated with the selected network */
3744 wpa_printf(MSG_DEBUG, "Already associated with the "
3745 "selected network - do nothing");
3746 return;
3747 }
3748
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003749 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003750 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003751 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003752 wpa_s->connect_without_scan =
3753 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003754
3755 /*
3756 * Don't optimize next scan freqs since a new ESS has been
3757 * selected.
3758 */
3759 os_free(wpa_s->next_scan_freqs);
3760 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003761 } else {
3762 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003763 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003765 wpa_s->disconnected = 0;
3766 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003767 wpa_s->last_owe_group = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003768 if (ssid)
3769 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003770
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003771 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003772 wpa_supplicant_fast_associate(wpa_s) != 1) {
3773 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003774 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003775 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003776 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003777
3778 if (ssid)
3779 wpas_notify_network_selected(wpa_s, ssid);
3780}
3781
3782
3783/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003784 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3785 * @wpa_s: wpa_supplicant structure for a network interface
3786 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3787 * @pkcs11_module_path: PKCS #11 module path or NULL
3788 * Returns: 0 on success; -1 on failure
3789 *
3790 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3791 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3792 * module path fails the paths will be reset to the default value (NULL).
3793 */
3794int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3795 const char *pkcs11_engine_path,
3796 const char *pkcs11_module_path)
3797{
3798 char *pkcs11_engine_path_copy = NULL;
3799 char *pkcs11_module_path_copy = NULL;
3800
3801 if (pkcs11_engine_path != NULL) {
3802 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3803 if (pkcs11_engine_path_copy == NULL)
3804 return -1;
3805 }
3806 if (pkcs11_module_path != NULL) {
3807 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003808 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003809 os_free(pkcs11_engine_path_copy);
3810 return -1;
3811 }
3812 }
3813
3814 os_free(wpa_s->conf->pkcs11_engine_path);
3815 os_free(wpa_s->conf->pkcs11_module_path);
3816 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3817 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3818
3819 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3820 eapol_sm_deinit(wpa_s->eapol);
3821 wpa_s->eapol = NULL;
3822 if (wpa_supplicant_init_eapol(wpa_s)) {
3823 /* Error -> Reset paths to the default value (NULL) once. */
3824 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3825 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3826 NULL);
3827
3828 return -1;
3829 }
3830 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3831
3832 return 0;
3833}
3834
3835
3836/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003837 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3838 * @wpa_s: wpa_supplicant structure for a network interface
3839 * @ap_scan: AP scan mode
3840 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3841 *
3842 */
3843int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3844{
3845
3846 int old_ap_scan;
3847
3848 if (ap_scan < 0 || ap_scan > 2)
3849 return -1;
3850
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003851 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3852 wpa_printf(MSG_INFO,
3853 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3854 }
3855
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003856#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003857 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3858 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3859 wpa_s->wpa_state < WPA_COMPLETED) {
3860 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3861 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003862 return 0;
3863 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003864#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003865
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003866 old_ap_scan = wpa_s->conf->ap_scan;
3867 wpa_s->conf->ap_scan = ap_scan;
3868
3869 if (old_ap_scan != wpa_s->conf->ap_scan)
3870 wpas_notify_ap_scan_changed(wpa_s);
3871
3872 return 0;
3873}
3874
3875
3876/**
3877 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3878 * @wpa_s: wpa_supplicant structure for a network interface
3879 * @expire_age: Expiration age in seconds
3880 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3881 *
3882 */
3883int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3884 unsigned int bss_expire_age)
3885{
3886 if (bss_expire_age < 10) {
3887 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3888 bss_expire_age);
3889 return -1;
3890 }
3891 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3892 bss_expire_age);
3893 wpa_s->conf->bss_expiration_age = bss_expire_age;
3894
3895 return 0;
3896}
3897
3898
3899/**
3900 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3901 * @wpa_s: wpa_supplicant structure for a network interface
3902 * @expire_count: number of scans after which an unseen BSS is reclaimed
3903 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3904 *
3905 */
3906int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3907 unsigned int bss_expire_count)
3908{
3909 if (bss_expire_count < 1) {
3910 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3911 bss_expire_count);
3912 return -1;
3913 }
3914 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3915 bss_expire_count);
3916 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3917
3918 return 0;
3919}
3920
3921
3922/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003923 * wpa_supplicant_set_scan_interval - Set scan interval
3924 * @wpa_s: wpa_supplicant structure for a network interface
3925 * @scan_interval: scan interval in seconds
3926 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3927 *
3928 */
3929int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3930 int scan_interval)
3931{
3932 if (scan_interval < 0) {
3933 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3934 scan_interval);
3935 return -1;
3936 }
3937 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3938 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003939 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003940
3941 return 0;
3942}
3943
3944
3945/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946 * wpa_supplicant_set_debug_params - Set global debug params
3947 * @global: wpa_global structure
3948 * @debug_level: debug level
3949 * @debug_timestamp: determines if show timestamp in debug data
3950 * @debug_show_keys: determines if show keys in debug data
3951 * Returns: 0 if succeed or -1 if debug_level has wrong value
3952 */
3953int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3954 int debug_timestamp, int debug_show_keys)
3955{
3956
3957 int old_level, old_timestamp, old_show_keys;
3958
3959 /* check for allowed debuglevels */
3960 if (debug_level != MSG_EXCESSIVE &&
3961 debug_level != MSG_MSGDUMP &&
3962 debug_level != MSG_DEBUG &&
3963 debug_level != MSG_INFO &&
3964 debug_level != MSG_WARNING &&
3965 debug_level != MSG_ERROR)
3966 return -1;
3967
3968 old_level = wpa_debug_level;
3969 old_timestamp = wpa_debug_timestamp;
3970 old_show_keys = wpa_debug_show_keys;
3971
3972 wpa_debug_level = debug_level;
3973 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3974 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3975
3976 if (wpa_debug_level != old_level)
3977 wpas_notify_debug_level_changed(global);
3978 if (wpa_debug_timestamp != old_timestamp)
3979 wpas_notify_debug_timestamp_changed(global);
3980 if (wpa_debug_show_keys != old_show_keys)
3981 wpas_notify_debug_show_keys_changed(global);
3982
3983 return 0;
3984}
3985
3986
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003987#ifdef CONFIG_OWE
3988static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
3989 const u8 *entry_ssid, size_t entry_ssid_len)
3990{
3991 const u8 *owe, *pos, *end;
3992 u8 ssid_len;
3993 struct wpa_bss *bss;
3994
3995 /* Check network profile SSID aganst the SSID in the
3996 * OWE Transition Mode element. */
3997
3998 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
3999 if (!bss)
4000 return 0;
4001
4002 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4003 if (!owe)
4004 return 0;
4005
4006 pos = owe + 6;
4007 end = owe + 2 + owe[1];
4008
4009 if (end - pos < ETH_ALEN + 1)
4010 return 0;
4011 pos += ETH_ALEN;
4012 ssid_len = *pos++;
4013 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4014 return 0;
4015
4016 return entry_ssid_len == ssid_len &&
4017 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4018}
4019#endif /* CONFIG_OWE */
4020
4021
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004022/**
4023 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4024 * @wpa_s: Pointer to wpa_supplicant data
4025 * Returns: A pointer to the current network structure or %NULL on failure
4026 */
4027struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4028{
4029 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004030 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004031 int res;
4032 size_t ssid_len;
4033 u8 bssid[ETH_ALEN];
4034 int wired;
4035
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004036 res = wpa_drv_get_ssid(wpa_s, ssid);
4037 if (res < 0) {
4038 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4039 "driver");
4040 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004041 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004042 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004043
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004044 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004045 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4046 "driver");
4047 return NULL;
4048 }
4049
4050 wired = wpa_s->conf->ap_scan == 0 &&
4051 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4052
4053 entry = wpa_s->conf->ssid;
4054 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004055 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004056 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004057 (!entry->ssid ||
4058 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4059 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004060 (!entry->bssid_set ||
4061 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4062 return entry;
4063#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004064 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004065 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4066 (entry->ssid == NULL || entry->ssid_len == 0) &&
4067 (!entry->bssid_set ||
4068 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4069 return entry;
4070#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004071
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004072#ifdef CONFIG_OWE
4073 if (!wpas_network_disabled(wpa_s, entry) &&
4074 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4075 entry->ssid_len) &&
4076 (!entry->bssid_set ||
4077 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4078 return entry;
4079#endif /* CONFIG_OWE */
4080
Dmitry Shmidt04949592012-07-19 12:16:46 -07004081 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004082 entry->ssid_len == 0 &&
4083 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4084 return entry;
4085
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004086 entry = entry->next;
4087 }
4088
4089 return NULL;
4090}
4091
4092
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004093static int select_driver(struct wpa_supplicant *wpa_s, int i)
4094{
4095 struct wpa_global *global = wpa_s->global;
4096
4097 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004098 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004099 if (global->drv_priv[i] == NULL) {
4100 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4101 "'%s'", wpa_drivers[i]->name);
4102 return -1;
4103 }
4104 }
4105
4106 wpa_s->driver = wpa_drivers[i];
4107 wpa_s->global_drv_priv = global->drv_priv[i];
4108
4109 return 0;
4110}
4111
4112
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004113static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4114 const char *name)
4115{
4116 int i;
4117 size_t len;
4118 const char *pos, *driver = name;
4119
4120 if (wpa_s == NULL)
4121 return -1;
4122
4123 if (wpa_drivers[0] == NULL) {
4124 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4125 "wpa_supplicant");
4126 return -1;
4127 }
4128
4129 if (name == NULL) {
4130 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004131 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004132 }
4133
4134 do {
4135 pos = os_strchr(driver, ',');
4136 if (pos)
4137 len = pos - driver;
4138 else
4139 len = os_strlen(driver);
4140
4141 for (i = 0; wpa_drivers[i]; i++) {
4142 if (os_strlen(wpa_drivers[i]->name) == len &&
4143 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004144 0) {
4145 /* First driver that succeeds wins */
4146 if (select_driver(wpa_s, i) == 0)
4147 return 0;
4148 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004149 }
4150
4151 driver = pos + 1;
4152 } while (pos);
4153
4154 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4155 return -1;
4156}
4157
4158
4159/**
4160 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4161 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4162 * with struct wpa_driver_ops::init()
4163 * @src_addr: Source address of the EAPOL frame
4164 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4165 * @len: Length of the EAPOL data
4166 *
4167 * This function is called for each received EAPOL frame. Most driver
4168 * interfaces rely on more generic OS mechanism for receiving frames through
4169 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4170 * take care of received EAPOL frames and deliver them to the core supplicant
4171 * code by calling this function.
4172 */
4173void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4174 const u8 *buf, size_t len)
4175{
4176 struct wpa_supplicant *wpa_s = ctx;
4177
4178 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4179 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4180
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004181#ifdef CONFIG_TESTING_OPTIONS
4182 if (wpa_s->ignore_auth_resp) {
4183 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4184 return;
4185 }
4186#endif /* CONFIG_TESTING_OPTIONS */
4187
Jouni Malinena05074c2012-12-21 21:35:35 +02004188 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4189 (wpa_s->last_eapol_matches_bssid &&
4190#ifdef CONFIG_AP
4191 !wpa_s->ap_iface &&
4192#endif /* CONFIG_AP */
4193 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004194 /*
4195 * There is possible race condition between receiving the
4196 * association event and the EAPOL frame since they are coming
4197 * through different paths from the driver. In order to avoid
4198 * issues in trying to process the EAPOL frame before receiving
4199 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004200 * the association event is received. This may also be needed in
4201 * driver-based roaming case, so also use src_addr != BSSID as a
4202 * trigger if we have previously confirmed that the
4203 * Authenticator uses BSSID as the src_addr (which is not the
4204 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004205 */
4206 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004207 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4208 wpa_supplicant_state_txt(wpa_s->wpa_state),
4209 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004210 wpabuf_free(wpa_s->pending_eapol_rx);
4211 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4212 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004213 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004214 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4215 ETH_ALEN);
4216 }
4217 return;
4218 }
4219
Jouni Malinena05074c2012-12-21 21:35:35 +02004220 wpa_s->last_eapol_matches_bssid =
4221 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4222
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004223#ifdef CONFIG_AP
4224 if (wpa_s->ap_iface) {
4225 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4226 return;
4227 }
4228#endif /* CONFIG_AP */
4229
4230 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4231 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4232 "no key management is configured");
4233 return;
4234 }
4235
4236 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004237 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004238 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4239 wpa_s->wpa_state != WPA_COMPLETED) &&
4240 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004241 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004242 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004243 int timeout = 10;
4244
4245 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4246 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4247 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4248 /* Use longer timeout for IEEE 802.1X/EAP */
4249 timeout = 70;
4250 }
4251
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004252#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004253 if (wpa_s->current_ssid && wpa_s->current_bss &&
4254 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4255 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4256 /*
4257 * Use shorter timeout if going through WPS AP iteration
4258 * for PIN config method with an AP that does not
4259 * advertise Selected Registrar.
4260 */
4261 struct wpabuf *wps_ie;
4262
4263 wps_ie = wpa_bss_get_vendor_ie_multi(
4264 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4265 if (wps_ie &&
4266 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4267 timeout = 10;
4268 wpabuf_free(wps_ie);
4269 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004270#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004271
4272 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004273 }
4274 wpa_s->eapol_received++;
4275
4276 if (wpa_s->countermeasures) {
4277 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4278 "EAPOL packet");
4279 return;
4280 }
4281
4282#ifdef CONFIG_IBSS_RSN
4283 if (wpa_s->current_ssid &&
4284 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4285 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4286 return;
4287 }
4288#endif /* CONFIG_IBSS_RSN */
4289
4290 /* Source address of the incoming EAPOL frame could be compared to the
4291 * current BSSID. However, it is possible that a centralized
4292 * Authenticator could be using another MAC address than the BSSID of
4293 * an AP, so just allow any address to be used for now. The replies are
4294 * still sent to the current BSSID (if available), though. */
4295
4296 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4297 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004298 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4299 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004300 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4301 return;
4302 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004303 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004304 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4305 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4306 /*
4307 * Set portValid = TRUE here since we are going to skip 4-way
4308 * handshake processing which would normally set portValid. We
4309 * need this to allow the EAPOL state machines to be completed
4310 * without going through EAPOL-Key handshake.
4311 */
4312 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
4313 }
4314}
4315
4316
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004317int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004318{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004319 if ((!wpa_s->p2p_mgmt ||
4320 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4321 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004322 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004323 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4324 wpa_drv_get_mac_addr(wpa_s),
4325 ETH_P_EAPOL,
4326 wpa_supplicant_rx_eapol, wpa_s, 0);
4327 if (wpa_s->l2 == NULL)
4328 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004329
4330 if (l2_packet_set_packet_filter(wpa_s->l2,
4331 L2_PACKET_FILTER_PKTTYPE))
4332 wpa_dbg(wpa_s, MSG_DEBUG,
4333 "Failed to attach pkt_type filter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004334 } else {
4335 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4336 if (addr)
4337 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4338 }
4339
4340 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4341 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
4342 return -1;
4343 }
4344
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004345 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004346 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004347
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004348 return 0;
4349}
4350
4351
Dmitry Shmidt04949592012-07-19 12:16:46 -07004352static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4353 const u8 *buf, size_t len)
4354{
4355 struct wpa_supplicant *wpa_s = ctx;
4356 const struct l2_ethhdr *eth;
4357
4358 if (len < sizeof(*eth))
4359 return;
4360 eth = (const struct l2_ethhdr *) buf;
4361
4362 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4363 !(eth->h_dest[0] & 0x01)) {
4364 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4365 " (bridge - not for this interface - ignore)",
4366 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4367 return;
4368 }
4369
4370 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4371 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4372 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4373 len - sizeof(*eth));
4374}
4375
4376
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004377/**
4378 * wpa_supplicant_driver_init - Initialize driver interface parameters
4379 * @wpa_s: Pointer to wpa_supplicant data
4380 * Returns: 0 on success, -1 on failure
4381 *
4382 * This function is called to initialize driver interface parameters.
4383 * wpa_drv_init() must have been called before this function to initialize the
4384 * driver interface.
4385 */
4386int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4387{
4388 static int interface_count = 0;
4389
4390 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4391 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004392
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004393 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4394 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004395 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004396 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4397
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004398 if (wpa_s->bridge_ifname[0]) {
4399 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4400 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004401 wpa_s->l2_br = l2_packet_init_bridge(
4402 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4403 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004404 if (wpa_s->l2_br == NULL) {
4405 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4406 "connection for the bridge interface '%s'",
4407 wpa_s->bridge_ifname);
4408 return -1;
4409 }
4410 }
4411
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004412 if (wpa_s->conf->ap_scan == 2 &&
4413 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4414 wpa_printf(MSG_INFO,
4415 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4416 }
4417
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004418 wpa_clear_keys(wpa_s, NULL);
4419
4420 /* Make sure that TKIP countermeasures are not left enabled (could
4421 * happen if wpa_supplicant is killed during countermeasures. */
4422 wpa_drv_set_countermeasures(wpa_s, 0);
4423
4424 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4425 wpa_drv_flush_pmkid(wpa_s);
4426
4427 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004428 wpa_s->prev_scan_wildcard = 0;
4429
Dmitry Shmidt04949592012-07-19 12:16:46 -07004430 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004431 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4432 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4433 interface_count = 0;
4434 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004435#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004436 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004437 wpa_supplicant_delayed_sched_scan(wpa_s,
4438 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004439 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004440 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004441 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004442#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004443 interface_count++;
4444 } else
4445 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4446
4447 return 0;
4448}
4449
4450
4451static int wpa_supplicant_daemon(const char *pid_file)
4452{
4453 wpa_printf(MSG_DEBUG, "Daemonize..");
4454 return os_daemonize(pid_file);
4455}
4456
4457
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004458static struct wpa_supplicant *
4459wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004460{
4461 struct wpa_supplicant *wpa_s;
4462
4463 wpa_s = os_zalloc(sizeof(*wpa_s));
4464 if (wpa_s == NULL)
4465 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004466 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004467 wpa_s->scan_interval = 5;
4468 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004469 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004470 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004471 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004472
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004473 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004474 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004475
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004476 return wpa_s;
4477}
4478
4479
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004480#ifdef CONFIG_HT_OVERRIDES
4481
4482static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4483 struct ieee80211_ht_capabilities *htcaps,
4484 struct ieee80211_ht_capabilities *htcaps_mask,
4485 const char *ht_mcs)
4486{
4487 /* parse ht_mcs into hex array */
4488 int i;
4489 const char *tmp = ht_mcs;
4490 char *end = NULL;
4491
4492 /* If ht_mcs is null, do not set anything */
4493 if (!ht_mcs)
4494 return 0;
4495
4496 /* This is what we are setting in the kernel */
4497 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4498
4499 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4500
4501 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004502 long v;
4503
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004504 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004505 v = strtol(tmp, &end, 16);
4506
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004507 if (errno == 0) {
4508 wpa_msg(wpa_s, MSG_DEBUG,
4509 "htcap value[%i]: %ld end: %p tmp: %p",
4510 i, v, end, tmp);
4511 if (end == tmp)
4512 break;
4513
4514 htcaps->supported_mcs_set[i] = v;
4515 tmp = end;
4516 } else {
4517 wpa_msg(wpa_s, MSG_ERROR,
4518 "Failed to parse ht-mcs: %s, error: %s\n",
4519 ht_mcs, strerror(errno));
4520 return -1;
4521 }
4522 }
4523
4524 /*
4525 * If we were able to parse any values, then set mask for the MCS set.
4526 */
4527 if (i) {
4528 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4529 IEEE80211_HT_MCS_MASK_LEN - 1);
4530 /* skip the 3 reserved bits */
4531 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4532 0x1f;
4533 }
4534
4535 return 0;
4536}
4537
4538
4539static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4540 struct ieee80211_ht_capabilities *htcaps,
4541 struct ieee80211_ht_capabilities *htcaps_mask,
4542 int disabled)
4543{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004544 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004545
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004546 if (disabled == -1)
4547 return 0;
4548
Hai Shalom74f70d42019-02-11 14:42:39 -08004549 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
4550
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004551 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
4552 htcaps_mask->ht_capabilities_info |= msk;
4553 if (disabled)
4554 htcaps->ht_capabilities_info &= msk;
4555 else
4556 htcaps->ht_capabilities_info |= msk;
4557
4558 return 0;
4559}
4560
4561
4562static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
4563 struct ieee80211_ht_capabilities *htcaps,
4564 struct ieee80211_ht_capabilities *htcaps_mask,
4565 int factor)
4566{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004567 if (factor == -1)
4568 return 0;
4569
Hai Shalom74f70d42019-02-11 14:42:39 -08004570 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
4571
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004572 if (factor < 0 || factor > 3) {
4573 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
4574 "Must be 0-3 or -1", factor);
4575 return -EINVAL;
4576 }
4577
4578 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
4579 htcaps->a_mpdu_params &= ~0x3;
4580 htcaps->a_mpdu_params |= factor & 0x3;
4581
4582 return 0;
4583}
4584
4585
4586static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
4587 struct ieee80211_ht_capabilities *htcaps,
4588 struct ieee80211_ht_capabilities *htcaps_mask,
4589 int density)
4590{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004591 if (density == -1)
4592 return 0;
4593
Hai Shalom74f70d42019-02-11 14:42:39 -08004594 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
4595
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004596 if (density < 0 || density > 7) {
4597 wpa_msg(wpa_s, MSG_ERROR,
4598 "ampdu_density: %d out of range. Must be 0-7 or -1.",
4599 density);
4600 return -EINVAL;
4601 }
4602
4603 htcaps_mask->a_mpdu_params |= 0x1C;
4604 htcaps->a_mpdu_params &= ~(0x1C);
4605 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
4606
4607 return 0;
4608}
4609
4610
4611static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
4612 struct ieee80211_ht_capabilities *htcaps,
4613 struct ieee80211_ht_capabilities *htcaps_mask,
4614 int disabled)
4615{
Hai Shalom74f70d42019-02-11 14:42:39 -08004616 if (disabled)
4617 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004618
Paul Stewart092955c2017-02-06 09:13:09 -08004619 set_disable_ht40(htcaps, disabled);
4620 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004621
4622 return 0;
4623}
4624
4625
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004626static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
4627 struct ieee80211_ht_capabilities *htcaps,
4628 struct ieee80211_ht_capabilities *htcaps_mask,
4629 int disabled)
4630{
4631 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004632 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
4633 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004634
Hai Shalom74f70d42019-02-11 14:42:39 -08004635 if (disabled)
4636 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004637
4638 if (disabled)
4639 htcaps->ht_capabilities_info &= ~msk;
4640 else
4641 htcaps->ht_capabilities_info |= msk;
4642
4643 htcaps_mask->ht_capabilities_info |= msk;
4644
4645 return 0;
4646}
4647
4648
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004649static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
4650 struct ieee80211_ht_capabilities *htcaps,
4651 struct ieee80211_ht_capabilities *htcaps_mask,
4652 int disabled)
4653{
4654 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004655 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004656
Hai Shalom74f70d42019-02-11 14:42:39 -08004657 if (disabled)
4658 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004659
4660 if (disabled)
4661 htcaps->ht_capabilities_info &= ~msk;
4662 else
4663 htcaps->ht_capabilities_info |= msk;
4664
4665 htcaps_mask->ht_capabilities_info |= msk;
4666
4667 return 0;
4668}
4669
4670
Hai Shalom74f70d42019-02-11 14:42:39 -08004671static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
4672 struct ieee80211_ht_capabilities *htcaps,
4673 struct ieee80211_ht_capabilities *htcaps_mask,
4674 int tx_stbc)
4675{
4676 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
4677
4678 if (tx_stbc == -1)
4679 return 0;
4680
4681 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
4682
4683 if (tx_stbc < 0 || tx_stbc > 1) {
4684 wpa_msg(wpa_s, MSG_ERROR,
4685 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
4686 return -EINVAL;
4687 }
4688
4689 htcaps_mask->ht_capabilities_info |= msk;
4690 htcaps->ht_capabilities_info &= ~msk;
4691 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
4692
4693 return 0;
4694}
4695
4696
4697static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
4698 struct ieee80211_ht_capabilities *htcaps,
4699 struct ieee80211_ht_capabilities *htcaps_mask,
4700 int rx_stbc)
4701{
4702 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
4703
4704 if (rx_stbc == -1)
4705 return 0;
4706
4707 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
4708
4709 if (rx_stbc < 0 || rx_stbc > 3) {
4710 wpa_msg(wpa_s, MSG_ERROR,
4711 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
4712 return -EINVAL;
4713 }
4714
4715 htcaps_mask->ht_capabilities_info |= msk;
4716 htcaps->ht_capabilities_info &= ~msk;
4717 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
4718
4719 return 0;
4720}
4721
4722
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004723void wpa_supplicant_apply_ht_overrides(
4724 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4725 struct wpa_driver_associate_params *params)
4726{
4727 struct ieee80211_ht_capabilities *htcaps;
4728 struct ieee80211_ht_capabilities *htcaps_mask;
4729
4730 if (!ssid)
4731 return;
4732
4733 params->disable_ht = ssid->disable_ht;
4734 if (!params->htcaps || !params->htcaps_mask)
4735 return;
4736
4737 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
4738 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
4739 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
4740 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
4741 ssid->disable_max_amsdu);
4742 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
4743 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
4744 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004745 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004746 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08004747 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
4748 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004749
4750 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004751 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004752 htcaps->ht_capabilities_info |= bit;
4753 htcaps_mask->ht_capabilities_info |= bit;
4754 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004755}
4756
4757#endif /* CONFIG_HT_OVERRIDES */
4758
4759
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004760#ifdef CONFIG_VHT_OVERRIDES
4761void wpa_supplicant_apply_vht_overrides(
4762 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4763 struct wpa_driver_associate_params *params)
4764{
4765 struct ieee80211_vht_capabilities *vhtcaps;
4766 struct ieee80211_vht_capabilities *vhtcaps_mask;
4767
4768 if (!ssid)
4769 return;
4770
4771 params->disable_vht = ssid->disable_vht;
4772
4773 vhtcaps = (void *) params->vhtcaps;
4774 vhtcaps_mask = (void *) params->vhtcaps_mask;
4775
4776 if (!vhtcaps || !vhtcaps_mask)
4777 return;
4778
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004779 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
4780 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004781
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004782#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08004783 if (ssid->disable_sgi) {
4784 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
4785 VHT_CAP_SHORT_GI_160);
4786 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
4787 VHT_CAP_SHORT_GI_160);
4788 wpa_msg(wpa_s, MSG_DEBUG,
4789 "disable-sgi override specified, vht-caps: 0x%x",
4790 vhtcaps->vht_capabilities_info);
4791 }
4792
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004793 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004794 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
4795 int max_ampdu;
4796
4797 max_ampdu = (ssid->vht_capa &
4798 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4799 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004800
4801 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4802 wpa_set_ampdu_factor(wpa_s,
4803 (void *) params->htcaps,
4804 (void *) params->htcaps_mask,
4805 max_ampdu);
4806 }
4807#endif /* CONFIG_HT_OVERRIDES */
4808
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004809#define OVERRIDE_MCS(i) \
4810 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4811 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004812 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004813 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004814 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4815 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004816 } \
4817 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4818 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004819 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004820 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004821 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4822 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004823 }
4824
4825 OVERRIDE_MCS(1);
4826 OVERRIDE_MCS(2);
4827 OVERRIDE_MCS(3);
4828 OVERRIDE_MCS(4);
4829 OVERRIDE_MCS(5);
4830 OVERRIDE_MCS(6);
4831 OVERRIDE_MCS(7);
4832 OVERRIDE_MCS(8);
4833}
4834#endif /* CONFIG_VHT_OVERRIDES */
4835
4836
Dmitry Shmidt04949592012-07-19 12:16:46 -07004837static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4838{
4839#ifdef PCSC_FUNCS
4840 size_t len;
4841
4842 if (!wpa_s->conf->pcsc_reader)
4843 return 0;
4844
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004845 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004846 if (!wpa_s->scard)
4847 return 1;
4848
4849 if (wpa_s->conf->pcsc_pin &&
4850 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4851 scard_deinit(wpa_s->scard);
4852 wpa_s->scard = NULL;
4853 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4854 return -1;
4855 }
4856
4857 len = sizeof(wpa_s->imsi) - 1;
4858 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4859 scard_deinit(wpa_s->scard);
4860 wpa_s->scard = NULL;
4861 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4862 return -1;
4863 }
4864 wpa_s->imsi[len] = '\0';
4865
4866 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4867
4868 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4869 wpa_s->imsi, wpa_s->mnc_len);
4870
4871 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4872 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4873#endif /* PCSC_FUNCS */
4874
4875 return 0;
4876}
4877
4878
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004879int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4880{
4881 char *val, *pos;
4882
4883 ext_password_deinit(wpa_s->ext_pw);
4884 wpa_s->ext_pw = NULL;
4885 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4886
4887 if (!wpa_s->conf->ext_password_backend)
4888 return 0;
4889
4890 val = os_strdup(wpa_s->conf->ext_password_backend);
4891 if (val == NULL)
4892 return -1;
4893 pos = os_strchr(val, ':');
4894 if (pos)
4895 *pos++ = '\0';
4896
4897 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4898
4899 wpa_s->ext_pw = ext_password_init(val, pos);
4900 os_free(val);
4901 if (wpa_s->ext_pw == NULL) {
4902 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4903 return -1;
4904 }
4905 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4906
4907 return 0;
4908}
4909
4910
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004911#ifdef CONFIG_FST
4912
4913static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4914{
4915 struct wpa_supplicant *wpa_s = ctx;
4916
4917 return (is_zero_ether_addr(wpa_s->bssid) ||
4918 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4919}
4920
4921
4922static void wpas_fst_get_channel_info_cb(void *ctx,
4923 enum hostapd_hw_mode *hw_mode,
4924 u8 *channel)
4925{
4926 struct wpa_supplicant *wpa_s = ctx;
4927
4928 if (wpa_s->current_bss) {
4929 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4930 channel);
4931 } else if (wpa_s->hw.num_modes) {
4932 *hw_mode = wpa_s->hw.modes[0].mode;
4933 } else {
4934 WPA_ASSERT(0);
4935 *hw_mode = 0;
4936 }
4937}
4938
4939
4940static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4941{
4942 struct wpa_supplicant *wpa_s = ctx;
4943
4944 *modes = wpa_s->hw.modes;
4945 return wpa_s->hw.num_modes;
4946}
4947
4948
4949static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4950{
4951 struct wpa_supplicant *wpa_s = ctx;
4952
4953 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4954 wpa_s->fst_ies = fst_ies;
4955}
4956
4957
4958static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4959{
4960 struct wpa_supplicant *wpa_s = ctx;
4961
Paul Stewart092955c2017-02-06 09:13:09 -08004962 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
4963 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
4964 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
4965 return -1;
4966 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004967 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08004968 wpa_s->own_addr, wpa_s->bssid,
4969 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004970 0);
4971}
4972
4973
4974static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4975{
4976 struct wpa_supplicant *wpa_s = ctx;
4977
4978 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4979 return wpa_s->received_mb_ies;
4980}
4981
4982
4983static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4984 const u8 *buf, size_t size)
4985{
4986 struct wpa_supplicant *wpa_s = ctx;
4987 struct mb_ies_info info;
4988
4989 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4990
4991 if (!mb_ies_info_by_ies(&info, buf, size)) {
4992 wpabuf_free(wpa_s->received_mb_ies);
4993 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4994 }
4995}
4996
4997
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004998static const u8 * wpas_fst_get_peer_first(void *ctx,
4999 struct fst_get_peer_ctx **get_ctx,
5000 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005001{
5002 struct wpa_supplicant *wpa_s = ctx;
5003
5004 *get_ctx = NULL;
5005 if (!is_zero_ether_addr(wpa_s->bssid))
5006 return (wpa_s->received_mb_ies || !mb_only) ?
5007 wpa_s->bssid : NULL;
5008 return NULL;
5009}
5010
5011
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005012static const u8 * wpas_fst_get_peer_next(void *ctx,
5013 struct fst_get_peer_ctx **get_ctx,
5014 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005015{
5016 return NULL;
5017}
5018
5019void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5020 struct fst_wpa_obj *iface_obj)
5021{
5022 iface_obj->ctx = wpa_s;
5023 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5024 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5025 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5026 iface_obj->set_ies = wpas_fst_set_ies_cb;
5027 iface_obj->send_action = wpas_fst_send_action_cb;
5028 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5029 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5030 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5031 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5032}
5033#endif /* CONFIG_FST */
5034
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005035static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005036 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005037{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005038 struct wowlan_triggers *triggers;
5039 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005040
5041 if (!wpa_s->conf->wowlan_triggers)
5042 return 0;
5043
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005044 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5045 if (triggers) {
5046 ret = wpa_drv_wowlan(wpa_s, triggers);
5047 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005048 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005049 return ret;
5050}
5051
5052
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005053enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005054{
5055 if (freq < 3000)
5056 return BAND_2_4_GHZ;
5057 if (freq > 50000)
5058 return BAND_60_GHZ;
5059 return BAND_5_GHZ;
5060}
5061
5062
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005063unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005064{
5065 int i;
5066 unsigned int band = 0;
5067
5068 if (freqs) {
5069 /* freqs are specified for the radio work */
5070 for (i = 0; freqs[i]; i++)
5071 band |= wpas_freq_to_band(freqs[i]);
5072 } else {
5073 /*
5074 * freqs are not specified, implies all
5075 * the supported freqs by HW
5076 */
5077 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5078 if (wpa_s->hw.modes[i].num_channels != 0) {
5079 if (wpa_s->hw.modes[i].mode ==
5080 HOSTAPD_MODE_IEEE80211B ||
5081 wpa_s->hw.modes[i].mode ==
5082 HOSTAPD_MODE_IEEE80211G)
5083 band |= BAND_2_4_GHZ;
5084 else if (wpa_s->hw.modes[i].mode ==
5085 HOSTAPD_MODE_IEEE80211A)
5086 band |= BAND_5_GHZ;
5087 else if (wpa_s->hw.modes[i].mode ==
5088 HOSTAPD_MODE_IEEE80211AD)
5089 band |= BAND_60_GHZ;
5090 else if (wpa_s->hw.modes[i].mode ==
5091 HOSTAPD_MODE_IEEE80211ANY)
5092 band = BAND_2_4_GHZ | BAND_5_GHZ |
5093 BAND_60_GHZ;
5094 }
5095 }
5096 }
5097
5098 return band;
5099}
5100
5101
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005102static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5103 const char *rn)
5104{
5105 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5106 struct wpa_radio *radio;
5107
5108 while (rn && iface) {
5109 radio = iface->radio;
5110 if (radio && os_strcmp(rn, radio->name) == 0) {
5111 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5112 wpa_s->ifname, rn);
5113 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5114 return radio;
5115 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005116
5117 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005118 }
5119
5120 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5121 wpa_s->ifname, rn ? rn : "N/A");
5122 radio = os_zalloc(sizeof(*radio));
5123 if (radio == NULL)
5124 return NULL;
5125
5126 if (rn)
5127 os_strlcpy(radio->name, rn, sizeof(radio->name));
5128 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005129 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005130 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5131
5132 return radio;
5133}
5134
5135
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005136static void radio_work_free(struct wpa_radio_work *work)
5137{
5138 if (work->wpa_s->scan_work == work) {
5139 /* This should not really happen. */
5140 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5141 work->type, work, work->started);
5142 work->wpa_s->scan_work = NULL;
5143 }
5144
5145#ifdef CONFIG_P2P
5146 if (work->wpa_s->p2p_scan_work == work) {
5147 /* This should not really happen. */
5148 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5149 work->type, work, work->started);
5150 work->wpa_s->p2p_scan_work = NULL;
5151 }
5152#endif /* CONFIG_P2P */
5153
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005154 if (work->started) {
5155 work->wpa_s->radio->num_active_works--;
5156 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005157 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005158 work->type, work,
5159 work->wpa_s->radio->num_active_works);
5160 }
5161
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005162 dl_list_del(&work->list);
5163 os_free(work);
5164}
5165
5166
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005167static int radio_work_is_connect(struct wpa_radio_work *work)
5168{
5169 return os_strcmp(work->type, "sme-connect") == 0 ||
5170 os_strcmp(work->type, "connect") == 0;
5171}
5172
5173
5174static int radio_work_is_scan(struct wpa_radio_work *work)
5175{
5176 return os_strcmp(work->type, "scan") == 0 ||
5177 os_strcmp(work->type, "p2p-scan") == 0;
5178}
5179
5180
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005181static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5182{
5183 struct wpa_radio_work *active_work = NULL;
5184 struct wpa_radio_work *tmp;
5185
5186 /* Get the active work to know the type and band. */
5187 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5188 if (tmp->started) {
5189 active_work = tmp;
5190 break;
5191 }
5192 }
5193
5194 if (!active_work) {
5195 /* No active work, start one */
5196 radio->num_active_works = 0;
5197 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5198 list) {
5199 if (os_strcmp(tmp->type, "scan") == 0 &&
5200 radio->external_scan_running &&
5201 (((struct wpa_driver_scan_params *)
5202 tmp->ctx)->only_new_results ||
5203 tmp->wpa_s->clear_driver_scan_cache))
5204 continue;
5205 return tmp;
5206 }
5207 return NULL;
5208 }
5209
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005210 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005211 /*
5212 * If the active work is either connect or sme-connect,
5213 * do not parallelize them with other radio works.
5214 */
5215 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5216 "Do not parallelize radio work with %s",
5217 active_work->type);
5218 return NULL;
5219 }
5220
5221 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5222 if (tmp->started)
5223 continue;
5224
5225 /*
5226 * If connect or sme-connect are enqueued, parallelize only
5227 * those operations ahead of them in the queue.
5228 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005229 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005230 break;
5231
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005232 /* Serialize parallel scan and p2p_scan operations on the same
5233 * interface since the driver_nl80211 mechanism for tracking
5234 * scan cookies does not yet have support for this. */
5235 if (active_work->wpa_s == tmp->wpa_s &&
5236 radio_work_is_scan(active_work) &&
5237 radio_work_is_scan(tmp)) {
5238 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5239 "Do not start work '%s' when another work '%s' is already scheduled",
5240 tmp->type, active_work->type);
5241 continue;
5242 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005243 /*
5244 * Check that the radio works are distinct and
5245 * on different bands.
5246 */
5247 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5248 (active_work->bands != tmp->bands)) {
5249 /*
5250 * If a scan has to be scheduled through nl80211 scan
5251 * interface and if an external scan is already running,
5252 * do not schedule the scan since it is likely to get
5253 * rejected by kernel.
5254 */
5255 if (os_strcmp(tmp->type, "scan") == 0 &&
5256 radio->external_scan_running &&
5257 (((struct wpa_driver_scan_params *)
5258 tmp->ctx)->only_new_results ||
5259 tmp->wpa_s->clear_driver_scan_cache))
5260 continue;
5261
5262 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5263 "active_work:%s new_work:%s",
5264 active_work->type, tmp->type);
5265 return tmp;
5266 }
5267 }
5268
5269 /* Did not find a radio work to schedule in parallel. */
5270 return NULL;
5271}
5272
5273
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005274static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5275{
5276 struct wpa_radio *radio = eloop_ctx;
5277 struct wpa_radio_work *work;
5278 struct os_reltime now, diff;
5279 struct wpa_supplicant *wpa_s;
5280
5281 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005282 if (work == NULL) {
5283 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005284 return;
5285 }
5286
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005287 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5288 radio_list);
5289
5290 if (!(wpa_s &&
5291 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5292 if (work->started)
5293 return; /* already started and still in progress */
5294
5295 if (wpa_s && wpa_s->radio->external_scan_running) {
5296 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5297 return;
5298 }
5299 } else {
5300 work = NULL;
5301 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5302 /* get the work to schedule next */
5303 work = radio_work_get_next_work(radio);
5304 }
5305 if (!work)
5306 return;
5307 }
5308
5309 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005310 os_get_reltime(&now);
5311 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005312 wpa_dbg(wpa_s, MSG_DEBUG,
5313 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005314 work->type, work, diff.sec, diff.usec);
5315 work->started = 1;
5316 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005317 radio->num_active_works++;
5318
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005319 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005320
5321 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5322 radio->num_active_works < MAX_ACTIVE_WORKS)
5323 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005324}
5325
5326
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005327/*
5328 * This function removes both started and pending radio works running on
5329 * the provided interface's radio.
5330 * Prior to the removal of the radio work, its callback (cb) is called with
5331 * deinit set to be 1. Each work's callback is responsible for clearing its
5332 * internal data and restoring to a correct state.
5333 * @wpa_s: wpa_supplicant data
5334 * @type: type of works to be removed
5335 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5336 * this interface's works.
5337 */
5338void radio_remove_works(struct wpa_supplicant *wpa_s,
5339 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005340{
5341 struct wpa_radio_work *work, *tmp;
5342 struct wpa_radio *radio = wpa_s->radio;
5343
5344 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5345 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005346 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005347 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005348
5349 /* skip other ifaces' works */
5350 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005351 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005352
5353 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5354 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005355 work->cb(work, 1);
5356 radio_work_free(work);
5357 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005358
5359 /* in case we removed the started work */
5360 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005361}
5362
5363
Roshan Pius3a1667e2018-07-03 15:17:14 -07005364void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5365{
5366 struct wpa_radio_work *work;
5367 struct wpa_radio *radio = wpa_s->radio;
5368
5369 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5370 if (work->ctx != ctx)
5371 continue;
5372 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5373 work->type, work, work->started ? " (started)" : "");
5374 radio_work_free(work);
5375 break;
5376 }
5377}
5378
5379
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005380static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5381{
5382 struct wpa_radio *radio = wpa_s->radio;
5383
5384 if (!radio)
5385 return;
5386
5387 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5388 wpa_s->ifname, radio->name);
5389 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005390 radio_remove_works(wpa_s, NULL, 0);
5391 wpa_s->radio = NULL;
5392 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005393 return; /* Interfaces remain for this radio */
5394
5395 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005396 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005397 os_free(radio);
5398}
5399
5400
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005401void radio_work_check_next(struct wpa_supplicant *wpa_s)
5402{
5403 struct wpa_radio *radio = wpa_s->radio;
5404
5405 if (dl_list_empty(&radio->work))
5406 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005407 if (wpa_s->ext_work_in_progress) {
5408 wpa_printf(MSG_DEBUG,
5409 "External radio work in progress - delay start of pending item");
5410 return;
5411 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005412 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5413 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5414}
5415
5416
5417/**
5418 * radio_add_work - Add a radio work item
5419 * @wpa_s: Pointer to wpa_supplicant data
5420 * @freq: Frequency of the offchannel operation in MHz or 0
5421 * @type: Unique identifier for each type of work
5422 * @next: Force as the next work to be executed
5423 * @cb: Callback function for indicating when radio is available
5424 * @ctx: Context pointer for the work (work->ctx in cb())
5425 * Returns: 0 on success, -1 on failure
5426 *
5427 * This function is used to request time for an operation that requires
5428 * exclusive radio control. Once the radio is available, the registered callback
5429 * function will be called. radio_work_done() must be called once the exclusive
5430 * radio operation has been completed, so that the radio is freed for other
5431 * operations. The special case of deinit=1 is used to free the context data
5432 * during interface removal. That does not allow the callback function to start
5433 * the radio operation, i.e., it must free any resources allocated for the radio
5434 * work and return.
5435 *
5436 * The @freq parameter can be used to indicate a single channel on which the
5437 * offchannel operation will occur. This may allow multiple radio work
5438 * operations to be performed in parallel if they apply for the same channel.
5439 * Setting this to 0 indicates that the work item may use multiple channels or
5440 * requires exclusive control of the radio.
5441 */
5442int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5443 const char *type, int next,
5444 void (*cb)(struct wpa_radio_work *work, int deinit),
5445 void *ctx)
5446{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005447 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005448 struct wpa_radio_work *work;
5449 int was_empty;
5450
5451 work = os_zalloc(sizeof(*work));
5452 if (work == NULL)
5453 return -1;
5454 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5455 os_get_reltime(&work->time);
5456 work->freq = freq;
5457 work->type = type;
5458 work->wpa_s = wpa_s;
5459 work->cb = cb;
5460 work->ctx = ctx;
5461
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005462 if (freq)
5463 work->bands = wpas_freq_to_band(freq);
5464 else if (os_strcmp(type, "scan") == 0 ||
5465 os_strcmp(type, "p2p-scan") == 0)
5466 work->bands = wpas_get_bands(wpa_s,
5467 ((struct wpa_driver_scan_params *)
5468 ctx)->freqs);
5469 else
5470 work->bands = wpas_get_bands(wpa_s, NULL);
5471
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005472 was_empty = dl_list_empty(&wpa_s->radio->work);
5473 if (next)
5474 dl_list_add(&wpa_s->radio->work, &work->list);
5475 else
5476 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5477 if (was_empty) {
5478 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5479 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005480 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5481 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5482 wpa_dbg(wpa_s, MSG_DEBUG,
5483 "Try to schedule a radio work (num_active_works=%u)",
5484 radio->num_active_works);
5485 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005486 }
5487
5488 return 0;
5489}
5490
5491
5492/**
5493 * radio_work_done - Indicate that a radio work item has been completed
5494 * @work: Completed work
5495 *
5496 * This function is called once the callback function registered with
5497 * radio_add_work() has completed its work.
5498 */
5499void radio_work_done(struct wpa_radio_work *work)
5500{
5501 struct wpa_supplicant *wpa_s = work->wpa_s;
5502 struct os_reltime now, diff;
5503 unsigned int started = work->started;
5504
5505 os_get_reltime(&now);
5506 os_reltime_sub(&now, &work->time, &diff);
5507 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5508 work->type, work, started ? "done" : "canceled",
5509 diff.sec, diff.usec);
5510 radio_work_free(work);
5511 if (started)
5512 radio_work_check_next(wpa_s);
5513}
5514
5515
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005516struct wpa_radio_work *
5517radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005518{
5519 struct wpa_radio_work *work;
5520 struct wpa_radio *radio = wpa_s->radio;
5521
5522 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5523 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005524 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005525 }
5526
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005527 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005528}
5529
5530
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005531static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005532 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005533{
5534 const char *ifname, *driver, *rn;
5535
5536 driver = iface->driver;
5537next_driver:
5538 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
5539 return -1;
5540
5541 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
5542 if (wpa_s->drv_priv == NULL) {
5543 const char *pos;
5544 pos = driver ? os_strchr(driver, ',') : NULL;
5545 if (pos) {
5546 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
5547 "driver interface - try next driver wrapper");
5548 driver = pos + 1;
5549 goto next_driver;
5550 }
5551 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
5552 "interface");
5553 return -1;
5554 }
5555 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
5556 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
5557 "driver_param '%s'", wpa_s->conf->driver_param);
5558 return -1;
5559 }
5560
5561 ifname = wpa_drv_get_ifname(wpa_s);
5562 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
5563 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
5564 "interface name with '%s'", ifname);
5565 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
5566 }
5567
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005568 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005569 if (rn && rn[0] == '\0')
5570 rn = NULL;
5571
5572 wpa_s->radio = radio_add_interface(wpa_s, rn);
5573 if (wpa_s->radio == NULL)
5574 return -1;
5575
5576 return 0;
5577}
5578
5579
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005580#ifdef CONFIG_GAS_SERVER
5581
5582static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
5583 unsigned int freq, const u8 *dst,
5584 const u8 *src, const u8 *bssid,
5585 const u8 *data, size_t data_len,
5586 enum offchannel_send_action_result result)
5587{
5588 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
5589 " result=%s",
5590 freq, MAC2STR(dst),
5591 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
5592 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
5593 "FAILED"));
5594 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
5595 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
5596}
5597
5598
5599static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
5600 struct wpabuf *buf, unsigned int wait_time)
5601{
5602 struct wpa_supplicant *wpa_s = ctx;
5603 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
5604
5605 if (wait_time > wpa_s->max_remain_on_chan)
5606 wait_time = wpa_s->max_remain_on_chan;
5607
5608 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
5609 wpabuf_head(buf), wpabuf_len(buf),
5610 wait_time, wpas_gas_server_tx_status, 0);
5611}
5612
5613#endif /* CONFIG_GAS_SERVER */
5614
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005615static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005616 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005617{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005618 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005619 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005620 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005621
5622 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
5623 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
5624 iface->confname ? iface->confname : "N/A",
5625 iface->driver ? iface->driver : "default",
5626 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
5627 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
5628
5629 if (iface->confname) {
5630#ifdef CONFIG_BACKEND_FILE
5631 wpa_s->confname = os_rel2abs_path(iface->confname);
5632 if (wpa_s->confname == NULL) {
5633 wpa_printf(MSG_ERROR, "Failed to get absolute path "
5634 "for configuration file '%s'.",
5635 iface->confname);
5636 return -1;
5637 }
5638 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
5639 iface->confname, wpa_s->confname);
5640#else /* CONFIG_BACKEND_FILE */
5641 wpa_s->confname = os_strdup(iface->confname);
5642#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005643 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005644 if (wpa_s->conf == NULL) {
5645 wpa_printf(MSG_ERROR, "Failed to read or parse "
5646 "configuration '%s'.", wpa_s->confname);
5647 return -1;
5648 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005649 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005650 if (wpa_s->confanother &&
5651 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
5652 wpa_printf(MSG_ERROR,
5653 "Failed to read or parse configuration '%s'.",
5654 wpa_s->confanother);
5655 return -1;
5656 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005657
5658 /*
5659 * Override ctrl_interface and driver_param if set on command
5660 * line.
5661 */
5662 if (iface->ctrl_interface) {
5663 os_free(wpa_s->conf->ctrl_interface);
5664 wpa_s->conf->ctrl_interface =
5665 os_strdup(iface->ctrl_interface);
5666 }
5667
5668 if (iface->driver_param) {
5669 os_free(wpa_s->conf->driver_param);
5670 wpa_s->conf->driver_param =
5671 os_strdup(iface->driver_param);
5672 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005673
5674 if (iface->p2p_mgmt && !iface->ctrl_interface) {
5675 os_free(wpa_s->conf->ctrl_interface);
5676 wpa_s->conf->ctrl_interface = NULL;
5677 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005678 } else
5679 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
5680 iface->driver_param);
5681
5682 if (wpa_s->conf == NULL) {
5683 wpa_printf(MSG_ERROR, "\nNo configuration found.");
5684 return -1;
5685 }
5686
5687 if (iface->ifname == NULL) {
5688 wpa_printf(MSG_ERROR, "\nInterface name is required.");
5689 return -1;
5690 }
5691 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
5692 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
5693 iface->ifname);
5694 return -1;
5695 }
5696 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
5697
5698 if (iface->bridge_ifname) {
5699 if (os_strlen(iface->bridge_ifname) >=
5700 sizeof(wpa_s->bridge_ifname)) {
5701 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
5702 "name '%s'.", iface->bridge_ifname);
5703 return -1;
5704 }
5705 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
5706 sizeof(wpa_s->bridge_ifname));
5707 }
5708
5709 /* RSNA Supplicant Key Management - INITIALIZE */
5710 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
5711 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
5712
5713 /* Initialize driver interface and register driver event handler before
5714 * L2 receive handler so that association events are processed before
5715 * EAPOL-Key packets if both become available for the same select()
5716 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005717 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005718 return -1;
5719
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005720 if (wpa_supplicant_init_wpa(wpa_s) < 0)
5721 return -1;
5722
5723 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
5724 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
5725 NULL);
5726 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
5727
5728 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
5729 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
5730 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
5731 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5732 "dot11RSNAConfigPMKLifetime");
5733 return -1;
5734 }
5735
5736 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
5737 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
5738 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
5739 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5740 "dot11RSNAConfigPMKReauthThreshold");
5741 return -1;
5742 }
5743
5744 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
5745 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
5746 wpa_s->conf->dot11RSNAConfigSATimeout)) {
5747 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5748 "dot11RSNAConfigSATimeout");
5749 return -1;
5750 }
5751
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005752 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
5753 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005754 &wpa_s->hw.flags,
5755 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005756 if (wpa_s->hw.modes) {
5757 u16 i;
5758
5759 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5760 if (wpa_s->hw.modes[i].vht_capab) {
5761 wpa_s->hw_capab = CAPAB_VHT;
5762 break;
5763 }
5764
5765 if (wpa_s->hw.modes[i].ht_capab &
5766 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
5767 wpa_s->hw_capab = CAPAB_HT40;
5768 else if (wpa_s->hw.modes[i].ht_capab &&
5769 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
5770 wpa_s->hw_capab = CAPAB_HT;
5771 }
5772 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005773
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005774 capa_res = wpa_drv_get_capa(wpa_s, &capa);
5775 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005776 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005777 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005778 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005779 wpa_s->drv_smps_modes = capa.smps_modes;
5780 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005781 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005782 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005783 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005784 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
5785 wpa_s->max_sched_scan_plan_interval =
5786 capa.max_sched_scan_plan_interval;
5787 wpa_s->max_sched_scan_plan_iterations =
5788 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005789 wpa_s->sched_scan_supported = capa.sched_scan_supported;
5790 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005791 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
5792 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005793 wpa_s->extended_capa = capa.extended_capa;
5794 wpa_s->extended_capa_mask = capa.extended_capa_mask;
5795 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005796 wpa_s->num_multichan_concurrent =
5797 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005798 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
5799
5800 if (capa.mac_addr_rand_scan_supported)
5801 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
5802 if (wpa_s->sched_scan_supported &&
5803 capa.mac_addr_rand_sched_scan_supported)
5804 wpa_s->mac_addr_rand_supported |=
5805 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08005806
5807 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
5808 if (wpa_s->extended_capa &&
5809 wpa_s->extended_capa_len >= 3 &&
5810 wpa_s->extended_capa[2] & 0x40)
5811 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005812 }
5813 if (wpa_s->max_remain_on_chan == 0)
5814 wpa_s->max_remain_on_chan = 1000;
5815
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005816 /*
5817 * Only take p2p_mgmt parameters when P2P Device is supported.
5818 * Doing it here as it determines whether l2_packet_init() will be done
5819 * during wpa_supplicant_driver_init().
5820 */
5821 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
5822 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005823
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005824 if (wpa_s->num_multichan_concurrent == 0)
5825 wpa_s->num_multichan_concurrent = 1;
5826
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005827 if (wpa_supplicant_driver_init(wpa_s) < 0)
5828 return -1;
5829
5830#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07005831 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005832 return -1;
5833#endif /* CONFIG_TDLS */
5834
5835 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
5836 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
5837 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
5838 return -1;
5839 }
5840
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005841#ifdef CONFIG_FST
5842 if (wpa_s->conf->fst_group_id) {
5843 struct fst_iface_cfg cfg;
5844 struct fst_wpa_obj iface_obj;
5845
5846 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
5847 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
5848 sizeof(cfg.group_id));
5849 cfg.priority = wpa_s->conf->fst_priority;
5850 cfg.llt = wpa_s->conf->fst_llt;
5851
5852 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
5853 &iface_obj, &cfg);
5854 if (!wpa_s->fst) {
5855 wpa_msg(wpa_s, MSG_ERROR,
5856 "FST: Cannot attach iface %s to group %s",
5857 wpa_s->ifname, cfg.group_id);
5858 return -1;
5859 }
5860 }
5861#endif /* CONFIG_FST */
5862
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005863 if (wpas_wps_init(wpa_s))
5864 return -1;
5865
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005866#ifdef CONFIG_GAS_SERVER
5867 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
5868 if (!wpa_s->gas_server) {
5869 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
5870 return -1;
5871 }
5872#endif /* CONFIG_GAS_SERVER */
5873
5874#ifdef CONFIG_DPP
5875 if (wpas_dpp_init(wpa_s) < 0)
5876 return -1;
5877#endif /* CONFIG_DPP */
5878
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005879 if (wpa_supplicant_init_eapol(wpa_s) < 0)
5880 return -1;
5881 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5882
5883 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
5884 if (wpa_s->ctrl_iface == NULL) {
5885 wpa_printf(MSG_ERROR,
5886 "Failed to initialize control interface '%s'.\n"
5887 "You may have another wpa_supplicant process "
5888 "already running or the file was\n"
5889 "left by an unclean termination of wpa_supplicant "
5890 "in which case you will need\n"
5891 "to manually remove this file before starting "
5892 "wpa_supplicant again.\n",
5893 wpa_s->conf->ctrl_interface);
5894 return -1;
5895 }
5896
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005897 wpa_s->gas = gas_query_init(wpa_s);
5898 if (wpa_s->gas == NULL) {
5899 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5900 return -1;
5901 }
5902
Roshan Pius3a1667e2018-07-03 15:17:14 -07005903 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
5904 wpa_s->p2p_mgmt) &&
5905 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005906 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5907 return -1;
5908 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005909
5910 if (wpa_bss_init(wpa_s) < 0)
5911 return -1;
5912
Paul Stewart092955c2017-02-06 09:13:09 -08005913#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5914#ifdef CONFIG_MESH
5915 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
5916#endif /* CONFIG_MESH */
5917#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5918
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005919 /*
5920 * Set Wake-on-WLAN triggers, if configured.
5921 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5922 * have effect anyway when the interface is down).
5923 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005924 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005925 return -1;
5926
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005927#ifdef CONFIG_EAP_PROXY
5928{
5929 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005930 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
5931 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005932 if (wpa_s->mnc_len > 0) {
5933 wpa_s->imsi[len] = '\0';
5934 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5935 wpa_s->imsi, wpa_s->mnc_len);
5936 } else {
5937 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5938 }
5939}
5940#endif /* CONFIG_EAP_PROXY */
5941
Dmitry Shmidt04949592012-07-19 12:16:46 -07005942 if (pcsc_reader_init(wpa_s) < 0)
5943 return -1;
5944
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005945 if (wpas_init_ext_pw(wpa_s) < 0)
5946 return -1;
5947
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005948 wpas_rrm_reset(wpa_s);
5949
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005950 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5951
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005952#ifdef CONFIG_HS20
5953 hs20_init(wpa_s);
5954#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005955#ifdef CONFIG_MBO
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005956 if (wpa_s->conf->oce) {
5957 if ((wpa_s->conf->oce & OCE_STA) &&
5958 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
5959 wpa_s->enable_oce = OCE_STA;
5960 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
5961 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
5962 /* TODO: Need to add STA-CFON support */
5963 wpa_printf(MSG_ERROR,
5964 "OCE STA-CFON feature is not yet supported");
5965 }
5966 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005967 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5968#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005969
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005970 wpa_supplicant_set_default_scan_ies(wpa_s);
5971
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005972 return 0;
5973}
5974
5975
5976static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005977 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005978{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005979 struct wpa_global *global = wpa_s->global;
5980 struct wpa_supplicant *iface, *prev;
5981
5982 if (wpa_s == wpa_s->parent)
5983 wpas_p2p_group_remove(wpa_s, "*");
5984
5985 iface = global->ifaces;
5986 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005987 if (iface->p2pdev == wpa_s)
5988 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005989 if (iface == wpa_s || iface->parent != wpa_s) {
5990 iface = iface->next;
5991 continue;
5992 }
5993 wpa_printf(MSG_DEBUG,
5994 "Remove remaining child interface %s from parent %s",
5995 iface->ifname, wpa_s->ifname);
5996 prev = iface;
5997 iface = iface->next;
5998 wpa_supplicant_remove_iface(global, prev, terminate);
5999 }
6000
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006001 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006002 if (wpa_s->drv_priv) {
6003 wpa_supplicant_deauthenticate(wpa_s,
6004 WLAN_REASON_DEAUTH_LEAVING);
6005
6006 wpa_drv_set_countermeasures(wpa_s, 0);
6007 wpa_clear_keys(wpa_s, NULL);
6008 }
6009
6010 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006011 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006012
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006013 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006014 radio_remove_interface(wpa_s);
6015
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006016#ifdef CONFIG_FST
6017 if (wpa_s->fst) {
6018 fst_detach(wpa_s->fst);
6019 wpa_s->fst = NULL;
6020 }
6021 if (wpa_s->received_mb_ies) {
6022 wpabuf_free(wpa_s->received_mb_ies);
6023 wpa_s->received_mb_ies = NULL;
6024 }
6025#endif /* CONFIG_FST */
6026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006027 if (wpa_s->drv_priv)
6028 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006029
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006030 if (notify)
6031 wpas_notify_iface_removed(wpa_s);
6032
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006033 if (terminate)
6034 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006035
6036 if (wpa_s->ctrl_iface) {
6037 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6038 wpa_s->ctrl_iface = NULL;
6039 }
6040
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006041#ifdef CONFIG_MESH
6042 if (wpa_s->ifmsh) {
6043 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6044 wpa_s->ifmsh = NULL;
6045 }
6046#endif /* CONFIG_MESH */
6047
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006048 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006049 wpa_config_free(wpa_s->conf);
6050 wpa_s->conf = NULL;
6051 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006052
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006053 os_free(wpa_s->ssids_from_scan_req);
6054
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006055 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006056}
6057
6058
Dmitry Shmidte4663042016-04-04 10:07:49 -07006059#ifdef CONFIG_MATCH_IFACE
6060
6061/**
6062 * wpa_supplicant_match_iface - Match an interface description to a name
6063 * @global: Pointer to global data from wpa_supplicant_init()
6064 * @ifname: Name of the interface to match
6065 * Returns: Pointer to the created interface description or %NULL on failure
6066 */
6067struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6068 const char *ifname)
6069{
6070 int i;
6071 struct wpa_interface *iface, *miface;
6072
6073 for (i = 0; i < global->params.match_iface_count; i++) {
6074 miface = &global->params.match_ifaces[i];
6075 if (!miface->ifname ||
6076 fnmatch(miface->ifname, ifname, 0) == 0) {
6077 iface = os_zalloc(sizeof(*iface));
6078 if (!iface)
6079 return NULL;
6080 *iface = *miface;
6081 iface->ifname = ifname;
6082 return iface;
6083 }
6084 }
6085
6086 return NULL;
6087}
6088
6089
6090/**
6091 * wpa_supplicant_match_existing - Match existing interfaces
6092 * @global: Pointer to global data from wpa_supplicant_init()
6093 * Returns: 0 on success, -1 on failure
6094 */
6095static int wpa_supplicant_match_existing(struct wpa_global *global)
6096{
6097 struct if_nameindex *ifi, *ifp;
6098 struct wpa_supplicant *wpa_s;
6099 struct wpa_interface *iface;
6100
6101 ifp = if_nameindex();
6102 if (!ifp) {
6103 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6104 return -1;
6105 }
6106
6107 for (ifi = ifp; ifi->if_name; ifi++) {
6108 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6109 if (wpa_s)
6110 continue;
6111 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6112 if (iface) {
6113 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6114 os_free(iface);
6115 if (wpa_s)
6116 wpa_s->matched = 1;
6117 }
6118 }
6119
6120 if_freenameindex(ifp);
6121 return 0;
6122}
6123
6124#endif /* CONFIG_MATCH_IFACE */
6125
6126
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006127/**
6128 * wpa_supplicant_add_iface - Add a new network interface
6129 * @global: Pointer to global data from wpa_supplicant_init()
6130 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006131 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006132 * Returns: Pointer to the created interface or %NULL on failure
6133 *
6134 * This function is used to add new network interfaces for %wpa_supplicant.
6135 * This can be called before wpa_supplicant_run() to add interfaces before the
6136 * main event loop has been started. In addition, new interfaces can be added
6137 * dynamically while %wpa_supplicant is already running. This could happen,
6138 * e.g., when a hotplug network adapter is inserted.
6139 */
6140struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006141 struct wpa_interface *iface,
6142 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006143{
6144 struct wpa_supplicant *wpa_s;
6145 struct wpa_interface t_iface;
6146 struct wpa_ssid *ssid;
6147
6148 if (global == NULL || iface == NULL)
6149 return NULL;
6150
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006151 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006152 if (wpa_s == NULL)
6153 return NULL;
6154
6155 wpa_s->global = global;
6156
6157 t_iface = *iface;
6158 if (global->params.override_driver) {
6159 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6160 "('%s' -> '%s')",
6161 iface->driver, global->params.override_driver);
6162 t_iface.driver = global->params.override_driver;
6163 }
6164 if (global->params.override_ctrl_interface) {
6165 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6166 "ctrl_interface ('%s' -> '%s')",
6167 iface->ctrl_interface,
6168 global->params.override_ctrl_interface);
6169 t_iface.ctrl_interface =
6170 global->params.override_ctrl_interface;
6171 }
6172 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6173 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6174 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006175 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006176 return NULL;
6177 }
6178
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006179 /* Notify the control interfaces about new iface */
6180 if (wpas_notify_iface_added(wpa_s)) {
6181 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6182 return NULL;
6183 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006184
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006185 /* Notify the control interfaces about new networks for non p2p mgmt
6186 * ifaces. */
6187 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006188 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6189 wpas_notify_network_added(wpa_s, ssid);
6190 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006191
6192 wpa_s->next = global->ifaces;
6193 global->ifaces = wpa_s;
6194
6195 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006196 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006197
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006198#ifdef CONFIG_P2P
6199 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006200 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006201 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006202 wpas_p2p_add_p2pdev_interface(
6203 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006204 wpa_printf(MSG_INFO,
6205 "P2P: Failed to enable P2P Device interface");
6206 /* Try to continue without. P2P will be disabled. */
6207 }
6208#endif /* CONFIG_P2P */
6209
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006210 return wpa_s;
6211}
6212
6213
6214/**
6215 * wpa_supplicant_remove_iface - Remove a network interface
6216 * @global: Pointer to global data from wpa_supplicant_init()
6217 * @wpa_s: Pointer to the network interface to be removed
6218 * Returns: 0 if interface was removed, -1 if interface was not found
6219 *
6220 * This function can be used to dynamically remove network interfaces from
6221 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6222 * addition, this function is used to remove all remaining interfaces when
6223 * %wpa_supplicant is terminated.
6224 */
6225int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006226 struct wpa_supplicant *wpa_s,
6227 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006228{
6229 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006230#ifdef CONFIG_MESH
6231 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6232 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006233 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006234#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006235
6236 /* Remove interface from the global list of interfaces */
6237 prev = global->ifaces;
6238 if (prev == wpa_s) {
6239 global->ifaces = wpa_s->next;
6240 } else {
6241 while (prev && prev->next != wpa_s)
6242 prev = prev->next;
6243 if (prev == NULL)
6244 return -1;
6245 prev->next = wpa_s->next;
6246 }
6247
6248 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6249
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006250#ifdef CONFIG_MESH
6251 if (mesh_if_created) {
6252 ifname = os_strdup(wpa_s->ifname);
6253 if (ifname == NULL) {
6254 wpa_dbg(wpa_s, MSG_ERROR,
6255 "mesh: Failed to malloc ifname");
6256 return -1;
6257 }
6258 }
6259#endif /* CONFIG_MESH */
6260
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006261 if (global->p2p_group_formation == wpa_s)
6262 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006263 if (global->p2p_invite_group == wpa_s)
6264 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006265 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006266
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006267#ifdef CONFIG_MESH
6268 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006269 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006270 os_free(ifname);
6271 }
6272#endif /* CONFIG_MESH */
6273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006274 return 0;
6275}
6276
6277
6278/**
6279 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6280 * @wpa_s: Pointer to the network interface
6281 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6282 */
6283const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6284{
6285 const char *eapol_method;
6286
6287 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6288 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6289 return "NO-EAP";
6290 }
6291
6292 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6293 if (eapol_method == NULL)
6294 return "UNKNOWN-EAP";
6295
6296 return eapol_method;
6297}
6298
6299
6300/**
6301 * wpa_supplicant_get_iface - Get a new network interface
6302 * @global: Pointer to global data from wpa_supplicant_init()
6303 * @ifname: Interface name
6304 * Returns: Pointer to the interface or %NULL if not found
6305 */
6306struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6307 const char *ifname)
6308{
6309 struct wpa_supplicant *wpa_s;
6310
6311 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6312 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6313 return wpa_s;
6314 }
6315 return NULL;
6316}
6317
6318
6319#ifndef CONFIG_NO_WPA_MSG
6320static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6321{
6322 struct wpa_supplicant *wpa_s = ctx;
6323 if (wpa_s == NULL)
6324 return NULL;
6325 return wpa_s->ifname;
6326}
6327#endif /* CONFIG_NO_WPA_MSG */
6328
6329
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006330#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6331#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6332#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6333
6334/* Periodic cleanup tasks */
6335static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6336{
6337 struct wpa_global *global = eloop_ctx;
6338 struct wpa_supplicant *wpa_s;
6339
6340 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6341 wpas_periodic, global, NULL);
6342
6343#ifdef CONFIG_P2P
6344 if (global->p2p)
6345 p2p_expire_peers(global->p2p);
6346#endif /* CONFIG_P2P */
6347
6348 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6349 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6350#ifdef CONFIG_AP
6351 ap_periodic(wpa_s);
6352#endif /* CONFIG_AP */
6353 }
6354}
6355
6356
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006357/**
6358 * wpa_supplicant_init - Initialize %wpa_supplicant
6359 * @params: Parameters for %wpa_supplicant
6360 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6361 *
6362 * This function is used to initialize %wpa_supplicant. After successful
6363 * initialization, the returned data pointer can be used to add and remove
6364 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6365 */
6366struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6367{
6368 struct wpa_global *global;
6369 int ret, i;
6370
6371 if (params == NULL)
6372 return NULL;
6373
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006374#ifdef CONFIG_DRIVER_NDIS
6375 {
6376 void driver_ndis_init_ops(void);
6377 driver_ndis_init_ops();
6378 }
6379#endif /* CONFIG_DRIVER_NDIS */
6380
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006381#ifndef CONFIG_NO_WPA_MSG
6382 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6383#endif /* CONFIG_NO_WPA_MSG */
6384
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006385 if (params->wpa_debug_file_path)
6386 wpa_debug_open_file(params->wpa_debug_file_path);
6387 else
6388 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006389 if (params->wpa_debug_syslog)
6390 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006391 if (params->wpa_debug_tracing) {
6392 ret = wpa_debug_open_linux_tracing();
6393 if (ret) {
6394 wpa_printf(MSG_ERROR,
6395 "Failed to enable trace logging");
6396 return NULL;
6397 }
6398 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006399
6400 ret = eap_register_methods();
6401 if (ret) {
6402 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6403 if (ret == -2)
6404 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6405 "the same EAP type.");
6406 return NULL;
6407 }
6408
6409 global = os_zalloc(sizeof(*global));
6410 if (global == NULL)
6411 return NULL;
6412 dl_list_init(&global->p2p_srv_bonjour);
6413 dl_list_init(&global->p2p_srv_upnp);
6414 global->params.daemonize = params->daemonize;
6415 global->params.wait_for_monitor = params->wait_for_monitor;
6416 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6417 if (params->pid_file)
6418 global->params.pid_file = os_strdup(params->pid_file);
6419 if (params->ctrl_interface)
6420 global->params.ctrl_interface =
6421 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006422 if (params->ctrl_interface_group)
6423 global->params.ctrl_interface_group =
6424 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006425 if (params->override_driver)
6426 global->params.override_driver =
6427 os_strdup(params->override_driver);
6428 if (params->override_ctrl_interface)
6429 global->params.override_ctrl_interface =
6430 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006431#ifdef CONFIG_MATCH_IFACE
6432 global->params.match_iface_count = params->match_iface_count;
6433 if (params->match_iface_count) {
6434 global->params.match_ifaces =
6435 os_calloc(params->match_iface_count,
6436 sizeof(struct wpa_interface));
6437 os_memcpy(global->params.match_ifaces,
6438 params->match_ifaces,
6439 params->match_iface_count *
6440 sizeof(struct wpa_interface));
6441 }
6442#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006443#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006444 if (params->conf_p2p_dev)
6445 global->params.conf_p2p_dev =
6446 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006447#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006448 wpa_debug_level = global->params.wpa_debug_level =
6449 params->wpa_debug_level;
6450 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6451 params->wpa_debug_show_keys;
6452 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6453 params->wpa_debug_timestamp;
6454
6455 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
6456
6457 if (eloop_init()) {
6458 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6459 wpa_supplicant_deinit(global);
6460 return NULL;
6461 }
6462
Jouni Malinen75ecf522011-06-27 15:19:46 -07006463 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006464
6465 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6466 if (global->ctrl_iface == NULL) {
6467 wpa_supplicant_deinit(global);
6468 return NULL;
6469 }
6470
6471 if (wpas_notify_supplicant_initialized(global)) {
6472 wpa_supplicant_deinit(global);
6473 return NULL;
6474 }
6475
6476 for (i = 0; wpa_drivers[i]; i++)
6477 global->drv_count++;
6478 if (global->drv_count == 0) {
6479 wpa_printf(MSG_ERROR, "No drivers enabled");
6480 wpa_supplicant_deinit(global);
6481 return NULL;
6482 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006483 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006484 if (global->drv_priv == NULL) {
6485 wpa_supplicant_deinit(global);
6486 return NULL;
6487 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006488
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006489#ifdef CONFIG_WIFI_DISPLAY
6490 if (wifi_display_init(global) < 0) {
6491 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6492 wpa_supplicant_deinit(global);
6493 return NULL;
6494 }
6495#endif /* CONFIG_WIFI_DISPLAY */
6496
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006497 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6498 wpas_periodic, global, NULL);
6499
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006500 return global;
6501}
6502
6503
6504/**
6505 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6506 * @global: Pointer to global data from wpa_supplicant_init()
6507 * Returns: 0 after successful event loop run, -1 on failure
6508 *
6509 * This function starts the main event loop and continues running as long as
6510 * there are any remaining events. In most cases, this function is running as
6511 * long as the %wpa_supplicant process in still in use.
6512 */
6513int wpa_supplicant_run(struct wpa_global *global)
6514{
6515 struct wpa_supplicant *wpa_s;
6516
6517 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006518 (wpa_supplicant_daemon(global->params.pid_file) ||
6519 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006520 return -1;
6521
Dmitry Shmidte4663042016-04-04 10:07:49 -07006522#ifdef CONFIG_MATCH_IFACE
6523 if (wpa_supplicant_match_existing(global))
6524 return -1;
6525#endif
6526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006527 if (global->params.wait_for_monitor) {
6528 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08006529 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006530 wpa_supplicant_ctrl_iface_wait(
6531 wpa_s->ctrl_iface);
6532 }
6533
6534 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
6535 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
6536
6537 eloop_run();
6538
6539 return 0;
6540}
6541
6542
6543/**
6544 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
6545 * @global: Pointer to global data from wpa_supplicant_init()
6546 *
6547 * This function is called to deinitialize %wpa_supplicant and to free all
6548 * allocated resources. Remaining network interfaces will also be removed.
6549 */
6550void wpa_supplicant_deinit(struct wpa_global *global)
6551{
6552 int i;
6553
6554 if (global == NULL)
6555 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006556
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006557 eloop_cancel_timeout(wpas_periodic, global, NULL);
6558
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006559#ifdef CONFIG_WIFI_DISPLAY
6560 wifi_display_deinit(global);
6561#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006562
6563 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006564 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006565
6566 if (global->ctrl_iface)
6567 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
6568
6569 wpas_notify_supplicant_deinitialized(global);
6570
6571 eap_peer_unregister_methods();
6572#ifdef CONFIG_AP
6573 eap_server_unregister_methods();
6574#endif /* CONFIG_AP */
6575
6576 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
6577 if (!global->drv_priv[i])
6578 continue;
6579 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
6580 }
6581 os_free(global->drv_priv);
6582
6583 random_deinit();
6584
6585 eloop_destroy();
6586
6587 if (global->params.pid_file) {
6588 os_daemonize_terminate(global->params.pid_file);
6589 os_free(global->params.pid_file);
6590 }
6591 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006592 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006593 os_free(global->params.override_driver);
6594 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006595#ifdef CONFIG_MATCH_IFACE
6596 os_free(global->params.match_ifaces);
6597#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006598#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006599 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006600#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006601
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07006602 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006603 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006604 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006605
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006606 os_free(global);
6607 wpa_debug_close_syslog();
6608 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006609 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006610}
6611
6612
6613void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
6614{
6615 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
6616 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
6617 char country[3];
6618 country[0] = wpa_s->conf->country[0];
6619 country[1] = wpa_s->conf->country[1];
6620 country[2] = '\0';
6621 if (wpa_drv_set_country(wpa_s, country) < 0) {
6622 wpa_printf(MSG_ERROR, "Failed to set country code "
6623 "'%s'", country);
6624 }
6625 }
6626
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006627 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
6628 wpas_init_ext_pw(wpa_s);
6629
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006630 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
6631 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6632
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006633 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
6634 struct wpa_driver_capa capa;
6635 int res = wpa_drv_get_capa(wpa_s, &capa);
6636
6637 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
6638 wpa_printf(MSG_ERROR,
6639 "Failed to update wowlan_triggers to '%s'",
6640 wpa_s->conf->wowlan_triggers);
6641 }
6642
Hai Shalom81f62d82019-07-22 12:10:00 -07006643 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
6644 wpa_supplicant_set_default_scan_ies(wpa_s);
6645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006646#ifdef CONFIG_WPS
6647 wpas_wps_update_config(wpa_s);
6648#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006649 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006650 wpa_s->conf->changed_parameters = 0;
6651}
6652
6653
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006654void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006655{
6656 int i;
6657
6658 for (i = 0; i < *num_freqs; i++) {
6659 if (freqs[i] == freq)
6660 return;
6661 }
6662
6663 freqs[*num_freqs] = freq;
6664 (*num_freqs)++;
6665}
6666
6667
6668static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
6669{
6670 struct wpa_bss *bss, *cbss;
6671 const int max_freqs = 10;
6672 int *freqs;
6673 int num_freqs = 0;
6674
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006675 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006676 if (freqs == NULL)
6677 return NULL;
6678
6679 cbss = wpa_s->current_bss;
6680
6681 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
6682 if (bss == cbss)
6683 continue;
6684 if (bss->ssid_len == cbss->ssid_len &&
6685 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
6686 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
6687 add_freq(freqs, &num_freqs, bss->freq);
6688 if (num_freqs == max_freqs)
6689 break;
6690 }
6691 }
6692
6693 if (num_freqs == 0) {
6694 os_free(freqs);
6695 freqs = NULL;
6696 }
6697
6698 return freqs;
6699}
6700
6701
6702void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6703{
6704 int timeout;
6705 int count;
6706 int *freqs = NULL;
6707
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006708 wpas_connect_work_done(wpa_s);
6709
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006710 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006711 * Remove possible authentication timeout since the connection failed.
6712 */
6713 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
6714
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006715 /*
6716 * There is no point in blacklisting the AP if this event is
6717 * generated based on local request to disconnect.
6718 */
6719 if (wpa_s->own_disconnect_req) {
6720 wpa_s->own_disconnect_req = 0;
6721 wpa_dbg(wpa_s, MSG_DEBUG,
6722 "Ignore connection failure due to local request to disconnect");
6723 return;
6724 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006725 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006726 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6727 "indication since interface has been put into "
6728 "disconnected state");
6729 return;
6730 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08006731 if (wpa_s->auto_reconnect_disabled) {
6732 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6733 "indication since auto connect is disabled");
6734 return;
6735 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006736
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006737 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006738 * Add the failed BSSID into the blacklist and speed up next scan
6739 * attempt if there could be other APs that could accept association.
6740 * The current blacklist count indicates how many times we have tried
6741 * connecting to this AP and multiple attempts mean that other APs are
6742 * either not available or has already been tried, so that we can start
6743 * increasing the delay here to avoid constant scanning.
6744 */
6745 count = wpa_blacklist_add(wpa_s, bssid);
6746 if (count == 1 && wpa_s->current_bss) {
6747 /*
6748 * This BSS was not in the blacklist before. If there is
6749 * another BSS available for the same ESS, we should try that
6750 * next. Otherwise, we may as well try this one once more
6751 * before allowing other, likely worse, ESSes to be considered.
6752 */
6753 freqs = get_bss_freqs_in_ess(wpa_s);
6754 if (freqs) {
6755 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
6756 "has been seen; try it next");
6757 wpa_blacklist_add(wpa_s, bssid);
6758 /*
6759 * On the next scan, go through only the known channels
6760 * used in this ESS based on previous scans to speed up
6761 * common load balancing use case.
6762 */
6763 os_free(wpa_s->next_scan_freqs);
6764 wpa_s->next_scan_freqs = freqs;
6765 }
6766 }
6767
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006768 /*
6769 * Add previous failure count in case the temporary blacklist was
6770 * cleared due to no other BSSes being available.
6771 */
6772 count += wpa_s->extra_blacklist_count;
6773
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006774 if (count > 3 && wpa_s->current_ssid) {
6775 wpa_printf(MSG_DEBUG, "Continuous association failures - "
6776 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006777 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006778 }
6779
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006780 switch (count) {
6781 case 1:
6782 timeout = 100;
6783 break;
6784 case 2:
6785 timeout = 500;
6786 break;
6787 case 3:
6788 timeout = 1000;
6789 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006790 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006791 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006792 break;
6793 default:
6794 timeout = 10000;
6795 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006796 }
6797
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006798 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
6799 "ms", count, timeout);
6800
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006801 /*
6802 * TODO: if more than one possible AP is available in scan results,
6803 * could try the other ones before requesting a new scan.
6804 */
Hai Shalom021b0b52019-04-10 11:17:58 -07006805
6806 /* speed up the connection attempt with normal scan */
6807 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006808 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
6809 1000 * (timeout % 1000));
6810}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006811
6812
Hai Shalomce48b4a2018-09-05 11:41:35 -07006813#ifdef CONFIG_FILS
6814void fils_connection_failure(struct wpa_supplicant *wpa_s)
6815{
6816 struct wpa_ssid *ssid = wpa_s->current_ssid;
6817 const u8 *realm, *username, *rrk;
6818 size_t realm_len, username_len, rrk_len;
6819 u16 next_seq_num;
6820
6821 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
6822 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
6823 &username, &username_len,
6824 &realm, &realm_len, &next_seq_num,
6825 &rrk, &rrk_len) != 0 ||
6826 !realm)
6827 return;
6828
6829 wpa_hexdump_ascii(MSG_DEBUG,
6830 "FILS: Store last connection failure realm",
6831 realm, realm_len);
6832 os_free(wpa_s->last_con_fail_realm);
6833 wpa_s->last_con_fail_realm = os_malloc(realm_len);
6834 if (wpa_s->last_con_fail_realm) {
6835 wpa_s->last_con_fail_realm_len = realm_len;
6836 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
6837 }
6838}
6839#endif /* CONFIG_FILS */
6840
6841
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006842int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
6843{
6844 return wpa_s->conf->ap_scan == 2 ||
6845 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
6846}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006847
Dmitry Shmidt04949592012-07-19 12:16:46 -07006848
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006849#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006850int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6851 struct wpa_ssid *ssid,
6852 const char *field,
6853 const char *value)
6854{
6855#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006856 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006857
6858 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
6859 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
6860 (const u8 *) value, os_strlen(value));
6861
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006862 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07006863 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006864#else /* IEEE8021X_EAPOL */
6865 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6866 return -1;
6867#endif /* IEEE8021X_EAPOL */
6868}
6869
6870int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6871 struct wpa_ssid *ssid,
6872 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07006873 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006874{
6875#ifdef IEEE8021X_EAPOL
6876 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08006877 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006878
6879 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07006880 case WPA_CTRL_REQ_EAP_IDENTITY:
6881 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08006882 os_free(eap->imsi_identity);
6883 if (value == NULL)
6884 return -1;
6885 identity = os_strchr(value, ':');
6886 if (identity == NULL) {
6887 /* plain identity */
6888 eap->identity = (u8 *)os_strdup(value);
6889 eap->identity_len = os_strlen(value);
6890 } else {
6891 /* have both plain identity and encrypted identity */
6892 imsi_identity = value;
6893 *identity++ = '\0';
6894 /* plain identity */
6895 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
6896 eap->imsi_identity_len = strlen(imsi_identity);
6897 /* encrypted identity */
6898 eap->identity = (u8 *)dup_binstr(identity,
6899 value_len - strlen(imsi_identity) - 1);
6900 eap->identity_len = value_len - strlen(imsi_identity) - 1;
6901 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006902 eap->pending_req_identity = 0;
6903 if (ssid == wpa_s->current_ssid)
6904 wpa_s->reassociate = 1;
6905 break;
6906 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006907 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006908 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006909 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006910 eap->pending_req_password = 0;
6911 if (ssid == wpa_s->current_ssid)
6912 wpa_s->reassociate = 1;
6913 break;
6914 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006915 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006916 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006917 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006918 eap->pending_req_new_password = 0;
6919 if (ssid == wpa_s->current_ssid)
6920 wpa_s->reassociate = 1;
6921 break;
6922 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006923 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006924 eap->pin = os_strdup(value);
6925 eap->pending_req_pin = 0;
6926 if (ssid == wpa_s->current_ssid)
6927 wpa_s->reassociate = 1;
6928 break;
6929 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006930 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006931 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006932 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006933 os_free(eap->pending_req_otp);
6934 eap->pending_req_otp = NULL;
6935 eap->pending_req_otp_len = 0;
6936 break;
6937 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006938 str_clear_free(eap->private_key_passwd);
6939 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006940 eap->pending_req_passphrase = 0;
6941 if (ssid == wpa_s->current_ssid)
6942 wpa_s->reassociate = 1;
6943 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006944 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006945 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07006946 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006947 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006948 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006949 case WPA_CTRL_REQ_PSK_PASSPHRASE:
6950 if (wpa_config_set(ssid, "psk", value, 0) < 0)
6951 return -1;
6952 ssid->mem_only_psk = 1;
6953 if (ssid->passphrase)
6954 wpa_config_update_psk(ssid);
6955 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
6956 wpa_supplicant_req_scan(wpa_s, 0, 0);
6957 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006958 case WPA_CTRL_REQ_EXT_CERT_CHECK:
6959 if (eap->pending_ext_cert_check != PENDING_CHECK)
6960 return -1;
6961 if (os_strcmp(value, "good") == 0)
6962 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
6963 else if (os_strcmp(value, "bad") == 0)
6964 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
6965 else
6966 return -1;
6967 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006968 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006969 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006970 return -1;
6971 }
6972
6973 return 0;
6974#else /* IEEE8021X_EAPOL */
6975 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6976 return -1;
6977#endif /* IEEE8021X_EAPOL */
6978}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006979#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006980
6981
6982int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6983{
6984 int i;
6985 unsigned int drv_enc;
6986
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006987 if (wpa_s->p2p_mgmt)
6988 return 1; /* no normal network profiles on p2p_mgmt interface */
6989
Dmitry Shmidt04949592012-07-19 12:16:46 -07006990 if (ssid == NULL)
6991 return 1;
6992
6993 if (ssid->disabled)
6994 return 1;
6995
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006996 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006997 drv_enc = wpa_s->drv_enc;
6998 else
6999 drv_enc = (unsigned int) -1;
7000
7001 for (i = 0; i < NUM_WEP_KEYS; i++) {
7002 size_t len = ssid->wep_key_len[i];
7003 if (len == 0)
7004 continue;
7005 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7006 continue;
7007 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7008 continue;
7009 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7010 continue;
7011 return 1; /* invalid WEP key */
7012 }
7013
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007014 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007015 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007016 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007017 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007018 return 1;
7019
Dmitry Shmidt04949592012-07-19 12:16:46 -07007020 return 0;
7021}
7022
7023
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007024int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7025{
7026#ifdef CONFIG_IEEE80211W
7027 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7028 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7029 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7030 /*
7031 * Driver does not support BIP -- ignore pmf=1 default
7032 * since the connection with PMF would fail and the
7033 * configuration does not require PMF to be enabled.
7034 */
7035 return NO_MGMT_FRAME_PROTECTION;
7036 }
7037
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007038 if (ssid &&
7039 (ssid->key_mgmt &
7040 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7041 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7042 /*
7043 * Do not use the default PMF value for non-RSN networks
7044 * since PMF is available only with RSN and pmf=2
7045 * configuration would otherwise prevent connections to
7046 * all open networks.
7047 */
7048 return NO_MGMT_FRAME_PROTECTION;
7049 }
7050
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007051 return wpa_s->conf->pmf;
7052 }
7053
7054 return ssid->ieee80211w;
7055#else /* CONFIG_IEEE80211W */
7056 return NO_MGMT_FRAME_PROTECTION;
7057#endif /* CONFIG_IEEE80211W */
7058}
7059
7060
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007061int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007062{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007063 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007064 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007065 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007066 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007067 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007068}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007069
7070
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007071void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007072{
7073 struct wpa_ssid *ssid = wpa_s->current_ssid;
7074 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007075 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007076
7077 if (ssid == NULL) {
7078 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7079 "SSID block");
7080 return;
7081 }
7082
7083 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7084 return;
7085
7086 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007087
7088#ifdef CONFIG_P2P
7089 if (ssid->p2p_group &&
7090 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7091 /*
7092 * Skip the wait time since there is a short timeout on the
7093 * connection to a P2P group.
7094 */
7095 return;
7096 }
7097#endif /* CONFIG_P2P */
7098
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007099 if (ssid->auth_failures > 50)
7100 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007101 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007102 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007103 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007104 dur = 90;
7105 else if (ssid->auth_failures > 3)
7106 dur = 60;
7107 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007108 dur = 30;
7109 else if (ssid->auth_failures > 1)
7110 dur = 20;
7111 else
7112 dur = 10;
7113
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007114 if (ssid->auth_failures > 1 &&
7115 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7116 dur += os_random() % (ssid->auth_failures * 10);
7117
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007118 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007119 if (now.sec + dur <= ssid->disabled_until.sec)
7120 return;
7121
7122 ssid->disabled_until.sec = now.sec + dur;
7123
7124 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007125 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007126 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007127 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007128}
7129
7130
7131void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7132 struct wpa_ssid *ssid, int clear_failures)
7133{
7134 if (ssid == NULL)
7135 return;
7136
7137 if (ssid->disabled_until.sec) {
7138 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7139 "id=%d ssid=\"%s\"",
7140 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7141 }
7142 ssid->disabled_until.sec = 0;
7143 ssid->disabled_until.usec = 0;
7144 if (clear_failures)
7145 ssid->auth_failures = 0;
7146}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007147
7148
7149int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7150{
7151 size_t i;
7152
7153 if (wpa_s->disallow_aps_bssid == NULL)
7154 return 0;
7155
7156 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7157 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7158 bssid, ETH_ALEN) == 0)
7159 return 1;
7160 }
7161
7162 return 0;
7163}
7164
7165
7166int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7167 size_t ssid_len)
7168{
7169 size_t i;
7170
7171 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7172 return 0;
7173
7174 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7175 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7176 if (ssid_len == s->ssid_len &&
7177 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7178 return 1;
7179 }
7180
7181 return 0;
7182}
7183
7184
7185/**
7186 * wpas_request_connection - Request a new connection
7187 * @wpa_s: Pointer to the network interface
7188 *
7189 * This function is used to request a new connection to be found. It will mark
7190 * the interface to allow reassociation and request a new scan to find a
7191 * suitable network to connect to.
7192 */
7193void wpas_request_connection(struct wpa_supplicant *wpa_s)
7194{
7195 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007196 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007197 wpa_supplicant_reinit_autoscan(wpa_s);
7198 wpa_s->extra_blacklist_count = 0;
7199 wpa_s->disconnected = 0;
7200 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007201 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007202
7203 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7204 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007205 else
7206 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007207}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007208
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007209
Roshan Pius02242d72016-08-09 15:31:48 -07007210/**
7211 * wpas_request_disconnection - Request disconnection
7212 * @wpa_s: Pointer to the network interface
7213 *
7214 * This function is used to request disconnection from the currently connected
7215 * network. This will stop any ongoing scans and initiate deauthentication.
7216 */
7217void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7218{
7219#ifdef CONFIG_SME
7220 wpa_s->sme.prev_bssid_set = 0;
7221#endif /* CONFIG_SME */
7222 wpa_s->reassociate = 0;
7223 wpa_s->disconnected = 1;
7224 wpa_supplicant_cancel_sched_scan(wpa_s);
7225 wpa_supplicant_cancel_scan(wpa_s);
7226 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7227 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007228 radio_remove_works(wpa_s, "connect", 0);
7229 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007230}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007231
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007232
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007233void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7234 struct wpa_used_freq_data *freqs_data,
7235 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007236{
7237 unsigned int i;
7238
7239 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7240 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007241 for (i = 0; i < len; i++) {
7242 struct wpa_used_freq_data *cur = &freqs_data[i];
7243 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7244 i, cur->freq, cur->flags);
7245 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007246}
7247
7248
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007249/*
7250 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007251 * are using the same radio as the current interface, and in addition, get
7252 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007253 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007254int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7255 struct wpa_used_freq_data *freqs_data,
7256 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007257{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007258 struct wpa_supplicant *ifs;
7259 u8 bssid[ETH_ALEN];
7260 int freq;
7261 unsigned int idx = 0, i;
7262
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007263 wpa_dbg(wpa_s, MSG_DEBUG,
7264 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007265 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007266
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007267 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7268 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007269 if (idx == len)
7270 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007271
7272 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7273 continue;
7274
7275 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007276 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7277 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007278 freq = ifs->current_ssid->frequency;
7279 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7280 freq = ifs->assoc_freq;
7281 else
7282 continue;
7283
7284 /* Hold only distinct freqs */
7285 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007286 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007287 break;
7288
7289 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007290 freqs_data[idx++].freq = freq;
7291
7292 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007293 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007294 WPA_FREQ_USED_BY_P2P_CLIENT :
7295 WPA_FREQ_USED_BY_INFRA_STATION;
7296 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007297 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007298
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007299 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007300 return idx;
7301}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007302
7303
7304/*
7305 * Find the operating frequencies of any of the virtual interfaces that
7306 * are using the same radio as the current interface.
7307 */
7308int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7309 int *freq_array, unsigned int len)
7310{
7311 struct wpa_used_freq_data *freqs_data;
7312 int num, i;
7313
7314 os_memset(freq_array, 0, sizeof(int) * len);
7315
7316 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7317 if (!freqs_data)
7318 return -1;
7319
7320 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7321 for (i = 0; i < num; i++)
7322 freq_array[i] = freqs_data[i].freq;
7323
7324 os_free(freqs_data);
7325
7326 return num;
7327}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007328
7329
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007330struct wpa_supplicant *
7331wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7332{
7333 switch (frame) {
7334#ifdef CONFIG_P2P
7335 case VENDOR_ELEM_PROBE_REQ_P2P:
7336 case VENDOR_ELEM_PROBE_RESP_P2P:
7337 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7338 case VENDOR_ELEM_BEACON_P2P_GO:
7339 case VENDOR_ELEM_P2P_PD_REQ:
7340 case VENDOR_ELEM_P2P_PD_RESP:
7341 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7342 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7343 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7344 case VENDOR_ELEM_P2P_INV_REQ:
7345 case VENDOR_ELEM_P2P_INV_RESP:
7346 case VENDOR_ELEM_P2P_ASSOC_REQ:
7347 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007348 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007349#endif /* CONFIG_P2P */
7350 default:
7351 return wpa_s;
7352 }
7353}
7354
7355
7356void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7357{
7358 unsigned int i;
7359 char buf[30];
7360
7361 wpa_printf(MSG_DEBUG, "Update vendor elements");
7362
7363 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7364 if (wpa_s->vendor_elem[i]) {
7365 int res;
7366
7367 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7368 if (!os_snprintf_error(sizeof(buf), res)) {
7369 wpa_hexdump_buf(MSG_DEBUG, buf,
7370 wpa_s->vendor_elem[i]);
7371 }
7372 }
7373 }
7374
7375#ifdef CONFIG_P2P
7376 if (wpa_s->parent == wpa_s &&
7377 wpa_s->global->p2p &&
7378 !wpa_s->global->p2p_disabled)
7379 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7380#endif /* CONFIG_P2P */
7381}
7382
7383
7384int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7385 const u8 *elem, size_t len)
7386{
7387 u8 *ie, *end;
7388
7389 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7390 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7391
7392 for (; ie + 1 < end; ie += 2 + ie[1]) {
7393 if (ie + len > end)
7394 break;
7395 if (os_memcmp(ie, elem, len) != 0)
7396 continue;
7397
7398 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7399 wpabuf_free(wpa_s->vendor_elem[frame]);
7400 wpa_s->vendor_elem[frame] = NULL;
7401 } else {
7402 os_memmove(ie, ie + len, end - (ie + len));
7403 wpa_s->vendor_elem[frame]->used -= len;
7404 }
7405 wpas_vendor_elem_update(wpa_s);
7406 return 0;
7407 }
7408
7409 return -1;
7410}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007411
7412
7413struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
7414 u16 num_modes, enum hostapd_hw_mode mode)
7415{
7416 u16 i;
7417
7418 for (i = 0; i < num_modes; i++) {
7419 if (modes[i].mode == mode)
7420 return &modes[i];
7421 }
7422
7423 return NULL;
7424}
7425
7426
7427static struct
7428wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7429 const u8 *bssid)
7430{
7431 struct wpa_bss_tmp_disallowed *bss;
7432
7433 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7434 struct wpa_bss_tmp_disallowed, list) {
7435 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7436 return bss;
7437 }
7438
7439 return NULL;
7440}
7441
7442
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007443static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7444{
7445 struct wpa_bss_tmp_disallowed *tmp;
7446 unsigned int num_bssid = 0;
7447 u8 *bssids;
7448 int ret;
7449
7450 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7451 if (!bssids)
7452 return -1;
7453 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7454 struct wpa_bss_tmp_disallowed, list) {
7455 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7456 ETH_ALEN);
7457 num_bssid++;
7458 }
7459 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7460 os_free(bssids);
7461 return ret;
7462}
7463
7464
7465static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7466{
7467 struct wpa_supplicant *wpa_s = eloop_ctx;
7468 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7469
7470 /* Make sure the bss is not already freed */
7471 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7472 struct wpa_bss_tmp_disallowed, list) {
7473 if (bss == tmp) {
7474 dl_list_del(&tmp->list);
7475 os_free(tmp);
7476 wpa_set_driver_tmp_disallow_list(wpa_s);
7477 break;
7478 }
7479 }
7480}
7481
7482
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007483void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08007484 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007485{
7486 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007487
7488 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7489 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007490 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08007491 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007492 }
7493
7494 bss = os_malloc(sizeof(*bss));
7495 if (!bss) {
7496 wpa_printf(MSG_DEBUG,
7497 "Failed to allocate memory for temp disallow BSS");
7498 return;
7499 }
7500
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007501 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7502 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007503 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08007504
7505finish:
7506 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007507 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7508 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007509}
7510
7511
Hai Shalom74f70d42019-02-11 14:42:39 -08007512int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
7513 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007514{
Hai Shalom74f70d42019-02-11 14:42:39 -08007515 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007516
7517 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7518 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007519 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
7520 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007521 break;
7522 }
7523 }
Hai Shalom74f70d42019-02-11 14:42:39 -08007524 if (!disallowed)
7525 return 0;
7526
7527 if (disallowed->rssi_threshold != 0 &&
7528 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007529 return 0;
7530
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007531 return 1;
7532}
Hai Shalom81f62d82019-07-22 12:10:00 -07007533
7534
7535int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
7536 unsigned int type, const u8 *addr,
7537 const u8 *mask)
7538{
7539 if ((addr && !mask) || (!addr && mask)) {
7540 wpa_printf(MSG_INFO,
7541 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
7542 return -1;
7543 }
7544
7545 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
7546 wpa_printf(MSG_INFO,
7547 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
7548 return -1;
7549 }
7550
7551 if (type & MAC_ADDR_RAND_SCAN) {
7552 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
7553 addr, mask))
7554 return -1;
7555 }
7556
7557 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
7558 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
7559 addr, mask))
7560 return -1;
7561
7562 if (wpa_s->sched_scanning && !wpa_s->pno)
7563 wpas_scan_restart_sched_scan(wpa_s);
7564 }
7565
7566 if (type & MAC_ADDR_RAND_PNO) {
7567 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
7568 addr, mask))
7569 return -1;
7570
7571 if (wpa_s->pno) {
7572 wpas_stop_pno(wpa_s);
7573 wpas_start_pno(wpa_s);
7574 }
7575 }
7576
7577 return 0;
7578}
7579
7580
7581int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
7582 unsigned int type)
7583{
7584 wpas_mac_addr_rand_scan_clear(wpa_s, type);
7585 if (wpa_s->pno) {
7586 if (type & MAC_ADDR_RAND_PNO) {
7587 wpas_stop_pno(wpa_s);
7588 wpas_start_pno(wpa_s);
7589 }
7590 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
7591 wpas_scan_restart_sched_scan(wpa_s);
7592 }
7593
7594 return 0;
7595}