blob: f043264ae4e8313072d0edfa1fa8b2aae72ce3e3 [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);
4346
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004347 return 0;
4348}
4349
4350
Dmitry Shmidt04949592012-07-19 12:16:46 -07004351static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4352 const u8 *buf, size_t len)
4353{
4354 struct wpa_supplicant *wpa_s = ctx;
4355 const struct l2_ethhdr *eth;
4356
4357 if (len < sizeof(*eth))
4358 return;
4359 eth = (const struct l2_ethhdr *) buf;
4360
4361 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4362 !(eth->h_dest[0] & 0x01)) {
4363 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4364 " (bridge - not for this interface - ignore)",
4365 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4366 return;
4367 }
4368
4369 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4370 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4371 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4372 len - sizeof(*eth));
4373}
4374
4375
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004376/**
4377 * wpa_supplicant_driver_init - Initialize driver interface parameters
4378 * @wpa_s: Pointer to wpa_supplicant data
4379 * Returns: 0 on success, -1 on failure
4380 *
4381 * This function is called to initialize driver interface parameters.
4382 * wpa_drv_init() must have been called before this function to initialize the
4383 * driver interface.
4384 */
4385int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4386{
4387 static int interface_count = 0;
4388
4389 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4390 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004391
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004392 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4393 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004394 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004395 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4396
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004397 if (wpa_s->bridge_ifname[0]) {
4398 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4399 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004400 wpa_s->l2_br = l2_packet_init_bridge(
4401 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4402 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004403 if (wpa_s->l2_br == NULL) {
4404 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4405 "connection for the bridge interface '%s'",
4406 wpa_s->bridge_ifname);
4407 return -1;
4408 }
4409 }
4410
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004411 if (wpa_s->conf->ap_scan == 2 &&
4412 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4413 wpa_printf(MSG_INFO,
4414 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4415 }
4416
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004417 wpa_clear_keys(wpa_s, NULL);
4418
4419 /* Make sure that TKIP countermeasures are not left enabled (could
4420 * happen if wpa_supplicant is killed during countermeasures. */
4421 wpa_drv_set_countermeasures(wpa_s, 0);
4422
4423 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4424 wpa_drv_flush_pmkid(wpa_s);
4425
4426 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004427 wpa_s->prev_scan_wildcard = 0;
4428
Dmitry Shmidt04949592012-07-19 12:16:46 -07004429 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004430 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4431 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4432 interface_count = 0;
4433 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004434#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004435 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004436 wpa_supplicant_delayed_sched_scan(wpa_s,
4437 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004438 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004439 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004440 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004441#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004442 interface_count++;
4443 } else
4444 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4445
4446 return 0;
4447}
4448
4449
4450static int wpa_supplicant_daemon(const char *pid_file)
4451{
4452 wpa_printf(MSG_DEBUG, "Daemonize..");
4453 return os_daemonize(pid_file);
4454}
4455
4456
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004457static struct wpa_supplicant *
4458wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004459{
4460 struct wpa_supplicant *wpa_s;
4461
4462 wpa_s = os_zalloc(sizeof(*wpa_s));
4463 if (wpa_s == NULL)
4464 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004465 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004466 wpa_s->scan_interval = 5;
4467 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004468 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004469 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004470 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004471
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004472 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004473 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004474
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004475 return wpa_s;
4476}
4477
4478
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004479#ifdef CONFIG_HT_OVERRIDES
4480
4481static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4482 struct ieee80211_ht_capabilities *htcaps,
4483 struct ieee80211_ht_capabilities *htcaps_mask,
4484 const char *ht_mcs)
4485{
4486 /* parse ht_mcs into hex array */
4487 int i;
4488 const char *tmp = ht_mcs;
4489 char *end = NULL;
4490
4491 /* If ht_mcs is null, do not set anything */
4492 if (!ht_mcs)
4493 return 0;
4494
4495 /* This is what we are setting in the kernel */
4496 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4497
4498 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4499
4500 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004501 long v;
4502
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004503 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004504 v = strtol(tmp, &end, 16);
4505
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004506 if (errno == 0) {
4507 wpa_msg(wpa_s, MSG_DEBUG,
4508 "htcap value[%i]: %ld end: %p tmp: %p",
4509 i, v, end, tmp);
4510 if (end == tmp)
4511 break;
4512
4513 htcaps->supported_mcs_set[i] = v;
4514 tmp = end;
4515 } else {
4516 wpa_msg(wpa_s, MSG_ERROR,
4517 "Failed to parse ht-mcs: %s, error: %s\n",
4518 ht_mcs, strerror(errno));
4519 return -1;
4520 }
4521 }
4522
4523 /*
4524 * If we were able to parse any values, then set mask for the MCS set.
4525 */
4526 if (i) {
4527 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4528 IEEE80211_HT_MCS_MASK_LEN - 1);
4529 /* skip the 3 reserved bits */
4530 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4531 0x1f;
4532 }
4533
4534 return 0;
4535}
4536
4537
4538static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4539 struct ieee80211_ht_capabilities *htcaps,
4540 struct ieee80211_ht_capabilities *htcaps_mask,
4541 int disabled)
4542{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004543 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004544
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004545 if (disabled == -1)
4546 return 0;
4547
Hai Shalom74f70d42019-02-11 14:42:39 -08004548 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
4549
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004550 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
4551 htcaps_mask->ht_capabilities_info |= msk;
4552 if (disabled)
4553 htcaps->ht_capabilities_info &= msk;
4554 else
4555 htcaps->ht_capabilities_info |= msk;
4556
4557 return 0;
4558}
4559
4560
4561static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
4562 struct ieee80211_ht_capabilities *htcaps,
4563 struct ieee80211_ht_capabilities *htcaps_mask,
4564 int factor)
4565{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004566 if (factor == -1)
4567 return 0;
4568
Hai Shalom74f70d42019-02-11 14:42:39 -08004569 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
4570
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004571 if (factor < 0 || factor > 3) {
4572 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
4573 "Must be 0-3 or -1", factor);
4574 return -EINVAL;
4575 }
4576
4577 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
4578 htcaps->a_mpdu_params &= ~0x3;
4579 htcaps->a_mpdu_params |= factor & 0x3;
4580
4581 return 0;
4582}
4583
4584
4585static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
4586 struct ieee80211_ht_capabilities *htcaps,
4587 struct ieee80211_ht_capabilities *htcaps_mask,
4588 int density)
4589{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004590 if (density == -1)
4591 return 0;
4592
Hai Shalom74f70d42019-02-11 14:42:39 -08004593 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
4594
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004595 if (density < 0 || density > 7) {
4596 wpa_msg(wpa_s, MSG_ERROR,
4597 "ampdu_density: %d out of range. Must be 0-7 or -1.",
4598 density);
4599 return -EINVAL;
4600 }
4601
4602 htcaps_mask->a_mpdu_params |= 0x1C;
4603 htcaps->a_mpdu_params &= ~(0x1C);
4604 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
4605
4606 return 0;
4607}
4608
4609
4610static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
4611 struct ieee80211_ht_capabilities *htcaps,
4612 struct ieee80211_ht_capabilities *htcaps_mask,
4613 int disabled)
4614{
Hai Shalom74f70d42019-02-11 14:42:39 -08004615 if (disabled)
4616 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004617
Paul Stewart092955c2017-02-06 09:13:09 -08004618 set_disable_ht40(htcaps, disabled);
4619 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004620
4621 return 0;
4622}
4623
4624
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004625static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
4626 struct ieee80211_ht_capabilities *htcaps,
4627 struct ieee80211_ht_capabilities *htcaps_mask,
4628 int disabled)
4629{
4630 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004631 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
4632 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004633
Hai Shalom74f70d42019-02-11 14:42:39 -08004634 if (disabled)
4635 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004636
4637 if (disabled)
4638 htcaps->ht_capabilities_info &= ~msk;
4639 else
4640 htcaps->ht_capabilities_info |= msk;
4641
4642 htcaps_mask->ht_capabilities_info |= msk;
4643
4644 return 0;
4645}
4646
4647
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004648static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
4649 struct ieee80211_ht_capabilities *htcaps,
4650 struct ieee80211_ht_capabilities *htcaps_mask,
4651 int disabled)
4652{
4653 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004654 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004655
Hai Shalom74f70d42019-02-11 14:42:39 -08004656 if (disabled)
4657 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004658
4659 if (disabled)
4660 htcaps->ht_capabilities_info &= ~msk;
4661 else
4662 htcaps->ht_capabilities_info |= msk;
4663
4664 htcaps_mask->ht_capabilities_info |= msk;
4665
4666 return 0;
4667}
4668
4669
Hai Shalom74f70d42019-02-11 14:42:39 -08004670static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
4671 struct ieee80211_ht_capabilities *htcaps,
4672 struct ieee80211_ht_capabilities *htcaps_mask,
4673 int tx_stbc)
4674{
4675 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
4676
4677 if (tx_stbc == -1)
4678 return 0;
4679
4680 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
4681
4682 if (tx_stbc < 0 || tx_stbc > 1) {
4683 wpa_msg(wpa_s, MSG_ERROR,
4684 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
4685 return -EINVAL;
4686 }
4687
4688 htcaps_mask->ht_capabilities_info |= msk;
4689 htcaps->ht_capabilities_info &= ~msk;
4690 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
4691
4692 return 0;
4693}
4694
4695
4696static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
4697 struct ieee80211_ht_capabilities *htcaps,
4698 struct ieee80211_ht_capabilities *htcaps_mask,
4699 int rx_stbc)
4700{
4701 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
4702
4703 if (rx_stbc == -1)
4704 return 0;
4705
4706 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
4707
4708 if (rx_stbc < 0 || rx_stbc > 3) {
4709 wpa_msg(wpa_s, MSG_ERROR,
4710 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
4711 return -EINVAL;
4712 }
4713
4714 htcaps_mask->ht_capabilities_info |= msk;
4715 htcaps->ht_capabilities_info &= ~msk;
4716 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
4717
4718 return 0;
4719}
4720
4721
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004722void wpa_supplicant_apply_ht_overrides(
4723 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4724 struct wpa_driver_associate_params *params)
4725{
4726 struct ieee80211_ht_capabilities *htcaps;
4727 struct ieee80211_ht_capabilities *htcaps_mask;
4728
4729 if (!ssid)
4730 return;
4731
4732 params->disable_ht = ssid->disable_ht;
4733 if (!params->htcaps || !params->htcaps_mask)
4734 return;
4735
4736 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
4737 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
4738 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
4739 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
4740 ssid->disable_max_amsdu);
4741 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
4742 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
4743 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004744 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004745 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08004746 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
4747 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004748
4749 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004750 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004751 htcaps->ht_capabilities_info |= bit;
4752 htcaps_mask->ht_capabilities_info |= bit;
4753 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004754}
4755
4756#endif /* CONFIG_HT_OVERRIDES */
4757
4758
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004759#ifdef CONFIG_VHT_OVERRIDES
4760void wpa_supplicant_apply_vht_overrides(
4761 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4762 struct wpa_driver_associate_params *params)
4763{
4764 struct ieee80211_vht_capabilities *vhtcaps;
4765 struct ieee80211_vht_capabilities *vhtcaps_mask;
4766
4767 if (!ssid)
4768 return;
4769
4770 params->disable_vht = ssid->disable_vht;
4771
4772 vhtcaps = (void *) params->vhtcaps;
4773 vhtcaps_mask = (void *) params->vhtcaps_mask;
4774
4775 if (!vhtcaps || !vhtcaps_mask)
4776 return;
4777
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004778 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
4779 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004780
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004781#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08004782 if (ssid->disable_sgi) {
4783 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
4784 VHT_CAP_SHORT_GI_160);
4785 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
4786 VHT_CAP_SHORT_GI_160);
4787 wpa_msg(wpa_s, MSG_DEBUG,
4788 "disable-sgi override specified, vht-caps: 0x%x",
4789 vhtcaps->vht_capabilities_info);
4790 }
4791
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004792 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004793 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
4794 int max_ampdu;
4795
4796 max_ampdu = (ssid->vht_capa &
4797 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4798 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004799
4800 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4801 wpa_set_ampdu_factor(wpa_s,
4802 (void *) params->htcaps,
4803 (void *) params->htcaps_mask,
4804 max_ampdu);
4805 }
4806#endif /* CONFIG_HT_OVERRIDES */
4807
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004808#define OVERRIDE_MCS(i) \
4809 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4810 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004811 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004812 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004813 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4814 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004815 } \
4816 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4817 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004818 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004819 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004820 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4821 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004822 }
4823
4824 OVERRIDE_MCS(1);
4825 OVERRIDE_MCS(2);
4826 OVERRIDE_MCS(3);
4827 OVERRIDE_MCS(4);
4828 OVERRIDE_MCS(5);
4829 OVERRIDE_MCS(6);
4830 OVERRIDE_MCS(7);
4831 OVERRIDE_MCS(8);
4832}
4833#endif /* CONFIG_VHT_OVERRIDES */
4834
4835
Dmitry Shmidt04949592012-07-19 12:16:46 -07004836static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4837{
4838#ifdef PCSC_FUNCS
4839 size_t len;
4840
4841 if (!wpa_s->conf->pcsc_reader)
4842 return 0;
4843
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004844 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004845 if (!wpa_s->scard)
4846 return 1;
4847
4848 if (wpa_s->conf->pcsc_pin &&
4849 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4850 scard_deinit(wpa_s->scard);
4851 wpa_s->scard = NULL;
4852 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4853 return -1;
4854 }
4855
4856 len = sizeof(wpa_s->imsi) - 1;
4857 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4858 scard_deinit(wpa_s->scard);
4859 wpa_s->scard = NULL;
4860 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4861 return -1;
4862 }
4863 wpa_s->imsi[len] = '\0';
4864
4865 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4866
4867 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4868 wpa_s->imsi, wpa_s->mnc_len);
4869
4870 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4871 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4872#endif /* PCSC_FUNCS */
4873
4874 return 0;
4875}
4876
4877
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004878int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4879{
4880 char *val, *pos;
4881
4882 ext_password_deinit(wpa_s->ext_pw);
4883 wpa_s->ext_pw = NULL;
4884 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4885
4886 if (!wpa_s->conf->ext_password_backend)
4887 return 0;
4888
4889 val = os_strdup(wpa_s->conf->ext_password_backend);
4890 if (val == NULL)
4891 return -1;
4892 pos = os_strchr(val, ':');
4893 if (pos)
4894 *pos++ = '\0';
4895
4896 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4897
4898 wpa_s->ext_pw = ext_password_init(val, pos);
4899 os_free(val);
4900 if (wpa_s->ext_pw == NULL) {
4901 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4902 return -1;
4903 }
4904 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4905
4906 return 0;
4907}
4908
4909
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004910#ifdef CONFIG_FST
4911
4912static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4913{
4914 struct wpa_supplicant *wpa_s = ctx;
4915
4916 return (is_zero_ether_addr(wpa_s->bssid) ||
4917 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4918}
4919
4920
4921static void wpas_fst_get_channel_info_cb(void *ctx,
4922 enum hostapd_hw_mode *hw_mode,
4923 u8 *channel)
4924{
4925 struct wpa_supplicant *wpa_s = ctx;
4926
4927 if (wpa_s->current_bss) {
4928 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4929 channel);
4930 } else if (wpa_s->hw.num_modes) {
4931 *hw_mode = wpa_s->hw.modes[0].mode;
4932 } else {
4933 WPA_ASSERT(0);
4934 *hw_mode = 0;
4935 }
4936}
4937
4938
4939static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4940{
4941 struct wpa_supplicant *wpa_s = ctx;
4942
4943 *modes = wpa_s->hw.modes;
4944 return wpa_s->hw.num_modes;
4945}
4946
4947
4948static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4949{
4950 struct wpa_supplicant *wpa_s = ctx;
4951
4952 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4953 wpa_s->fst_ies = fst_ies;
4954}
4955
4956
4957static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4958{
4959 struct wpa_supplicant *wpa_s = ctx;
4960
Paul Stewart092955c2017-02-06 09:13:09 -08004961 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
4962 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
4963 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
4964 return -1;
4965 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004966 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08004967 wpa_s->own_addr, wpa_s->bssid,
4968 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004969 0);
4970}
4971
4972
4973static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4974{
4975 struct wpa_supplicant *wpa_s = ctx;
4976
4977 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4978 return wpa_s->received_mb_ies;
4979}
4980
4981
4982static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4983 const u8 *buf, size_t size)
4984{
4985 struct wpa_supplicant *wpa_s = ctx;
4986 struct mb_ies_info info;
4987
4988 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4989
4990 if (!mb_ies_info_by_ies(&info, buf, size)) {
4991 wpabuf_free(wpa_s->received_mb_ies);
4992 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4993 }
4994}
4995
4996
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004997static const u8 * wpas_fst_get_peer_first(void *ctx,
4998 struct fst_get_peer_ctx **get_ctx,
4999 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005000{
5001 struct wpa_supplicant *wpa_s = ctx;
5002
5003 *get_ctx = NULL;
5004 if (!is_zero_ether_addr(wpa_s->bssid))
5005 return (wpa_s->received_mb_ies || !mb_only) ?
5006 wpa_s->bssid : NULL;
5007 return NULL;
5008}
5009
5010
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005011static const u8 * wpas_fst_get_peer_next(void *ctx,
5012 struct fst_get_peer_ctx **get_ctx,
5013 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005014{
5015 return NULL;
5016}
5017
5018void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5019 struct fst_wpa_obj *iface_obj)
5020{
5021 iface_obj->ctx = wpa_s;
5022 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5023 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5024 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5025 iface_obj->set_ies = wpas_fst_set_ies_cb;
5026 iface_obj->send_action = wpas_fst_send_action_cb;
5027 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5028 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5029 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5030 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5031}
5032#endif /* CONFIG_FST */
5033
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005034static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005035 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005036{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005037 struct wowlan_triggers *triggers;
5038 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005039
5040 if (!wpa_s->conf->wowlan_triggers)
5041 return 0;
5042
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005043 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5044 if (triggers) {
5045 ret = wpa_drv_wowlan(wpa_s, triggers);
5046 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005047 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005048 return ret;
5049}
5050
5051
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005052enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005053{
5054 if (freq < 3000)
5055 return BAND_2_4_GHZ;
5056 if (freq > 50000)
5057 return BAND_60_GHZ;
5058 return BAND_5_GHZ;
5059}
5060
5061
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005062unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005063{
5064 int i;
5065 unsigned int band = 0;
5066
5067 if (freqs) {
5068 /* freqs are specified for the radio work */
5069 for (i = 0; freqs[i]; i++)
5070 band |= wpas_freq_to_band(freqs[i]);
5071 } else {
5072 /*
5073 * freqs are not specified, implies all
5074 * the supported freqs by HW
5075 */
5076 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5077 if (wpa_s->hw.modes[i].num_channels != 0) {
5078 if (wpa_s->hw.modes[i].mode ==
5079 HOSTAPD_MODE_IEEE80211B ||
5080 wpa_s->hw.modes[i].mode ==
5081 HOSTAPD_MODE_IEEE80211G)
5082 band |= BAND_2_4_GHZ;
5083 else if (wpa_s->hw.modes[i].mode ==
5084 HOSTAPD_MODE_IEEE80211A)
5085 band |= BAND_5_GHZ;
5086 else if (wpa_s->hw.modes[i].mode ==
5087 HOSTAPD_MODE_IEEE80211AD)
5088 band |= BAND_60_GHZ;
5089 else if (wpa_s->hw.modes[i].mode ==
5090 HOSTAPD_MODE_IEEE80211ANY)
5091 band = BAND_2_4_GHZ | BAND_5_GHZ |
5092 BAND_60_GHZ;
5093 }
5094 }
5095 }
5096
5097 return band;
5098}
5099
5100
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005101static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5102 const char *rn)
5103{
5104 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5105 struct wpa_radio *radio;
5106
5107 while (rn && iface) {
5108 radio = iface->radio;
5109 if (radio && os_strcmp(rn, radio->name) == 0) {
5110 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5111 wpa_s->ifname, rn);
5112 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5113 return radio;
5114 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005115
5116 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005117 }
5118
5119 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5120 wpa_s->ifname, rn ? rn : "N/A");
5121 radio = os_zalloc(sizeof(*radio));
5122 if (radio == NULL)
5123 return NULL;
5124
5125 if (rn)
5126 os_strlcpy(radio->name, rn, sizeof(radio->name));
5127 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005128 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005129 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5130
5131 return radio;
5132}
5133
5134
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005135static void radio_work_free(struct wpa_radio_work *work)
5136{
5137 if (work->wpa_s->scan_work == work) {
5138 /* This should not really happen. */
5139 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5140 work->type, work, work->started);
5141 work->wpa_s->scan_work = NULL;
5142 }
5143
5144#ifdef CONFIG_P2P
5145 if (work->wpa_s->p2p_scan_work == work) {
5146 /* This should not really happen. */
5147 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5148 work->type, work, work->started);
5149 work->wpa_s->p2p_scan_work = NULL;
5150 }
5151#endif /* CONFIG_P2P */
5152
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005153 if (work->started) {
5154 work->wpa_s->radio->num_active_works--;
5155 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005156 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005157 work->type, work,
5158 work->wpa_s->radio->num_active_works);
5159 }
5160
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005161 dl_list_del(&work->list);
5162 os_free(work);
5163}
5164
5165
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005166static int radio_work_is_connect(struct wpa_radio_work *work)
5167{
5168 return os_strcmp(work->type, "sme-connect") == 0 ||
5169 os_strcmp(work->type, "connect") == 0;
5170}
5171
5172
5173static int radio_work_is_scan(struct wpa_radio_work *work)
5174{
5175 return os_strcmp(work->type, "scan") == 0 ||
5176 os_strcmp(work->type, "p2p-scan") == 0;
5177}
5178
5179
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005180static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5181{
5182 struct wpa_radio_work *active_work = NULL;
5183 struct wpa_radio_work *tmp;
5184
5185 /* Get the active work to know the type and band. */
5186 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5187 if (tmp->started) {
5188 active_work = tmp;
5189 break;
5190 }
5191 }
5192
5193 if (!active_work) {
5194 /* No active work, start one */
5195 radio->num_active_works = 0;
5196 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5197 list) {
5198 if (os_strcmp(tmp->type, "scan") == 0 &&
5199 radio->external_scan_running &&
5200 (((struct wpa_driver_scan_params *)
5201 tmp->ctx)->only_new_results ||
5202 tmp->wpa_s->clear_driver_scan_cache))
5203 continue;
5204 return tmp;
5205 }
5206 return NULL;
5207 }
5208
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005209 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005210 /*
5211 * If the active work is either connect or sme-connect,
5212 * do not parallelize them with other radio works.
5213 */
5214 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5215 "Do not parallelize radio work with %s",
5216 active_work->type);
5217 return NULL;
5218 }
5219
5220 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5221 if (tmp->started)
5222 continue;
5223
5224 /*
5225 * If connect or sme-connect are enqueued, parallelize only
5226 * those operations ahead of them in the queue.
5227 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005228 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005229 break;
5230
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005231 /* Serialize parallel scan and p2p_scan operations on the same
5232 * interface since the driver_nl80211 mechanism for tracking
5233 * scan cookies does not yet have support for this. */
5234 if (active_work->wpa_s == tmp->wpa_s &&
5235 radio_work_is_scan(active_work) &&
5236 radio_work_is_scan(tmp)) {
5237 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5238 "Do not start work '%s' when another work '%s' is already scheduled",
5239 tmp->type, active_work->type);
5240 continue;
5241 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005242 /*
5243 * Check that the radio works are distinct and
5244 * on different bands.
5245 */
5246 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5247 (active_work->bands != tmp->bands)) {
5248 /*
5249 * If a scan has to be scheduled through nl80211 scan
5250 * interface and if an external scan is already running,
5251 * do not schedule the scan since it is likely to get
5252 * rejected by kernel.
5253 */
5254 if (os_strcmp(tmp->type, "scan") == 0 &&
5255 radio->external_scan_running &&
5256 (((struct wpa_driver_scan_params *)
5257 tmp->ctx)->only_new_results ||
5258 tmp->wpa_s->clear_driver_scan_cache))
5259 continue;
5260
5261 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5262 "active_work:%s new_work:%s",
5263 active_work->type, tmp->type);
5264 return tmp;
5265 }
5266 }
5267
5268 /* Did not find a radio work to schedule in parallel. */
5269 return NULL;
5270}
5271
5272
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005273static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5274{
5275 struct wpa_radio *radio = eloop_ctx;
5276 struct wpa_radio_work *work;
5277 struct os_reltime now, diff;
5278 struct wpa_supplicant *wpa_s;
5279
5280 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005281 if (work == NULL) {
5282 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005283 return;
5284 }
5285
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005286 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5287 radio_list);
5288
5289 if (!(wpa_s &&
5290 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5291 if (work->started)
5292 return; /* already started and still in progress */
5293
5294 if (wpa_s && wpa_s->radio->external_scan_running) {
5295 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5296 return;
5297 }
5298 } else {
5299 work = NULL;
5300 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5301 /* get the work to schedule next */
5302 work = radio_work_get_next_work(radio);
5303 }
5304 if (!work)
5305 return;
5306 }
5307
5308 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005309 os_get_reltime(&now);
5310 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005311 wpa_dbg(wpa_s, MSG_DEBUG,
5312 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005313 work->type, work, diff.sec, diff.usec);
5314 work->started = 1;
5315 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005316 radio->num_active_works++;
5317
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005318 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005319
5320 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5321 radio->num_active_works < MAX_ACTIVE_WORKS)
5322 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005323}
5324
5325
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005326/*
5327 * This function removes both started and pending radio works running on
5328 * the provided interface's radio.
5329 * Prior to the removal of the radio work, its callback (cb) is called with
5330 * deinit set to be 1. Each work's callback is responsible for clearing its
5331 * internal data and restoring to a correct state.
5332 * @wpa_s: wpa_supplicant data
5333 * @type: type of works to be removed
5334 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5335 * this interface's works.
5336 */
5337void radio_remove_works(struct wpa_supplicant *wpa_s,
5338 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005339{
5340 struct wpa_radio_work *work, *tmp;
5341 struct wpa_radio *radio = wpa_s->radio;
5342
5343 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5344 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005345 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005346 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005347
5348 /* skip other ifaces' works */
5349 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005350 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005351
5352 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5353 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005354 work->cb(work, 1);
5355 radio_work_free(work);
5356 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005357
5358 /* in case we removed the started work */
5359 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005360}
5361
5362
Roshan Pius3a1667e2018-07-03 15:17:14 -07005363void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5364{
5365 struct wpa_radio_work *work;
5366 struct wpa_radio *radio = wpa_s->radio;
5367
5368 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5369 if (work->ctx != ctx)
5370 continue;
5371 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5372 work->type, work, work->started ? " (started)" : "");
5373 radio_work_free(work);
5374 break;
5375 }
5376}
5377
5378
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005379static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5380{
5381 struct wpa_radio *radio = wpa_s->radio;
5382
5383 if (!radio)
5384 return;
5385
5386 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5387 wpa_s->ifname, radio->name);
5388 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005389 radio_remove_works(wpa_s, NULL, 0);
5390 wpa_s->radio = NULL;
5391 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005392 return; /* Interfaces remain for this radio */
5393
5394 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005395 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005396 os_free(radio);
5397}
5398
5399
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005400void radio_work_check_next(struct wpa_supplicant *wpa_s)
5401{
5402 struct wpa_radio *radio = wpa_s->radio;
5403
5404 if (dl_list_empty(&radio->work))
5405 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005406 if (wpa_s->ext_work_in_progress) {
5407 wpa_printf(MSG_DEBUG,
5408 "External radio work in progress - delay start of pending item");
5409 return;
5410 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005411 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5412 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5413}
5414
5415
5416/**
5417 * radio_add_work - Add a radio work item
5418 * @wpa_s: Pointer to wpa_supplicant data
5419 * @freq: Frequency of the offchannel operation in MHz or 0
5420 * @type: Unique identifier for each type of work
5421 * @next: Force as the next work to be executed
5422 * @cb: Callback function for indicating when radio is available
5423 * @ctx: Context pointer for the work (work->ctx in cb())
5424 * Returns: 0 on success, -1 on failure
5425 *
5426 * This function is used to request time for an operation that requires
5427 * exclusive radio control. Once the radio is available, the registered callback
5428 * function will be called. radio_work_done() must be called once the exclusive
5429 * radio operation has been completed, so that the radio is freed for other
5430 * operations. The special case of deinit=1 is used to free the context data
5431 * during interface removal. That does not allow the callback function to start
5432 * the radio operation, i.e., it must free any resources allocated for the radio
5433 * work and return.
5434 *
5435 * The @freq parameter can be used to indicate a single channel on which the
5436 * offchannel operation will occur. This may allow multiple radio work
5437 * operations to be performed in parallel if they apply for the same channel.
5438 * Setting this to 0 indicates that the work item may use multiple channels or
5439 * requires exclusive control of the radio.
5440 */
5441int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5442 const char *type, int next,
5443 void (*cb)(struct wpa_radio_work *work, int deinit),
5444 void *ctx)
5445{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005446 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005447 struct wpa_radio_work *work;
5448 int was_empty;
5449
5450 work = os_zalloc(sizeof(*work));
5451 if (work == NULL)
5452 return -1;
5453 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5454 os_get_reltime(&work->time);
5455 work->freq = freq;
5456 work->type = type;
5457 work->wpa_s = wpa_s;
5458 work->cb = cb;
5459 work->ctx = ctx;
5460
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005461 if (freq)
5462 work->bands = wpas_freq_to_band(freq);
5463 else if (os_strcmp(type, "scan") == 0 ||
5464 os_strcmp(type, "p2p-scan") == 0)
5465 work->bands = wpas_get_bands(wpa_s,
5466 ((struct wpa_driver_scan_params *)
5467 ctx)->freqs);
5468 else
5469 work->bands = wpas_get_bands(wpa_s, NULL);
5470
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005471 was_empty = dl_list_empty(&wpa_s->radio->work);
5472 if (next)
5473 dl_list_add(&wpa_s->radio->work, &work->list);
5474 else
5475 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5476 if (was_empty) {
5477 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5478 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005479 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5480 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5481 wpa_dbg(wpa_s, MSG_DEBUG,
5482 "Try to schedule a radio work (num_active_works=%u)",
5483 radio->num_active_works);
5484 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005485 }
5486
5487 return 0;
5488}
5489
5490
5491/**
5492 * radio_work_done - Indicate that a radio work item has been completed
5493 * @work: Completed work
5494 *
5495 * This function is called once the callback function registered with
5496 * radio_add_work() has completed its work.
5497 */
5498void radio_work_done(struct wpa_radio_work *work)
5499{
5500 struct wpa_supplicant *wpa_s = work->wpa_s;
5501 struct os_reltime now, diff;
5502 unsigned int started = work->started;
5503
5504 os_get_reltime(&now);
5505 os_reltime_sub(&now, &work->time, &diff);
5506 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5507 work->type, work, started ? "done" : "canceled",
5508 diff.sec, diff.usec);
5509 radio_work_free(work);
5510 if (started)
5511 radio_work_check_next(wpa_s);
5512}
5513
5514
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005515struct wpa_radio_work *
5516radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005517{
5518 struct wpa_radio_work *work;
5519 struct wpa_radio *radio = wpa_s->radio;
5520
5521 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5522 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005523 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005524 }
5525
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005526 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005527}
5528
5529
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005530static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005531 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005532{
5533 const char *ifname, *driver, *rn;
5534
5535 driver = iface->driver;
5536next_driver:
5537 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
5538 return -1;
5539
5540 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
5541 if (wpa_s->drv_priv == NULL) {
5542 const char *pos;
5543 pos = driver ? os_strchr(driver, ',') : NULL;
5544 if (pos) {
5545 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
5546 "driver interface - try next driver wrapper");
5547 driver = pos + 1;
5548 goto next_driver;
5549 }
5550 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
5551 "interface");
5552 return -1;
5553 }
5554 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
5555 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
5556 "driver_param '%s'", wpa_s->conf->driver_param);
5557 return -1;
5558 }
5559
5560 ifname = wpa_drv_get_ifname(wpa_s);
5561 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
5562 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
5563 "interface name with '%s'", ifname);
5564 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
5565 }
5566
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005567 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005568 if (rn && rn[0] == '\0')
5569 rn = NULL;
5570
5571 wpa_s->radio = radio_add_interface(wpa_s, rn);
5572 if (wpa_s->radio == NULL)
5573 return -1;
5574
5575 return 0;
5576}
5577
5578
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005579#ifdef CONFIG_GAS_SERVER
5580
5581static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
5582 unsigned int freq, const u8 *dst,
5583 const u8 *src, const u8 *bssid,
5584 const u8 *data, size_t data_len,
5585 enum offchannel_send_action_result result)
5586{
5587 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
5588 " result=%s",
5589 freq, MAC2STR(dst),
5590 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
5591 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
5592 "FAILED"));
5593 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
5594 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
5595}
5596
5597
5598static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
5599 struct wpabuf *buf, unsigned int wait_time)
5600{
5601 struct wpa_supplicant *wpa_s = ctx;
5602 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
5603
5604 if (wait_time > wpa_s->max_remain_on_chan)
5605 wait_time = wpa_s->max_remain_on_chan;
5606
5607 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
5608 wpabuf_head(buf), wpabuf_len(buf),
5609 wait_time, wpas_gas_server_tx_status, 0);
5610}
5611
5612#endif /* CONFIG_GAS_SERVER */
5613
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005614static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005615 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005616{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005617 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005618 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005619 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005620
5621 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
5622 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
5623 iface->confname ? iface->confname : "N/A",
5624 iface->driver ? iface->driver : "default",
5625 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
5626 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
5627
5628 if (iface->confname) {
5629#ifdef CONFIG_BACKEND_FILE
5630 wpa_s->confname = os_rel2abs_path(iface->confname);
5631 if (wpa_s->confname == NULL) {
5632 wpa_printf(MSG_ERROR, "Failed to get absolute path "
5633 "for configuration file '%s'.",
5634 iface->confname);
5635 return -1;
5636 }
5637 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
5638 iface->confname, wpa_s->confname);
5639#else /* CONFIG_BACKEND_FILE */
5640 wpa_s->confname = os_strdup(iface->confname);
5641#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005642 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005643 if (wpa_s->conf == NULL) {
5644 wpa_printf(MSG_ERROR, "Failed to read or parse "
5645 "configuration '%s'.", wpa_s->confname);
5646 return -1;
5647 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005648 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005649 if (wpa_s->confanother &&
5650 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
5651 wpa_printf(MSG_ERROR,
5652 "Failed to read or parse configuration '%s'.",
5653 wpa_s->confanother);
5654 return -1;
5655 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005656
5657 /*
5658 * Override ctrl_interface and driver_param if set on command
5659 * line.
5660 */
5661 if (iface->ctrl_interface) {
5662 os_free(wpa_s->conf->ctrl_interface);
5663 wpa_s->conf->ctrl_interface =
5664 os_strdup(iface->ctrl_interface);
5665 }
5666
5667 if (iface->driver_param) {
5668 os_free(wpa_s->conf->driver_param);
5669 wpa_s->conf->driver_param =
5670 os_strdup(iface->driver_param);
5671 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005672
5673 if (iface->p2p_mgmt && !iface->ctrl_interface) {
5674 os_free(wpa_s->conf->ctrl_interface);
5675 wpa_s->conf->ctrl_interface = NULL;
5676 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005677 } else
5678 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
5679 iface->driver_param);
5680
5681 if (wpa_s->conf == NULL) {
5682 wpa_printf(MSG_ERROR, "\nNo configuration found.");
5683 return -1;
5684 }
5685
5686 if (iface->ifname == NULL) {
5687 wpa_printf(MSG_ERROR, "\nInterface name is required.");
5688 return -1;
5689 }
5690 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
5691 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
5692 iface->ifname);
5693 return -1;
5694 }
5695 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
5696
5697 if (iface->bridge_ifname) {
5698 if (os_strlen(iface->bridge_ifname) >=
5699 sizeof(wpa_s->bridge_ifname)) {
5700 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
5701 "name '%s'.", iface->bridge_ifname);
5702 return -1;
5703 }
5704 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
5705 sizeof(wpa_s->bridge_ifname));
5706 }
5707
5708 /* RSNA Supplicant Key Management - INITIALIZE */
5709 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
5710 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
5711
5712 /* Initialize driver interface and register driver event handler before
5713 * L2 receive handler so that association events are processed before
5714 * EAPOL-Key packets if both become available for the same select()
5715 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005716 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005717 return -1;
5718
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005719 if (wpa_supplicant_init_wpa(wpa_s) < 0)
5720 return -1;
5721
5722 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
5723 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
5724 NULL);
5725 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
5726
5727 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
5728 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
5729 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
5730 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5731 "dot11RSNAConfigPMKLifetime");
5732 return -1;
5733 }
5734
5735 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
5736 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
5737 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
5738 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5739 "dot11RSNAConfigPMKReauthThreshold");
5740 return -1;
5741 }
5742
5743 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
5744 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
5745 wpa_s->conf->dot11RSNAConfigSATimeout)) {
5746 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5747 "dot11RSNAConfigSATimeout");
5748 return -1;
5749 }
5750
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005751 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
5752 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005753 &wpa_s->hw.flags,
5754 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005755 if (wpa_s->hw.modes) {
5756 u16 i;
5757
5758 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5759 if (wpa_s->hw.modes[i].vht_capab) {
5760 wpa_s->hw_capab = CAPAB_VHT;
5761 break;
5762 }
5763
5764 if (wpa_s->hw.modes[i].ht_capab &
5765 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
5766 wpa_s->hw_capab = CAPAB_HT40;
5767 else if (wpa_s->hw.modes[i].ht_capab &&
5768 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
5769 wpa_s->hw_capab = CAPAB_HT;
5770 }
5771 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005772
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005773 capa_res = wpa_drv_get_capa(wpa_s, &capa);
5774 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005775 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005776 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005777 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005778 wpa_s->drv_smps_modes = capa.smps_modes;
5779 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005780 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005781 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005782 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005783 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
5784 wpa_s->max_sched_scan_plan_interval =
5785 capa.max_sched_scan_plan_interval;
5786 wpa_s->max_sched_scan_plan_iterations =
5787 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005788 wpa_s->sched_scan_supported = capa.sched_scan_supported;
5789 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005790 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
5791 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005792 wpa_s->extended_capa = capa.extended_capa;
5793 wpa_s->extended_capa_mask = capa.extended_capa_mask;
5794 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005795 wpa_s->num_multichan_concurrent =
5796 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005797 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
5798
5799 if (capa.mac_addr_rand_scan_supported)
5800 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
5801 if (wpa_s->sched_scan_supported &&
5802 capa.mac_addr_rand_sched_scan_supported)
5803 wpa_s->mac_addr_rand_supported |=
5804 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08005805
5806 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
5807 if (wpa_s->extended_capa &&
5808 wpa_s->extended_capa_len >= 3 &&
5809 wpa_s->extended_capa[2] & 0x40)
5810 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005811 }
5812 if (wpa_s->max_remain_on_chan == 0)
5813 wpa_s->max_remain_on_chan = 1000;
5814
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005815 /*
5816 * Only take p2p_mgmt parameters when P2P Device is supported.
5817 * Doing it here as it determines whether l2_packet_init() will be done
5818 * during wpa_supplicant_driver_init().
5819 */
5820 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
5821 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005822
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005823 if (wpa_s->num_multichan_concurrent == 0)
5824 wpa_s->num_multichan_concurrent = 1;
5825
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005826 if (wpa_supplicant_driver_init(wpa_s) < 0)
5827 return -1;
5828
5829#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07005830 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005831 return -1;
5832#endif /* CONFIG_TDLS */
5833
5834 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
5835 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
5836 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
5837 return -1;
5838 }
5839
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005840#ifdef CONFIG_FST
5841 if (wpa_s->conf->fst_group_id) {
5842 struct fst_iface_cfg cfg;
5843 struct fst_wpa_obj iface_obj;
5844
5845 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
5846 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
5847 sizeof(cfg.group_id));
5848 cfg.priority = wpa_s->conf->fst_priority;
5849 cfg.llt = wpa_s->conf->fst_llt;
5850
5851 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
5852 &iface_obj, &cfg);
5853 if (!wpa_s->fst) {
5854 wpa_msg(wpa_s, MSG_ERROR,
5855 "FST: Cannot attach iface %s to group %s",
5856 wpa_s->ifname, cfg.group_id);
5857 return -1;
5858 }
5859 }
5860#endif /* CONFIG_FST */
5861
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005862 if (wpas_wps_init(wpa_s))
5863 return -1;
5864
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005865#ifdef CONFIG_GAS_SERVER
5866 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
5867 if (!wpa_s->gas_server) {
5868 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
5869 return -1;
5870 }
5871#endif /* CONFIG_GAS_SERVER */
5872
5873#ifdef CONFIG_DPP
5874 if (wpas_dpp_init(wpa_s) < 0)
5875 return -1;
5876#endif /* CONFIG_DPP */
5877
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005878 if (wpa_supplicant_init_eapol(wpa_s) < 0)
5879 return -1;
5880 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5881
5882 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
5883 if (wpa_s->ctrl_iface == NULL) {
5884 wpa_printf(MSG_ERROR,
5885 "Failed to initialize control interface '%s'.\n"
5886 "You may have another wpa_supplicant process "
5887 "already running or the file was\n"
5888 "left by an unclean termination of wpa_supplicant "
5889 "in which case you will need\n"
5890 "to manually remove this file before starting "
5891 "wpa_supplicant again.\n",
5892 wpa_s->conf->ctrl_interface);
5893 return -1;
5894 }
5895
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005896 wpa_s->gas = gas_query_init(wpa_s);
5897 if (wpa_s->gas == NULL) {
5898 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5899 return -1;
5900 }
5901
Roshan Pius3a1667e2018-07-03 15:17:14 -07005902 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
5903 wpa_s->p2p_mgmt) &&
5904 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005905 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5906 return -1;
5907 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005908
5909 if (wpa_bss_init(wpa_s) < 0)
5910 return -1;
5911
Paul Stewart092955c2017-02-06 09:13:09 -08005912#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5913#ifdef CONFIG_MESH
5914 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
5915#endif /* CONFIG_MESH */
5916#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5917
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005918 /*
5919 * Set Wake-on-WLAN triggers, if configured.
5920 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5921 * have effect anyway when the interface is down).
5922 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005923 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005924 return -1;
5925
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005926#ifdef CONFIG_EAP_PROXY
5927{
5928 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005929 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
5930 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005931 if (wpa_s->mnc_len > 0) {
5932 wpa_s->imsi[len] = '\0';
5933 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5934 wpa_s->imsi, wpa_s->mnc_len);
5935 } else {
5936 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5937 }
5938}
5939#endif /* CONFIG_EAP_PROXY */
5940
Dmitry Shmidt04949592012-07-19 12:16:46 -07005941 if (pcsc_reader_init(wpa_s) < 0)
5942 return -1;
5943
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005944 if (wpas_init_ext_pw(wpa_s) < 0)
5945 return -1;
5946
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005947 wpas_rrm_reset(wpa_s);
5948
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005949 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5950
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005951#ifdef CONFIG_HS20
5952 hs20_init(wpa_s);
5953#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005954#ifdef CONFIG_MBO
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005955 if (wpa_s->conf->oce) {
5956 if ((wpa_s->conf->oce & OCE_STA) &&
5957 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
5958 wpa_s->enable_oce = OCE_STA;
5959 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
5960 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
5961 /* TODO: Need to add STA-CFON support */
5962 wpa_printf(MSG_ERROR,
5963 "OCE STA-CFON feature is not yet supported");
5964 }
5965 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005966 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5967#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005968
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005969 wpa_supplicant_set_default_scan_ies(wpa_s);
5970
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005971 return 0;
5972}
5973
5974
5975static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005976 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005977{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005978 struct wpa_global *global = wpa_s->global;
5979 struct wpa_supplicant *iface, *prev;
5980
5981 if (wpa_s == wpa_s->parent)
5982 wpas_p2p_group_remove(wpa_s, "*");
5983
5984 iface = global->ifaces;
5985 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005986 if (iface->p2pdev == wpa_s)
5987 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005988 if (iface == wpa_s || iface->parent != wpa_s) {
5989 iface = iface->next;
5990 continue;
5991 }
5992 wpa_printf(MSG_DEBUG,
5993 "Remove remaining child interface %s from parent %s",
5994 iface->ifname, wpa_s->ifname);
5995 prev = iface;
5996 iface = iface->next;
5997 wpa_supplicant_remove_iface(global, prev, terminate);
5998 }
5999
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006000 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006001 if (wpa_s->drv_priv) {
6002 wpa_supplicant_deauthenticate(wpa_s,
6003 WLAN_REASON_DEAUTH_LEAVING);
6004
6005 wpa_drv_set_countermeasures(wpa_s, 0);
6006 wpa_clear_keys(wpa_s, NULL);
6007 }
6008
6009 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006010 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006011
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006012 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006013 radio_remove_interface(wpa_s);
6014
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006015#ifdef CONFIG_FST
6016 if (wpa_s->fst) {
6017 fst_detach(wpa_s->fst);
6018 wpa_s->fst = NULL;
6019 }
6020 if (wpa_s->received_mb_ies) {
6021 wpabuf_free(wpa_s->received_mb_ies);
6022 wpa_s->received_mb_ies = NULL;
6023 }
6024#endif /* CONFIG_FST */
6025
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006026 if (wpa_s->drv_priv)
6027 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006028
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006029 if (notify)
6030 wpas_notify_iface_removed(wpa_s);
6031
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006032 if (terminate)
6033 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006034
6035 if (wpa_s->ctrl_iface) {
6036 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6037 wpa_s->ctrl_iface = NULL;
6038 }
6039
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006040#ifdef CONFIG_MESH
6041 if (wpa_s->ifmsh) {
6042 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6043 wpa_s->ifmsh = NULL;
6044 }
6045#endif /* CONFIG_MESH */
6046
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006047 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006048 wpa_config_free(wpa_s->conf);
6049 wpa_s->conf = NULL;
6050 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006051
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006052 os_free(wpa_s->ssids_from_scan_req);
6053
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006054 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006055}
6056
6057
Dmitry Shmidte4663042016-04-04 10:07:49 -07006058#ifdef CONFIG_MATCH_IFACE
6059
6060/**
6061 * wpa_supplicant_match_iface - Match an interface description to a name
6062 * @global: Pointer to global data from wpa_supplicant_init()
6063 * @ifname: Name of the interface to match
6064 * Returns: Pointer to the created interface description or %NULL on failure
6065 */
6066struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6067 const char *ifname)
6068{
6069 int i;
6070 struct wpa_interface *iface, *miface;
6071
6072 for (i = 0; i < global->params.match_iface_count; i++) {
6073 miface = &global->params.match_ifaces[i];
6074 if (!miface->ifname ||
6075 fnmatch(miface->ifname, ifname, 0) == 0) {
6076 iface = os_zalloc(sizeof(*iface));
6077 if (!iface)
6078 return NULL;
6079 *iface = *miface;
6080 iface->ifname = ifname;
6081 return iface;
6082 }
6083 }
6084
6085 return NULL;
6086}
6087
6088
6089/**
6090 * wpa_supplicant_match_existing - Match existing interfaces
6091 * @global: Pointer to global data from wpa_supplicant_init()
6092 * Returns: 0 on success, -1 on failure
6093 */
6094static int wpa_supplicant_match_existing(struct wpa_global *global)
6095{
6096 struct if_nameindex *ifi, *ifp;
6097 struct wpa_supplicant *wpa_s;
6098 struct wpa_interface *iface;
6099
6100 ifp = if_nameindex();
6101 if (!ifp) {
6102 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6103 return -1;
6104 }
6105
6106 for (ifi = ifp; ifi->if_name; ifi++) {
6107 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6108 if (wpa_s)
6109 continue;
6110 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6111 if (iface) {
6112 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6113 os_free(iface);
6114 if (wpa_s)
6115 wpa_s->matched = 1;
6116 }
6117 }
6118
6119 if_freenameindex(ifp);
6120 return 0;
6121}
6122
6123#endif /* CONFIG_MATCH_IFACE */
6124
6125
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006126/**
6127 * wpa_supplicant_add_iface - Add a new network interface
6128 * @global: Pointer to global data from wpa_supplicant_init()
6129 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006130 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006131 * Returns: Pointer to the created interface or %NULL on failure
6132 *
6133 * This function is used to add new network interfaces for %wpa_supplicant.
6134 * This can be called before wpa_supplicant_run() to add interfaces before the
6135 * main event loop has been started. In addition, new interfaces can be added
6136 * dynamically while %wpa_supplicant is already running. This could happen,
6137 * e.g., when a hotplug network adapter is inserted.
6138 */
6139struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006140 struct wpa_interface *iface,
6141 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006142{
6143 struct wpa_supplicant *wpa_s;
6144 struct wpa_interface t_iface;
6145 struct wpa_ssid *ssid;
6146
6147 if (global == NULL || iface == NULL)
6148 return NULL;
6149
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006150 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006151 if (wpa_s == NULL)
6152 return NULL;
6153
6154 wpa_s->global = global;
6155
6156 t_iface = *iface;
6157 if (global->params.override_driver) {
6158 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6159 "('%s' -> '%s')",
6160 iface->driver, global->params.override_driver);
6161 t_iface.driver = global->params.override_driver;
6162 }
6163 if (global->params.override_ctrl_interface) {
6164 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6165 "ctrl_interface ('%s' -> '%s')",
6166 iface->ctrl_interface,
6167 global->params.override_ctrl_interface);
6168 t_iface.ctrl_interface =
6169 global->params.override_ctrl_interface;
6170 }
6171 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6172 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6173 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006174 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006175 return NULL;
6176 }
6177
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006178 /* Notify the control interfaces about new iface */
6179 if (wpas_notify_iface_added(wpa_s)) {
6180 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6181 return NULL;
6182 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006183
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006184 /* Notify the control interfaces about new networks for non p2p mgmt
6185 * ifaces. */
6186 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006187 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6188 wpas_notify_network_added(wpa_s, ssid);
6189 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006190
6191 wpa_s->next = global->ifaces;
6192 global->ifaces = wpa_s;
6193
6194 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006195 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006196
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006197#ifdef CONFIG_P2P
6198 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006199 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006200 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006201 wpas_p2p_add_p2pdev_interface(
6202 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006203 wpa_printf(MSG_INFO,
6204 "P2P: Failed to enable P2P Device interface");
6205 /* Try to continue without. P2P will be disabled. */
6206 }
6207#endif /* CONFIG_P2P */
6208
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006209 return wpa_s;
6210}
6211
6212
6213/**
6214 * wpa_supplicant_remove_iface - Remove a network interface
6215 * @global: Pointer to global data from wpa_supplicant_init()
6216 * @wpa_s: Pointer to the network interface to be removed
6217 * Returns: 0 if interface was removed, -1 if interface was not found
6218 *
6219 * This function can be used to dynamically remove network interfaces from
6220 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6221 * addition, this function is used to remove all remaining interfaces when
6222 * %wpa_supplicant is terminated.
6223 */
6224int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006225 struct wpa_supplicant *wpa_s,
6226 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006227{
6228 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006229#ifdef CONFIG_MESH
6230 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6231 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006232 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006233#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006234
6235 /* Remove interface from the global list of interfaces */
6236 prev = global->ifaces;
6237 if (prev == wpa_s) {
6238 global->ifaces = wpa_s->next;
6239 } else {
6240 while (prev && prev->next != wpa_s)
6241 prev = prev->next;
6242 if (prev == NULL)
6243 return -1;
6244 prev->next = wpa_s->next;
6245 }
6246
6247 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6248
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006249#ifdef CONFIG_MESH
6250 if (mesh_if_created) {
6251 ifname = os_strdup(wpa_s->ifname);
6252 if (ifname == NULL) {
6253 wpa_dbg(wpa_s, MSG_ERROR,
6254 "mesh: Failed to malloc ifname");
6255 return -1;
6256 }
6257 }
6258#endif /* CONFIG_MESH */
6259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006260 if (global->p2p_group_formation == wpa_s)
6261 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006262 if (global->p2p_invite_group == wpa_s)
6263 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006264 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006265
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006266#ifdef CONFIG_MESH
6267 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006268 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006269 os_free(ifname);
6270 }
6271#endif /* CONFIG_MESH */
6272
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006273 return 0;
6274}
6275
6276
6277/**
6278 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6279 * @wpa_s: Pointer to the network interface
6280 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6281 */
6282const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6283{
6284 const char *eapol_method;
6285
6286 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6287 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6288 return "NO-EAP";
6289 }
6290
6291 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6292 if (eapol_method == NULL)
6293 return "UNKNOWN-EAP";
6294
6295 return eapol_method;
6296}
6297
6298
6299/**
6300 * wpa_supplicant_get_iface - Get a new network interface
6301 * @global: Pointer to global data from wpa_supplicant_init()
6302 * @ifname: Interface name
6303 * Returns: Pointer to the interface or %NULL if not found
6304 */
6305struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6306 const char *ifname)
6307{
6308 struct wpa_supplicant *wpa_s;
6309
6310 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6311 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6312 return wpa_s;
6313 }
6314 return NULL;
6315}
6316
6317
6318#ifndef CONFIG_NO_WPA_MSG
6319static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6320{
6321 struct wpa_supplicant *wpa_s = ctx;
6322 if (wpa_s == NULL)
6323 return NULL;
6324 return wpa_s->ifname;
6325}
6326#endif /* CONFIG_NO_WPA_MSG */
6327
6328
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006329#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6330#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6331#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6332
6333/* Periodic cleanup tasks */
6334static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6335{
6336 struct wpa_global *global = eloop_ctx;
6337 struct wpa_supplicant *wpa_s;
6338
6339 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6340 wpas_periodic, global, NULL);
6341
6342#ifdef CONFIG_P2P
6343 if (global->p2p)
6344 p2p_expire_peers(global->p2p);
6345#endif /* CONFIG_P2P */
6346
6347 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6348 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6349#ifdef CONFIG_AP
6350 ap_periodic(wpa_s);
6351#endif /* CONFIG_AP */
6352 }
6353}
6354
6355
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006356/**
6357 * wpa_supplicant_init - Initialize %wpa_supplicant
6358 * @params: Parameters for %wpa_supplicant
6359 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6360 *
6361 * This function is used to initialize %wpa_supplicant. After successful
6362 * initialization, the returned data pointer can be used to add and remove
6363 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6364 */
6365struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6366{
6367 struct wpa_global *global;
6368 int ret, i;
6369
6370 if (params == NULL)
6371 return NULL;
6372
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006373#ifdef CONFIG_DRIVER_NDIS
6374 {
6375 void driver_ndis_init_ops(void);
6376 driver_ndis_init_ops();
6377 }
6378#endif /* CONFIG_DRIVER_NDIS */
6379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006380#ifndef CONFIG_NO_WPA_MSG
6381 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6382#endif /* CONFIG_NO_WPA_MSG */
6383
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006384 if (params->wpa_debug_file_path)
6385 wpa_debug_open_file(params->wpa_debug_file_path);
6386 else
6387 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006388 if (params->wpa_debug_syslog)
6389 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006390 if (params->wpa_debug_tracing) {
6391 ret = wpa_debug_open_linux_tracing();
6392 if (ret) {
6393 wpa_printf(MSG_ERROR,
6394 "Failed to enable trace logging");
6395 return NULL;
6396 }
6397 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006398
6399 ret = eap_register_methods();
6400 if (ret) {
6401 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6402 if (ret == -2)
6403 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6404 "the same EAP type.");
6405 return NULL;
6406 }
6407
6408 global = os_zalloc(sizeof(*global));
6409 if (global == NULL)
6410 return NULL;
6411 dl_list_init(&global->p2p_srv_bonjour);
6412 dl_list_init(&global->p2p_srv_upnp);
6413 global->params.daemonize = params->daemonize;
6414 global->params.wait_for_monitor = params->wait_for_monitor;
6415 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6416 if (params->pid_file)
6417 global->params.pid_file = os_strdup(params->pid_file);
6418 if (params->ctrl_interface)
6419 global->params.ctrl_interface =
6420 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006421 if (params->ctrl_interface_group)
6422 global->params.ctrl_interface_group =
6423 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006424 if (params->override_driver)
6425 global->params.override_driver =
6426 os_strdup(params->override_driver);
6427 if (params->override_ctrl_interface)
6428 global->params.override_ctrl_interface =
6429 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006430#ifdef CONFIG_MATCH_IFACE
6431 global->params.match_iface_count = params->match_iface_count;
6432 if (params->match_iface_count) {
6433 global->params.match_ifaces =
6434 os_calloc(params->match_iface_count,
6435 sizeof(struct wpa_interface));
6436 os_memcpy(global->params.match_ifaces,
6437 params->match_ifaces,
6438 params->match_iface_count *
6439 sizeof(struct wpa_interface));
6440 }
6441#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006442#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006443 if (params->conf_p2p_dev)
6444 global->params.conf_p2p_dev =
6445 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006446#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006447 wpa_debug_level = global->params.wpa_debug_level =
6448 params->wpa_debug_level;
6449 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6450 params->wpa_debug_show_keys;
6451 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6452 params->wpa_debug_timestamp;
6453
6454 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
6455
6456 if (eloop_init()) {
6457 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6458 wpa_supplicant_deinit(global);
6459 return NULL;
6460 }
6461
Jouni Malinen75ecf522011-06-27 15:19:46 -07006462 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006463
6464 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6465 if (global->ctrl_iface == NULL) {
6466 wpa_supplicant_deinit(global);
6467 return NULL;
6468 }
6469
6470 if (wpas_notify_supplicant_initialized(global)) {
6471 wpa_supplicant_deinit(global);
6472 return NULL;
6473 }
6474
6475 for (i = 0; wpa_drivers[i]; i++)
6476 global->drv_count++;
6477 if (global->drv_count == 0) {
6478 wpa_printf(MSG_ERROR, "No drivers enabled");
6479 wpa_supplicant_deinit(global);
6480 return NULL;
6481 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006482 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006483 if (global->drv_priv == NULL) {
6484 wpa_supplicant_deinit(global);
6485 return NULL;
6486 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006487
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006488#ifdef CONFIG_WIFI_DISPLAY
6489 if (wifi_display_init(global) < 0) {
6490 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6491 wpa_supplicant_deinit(global);
6492 return NULL;
6493 }
6494#endif /* CONFIG_WIFI_DISPLAY */
6495
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006496 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6497 wpas_periodic, global, NULL);
6498
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006499 return global;
6500}
6501
6502
6503/**
6504 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6505 * @global: Pointer to global data from wpa_supplicant_init()
6506 * Returns: 0 after successful event loop run, -1 on failure
6507 *
6508 * This function starts the main event loop and continues running as long as
6509 * there are any remaining events. In most cases, this function is running as
6510 * long as the %wpa_supplicant process in still in use.
6511 */
6512int wpa_supplicant_run(struct wpa_global *global)
6513{
6514 struct wpa_supplicant *wpa_s;
6515
6516 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006517 (wpa_supplicant_daemon(global->params.pid_file) ||
6518 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006519 return -1;
6520
Dmitry Shmidte4663042016-04-04 10:07:49 -07006521#ifdef CONFIG_MATCH_IFACE
6522 if (wpa_supplicant_match_existing(global))
6523 return -1;
6524#endif
6525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006526 if (global->params.wait_for_monitor) {
6527 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08006528 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006529 wpa_supplicant_ctrl_iface_wait(
6530 wpa_s->ctrl_iface);
6531 }
6532
6533 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
6534 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
6535
6536 eloop_run();
6537
6538 return 0;
6539}
6540
6541
6542/**
6543 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
6544 * @global: Pointer to global data from wpa_supplicant_init()
6545 *
6546 * This function is called to deinitialize %wpa_supplicant and to free all
6547 * allocated resources. Remaining network interfaces will also be removed.
6548 */
6549void wpa_supplicant_deinit(struct wpa_global *global)
6550{
6551 int i;
6552
6553 if (global == NULL)
6554 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006555
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006556 eloop_cancel_timeout(wpas_periodic, global, NULL);
6557
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006558#ifdef CONFIG_WIFI_DISPLAY
6559 wifi_display_deinit(global);
6560#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006561
6562 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006563 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006564
6565 if (global->ctrl_iface)
6566 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
6567
6568 wpas_notify_supplicant_deinitialized(global);
6569
6570 eap_peer_unregister_methods();
6571#ifdef CONFIG_AP
6572 eap_server_unregister_methods();
6573#endif /* CONFIG_AP */
6574
6575 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
6576 if (!global->drv_priv[i])
6577 continue;
6578 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
6579 }
6580 os_free(global->drv_priv);
6581
6582 random_deinit();
6583
6584 eloop_destroy();
6585
6586 if (global->params.pid_file) {
6587 os_daemonize_terminate(global->params.pid_file);
6588 os_free(global->params.pid_file);
6589 }
6590 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006591 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006592 os_free(global->params.override_driver);
6593 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006594#ifdef CONFIG_MATCH_IFACE
6595 os_free(global->params.match_ifaces);
6596#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006597#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006598 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006599#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006600
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07006601 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006602 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006603 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006604
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006605 os_free(global);
6606 wpa_debug_close_syslog();
6607 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006608 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006609}
6610
6611
6612void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
6613{
6614 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
6615 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
6616 char country[3];
6617 country[0] = wpa_s->conf->country[0];
6618 country[1] = wpa_s->conf->country[1];
6619 country[2] = '\0';
6620 if (wpa_drv_set_country(wpa_s, country) < 0) {
6621 wpa_printf(MSG_ERROR, "Failed to set country code "
6622 "'%s'", country);
6623 }
6624 }
6625
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006626 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
6627 wpas_init_ext_pw(wpa_s);
6628
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006629 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
6630 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6631
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006632 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
6633 struct wpa_driver_capa capa;
6634 int res = wpa_drv_get_capa(wpa_s, &capa);
6635
6636 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
6637 wpa_printf(MSG_ERROR,
6638 "Failed to update wowlan_triggers to '%s'",
6639 wpa_s->conf->wowlan_triggers);
6640 }
6641
Hai Shalom81f62d82019-07-22 12:10:00 -07006642 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
6643 wpa_supplicant_set_default_scan_ies(wpa_s);
6644
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006645#ifdef CONFIG_WPS
6646 wpas_wps_update_config(wpa_s);
6647#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006648 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006649 wpa_s->conf->changed_parameters = 0;
6650}
6651
6652
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006653void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006654{
6655 int i;
6656
6657 for (i = 0; i < *num_freqs; i++) {
6658 if (freqs[i] == freq)
6659 return;
6660 }
6661
6662 freqs[*num_freqs] = freq;
6663 (*num_freqs)++;
6664}
6665
6666
6667static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
6668{
6669 struct wpa_bss *bss, *cbss;
6670 const int max_freqs = 10;
6671 int *freqs;
6672 int num_freqs = 0;
6673
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006674 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006675 if (freqs == NULL)
6676 return NULL;
6677
6678 cbss = wpa_s->current_bss;
6679
6680 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
6681 if (bss == cbss)
6682 continue;
6683 if (bss->ssid_len == cbss->ssid_len &&
6684 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
6685 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
6686 add_freq(freqs, &num_freqs, bss->freq);
6687 if (num_freqs == max_freqs)
6688 break;
6689 }
6690 }
6691
6692 if (num_freqs == 0) {
6693 os_free(freqs);
6694 freqs = NULL;
6695 }
6696
6697 return freqs;
6698}
6699
6700
6701void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6702{
6703 int timeout;
6704 int count;
6705 int *freqs = NULL;
6706
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006707 wpas_connect_work_done(wpa_s);
6708
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006709 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006710 * Remove possible authentication timeout since the connection failed.
6711 */
6712 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
6713
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006714 /*
6715 * There is no point in blacklisting the AP if this event is
6716 * generated based on local request to disconnect.
6717 */
6718 if (wpa_s->own_disconnect_req) {
6719 wpa_s->own_disconnect_req = 0;
6720 wpa_dbg(wpa_s, MSG_DEBUG,
6721 "Ignore connection failure due to local request to disconnect");
6722 return;
6723 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006724 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006725 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6726 "indication since interface has been put into "
6727 "disconnected state");
6728 return;
6729 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08006730 if (wpa_s->auto_reconnect_disabled) {
6731 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6732 "indication since auto connect is disabled");
6733 return;
6734 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006735
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006736 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006737 * Add the failed BSSID into the blacklist and speed up next scan
6738 * attempt if there could be other APs that could accept association.
6739 * The current blacklist count indicates how many times we have tried
6740 * connecting to this AP and multiple attempts mean that other APs are
6741 * either not available or has already been tried, so that we can start
6742 * increasing the delay here to avoid constant scanning.
6743 */
6744 count = wpa_blacklist_add(wpa_s, bssid);
6745 if (count == 1 && wpa_s->current_bss) {
6746 /*
6747 * This BSS was not in the blacklist before. If there is
6748 * another BSS available for the same ESS, we should try that
6749 * next. Otherwise, we may as well try this one once more
6750 * before allowing other, likely worse, ESSes to be considered.
6751 */
6752 freqs = get_bss_freqs_in_ess(wpa_s);
6753 if (freqs) {
6754 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
6755 "has been seen; try it next");
6756 wpa_blacklist_add(wpa_s, bssid);
6757 /*
6758 * On the next scan, go through only the known channels
6759 * used in this ESS based on previous scans to speed up
6760 * common load balancing use case.
6761 */
6762 os_free(wpa_s->next_scan_freqs);
6763 wpa_s->next_scan_freqs = freqs;
6764 }
6765 }
6766
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006767 /*
6768 * Add previous failure count in case the temporary blacklist was
6769 * cleared due to no other BSSes being available.
6770 */
6771 count += wpa_s->extra_blacklist_count;
6772
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006773 if (count > 3 && wpa_s->current_ssid) {
6774 wpa_printf(MSG_DEBUG, "Continuous association failures - "
6775 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006776 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006777 }
6778
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006779 switch (count) {
6780 case 1:
6781 timeout = 100;
6782 break;
6783 case 2:
6784 timeout = 500;
6785 break;
6786 case 3:
6787 timeout = 1000;
6788 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006789 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006790 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006791 break;
6792 default:
6793 timeout = 10000;
6794 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006795 }
6796
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006797 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
6798 "ms", count, timeout);
6799
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006800 /*
6801 * TODO: if more than one possible AP is available in scan results,
6802 * could try the other ones before requesting a new scan.
6803 */
Hai Shalom021b0b52019-04-10 11:17:58 -07006804
6805 /* speed up the connection attempt with normal scan */
6806 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006807 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
6808 1000 * (timeout % 1000));
6809}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006810
6811
Hai Shalomce48b4a2018-09-05 11:41:35 -07006812#ifdef CONFIG_FILS
6813void fils_connection_failure(struct wpa_supplicant *wpa_s)
6814{
6815 struct wpa_ssid *ssid = wpa_s->current_ssid;
6816 const u8 *realm, *username, *rrk;
6817 size_t realm_len, username_len, rrk_len;
6818 u16 next_seq_num;
6819
6820 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
6821 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
6822 &username, &username_len,
6823 &realm, &realm_len, &next_seq_num,
6824 &rrk, &rrk_len) != 0 ||
6825 !realm)
6826 return;
6827
6828 wpa_hexdump_ascii(MSG_DEBUG,
6829 "FILS: Store last connection failure realm",
6830 realm, realm_len);
6831 os_free(wpa_s->last_con_fail_realm);
6832 wpa_s->last_con_fail_realm = os_malloc(realm_len);
6833 if (wpa_s->last_con_fail_realm) {
6834 wpa_s->last_con_fail_realm_len = realm_len;
6835 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
6836 }
6837}
6838#endif /* CONFIG_FILS */
6839
6840
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006841int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
6842{
6843 return wpa_s->conf->ap_scan == 2 ||
6844 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
6845}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006846
Dmitry Shmidt04949592012-07-19 12:16:46 -07006847
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006848#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006849int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6850 struct wpa_ssid *ssid,
6851 const char *field,
6852 const char *value)
6853{
6854#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006855 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006856
6857 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
6858 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
6859 (const u8 *) value, os_strlen(value));
6860
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006861 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07006862 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006863#else /* IEEE8021X_EAPOL */
6864 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6865 return -1;
6866#endif /* IEEE8021X_EAPOL */
6867}
6868
6869int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6870 struct wpa_ssid *ssid,
6871 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07006872 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006873{
6874#ifdef IEEE8021X_EAPOL
6875 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08006876 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006877
6878 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07006879 case WPA_CTRL_REQ_EAP_IDENTITY:
6880 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08006881 os_free(eap->imsi_identity);
6882 if (value == NULL)
6883 return -1;
6884 identity = os_strchr(value, ':');
6885 if (identity == NULL) {
6886 /* plain identity */
6887 eap->identity = (u8 *)os_strdup(value);
6888 eap->identity_len = os_strlen(value);
6889 } else {
6890 /* have both plain identity and encrypted identity */
6891 imsi_identity = value;
6892 *identity++ = '\0';
6893 /* plain identity */
6894 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
6895 eap->imsi_identity_len = strlen(imsi_identity);
6896 /* encrypted identity */
6897 eap->identity = (u8 *)dup_binstr(identity,
6898 value_len - strlen(imsi_identity) - 1);
6899 eap->identity_len = value_len - strlen(imsi_identity) - 1;
6900 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006901 eap->pending_req_identity = 0;
6902 if (ssid == wpa_s->current_ssid)
6903 wpa_s->reassociate = 1;
6904 break;
6905 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006906 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006907 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006908 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006909 eap->pending_req_password = 0;
6910 if (ssid == wpa_s->current_ssid)
6911 wpa_s->reassociate = 1;
6912 break;
6913 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006914 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006915 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006916 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006917 eap->pending_req_new_password = 0;
6918 if (ssid == wpa_s->current_ssid)
6919 wpa_s->reassociate = 1;
6920 break;
6921 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006922 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006923 eap->pin = os_strdup(value);
6924 eap->pending_req_pin = 0;
6925 if (ssid == wpa_s->current_ssid)
6926 wpa_s->reassociate = 1;
6927 break;
6928 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006929 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006930 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006931 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006932 os_free(eap->pending_req_otp);
6933 eap->pending_req_otp = NULL;
6934 eap->pending_req_otp_len = 0;
6935 break;
6936 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006937 str_clear_free(eap->private_key_passwd);
6938 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006939 eap->pending_req_passphrase = 0;
6940 if (ssid == wpa_s->current_ssid)
6941 wpa_s->reassociate = 1;
6942 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006943 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006944 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07006945 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006946 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006947 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006948 case WPA_CTRL_REQ_PSK_PASSPHRASE:
6949 if (wpa_config_set(ssid, "psk", value, 0) < 0)
6950 return -1;
6951 ssid->mem_only_psk = 1;
6952 if (ssid->passphrase)
6953 wpa_config_update_psk(ssid);
6954 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
6955 wpa_supplicant_req_scan(wpa_s, 0, 0);
6956 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006957 case WPA_CTRL_REQ_EXT_CERT_CHECK:
6958 if (eap->pending_ext_cert_check != PENDING_CHECK)
6959 return -1;
6960 if (os_strcmp(value, "good") == 0)
6961 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
6962 else if (os_strcmp(value, "bad") == 0)
6963 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
6964 else
6965 return -1;
6966 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006967 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006968 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006969 return -1;
6970 }
6971
6972 return 0;
6973#else /* IEEE8021X_EAPOL */
6974 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6975 return -1;
6976#endif /* IEEE8021X_EAPOL */
6977}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006978#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006979
6980
6981int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6982{
6983 int i;
6984 unsigned int drv_enc;
6985
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006986 if (wpa_s->p2p_mgmt)
6987 return 1; /* no normal network profiles on p2p_mgmt interface */
6988
Dmitry Shmidt04949592012-07-19 12:16:46 -07006989 if (ssid == NULL)
6990 return 1;
6991
6992 if (ssid->disabled)
6993 return 1;
6994
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006995 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006996 drv_enc = wpa_s->drv_enc;
6997 else
6998 drv_enc = (unsigned int) -1;
6999
7000 for (i = 0; i < NUM_WEP_KEYS; i++) {
7001 size_t len = ssid->wep_key_len[i];
7002 if (len == 0)
7003 continue;
7004 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7005 continue;
7006 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7007 continue;
7008 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7009 continue;
7010 return 1; /* invalid WEP key */
7011 }
7012
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007013 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007014 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007015 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007016 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007017 return 1;
7018
Dmitry Shmidt04949592012-07-19 12:16:46 -07007019 return 0;
7020}
7021
7022
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007023int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7024{
7025#ifdef CONFIG_IEEE80211W
7026 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7027 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7028 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7029 /*
7030 * Driver does not support BIP -- ignore pmf=1 default
7031 * since the connection with PMF would fail and the
7032 * configuration does not require PMF to be enabled.
7033 */
7034 return NO_MGMT_FRAME_PROTECTION;
7035 }
7036
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007037 if (ssid &&
7038 (ssid->key_mgmt &
7039 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7040 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7041 /*
7042 * Do not use the default PMF value for non-RSN networks
7043 * since PMF is available only with RSN and pmf=2
7044 * configuration would otherwise prevent connections to
7045 * all open networks.
7046 */
7047 return NO_MGMT_FRAME_PROTECTION;
7048 }
7049
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007050 return wpa_s->conf->pmf;
7051 }
7052
7053 return ssid->ieee80211w;
7054#else /* CONFIG_IEEE80211W */
7055 return NO_MGMT_FRAME_PROTECTION;
7056#endif /* CONFIG_IEEE80211W */
7057}
7058
7059
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007060int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007061{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007062 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007063 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007064 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007065 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007066 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007067}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007068
7069
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007070void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007071{
7072 struct wpa_ssid *ssid = wpa_s->current_ssid;
7073 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007074 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007075
7076 if (ssid == NULL) {
7077 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7078 "SSID block");
7079 return;
7080 }
7081
7082 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7083 return;
7084
7085 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007086
7087#ifdef CONFIG_P2P
7088 if (ssid->p2p_group &&
7089 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7090 /*
7091 * Skip the wait time since there is a short timeout on the
7092 * connection to a P2P group.
7093 */
7094 return;
7095 }
7096#endif /* CONFIG_P2P */
7097
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007098 if (ssid->auth_failures > 50)
7099 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007100 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007101 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007102 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007103 dur = 90;
7104 else if (ssid->auth_failures > 3)
7105 dur = 60;
7106 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007107 dur = 30;
7108 else if (ssid->auth_failures > 1)
7109 dur = 20;
7110 else
7111 dur = 10;
7112
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007113 if (ssid->auth_failures > 1 &&
7114 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7115 dur += os_random() % (ssid->auth_failures * 10);
7116
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007117 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007118 if (now.sec + dur <= ssid->disabled_until.sec)
7119 return;
7120
7121 ssid->disabled_until.sec = now.sec + dur;
7122
7123 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007124 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007125 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007126 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007127}
7128
7129
7130void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7131 struct wpa_ssid *ssid, int clear_failures)
7132{
7133 if (ssid == NULL)
7134 return;
7135
7136 if (ssid->disabled_until.sec) {
7137 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7138 "id=%d ssid=\"%s\"",
7139 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7140 }
7141 ssid->disabled_until.sec = 0;
7142 ssid->disabled_until.usec = 0;
7143 if (clear_failures)
7144 ssid->auth_failures = 0;
7145}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007146
7147
7148int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7149{
7150 size_t i;
7151
7152 if (wpa_s->disallow_aps_bssid == NULL)
7153 return 0;
7154
7155 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7156 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7157 bssid, ETH_ALEN) == 0)
7158 return 1;
7159 }
7160
7161 return 0;
7162}
7163
7164
7165int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7166 size_t ssid_len)
7167{
7168 size_t i;
7169
7170 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7171 return 0;
7172
7173 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7174 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7175 if (ssid_len == s->ssid_len &&
7176 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7177 return 1;
7178 }
7179
7180 return 0;
7181}
7182
7183
7184/**
7185 * wpas_request_connection - Request a new connection
7186 * @wpa_s: Pointer to the network interface
7187 *
7188 * This function is used to request a new connection to be found. It will mark
7189 * the interface to allow reassociation and request a new scan to find a
7190 * suitable network to connect to.
7191 */
7192void wpas_request_connection(struct wpa_supplicant *wpa_s)
7193{
7194 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007195 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007196 wpa_supplicant_reinit_autoscan(wpa_s);
7197 wpa_s->extra_blacklist_count = 0;
7198 wpa_s->disconnected = 0;
7199 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007200 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007201
7202 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7203 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007204 else
7205 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007206}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007207
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007208
Roshan Pius02242d72016-08-09 15:31:48 -07007209/**
7210 * wpas_request_disconnection - Request disconnection
7211 * @wpa_s: Pointer to the network interface
7212 *
7213 * This function is used to request disconnection from the currently connected
7214 * network. This will stop any ongoing scans and initiate deauthentication.
7215 */
7216void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7217{
7218#ifdef CONFIG_SME
7219 wpa_s->sme.prev_bssid_set = 0;
7220#endif /* CONFIG_SME */
7221 wpa_s->reassociate = 0;
7222 wpa_s->disconnected = 1;
7223 wpa_supplicant_cancel_sched_scan(wpa_s);
7224 wpa_supplicant_cancel_scan(wpa_s);
7225 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7226 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007227 radio_remove_works(wpa_s, "connect", 0);
7228 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007229}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007230
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007231
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007232void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7233 struct wpa_used_freq_data *freqs_data,
7234 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007235{
7236 unsigned int i;
7237
7238 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7239 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007240 for (i = 0; i < len; i++) {
7241 struct wpa_used_freq_data *cur = &freqs_data[i];
7242 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7243 i, cur->freq, cur->flags);
7244 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007245}
7246
7247
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007248/*
7249 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007250 * are using the same radio as the current interface, and in addition, get
7251 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007252 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007253int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7254 struct wpa_used_freq_data *freqs_data,
7255 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007256{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007257 struct wpa_supplicant *ifs;
7258 u8 bssid[ETH_ALEN];
7259 int freq;
7260 unsigned int idx = 0, i;
7261
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007262 wpa_dbg(wpa_s, MSG_DEBUG,
7263 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007264 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007265
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007266 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7267 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007268 if (idx == len)
7269 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007270
7271 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7272 continue;
7273
7274 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007275 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7276 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007277 freq = ifs->current_ssid->frequency;
7278 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7279 freq = ifs->assoc_freq;
7280 else
7281 continue;
7282
7283 /* Hold only distinct freqs */
7284 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007285 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007286 break;
7287
7288 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007289 freqs_data[idx++].freq = freq;
7290
7291 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007292 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007293 WPA_FREQ_USED_BY_P2P_CLIENT :
7294 WPA_FREQ_USED_BY_INFRA_STATION;
7295 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007296 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007297
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007298 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007299 return idx;
7300}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007301
7302
7303/*
7304 * Find the operating frequencies of any of the virtual interfaces that
7305 * are using the same radio as the current interface.
7306 */
7307int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7308 int *freq_array, unsigned int len)
7309{
7310 struct wpa_used_freq_data *freqs_data;
7311 int num, i;
7312
7313 os_memset(freq_array, 0, sizeof(int) * len);
7314
7315 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7316 if (!freqs_data)
7317 return -1;
7318
7319 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7320 for (i = 0; i < num; i++)
7321 freq_array[i] = freqs_data[i].freq;
7322
7323 os_free(freqs_data);
7324
7325 return num;
7326}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007327
7328
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007329struct wpa_supplicant *
7330wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7331{
7332 switch (frame) {
7333#ifdef CONFIG_P2P
7334 case VENDOR_ELEM_PROBE_REQ_P2P:
7335 case VENDOR_ELEM_PROBE_RESP_P2P:
7336 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7337 case VENDOR_ELEM_BEACON_P2P_GO:
7338 case VENDOR_ELEM_P2P_PD_REQ:
7339 case VENDOR_ELEM_P2P_PD_RESP:
7340 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7341 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7342 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7343 case VENDOR_ELEM_P2P_INV_REQ:
7344 case VENDOR_ELEM_P2P_INV_RESP:
7345 case VENDOR_ELEM_P2P_ASSOC_REQ:
7346 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007347 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007348#endif /* CONFIG_P2P */
7349 default:
7350 return wpa_s;
7351 }
7352}
7353
7354
7355void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7356{
7357 unsigned int i;
7358 char buf[30];
7359
7360 wpa_printf(MSG_DEBUG, "Update vendor elements");
7361
7362 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7363 if (wpa_s->vendor_elem[i]) {
7364 int res;
7365
7366 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7367 if (!os_snprintf_error(sizeof(buf), res)) {
7368 wpa_hexdump_buf(MSG_DEBUG, buf,
7369 wpa_s->vendor_elem[i]);
7370 }
7371 }
7372 }
7373
7374#ifdef CONFIG_P2P
7375 if (wpa_s->parent == wpa_s &&
7376 wpa_s->global->p2p &&
7377 !wpa_s->global->p2p_disabled)
7378 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7379#endif /* CONFIG_P2P */
7380}
7381
7382
7383int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7384 const u8 *elem, size_t len)
7385{
7386 u8 *ie, *end;
7387
7388 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7389 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7390
7391 for (; ie + 1 < end; ie += 2 + ie[1]) {
7392 if (ie + len > end)
7393 break;
7394 if (os_memcmp(ie, elem, len) != 0)
7395 continue;
7396
7397 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7398 wpabuf_free(wpa_s->vendor_elem[frame]);
7399 wpa_s->vendor_elem[frame] = NULL;
7400 } else {
7401 os_memmove(ie, ie + len, end - (ie + len));
7402 wpa_s->vendor_elem[frame]->used -= len;
7403 }
7404 wpas_vendor_elem_update(wpa_s);
7405 return 0;
7406 }
7407
7408 return -1;
7409}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007410
7411
7412struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
7413 u16 num_modes, enum hostapd_hw_mode mode)
7414{
7415 u16 i;
7416
7417 for (i = 0; i < num_modes; i++) {
7418 if (modes[i].mode == mode)
7419 return &modes[i];
7420 }
7421
7422 return NULL;
7423}
7424
7425
7426static struct
7427wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7428 const u8 *bssid)
7429{
7430 struct wpa_bss_tmp_disallowed *bss;
7431
7432 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7433 struct wpa_bss_tmp_disallowed, list) {
7434 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7435 return bss;
7436 }
7437
7438 return NULL;
7439}
7440
7441
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007442static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7443{
7444 struct wpa_bss_tmp_disallowed *tmp;
7445 unsigned int num_bssid = 0;
7446 u8 *bssids;
7447 int ret;
7448
7449 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7450 if (!bssids)
7451 return -1;
7452 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7453 struct wpa_bss_tmp_disallowed, list) {
7454 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7455 ETH_ALEN);
7456 num_bssid++;
7457 }
7458 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7459 os_free(bssids);
7460 return ret;
7461}
7462
7463
7464static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7465{
7466 struct wpa_supplicant *wpa_s = eloop_ctx;
7467 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7468
7469 /* Make sure the bss is not already freed */
7470 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7471 struct wpa_bss_tmp_disallowed, list) {
7472 if (bss == tmp) {
7473 dl_list_del(&tmp->list);
7474 os_free(tmp);
7475 wpa_set_driver_tmp_disallow_list(wpa_s);
7476 break;
7477 }
7478 }
7479}
7480
7481
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007482void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08007483 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007484{
7485 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007486
7487 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7488 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007489 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08007490 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007491 }
7492
7493 bss = os_malloc(sizeof(*bss));
7494 if (!bss) {
7495 wpa_printf(MSG_DEBUG,
7496 "Failed to allocate memory for temp disallow BSS");
7497 return;
7498 }
7499
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007500 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7501 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007502 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08007503
7504finish:
7505 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007506 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7507 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007508}
7509
7510
Hai Shalom74f70d42019-02-11 14:42:39 -08007511int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
7512 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007513{
Hai Shalom74f70d42019-02-11 14:42:39 -08007514 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007515
7516 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7517 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007518 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
7519 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007520 break;
7521 }
7522 }
Hai Shalom74f70d42019-02-11 14:42:39 -08007523 if (!disallowed)
7524 return 0;
7525
7526 if (disallowed->rssi_threshold != 0 &&
7527 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007528 return 0;
7529
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007530 return 1;
7531}
Hai Shalom81f62d82019-07-22 12:10:00 -07007532
7533
7534int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
7535 unsigned int type, const u8 *addr,
7536 const u8 *mask)
7537{
7538 if ((addr && !mask) || (!addr && mask)) {
7539 wpa_printf(MSG_INFO,
7540 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
7541 return -1;
7542 }
7543
7544 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
7545 wpa_printf(MSG_INFO,
7546 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
7547 return -1;
7548 }
7549
7550 if (type & MAC_ADDR_RAND_SCAN) {
7551 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
7552 addr, mask))
7553 return -1;
7554 }
7555
7556 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
7557 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
7558 addr, mask))
7559 return -1;
7560
7561 if (wpa_s->sched_scanning && !wpa_s->pno)
7562 wpas_scan_restart_sched_scan(wpa_s);
7563 }
7564
7565 if (type & MAC_ADDR_RAND_PNO) {
7566 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
7567 addr, mask))
7568 return -1;
7569
7570 if (wpa_s->pno) {
7571 wpas_stop_pno(wpa_s);
7572 wpas_start_pno(wpa_s);
7573 }
7574 }
7575
7576 return 0;
7577}
7578
7579
7580int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
7581 unsigned int type)
7582{
7583 wpas_mac_addr_rand_scan_clear(wpa_s, type);
7584 if (wpa_s->pno) {
7585 if (type & MAC_ADDR_RAND_PNO) {
7586 wpas_stop_pno(wpa_s);
7587 wpas_start_pno(wpa_s);
7588 }
7589 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
7590 wpas_scan_restart_sched_scan(wpa_s);
7591 }
7592
7593 return 0;
7594}