blob: 089830f89bd632ea11d8098b3923745402582f3b [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Hai Shalom74f70d42019-02-11 14:42:39 -08003 * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
20#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "eapol_supp/eapol_supp_sm.h"
23#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070024#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "eap_server/eap_methods.h"
26#include "rsn_supp/wpa.h"
27#include "eloop.h"
28#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070029#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "l2_packet/l2_packet.h"
31#include "wpa_supplicant_i.h"
32#include "driver_i.h"
33#include "ctrl_iface.h"
34#include "pcsc_funcs.h"
35#include "common/version.h"
36#include "rsn_supp/preauth.h"
37#include "rsn_supp/pmksa_cache.h"
38#include "common/wpa_ctrl.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070039#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080041#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070042#include "common/gas_server.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070043#include "common/dpp.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070044#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080045#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "blacklist.h"
47#include "wpas_glue.h"
48#include "wps_supplicant.h"
49#include "ibss_rsn.h"
50#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080051#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070052#include "ap.h"
53#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070054#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070055#include "notify.h"
56#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070057#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070058#include "bss.h"
59#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080060#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070061#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070062#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070063#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080064#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070065#include "dpp_supplicant.h"
66#ifdef CONFIG_MESH
67#include "ap/ap_config.h"
68#include "ap/hostapd.h"
69#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070071const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072"wpa_supplicant v" VERSION_STR "\n"
Hai Shalom74f70d42019-02-11 14:42:39 -080073"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070075const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080076"This software may be distributed under the terms of the BSD license.\n"
77"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070078#ifdef EAP_TLS_OPENSSL
79"\nThis product includes software developed by the OpenSSL Project\n"
80"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
81#endif /* EAP_TLS_OPENSSL */
82;
83
84#ifndef CONFIG_NO_STDOUT_DEBUG
85/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070086const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080087"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070088const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080089"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070090"\n"
91"Redistribution and use in source and binary forms, with or without\n"
92"modification, are permitted provided that the following conditions are\n"
93"met:\n"
94"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070095const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096"1. Redistributions of source code must retain the above copyright\n"
97" notice, this list of conditions and the following disclaimer.\n"
98"\n"
99"2. Redistributions in binary form must reproduce the above copyright\n"
100" notice, this list of conditions and the following disclaimer in the\n"
101" documentation and/or other materials provided with the distribution.\n"
102"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700103const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700104"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
105" names of its contributors may be used to endorse or promote products\n"
106" derived from this software without specific prior written permission.\n"
107"\n"
108"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
109"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
110"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
111"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700112const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700113"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
114"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
115"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
116"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
117"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
118"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
119"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
120"\n";
121#endif /* CONFIG_NO_STDOUT_DEBUG */
122
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700123
124static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
125#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
126static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
127#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700128#ifdef CONFIG_OWE
129static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
130#endif /* CONFIG_OWE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700131
132
Hai Shalomfdcde762020-04-02 11:19:20 -0700133#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700134/* Configure default/group WEP keys for static WEP */
135int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
136{
137 int i, set = 0;
138
139 for (i = 0; i < NUM_WEP_KEYS; i++) {
140 if (ssid->wep_key_len[i] == 0)
141 continue;
142
143 set = 1;
144 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
145 i, i == ssid->wep_tx_keyidx, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700146 ssid->wep_key[i], ssid->wep_key_len[i],
147 i == ssid->wep_tx_keyidx ?
148 KEY_FLAG_GROUP_RX_TX_DEFAULT :
149 KEY_FLAG_GROUP_RX_TX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700150 }
151
152 return set;
153}
Hai Shalomfdcde762020-04-02 11:19:20 -0700154#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700155
156
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700157int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
158 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700159{
160 u8 key[32];
161 size_t keylen;
162 enum wpa_alg alg;
163 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800164 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700165
166 /* IBSS/WPA-None uses only one key (Group) for both receiving and
167 * sending unicast and multicast packets. */
168
169 if (ssid->mode != WPAS_MODE_IBSS) {
170 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
171 "IBSS/ad-hoc) for WPA-None", ssid->mode);
172 return -1;
173 }
174
175 if (!ssid->psk_set) {
176 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
177 "WPA-None");
178 return -1;
179 }
180
181 switch (wpa_s->group_cipher) {
182 case WPA_CIPHER_CCMP:
183 os_memcpy(key, ssid->psk, 16);
184 keylen = 16;
185 alg = WPA_ALG_CCMP;
186 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700187 case WPA_CIPHER_GCMP:
188 os_memcpy(key, ssid->psk, 16);
189 keylen = 16;
190 alg = WPA_ALG_GCMP;
191 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700192 case WPA_CIPHER_TKIP:
193 /* WPA-None uses the same Michael MIC key for both TX and RX */
194 os_memcpy(key, ssid->psk, 16 + 8);
195 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
196 keylen = 32;
197 alg = WPA_ALG_TKIP;
198 break;
199 default:
200 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
201 "WPA-None", wpa_s->group_cipher);
202 return -1;
203 }
204
205 /* TODO: should actually remember the previously used seq#, both for TX
206 * and RX from each STA.. */
207
Hai Shalomfdcde762020-04-02 11:19:20 -0700208 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen,
209 KEY_FLAG_GROUP_RX_TX_DEFAULT);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800210 os_memset(key, 0, sizeof(key));
211 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700212}
213
214
215static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
216{
217 struct wpa_supplicant *wpa_s = eloop_ctx;
218 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700219 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
220 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
221 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700222 bssid = wpa_s->pending_bssid;
223 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
224 MAC2STR(bssid));
225 wpa_blacklist_add(wpa_s, bssid);
226 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800227 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228 wpa_s->reassociate = 1;
Roshan Pius38e96762017-01-23 14:52:00 -0800229 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700230
231 /*
232 * If we timed out, the AP or the local radio may be busy.
233 * So, wait a second until scanning again.
234 */
235 wpa_supplicant_req_scan(wpa_s, 1, 0);
236}
237
238
239/**
240 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
241 * @wpa_s: Pointer to wpa_supplicant data
242 * @sec: Number of seconds after which to time out authentication
243 * @usec: Number of microseconds after which to time out authentication
244 *
245 * This function is used to schedule a timeout for the current authentication
246 * attempt.
247 */
248void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
249 int sec, int usec)
250{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700251 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700252 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
253 return;
254
255 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
256 "%d usec", sec, usec);
257 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700258 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700259 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
260}
261
262
Roshan Pius3a1667e2018-07-03 15:17:14 -0700263/*
264 * wpas_auth_timeout_restart - Restart and change timeout for authentication
265 * @wpa_s: Pointer to wpa_supplicant data
266 * @sec_diff: difference in seconds applied to original timeout value
267 */
268void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
269{
270 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
271
272 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
273 wpa_dbg(wpa_s, MSG_DEBUG,
274 "Authentication timeout restart: %d sec", new_sec);
275 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
276 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
277 wpa_s, NULL);
278 }
279}
280
281
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700282/**
283 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
284 * @wpa_s: Pointer to wpa_supplicant data
285 *
286 * This function is used to cancel authentication timeout scheduled with
287 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
288 * been completed.
289 */
290void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
291{
292 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
293 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
294 wpa_blacklist_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700295 os_free(wpa_s->last_con_fail_realm);
296 wpa_s->last_con_fail_realm = NULL;
297 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700298}
299
300
301/**
302 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
303 * @wpa_s: Pointer to wpa_supplicant data
304 *
305 * This function is used to configure EAPOL state machine based on the selected
306 * authentication mode.
307 */
308void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
309{
310#ifdef IEEE8021X_EAPOL
311 struct eapol_config eapol_conf;
312 struct wpa_ssid *ssid = wpa_s->current_ssid;
313
314#ifdef CONFIG_IBSS_RSN
315 if (ssid->mode == WPAS_MODE_IBSS &&
316 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
317 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
318 /*
319 * RSN IBSS authentication is per-STA and we can disable the
320 * per-BSSID EAPOL authentication.
321 */
322 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
323 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
324 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
325 return;
326 }
327#endif /* CONFIG_IBSS_RSN */
328
329 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
330 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
331
332 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
333 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
334 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
335 else
336 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
337
338 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
339 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
340 eapol_conf.accept_802_1x_keys = 1;
341 eapol_conf.required_keys = 0;
342 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
343 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
344 }
345 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
346 eapol_conf.required_keys |=
347 EAPOL_REQUIRE_KEY_BROADCAST;
348 }
349
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700350 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700351 eapol_conf.required_keys = 0;
352 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700353 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354 eapol_conf.workaround = ssid->eap_workaround;
355 eapol_conf.eap_disabled =
356 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
357 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
358 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700359 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800360
361#ifdef CONFIG_WPS
362 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
363 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
364 if (wpa_s->current_bss) {
365 struct wpabuf *ie;
366 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
367 WPS_IE_VENDOR_TYPE);
368 if (ie) {
369 if (wps_is_20(ie))
370 eapol_conf.wps |=
371 EAPOL_PEER_IS_WPS20_AP;
372 wpabuf_free(ie);
373 }
374 }
375 }
376#endif /* CONFIG_WPS */
377
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700378 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700379
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800380#ifdef CONFIG_MACSEC
381 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
382 ieee802_1x_create_preshared_mka(wpa_s, ssid);
383 else
384 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
385#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800386#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700387}
388
389
390/**
391 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
392 * @wpa_s: Pointer to wpa_supplicant data
393 * @ssid: Configuration data for the network
394 *
395 * This function is used to configure WPA state machine and related parameters
396 * to a mode where WPA is not enabled. This is called as part of the
397 * authentication configuration when the selected network does not use WPA.
398 */
399void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
400 struct wpa_ssid *ssid)
401{
Hai Shalomfdcde762020-04-02 11:19:20 -0700402#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700403 int i;
Hai Shalomfdcde762020-04-02 11:19:20 -0700404#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700405
406 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
407 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
408 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
409 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
410 else
411 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
412 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
413 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700414 wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700416 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
417 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
419 wpa_s->group_cipher = WPA_CIPHER_NONE;
420 wpa_s->mgmt_group_cipher = 0;
421
Hai Shalomfdcde762020-04-02 11:19:20 -0700422#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700423 for (i = 0; i < NUM_WEP_KEYS; i++) {
424 if (ssid->wep_key_len[i] > 5) {
425 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
426 wpa_s->group_cipher = WPA_CIPHER_WEP104;
427 break;
428 } else if (ssid->wep_key_len[i] > 0) {
429 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
430 wpa_s->group_cipher = WPA_CIPHER_WEP40;
431 break;
432 }
433 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700434#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700435
436 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
437 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
438 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
439 wpa_s->pairwise_cipher);
440 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
442 wpa_s->mgmt_group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443
444 pmksa_cache_clear_current(wpa_s->wpa);
445}
446
447
Dmitry Shmidt04949592012-07-19 12:16:46 -0700448void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800449{
450 int i;
451 if (wpa_s->hw.modes == NULL)
452 return;
453
454 for (i = 0; i < wpa_s->hw.num_modes; i++) {
455 os_free(wpa_s->hw.modes[i].channels);
456 os_free(wpa_s->hw.modes[i].rates);
457 }
458
459 os_free(wpa_s->hw.modes);
460 wpa_s->hw.modes = NULL;
461}
462
463
Hai Shalom74f70d42019-02-11 14:42:39 -0800464void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800465{
466 struct wpa_bss_tmp_disallowed *bss, *prev;
467
468 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
469 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700470 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800471 dl_list_del(&bss->list);
472 os_free(bss);
473 }
474}
475
476
Paul Stewart092955c2017-02-06 09:13:09 -0800477void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
478{
479 struct fils_hlp_req *req;
480
481 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
482 list)) != NULL) {
483 dl_list_del(&req->list);
484 wpabuf_free(req->pkt);
485 os_free(req);
486 }
487}
488
489
Hai Shalomfdcde762020-04-02 11:19:20 -0700490void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
491{
492 struct wpa_supplicant *wpa_s = eloop_ctx;
493
494 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
495 return;
496 wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
497 wpa_bss_flush(wpa_s);
498}
499
500
501#ifdef CONFIG_TESTING_OPTIONS
502void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
503{
504 struct driver_signal_override *dso;
505
506 while ((dso = dl_list_first(&wpa_s->drv_signal_override,
507 struct driver_signal_override, list))) {
508 dl_list_del(&dso->list);
509 os_free(dso);
510 }
511}
512#endif /* CONFIG_TESTING_OPTIONS */
513
514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
516{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700517 int i;
518
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700519 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700520 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700521 scard_deinit(wpa_s->scard);
522 wpa_s->scard = NULL;
523 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
524 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
525 l2_packet_deinit(wpa_s->l2);
526 wpa_s->l2 = NULL;
527 if (wpa_s->l2_br) {
528 l2_packet_deinit(wpa_s->l2_br);
529 wpa_s->l2_br = NULL;
530 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800531#ifdef CONFIG_TESTING_OPTIONS
532 l2_packet_deinit(wpa_s->l2_test);
533 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800534 os_free(wpa_s->get_pref_freq_list_override);
535 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700536 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
537 wpa_s->last_assoc_req_wpa_ie = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800538 os_free(wpa_s->extra_sae_rejected_groups);
539 wpa_s->extra_sae_rejected_groups = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700540 wpabuf_free(wpa_s->rsne_override_eapol);
541 wpa_s->rsne_override_eapol = NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800542 wpabuf_free(wpa_s->rsnxe_override_assoc);
543 wpa_s->rsnxe_override_assoc = NULL;
544 wpabuf_free(wpa_s->rsnxe_override_eapol);
545 wpa_s->rsnxe_override_eapol = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -0700546 wpas_clear_driver_signal_override(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800547#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549 if (wpa_s->conf != NULL) {
550 struct wpa_ssid *ssid;
551 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
552 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700553 }
554
555 os_free(wpa_s->confname);
556 wpa_s->confname = NULL;
557
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700558 os_free(wpa_s->confanother);
559 wpa_s->confanother = NULL;
560
Hai Shalomce48b4a2018-09-05 11:41:35 -0700561 os_free(wpa_s->last_con_fail_realm);
562 wpa_s->last_con_fail_realm = NULL;
563 wpa_s->last_con_fail_realm_len = 0;
564
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700565 wpa_sm_set_eapol(wpa_s->wpa, NULL);
566 eapol_sm_deinit(wpa_s->eapol);
567 wpa_s->eapol = NULL;
568
569 rsn_preauth_deinit(wpa_s->wpa);
570
571#ifdef CONFIG_TDLS
572 wpa_tdls_deinit(wpa_s->wpa);
573#endif /* CONFIG_TDLS */
574
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800575 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700576 pmksa_candidate_free(wpa_s->wpa);
577 wpa_sm_deinit(wpa_s->wpa);
578 wpa_s->wpa = NULL;
579 wpa_blacklist_clear(wpa_s);
580
581 wpa_bss_deinit(wpa_s);
582
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700583 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700584 wpa_supplicant_cancel_scan(wpa_s);
585 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800586 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
587#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
588 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
589 wpa_s, NULL);
590#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700592 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700593 eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700594
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700595 wpas_wps_deinit(wpa_s);
596
597 wpabuf_free(wpa_s->pending_eapol_rx);
598 wpa_s->pending_eapol_rx = NULL;
599
600#ifdef CONFIG_IBSS_RSN
601 ibss_rsn_deinit(wpa_s->ibss_rsn);
602 wpa_s->ibss_rsn = NULL;
603#endif /* CONFIG_IBSS_RSN */
604
605 sme_deinit(wpa_s);
606
607#ifdef CONFIG_AP
608 wpa_supplicant_ap_deinit(wpa_s);
609#endif /* CONFIG_AP */
610
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700611 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700612
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800613#ifdef CONFIG_OFFCHANNEL
614 offchannel_deinit(wpa_s);
615#endif /* CONFIG_OFFCHANNEL */
616
617 wpa_supplicant_cancel_sched_scan(wpa_s);
618
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700619 os_free(wpa_s->next_scan_freqs);
620 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800621
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800622 os_free(wpa_s->manual_scan_freqs);
623 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700624 os_free(wpa_s->select_network_scan_freqs);
625 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800626
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700627 os_free(wpa_s->manual_sched_scan_freqs);
628 wpa_s->manual_sched_scan_freqs = NULL;
629
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800630 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
631
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700632 /*
633 * Need to remove any pending gas-query radio work before the
634 * gas_query_deinit() call because gas_query::work has not yet been set
635 * for works that have not been started. gas_query_free() will be unable
636 * to cancel such pending radio works and once the pending gas-query
637 * radio work eventually gets removed, the deinit notification call to
638 * gas_query_start_cb() would result in dereferencing freed memory.
639 */
640 if (wpa_s->radio)
641 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800642 gas_query_deinit(wpa_s->gas);
643 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700644 gas_server_deinit(wpa_s->gas_server);
645 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800646
647 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700648
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700649 ieee802_1x_dealloc_kay_sm(wpa_s);
650
Dmitry Shmidt04949592012-07-19 12:16:46 -0700651 os_free(wpa_s->bssid_filter);
652 wpa_s->bssid_filter = NULL;
653
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800654 os_free(wpa_s->disallow_aps_bssid);
655 wpa_s->disallow_aps_bssid = NULL;
656 os_free(wpa_s->disallow_aps_ssid);
657 wpa_s->disallow_aps_ssid = NULL;
658
Dmitry Shmidt04949592012-07-19 12:16:46 -0700659 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700660#ifdef CONFIG_WNM
661 wnm_deallocate_memory(wpa_s);
662#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700663
664 ext_password_deinit(wpa_s->ext_pw);
665 wpa_s->ext_pw = NULL;
666
667 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800668 wpa_s->last_gas_resp = NULL;
669 wpabuf_free(wpa_s->prev_gas_resp);
670 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700671
672 os_free(wpa_s->last_scan_res);
673 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800674
675#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700676 if (wpa_s->drv_priv)
677 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700678 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800679#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700680
681 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
682 wpabuf_free(wpa_s->vendor_elem[i]);
683 wpa_s->vendor_elem[i] = NULL;
684 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800685
686 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800687
688 wpa_s->sched_scan_plans_num = 0;
689 os_free(wpa_s->sched_scan_plans);
690 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800691
692#ifdef CONFIG_MBO
693 wpa_s->non_pref_chan_num = 0;
694 os_free(wpa_s->non_pref_chan);
695 wpa_s->non_pref_chan = NULL;
696#endif /* CONFIG_MBO */
697
698 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700699
700 wpabuf_free(wpa_s->lci);
701 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800702 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800703
704#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
705#ifdef CONFIG_MESH
706 {
707 struct external_pmksa_cache *entry;
708
709 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
710 struct external_pmksa_cache,
711 list)) != NULL) {
712 dl_list_del(&entry->list);
713 os_free(entry->pmksa_cache);
714 os_free(entry);
715 }
716 }
717#endif /* CONFIG_MESH */
718#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
719
720 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800721
722 wpabuf_free(wpa_s->ric_ies);
723 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700724
725#ifdef CONFIG_DPP
726 wpas_dpp_deinit(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -0700727 dpp_global_deinit(wpa_s->dpp);
728 wpa_s->dpp = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700729#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730}
731
732
733/**
734 * wpa_clear_keys - Clear keys configured for the driver
735 * @wpa_s: Pointer to wpa_supplicant data
736 * @addr: Previously used BSSID or %NULL if not available
737 *
738 * This function clears the encryption keys that has been previously configured
739 * for the driver.
740 */
741void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
742{
Hai Shalomc3565922019-10-28 11:58:20 -0700743 int i, max = 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744
745 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800746 for (i = 0; i < max; i++) {
747 if (wpa_s->keys_cleared & BIT(i))
748 continue;
749 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -0700750 NULL, 0, KEY_FLAG_GROUP);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800751 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700752 /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */
753 if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800754 !is_zero_ether_addr(addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700755 if (!(wpa_s->keys_cleared & BIT(0)))
756 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL,
757 0, NULL, 0, KEY_FLAG_PAIRWISE);
758 if (!(wpa_s->keys_cleared & BIT(15)))
759 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL,
760 0, NULL, 0, KEY_FLAG_PAIRWISE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700761 /* MLME-SETPROTECTION.request(None) */
762 wpa_drv_mlme_setprotection(
763 wpa_s, addr,
764 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
765 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
766 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800767 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700768}
769
770
771/**
772 * wpa_supplicant_state_txt - Get the connection state name as a text string
773 * @state: State (wpa_state; WPA_*)
774 * Returns: The state name as a printable text string
775 */
776const char * wpa_supplicant_state_txt(enum wpa_states state)
777{
778 switch (state) {
779 case WPA_DISCONNECTED:
780 return "DISCONNECTED";
781 case WPA_INACTIVE:
782 return "INACTIVE";
783 case WPA_INTERFACE_DISABLED:
784 return "INTERFACE_DISABLED";
785 case WPA_SCANNING:
786 return "SCANNING";
787 case WPA_AUTHENTICATING:
788 return "AUTHENTICATING";
789 case WPA_ASSOCIATING:
790 return "ASSOCIATING";
791 case WPA_ASSOCIATED:
792 return "ASSOCIATED";
793 case WPA_4WAY_HANDSHAKE:
794 return "4WAY_HANDSHAKE";
795 case WPA_GROUP_HANDSHAKE:
796 return "GROUP_HANDSHAKE";
797 case WPA_COMPLETED:
798 return "COMPLETED";
799 default:
800 return "UNKNOWN";
801 }
802}
803
804
805#ifdef CONFIG_BGSCAN
806
807static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
808{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800809 const char *name;
810
811 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
812 name = wpa_s->current_ssid->bgscan;
813 else
814 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800815 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800816 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800817 if (wpas_driver_bss_selection(wpa_s))
818 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
820 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800821#ifdef CONFIG_P2P
822 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
823 return;
824#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700825
826 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800827 if (wpa_s->current_ssid) {
828 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700829 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
830 "bgscan");
831 /*
832 * Live without bgscan; it is only used as a roaming
833 * optimization, so the initial connection is not
834 * affected.
835 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700836 } else {
837 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700838 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700839 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
840 0);
841 if (scan_res) {
842 bgscan_notify_scan(wpa_s, scan_res);
843 wpa_scan_results_free(scan_res);
844 }
845 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700846 } else
847 wpa_s->bgscan_ssid = NULL;
848}
849
850
851static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
852{
853 if (wpa_s->bgscan_ssid != NULL) {
854 bgscan_deinit(wpa_s);
855 wpa_s->bgscan_ssid = NULL;
856 }
857}
858
859#endif /* CONFIG_BGSCAN */
860
861
Dmitry Shmidt04949592012-07-19 12:16:46 -0700862static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
863{
864 if (autoscan_init(wpa_s, 0))
865 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
866}
867
868
869static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
870{
871 autoscan_deinit(wpa_s);
872}
873
874
875void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
876{
877 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
878 wpa_s->wpa_state == WPA_SCANNING) {
879 autoscan_deinit(wpa_s);
880 wpa_supplicant_start_autoscan(wpa_s);
881 }
882}
883
884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885/**
886 * wpa_supplicant_set_state - Set current connection state
887 * @wpa_s: Pointer to wpa_supplicant data
888 * @state: The new connection state
889 *
890 * This function is called whenever the connection state changes, e.g.,
891 * association is completed for WPA/WPA2 4-Way Handshake is started.
892 */
893void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
894 enum wpa_states state)
895{
896 enum wpa_states old_state = wpa_s->wpa_state;
Hai Shalomc3565922019-10-28 11:58:20 -0700897#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
898 Boolean update_fils_connect_params = FALSE;
899#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700900
901 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
902 wpa_supplicant_state_txt(wpa_s->wpa_state),
903 wpa_supplicant_state_txt(state));
904
Hai Shalom74f70d42019-02-11 14:42:39 -0800905 if (state == WPA_COMPLETED &&
906 os_reltime_initialized(&wpa_s->roam_start)) {
907 os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time);
908 wpa_s->roam_start.sec = 0;
909 wpa_s->roam_start.usec = 0;
910 wpas_notify_auth_changed(wpa_s);
911 wpas_notify_roam_time(wpa_s);
912 wpas_notify_roam_complete(wpa_s);
913 } else if (state == WPA_DISCONNECTED &&
914 os_reltime_initialized(&wpa_s->roam_start)) {
915 wpa_s->roam_start.sec = 0;
916 wpa_s->roam_start.usec = 0;
917 wpa_s->roam_time.sec = 0;
918 wpa_s->roam_time.usec = 0;
919 wpas_notify_roam_complete(wpa_s);
920 }
921
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800922 if (state == WPA_INTERFACE_DISABLED) {
923 /* Assure normal scan when interface is restored */
924 wpa_s->normal_scans = 0;
925 }
926
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700927 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800928 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700929 /* Reinitialize normal_scan counter */
930 wpa_s->normal_scans = 0;
931 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800932
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700933#ifdef CONFIG_P2P
934 /*
935 * P2PS client has to reply to Probe Request frames received on the
936 * group operating channel. Enable Probe Request frame reporting for
937 * P2P connected client in case p2p_cli_probe configuration property is
938 * set to 1.
939 */
940 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
941 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
942 wpa_s->current_ssid->p2p_group) {
943 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
944 wpa_dbg(wpa_s, MSG_DEBUG,
945 "P2P: Enable CLI Probe Request RX reporting");
946 wpa_s->p2p_cli_probe =
947 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
948 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
949 wpa_dbg(wpa_s, MSG_DEBUG,
950 "P2P: Disable CLI Probe Request RX reporting");
951 wpa_s->p2p_cli_probe = 0;
952 wpa_drv_probe_req_report(wpa_s, 0);
953 }
954 }
955#endif /* CONFIG_P2P */
956
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700957 if (state != WPA_SCANNING)
958 wpa_supplicant_notify_scanning(wpa_s, 0);
959
960 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700961 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700962 int fils_hlp_sent = 0;
963
964#ifdef CONFIG_SME
965 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
966 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
967 fils_hlp_sent = 1;
968#endif /* CONFIG_SME */
969 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
970 wpa_auth_alg_fils(wpa_s->auth_alg))
971 fils_hlp_sent = 1;
972
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700973#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700975 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800976 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700977 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700978 ssid && ssid->id_str ? ssid->id_str : "",
979 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700981 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700982 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800983 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700984 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700985 wpa_drv_set_operstate(wpa_s, 1);
986#ifndef IEEE8021X_EAPOL
987 wpa_drv_set_supp_port(wpa_s, 1);
988#endif /* IEEE8021X_EAPOL */
989 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700990 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700992
993 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700994
995#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
996 if (!fils_hlp_sent && ssid && ssid->eap.erp)
Hai Shalomc3565922019-10-28 11:58:20 -0700997 update_fils_connect_params = TRUE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700998#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Hai Shalomc3565922019-10-28 11:58:20 -0700999#ifdef CONFIG_OWE
1000 if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
1001 wpas_update_owe_connect_params(wpa_s);
1002#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
1004 state == WPA_ASSOCIATED) {
1005 wpa_s->new_connection = 1;
1006 wpa_drv_set_operstate(wpa_s, 0);
1007#ifndef IEEE8021X_EAPOL
1008 wpa_drv_set_supp_port(wpa_s, 0);
1009#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001010 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001011 }
1012 wpa_s->wpa_state = state;
1013
1014#ifdef CONFIG_BGSCAN
1015 if (state == WPA_COMPLETED)
1016 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001017 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001018 wpa_supplicant_stop_bgscan(wpa_s);
1019#endif /* CONFIG_BGSCAN */
1020
Hai Shalom5f92bc92019-04-18 11:54:11 -07001021 if (state > WPA_SCANNING)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001022 wpa_supplicant_stop_autoscan(wpa_s);
1023
1024 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
1025 wpa_supplicant_start_autoscan(wpa_s);
1026
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001027 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
1028 wmm_ac_notify_disassoc(wpa_s);
1029
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 if (wpa_s->wpa_state != old_state) {
1031 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1032
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07001033 /*
1034 * Notify the P2P Device interface about a state change in one
1035 * of the interfaces.
1036 */
1037 wpas_p2p_indicate_state_change(wpa_s);
1038
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 if (wpa_s->wpa_state == WPA_COMPLETED ||
1040 old_state == WPA_COMPLETED)
1041 wpas_notify_auth_changed(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001042#ifdef CONFIG_DPP2
1043 if (wpa_s->wpa_state == WPA_COMPLETED)
1044 wpas_dpp_connected(wpa_s);
1045#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 }
Hai Shalomc3565922019-10-28 11:58:20 -07001047#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
1048 if (update_fils_connect_params)
1049 wpas_update_fils_connect_params(wpa_s);
1050#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001051}
1052
1053
1054void wpa_supplicant_terminate_proc(struct wpa_global *global)
1055{
1056 int pending = 0;
1057#ifdef CONFIG_WPS
1058 struct wpa_supplicant *wpa_s = global->ifaces;
1059 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001060 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001061 if (wpas_wps_terminate_pending(wpa_s) == 1)
1062 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001063#ifdef CONFIG_P2P
1064 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
1065 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
1066 wpas_p2p_disconnect(wpa_s);
1067#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001068 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069 }
1070#endif /* CONFIG_WPS */
1071 if (pending)
1072 return;
1073 eloop_terminate();
1074}
1075
1076
1077static void wpa_supplicant_terminate(int sig, void *signal_ctx)
1078{
1079 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001080 wpa_supplicant_terminate_proc(global);
1081}
1082
1083
1084void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1085{
1086 enum wpa_states old_state = wpa_s->wpa_state;
1087
1088 wpa_s->pairwise_cipher = 0;
1089 wpa_s->group_cipher = 0;
1090 wpa_s->mgmt_group_cipher = 0;
1091 wpa_s->key_mgmt = 0;
1092 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001093 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001094
1095 if (wpa_s->wpa_state != old_state)
1096 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1097}
1098
1099
1100/**
1101 * wpa_supplicant_reload_configuration - Reload configuration data
1102 * @wpa_s: Pointer to wpa_supplicant data
1103 * Returns: 0 on success or -1 if configuration parsing failed
1104 *
1105 * This function can be used to request that the configuration data is reloaded
1106 * (e.g., after configuration file change). This function is reloading
1107 * configuration only for one interface, so this may need to be called multiple
1108 * times if %wpa_supplicant is controlling multiple interfaces and all
1109 * interfaces need reconfiguration.
1110 */
1111int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1112{
1113 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001114 int reconf_ctrl;
1115 int old_ap_scan;
1116
1117 if (wpa_s->confname == NULL)
1118 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001119 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120 if (conf == NULL) {
1121 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1122 "file '%s' - exiting", wpa_s->confname);
1123 return -1;
1124 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001125 if (wpa_s->confanother &&
1126 !wpa_config_read(wpa_s->confanother, conf)) {
1127 wpa_msg(wpa_s, MSG_ERROR,
1128 "Failed to parse the configuration file '%s' - exiting",
1129 wpa_s->confanother);
1130 return -1;
1131 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001132
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001133 conf->changed_parameters = (unsigned int) -1;
1134
1135 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1136 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1137 os_strcmp(conf->ctrl_interface,
1138 wpa_s->conf->ctrl_interface) != 0);
1139
1140 if (reconf_ctrl && wpa_s->ctrl_iface) {
1141 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1142 wpa_s->ctrl_iface = NULL;
1143 }
1144
1145 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001146 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001147 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1148 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001149 wpa_supplicant_deauthenticate(wpa_s,
1150 WLAN_REASON_DEAUTH_LEAVING);
1151 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152
1153 /*
1154 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001155 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001156 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001157 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1158 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1159 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160 /*
1161 * Clear forced success to clear EAP state for next
1162 * authentication.
1163 */
1164 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1165 }
1166 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1167 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001168 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001169 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1170 rsn_preauth_deinit(wpa_s->wpa);
1171
1172 old_ap_scan = wpa_s->conf->ap_scan;
1173 wpa_config_free(wpa_s->conf);
1174 wpa_s->conf = conf;
1175 if (old_ap_scan != wpa_s->conf->ap_scan)
1176 wpas_notify_ap_scan_changed(wpa_s);
1177
1178 if (reconf_ctrl)
1179 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1180
1181 wpa_supplicant_update_config(wpa_s);
1182
1183 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001184 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001185 wpa_s->reassociate = 1;
1186 wpa_supplicant_req_scan(wpa_s, 0, 0);
1187 }
1188 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1189 return 0;
1190}
1191
1192
1193static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1194{
1195 struct wpa_global *global = signal_ctx;
1196 struct wpa_supplicant *wpa_s;
1197 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1198 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1199 sig);
1200 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1201 wpa_supplicant_terminate_proc(global);
1202 }
1203 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001204
1205 if (wpa_debug_reopen_file() < 0) {
1206 /* Ignore errors since we cannot really do much to fix this */
1207 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1208 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209}
1210
1211
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001212static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1213 struct wpa_ssid *ssid,
1214 struct wpa_ie_data *ie)
1215{
1216 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1217 if (ret) {
1218 if (ret == -2) {
1219 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1220 "from association info");
1221 }
1222 return -1;
1223 }
1224
1225 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1226 "cipher suites");
1227 if (!(ie->group_cipher & ssid->group_cipher)) {
1228 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1229 "cipher 0x%x (mask 0x%x) - reject",
1230 ie->group_cipher, ssid->group_cipher);
1231 return -1;
1232 }
1233 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1234 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1235 "cipher 0x%x (mask 0x%x) - reject",
1236 ie->pairwise_cipher, ssid->pairwise_cipher);
1237 return -1;
1238 }
1239 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1240 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1241 "management 0x%x (mask 0x%x) - reject",
1242 ie->key_mgmt, ssid->key_mgmt);
1243 return -1;
1244 }
1245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001246 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001247 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001248 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1249 "that does not support management frame protection - "
1250 "reject");
1251 return -1;
1252 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001253
1254 return 0;
1255}
1256
1257
Hai Shalom021b0b52019-04-10 11:17:58 -07001258static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1259 int freq)
1260{
1261 if (!ie->has_group)
1262 ie->group_cipher = wpa_default_rsn_cipher(freq);
1263 if (!ie->has_pairwise)
1264 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1265 return (ie->group_cipher & ssid->group_cipher) &&
1266 (ie->pairwise_cipher & ssid->pairwise_cipher);
1267}
1268
1269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001270/**
1271 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1272 * @wpa_s: Pointer to wpa_supplicant data
1273 * @bss: Scan results for the selected BSS, or %NULL if not available
1274 * @ssid: Configuration data for the selected network
1275 * @wpa_ie: Buffer for the WPA/RSN IE
1276 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1277 * used buffer length in case the functions returns success.
1278 * Returns: 0 on success or -1 on failure
1279 *
1280 * This function is used to configure authentication and encryption parameters
1281 * based on the network configuration and scan result for the selected BSS (if
1282 * available).
1283 */
1284int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1285 struct wpa_bss *bss, struct wpa_ssid *ssid,
1286 u8 *wpa_ie, size_t *wpa_ie_len)
1287{
1288 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001289 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001290 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001291
1292 if (bss) {
1293 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1294 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001295 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001296 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001297 } else {
1298 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1299 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300
1301 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1302 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001303 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001304 (ie.key_mgmt & ssid->key_mgmt)) {
1305 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1306 proto = WPA_PROTO_RSN;
1307 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001308 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001309 (ie.group_cipher & ssid->group_cipher) &&
1310 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1311 (ie.key_mgmt & ssid->key_mgmt)) {
1312 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1313 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001314#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001315 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1316 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1317 (ie.group_cipher & ssid->group_cipher) &&
1318 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1319 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001320 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001321 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001322 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1323 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1324 (ie.group_cipher & ssid->group_cipher) &&
1325 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1326 (ie.key_mgmt & ssid->key_mgmt)) {
1327 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1328 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001329#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 } else if (bss) {
1331 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001332 wpa_dbg(wpa_s, MSG_DEBUG,
1333 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1334 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1335 ssid->key_mgmt);
1336 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1337 MAC2STR(bss->bssid),
1338 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1339 bss_wpa ? " WPA" : "",
1340 bss_rsn ? " RSN" : "",
1341 bss_osen ? " OSEN" : "");
1342 if (bss_rsn) {
1343 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1344 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1345 wpa_dbg(wpa_s, MSG_DEBUG,
1346 "Could not parse RSN element");
1347 } else {
1348 wpa_dbg(wpa_s, MSG_DEBUG,
1349 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1350 ie.pairwise_cipher, ie.group_cipher,
1351 ie.key_mgmt);
1352 }
1353 }
1354 if (bss_wpa) {
1355 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1356 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1357 wpa_dbg(wpa_s, MSG_DEBUG,
1358 "Could not parse WPA element");
1359 } else {
1360 wpa_dbg(wpa_s, MSG_DEBUG,
1361 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1362 ie.pairwise_cipher, ie.group_cipher,
1363 ie.key_mgmt);
1364 }
1365 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366 return -1;
1367 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001368 if (ssid->proto & WPA_PROTO_OSEN)
1369 proto = WPA_PROTO_OSEN;
1370 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001371 proto = WPA_PROTO_RSN;
1372 else
1373 proto = WPA_PROTO_WPA;
1374 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1375 os_memset(&ie, 0, sizeof(ie));
1376 ie.group_cipher = ssid->group_cipher;
1377 ie.pairwise_cipher = ssid->pairwise_cipher;
1378 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001379 ie.mgmt_group_cipher = 0;
1380 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1381 if (ssid->group_mgmt_cipher &
1382 WPA_CIPHER_BIP_GMAC_256)
1383 ie.mgmt_group_cipher =
1384 WPA_CIPHER_BIP_GMAC_256;
1385 else if (ssid->group_mgmt_cipher &
1386 WPA_CIPHER_BIP_CMAC_256)
1387 ie.mgmt_group_cipher =
1388 WPA_CIPHER_BIP_CMAC_256;
1389 else if (ssid->group_mgmt_cipher &
1390 WPA_CIPHER_BIP_GMAC_128)
1391 ie.mgmt_group_cipher =
1392 WPA_CIPHER_BIP_GMAC_128;
1393 else
1394 ie.mgmt_group_cipher =
1395 WPA_CIPHER_AES_128_CMAC;
1396 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001397#ifdef CONFIG_OWE
1398 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1399 !ssid->owe_only &&
1400 !bss_wpa && !bss_rsn && !bss_osen) {
1401 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1402 wpa_s->wpa_proto = 0;
1403 *wpa_ie_len = 0;
1404 return 0;
1405 }
1406#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001407 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1408 "based on configuration");
1409 } else
1410 proto = ie.proto;
1411 }
1412
1413 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1414 "pairwise %d key_mgmt %d proto %d",
1415 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416 if (ssid->ieee80211w) {
1417 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1418 ie.mgmt_group_cipher);
1419 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001421 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001422 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1423 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001424 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001425
1426 if (bss || !wpa_s->ap_ies_from_associnfo) {
1427 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1428 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1429 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001430 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1431 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1432 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433 return -1;
1434 }
1435
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001436#ifdef CONFIG_NO_WPA
1437 wpa_s->group_cipher = WPA_CIPHER_NONE;
1438 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1439#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001440 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001441 wpa_dbg(wpa_s, MSG_DEBUG,
1442 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1443 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001444 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1445 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1447 "cipher");
1448 return -1;
1449 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001450 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1451 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001452
1453 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001454 wpa_dbg(wpa_s, MSG_DEBUG,
1455 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1456 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001457 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1458 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1460 "cipher");
1461 return -1;
1462 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001463 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1464 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001465#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466
1467 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001468#ifdef CONFIG_SAE
1469 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1470 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1471#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001472#ifdef CONFIG_IEEE80211R
1473 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1474 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1475 sel &= ~WPA_KEY_MGMT_FT;
1476#endif /* CONFIG_IEEE80211R */
1477 wpa_dbg(wpa_s, MSG_DEBUG,
1478 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1479 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001480 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001481#ifdef CONFIG_IEEE80211R
1482#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001483 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1484 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001485 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1486 wpa_dbg(wpa_s, MSG_DEBUG,
1487 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001488 if (!ssid->ft_eap_pmksa_caching &&
1489 pmksa_cache_get_current(wpa_s->wpa)) {
1490 /* PMKSA caching with FT may have interoperability
1491 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001492 wpa_dbg(wpa_s, MSG_DEBUG,
1493 "WPA: Disable PMKSA caching for FT/802.1X connection");
1494 pmksa_cache_clear_current(wpa_s->wpa);
1495 }
1496#endif /* CONFIG_SHA384 */
1497#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001498#ifdef CONFIG_SUITEB192
1499 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1500 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1501 wpa_dbg(wpa_s, MSG_DEBUG,
1502 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1503#endif /* CONFIG_SUITEB192 */
1504#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001505 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1506 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1507 wpa_dbg(wpa_s, MSG_DEBUG,
1508 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001509#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001510#ifdef CONFIG_FILS
1511#ifdef CONFIG_IEEE80211R
1512 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1513 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1514 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1515 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1516 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1517 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1518#endif /* CONFIG_IEEE80211R */
1519 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1520 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1521 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1522 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1523 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1524 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1525#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001526#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001527 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1528 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1530 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001531 if (!ssid->ft_eap_pmksa_caching &&
1532 pmksa_cache_get_current(wpa_s->wpa)) {
1533 /* PMKSA caching with FT may have interoperability
1534 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001535 wpa_dbg(wpa_s, MSG_DEBUG,
1536 "WPA: Disable PMKSA caching for FT/802.1X connection");
1537 pmksa_cache_clear_current(wpa_s->wpa);
1538 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001539#endif /* CONFIG_IEEE80211R */
1540#ifdef CONFIG_DPP
1541 } else if (sel & WPA_KEY_MGMT_DPP) {
1542 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1543 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1544#endif /* CONFIG_DPP */
1545#ifdef CONFIG_SAE
1546 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1547 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1548 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1549 } else if (sel & WPA_KEY_MGMT_SAE) {
1550 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1551 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1552#endif /* CONFIG_SAE */
1553#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001554 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1555 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1556 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1557#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1559 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1560 wpa_dbg(wpa_s, MSG_DEBUG,
1561 "WPA: using KEY_MGMT 802.1X with SHA256");
1562 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1563 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1564 wpa_dbg(wpa_s, MSG_DEBUG,
1565 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001566 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1567 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1568 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1569 } else if (sel & WPA_KEY_MGMT_PSK) {
1570 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1571 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1572 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1573 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1574 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001575#ifdef CONFIG_HS20
1576 } else if (sel & WPA_KEY_MGMT_OSEN) {
1577 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1578 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1579#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001580#ifdef CONFIG_OWE
1581 } else if (sel & WPA_KEY_MGMT_OWE) {
1582 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1583 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1584#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001585 } else {
1586 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1587 "authenticated key management type");
1588 return -1;
1589 }
1590
1591 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1592 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1593 wpa_s->pairwise_cipher);
1594 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1595
Hai Shalomc3565922019-10-28 11:58:20 -07001596 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1597 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1598 wpa_msg(wpa_s, MSG_INFO,
1599 "RSN: Management frame protection required but the selected AP does not enable it");
1600 return -1;
1601 }
1602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001603 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001604 if (ssid->group_mgmt_cipher)
1605 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001606 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001607 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1608 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001609 wpa_dbg(wpa_s, MSG_DEBUG,
1610 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1611 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001612 if (sel & WPA_CIPHER_AES_128_CMAC) {
1613 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1614 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1615 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001616 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1617 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1618 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1619 "BIP-GMAC-128");
1620 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1621 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1622 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1623 "BIP-GMAC-256");
1624 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1625 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1626 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1627 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001628 } else {
1629 wpa_s->mgmt_group_cipher = 0;
1630 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1631 }
1632 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1633 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001634 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001635 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001636#ifdef CONFIG_OCV
1637 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
1638#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001639 sae_pwe = wpa_s->conf->sae_pwe;
1640 if (ssid->sae_password_id && sae_pwe != 3)
1641 sae_pwe = 1;
1642 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001643#ifdef CONFIG_TESTING_OPTIONS
1644 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1645 wpa_s->ft_rsnxe_used);
1646#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001647
1648 /* Extended Key ID is only supported in infrastructure BSS so far */
1649 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1650 (ssid->proto & WPA_PROTO_RSN) &&
1651 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1652 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1653 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1654 int use_ext_key_id = 0;
1655
1656 wpa_msg(wpa_s, MSG_DEBUG,
1657 "WPA: Enable Extended Key ID support");
1658 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1659 wpa_s->conf->extended_key_id);
1660 if (bss_rsn &&
1661 wpa_s->conf->extended_key_id &&
1662 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1663 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1664 use_ext_key_id = 1;
1665 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1666 use_ext_key_id);
1667 } else {
1668 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1669 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1670 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671
1672 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1673 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1674 return -1;
1675 }
1676
Hai Shalomc3565922019-10-28 11:58:20 -07001677 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1678 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1679 &wpa_s->rsnxe_len)) {
1680 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1681 return -1;
1682 }
1683
Hai Shalom021b0b52019-04-10 11:17:58 -07001684 if (0) {
1685#ifdef CONFIG_DPP
1686 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1687 /* Use PMK from DPP network introduction (PMKSA entry) */
1688 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1689#endif /* CONFIG_DPP */
1690 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001691 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001692 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001693
Roshan Pius3a1667e2018-07-03 15:17:14 -07001694 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1695 WPA_KEY_MGMT_FT_PSK |
1696 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1697
1698 if (ssid->psk_set && !sae_only) {
1699 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1700 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001701 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1702 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001703 psk_set = 1;
1704 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001705
Roshan Pius3a1667e2018-07-03 15:17:14 -07001706 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1707 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001708 psk_set = 1;
1709
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001710#ifndef CONFIG_NO_PBKDF2
1711 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001712 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001713 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001714 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1715 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001716 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1717 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001718 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001719 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001720 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001721 }
1722#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001723#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001724 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001725 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1726 ssid->ext_psk);
1727 char pw_str[64 + 1];
1728 u8 psk[PMK_LEN];
1729
1730 if (pw == NULL) {
1731 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1732 "found from external storage");
1733 return -1;
1734 }
1735
1736 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1737 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1738 "PSK length %d in external storage",
1739 (int) wpabuf_len(pw));
1740 ext_password_free(pw);
1741 return -1;
1742 }
1743
1744 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1745 pw_str[wpabuf_len(pw)] = '\0';
1746
1747#ifndef CONFIG_NO_PBKDF2
1748 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1749 {
1750 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1751 4096, psk, PMK_LEN);
1752 os_memset(pw_str, 0, sizeof(pw_str));
1753 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1754 "external passphrase)",
1755 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001756 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1757 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001758 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001759 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001760 } else
1761#endif /* CONFIG_NO_PBKDF2 */
1762 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1763 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1764 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1765 "Invalid PSK hex string");
1766 os_memset(pw_str, 0, sizeof(pw_str));
1767 ext_password_free(pw);
1768 return -1;
1769 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001770 wpa_hexdump_key(MSG_MSGDUMP,
1771 "PSK (from external PSK)",
1772 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001773 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1774 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001775 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001776 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001777 } else {
1778 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1779 "PSK available");
1780 os_memset(pw_str, 0, sizeof(pw_str));
1781 ext_password_free(pw);
1782 return -1;
1783 }
1784
1785 os_memset(pw_str, 0, sizeof(pw_str));
1786 ext_password_free(pw);
1787 }
1788#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001789
1790 if (!psk_set) {
1791 wpa_msg(wpa_s, MSG_INFO,
1792 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001793 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001794 return -1;
1795 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001796#ifdef CONFIG_OWE
1797 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1798 /* OWE Diffie-Hellman exchange in (Re)Association
1799 * Request/Response frames set the PMK, so do not override it
1800 * here. */
1801#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001802 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001803 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1804
Hai Shalomfdcde762020-04-02 11:19:20 -07001805 if (ssid->mode != WPAS_MODE_IBSS &&
1806 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1807 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1808 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1809 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1810 wpa_msg(wpa_s, MSG_INFO,
1811 "Disable PTK0 rekey support - replaced with reconnect");
1812 wpa_s->deny_ptk0_rekey = 1;
1813 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1814 } else {
1815 wpa_s->deny_ptk0_rekey = 0;
1816 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1817 }
1818
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001819 return 0;
1820}
1821
1822
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001823static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1824{
1825 *pos = 0x00;
1826
1827 switch (idx) {
1828 case 0: /* Bits 0-7 */
1829 break;
1830 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001831 if (wpa_s->conf->coloc_intf_reporting) {
1832 /* Bit 13 - Collocated Interference Reporting */
1833 *pos |= 0x20;
1834 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001835 break;
1836 case 2: /* Bits 16-23 */
1837#ifdef CONFIG_WNM
1838 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001839 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001840 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001841#endif /* CONFIG_WNM */
1842 break;
1843 case 3: /* Bits 24-31 */
1844#ifdef CONFIG_WNM
1845 *pos |= 0x02; /* Bit 25 - SSID List */
1846#endif /* CONFIG_WNM */
1847#ifdef CONFIG_INTERWORKING
1848 if (wpa_s->conf->interworking)
1849 *pos |= 0x80; /* Bit 31 - Interworking */
1850#endif /* CONFIG_INTERWORKING */
1851 break;
1852 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001853#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001854 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001855 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001856#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001857 break;
1858 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001859#ifdef CONFIG_HS20
1860 if (wpa_s->conf->hs20)
1861 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1862#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001863#ifdef CONFIG_MBO
1864 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1865#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001866 break;
1867 case 6: /* Bits 48-55 */
1868 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001869 case 7: /* Bits 56-63 */
1870 break;
1871 case 8: /* Bits 64-71 */
1872 if (wpa_s->conf->ftm_responder)
1873 *pos |= 0x40; /* Bit 70 - FTM responder */
1874 if (wpa_s->conf->ftm_initiator)
1875 *pos |= 0x80; /* Bit 71 - FTM initiator */
1876 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001877 case 9: /* Bits 72-79 */
1878#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001879 if (!wpa_s->disable_fils)
1880 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001881#endif /* CONFIG_FILS */
1882 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001883 }
1884}
1885
1886
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001887int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001888{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001889 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001890 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001891
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001892 if (len < wpa_s->extended_capa_len)
1893 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001894 if (buflen < (size_t) len + 2) {
1895 wpa_printf(MSG_INFO,
1896 "Not enough room for building extended capabilities element");
1897 return -1;
1898 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001899
1900 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001901 *pos++ = len;
1902 for (i = 0; i < len; i++, pos++) {
1903 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001904
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001905 if (i < wpa_s->extended_capa_len) {
1906 *pos &= ~wpa_s->extended_capa_mask[i];
1907 *pos |= wpa_s->extended_capa[i];
1908 }
1909 }
1910
1911 while (len > 0 && buf[1 + len] == 0) {
1912 len--;
1913 buf[1] = len;
1914 }
1915 if (len == 0)
1916 return 0;
1917
1918 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001919}
1920
1921
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001922static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1923 struct wpa_bss *test_bss)
1924{
1925 struct wpa_bss *bss;
1926
1927 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1928 if (bss == test_bss)
1929 return 1;
1930 }
1931
1932 return 0;
1933}
1934
1935
1936static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1937 struct wpa_ssid *test_ssid)
1938{
1939 struct wpa_ssid *ssid;
1940
1941 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1942 if (ssid == test_ssid)
1943 return 1;
1944 }
1945
1946 return 0;
1947}
1948
1949
1950int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1951 struct wpa_ssid *test_ssid)
1952{
1953 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1954 return 0;
1955
1956 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1957}
1958
1959
1960void wpas_connect_work_free(struct wpa_connect_work *cwork)
1961{
1962 if (cwork == NULL)
1963 return;
1964 os_free(cwork);
1965}
1966
1967
1968void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1969{
1970 struct wpa_connect_work *cwork;
1971 struct wpa_radio_work *work = wpa_s->connect_work;
1972
1973 if (!work)
1974 return;
1975
1976 wpa_s->connect_work = NULL;
1977 cwork = work->ctx;
1978 work->ctx = NULL;
1979 wpas_connect_work_free(cwork);
1980 radio_work_done(work);
1981}
1982
1983
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001984int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1985{
1986 struct os_reltime now;
1987 u8 addr[ETH_ALEN];
1988
1989 os_get_reltime(&now);
1990 if (wpa_s->last_mac_addr_style == style &&
1991 wpa_s->last_mac_addr_change.sec != 0 &&
1992 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1993 wpa_s->conf->rand_addr_lifetime)) {
1994 wpa_msg(wpa_s, MSG_DEBUG,
1995 "Previously selected random MAC address has not yet expired");
1996 return 0;
1997 }
1998
1999 switch (style) {
2000 case 1:
2001 if (random_mac_addr(addr) < 0)
2002 return -1;
2003 break;
2004 case 2:
2005 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2006 if (random_mac_addr_keep_oui(addr) < 0)
2007 return -1;
2008 break;
2009 default:
2010 return -1;
2011 }
2012
2013 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2014 wpa_msg(wpa_s, MSG_INFO,
2015 "Failed to set random MAC address");
2016 return -1;
2017 }
2018
2019 os_get_reltime(&wpa_s->last_mac_addr_change);
2020 wpa_s->mac_addr_changed = 1;
2021 wpa_s->last_mac_addr_style = style;
2022
2023 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2024 wpa_msg(wpa_s, MSG_INFO,
2025 "Could not update MAC address information");
2026 return -1;
2027 }
2028
2029 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2030 MAC2STR(addr));
2031
2032 return 0;
2033}
2034
2035
2036int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2037{
2038 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2039 !wpa_s->conf->preassoc_mac_addr)
2040 return 0;
2041
2042 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2043}
2044
2045
Hai Shalomc3565922019-10-28 11:58:20 -07002046static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2047{
2048#ifdef CONFIG_SAE
2049 int *groups = conf->sae_groups;
2050 int default_groups[] = { 19, 20, 21, 0 };
2051 const char *password;
2052
2053 if (!groups || groups[0] <= 0)
2054 groups = default_groups;
2055
2056 password = ssid->sae_password;
2057 if (!password)
2058 password = ssid->passphrase;
2059
Hai Shalomfdcde762020-04-02 11:19:20 -07002060 if ((conf->sae_pwe == 0 && !ssid->sae_password_id) || !password ||
2061 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002062 /* PT derivation not needed */
2063 sae_deinit_pt(ssid->pt);
2064 ssid->pt = NULL;
2065 return;
2066 }
2067
2068 if (ssid->pt)
2069 return; /* PT already derived */
2070 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2071 (const u8 *) password, os_strlen(password),
2072 ssid->sae_password_id);
2073#endif /* CONFIG_SAE */
2074}
2075
2076
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002077static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2078{
2079#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2080 os_free(wpa_s->sme.sae_rejected_groups);
2081 wpa_s->sme.sae_rejected_groups = NULL;
2082#ifdef CONFIG_TESTING_OPTIONS
2083 if (wpa_s->extra_sae_rejected_groups) {
2084 int i, *groups = wpa_s->extra_sae_rejected_groups;
2085
2086 for (i = 0; groups[i]; i++) {
2087 wpa_printf(MSG_DEBUG,
2088 "TESTING: Indicate rejection of an extra SAE group %d",
2089 groups[i]);
2090 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2091 groups[i]);
2092 }
2093 }
2094#endif /* CONFIG_TESTING_OPTIONS */
2095#endif /* CONFIG_SAE && CONFIG_SME */
2096}
2097
2098
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002099static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2100
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002101/**
2102 * wpa_supplicant_associate - Request association
2103 * @wpa_s: Pointer to wpa_supplicant data
2104 * @bss: Scan results for the selected BSS, or %NULL if not available
2105 * @ssid: Configuration data for the selected network
2106 *
2107 * This function is used to request %wpa_supplicant to associate with a BSS.
2108 */
2109void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2110 struct wpa_bss *bss, struct wpa_ssid *ssid)
2111{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002112 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002113 int rand_style;
2114
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002115 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002116 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002117
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002118 /*
2119 * If we are starting a new connection, any previously pending EAPOL
2120 * RX cannot be valid anymore.
2121 */
2122 wpabuf_free(wpa_s->pending_eapol_rx);
2123 wpa_s->pending_eapol_rx = NULL;
2124
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002125 if (ssid->mac_addr == -1)
2126 rand_style = wpa_s->conf->mac_addr;
2127 else
2128 rand_style = ssid->mac_addr;
2129
Hai Shalomfdcde762020-04-02 11:19:20 -07002130 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002131 wmm_ac_clear_saved_tspecs(wpa_s);
2132 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002133 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002134#ifdef CONFIG_TESTING_OPTIONS
2135 wpa_s->testing_resend_assoc = 0;
2136#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002137
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002138 if (wpa_s->last_ssid == ssid) {
2139 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002140 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002141 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2142 wmm_ac_save_tspecs(wpa_s);
2143 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002144 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2145 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002146 }
Hai Shalomc3565922019-10-28 11:58:20 -07002147 } else {
2148#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002149 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002150 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2151#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002152 }
2153
2154 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002155 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2156 return;
2157 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002158 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002159 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2160 wpa_msg(wpa_s, MSG_INFO,
2161 "Could not restore permanent MAC address");
2162 return;
2163 }
2164 wpa_s->mac_addr_changed = 0;
2165 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2166 wpa_msg(wpa_s, MSG_INFO,
2167 "Could not update MAC address information");
2168 return;
2169 }
2170 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2171 }
2172 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002173
2174#ifdef CONFIG_IBSS_RSN
2175 ibss_rsn_deinit(wpa_s->ibss_rsn);
2176 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002177#else /* CONFIG_IBSS_RSN */
2178 if (ssid->mode == WPAS_MODE_IBSS &&
2179 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2180 wpa_msg(wpa_s, MSG_INFO,
2181 "IBSS RSN not supported in the build");
2182 return;
2183 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002184#endif /* CONFIG_IBSS_RSN */
2185
2186 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2187 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2188#ifdef CONFIG_AP
2189 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2190 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2191 "mode");
2192 return;
2193 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002194 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2195 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002196 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2197 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002198 return;
2199 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002200 wpa_s->current_bss = bss;
2201#else /* CONFIG_AP */
2202 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2203 "the build");
2204#endif /* CONFIG_AP */
2205 return;
2206 }
2207
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002208 if (ssid->mode == WPAS_MODE_MESH) {
2209#ifdef CONFIG_MESH
2210 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2211 wpa_msg(wpa_s, MSG_INFO,
2212 "Driver does not support mesh mode");
2213 return;
2214 }
2215 if (bss)
2216 ssid->frequency = bss->freq;
2217 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2218 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2219 return;
2220 }
2221 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002222 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
2223 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
2224 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002225 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002226#else /* CONFIG_MESH */
2227 wpa_msg(wpa_s, MSG_ERROR,
2228 "mesh mode support not included in the build");
2229#endif /* CONFIG_MESH */
2230 return;
2231 }
2232
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002233 /*
2234 * Set WPA state machine configuration to match the selected network now
2235 * so that the information is available before wpas_start_assoc_cb()
2236 * gets called. This is needed at least for RSN pre-authentication where
2237 * candidate APs are added to a list based on scan result processing
2238 * before completion of the first association.
2239 */
2240 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2241
2242#ifdef CONFIG_DPP
2243 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2244 return;
2245#endif /* CONFIG_DPP */
2246
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002247#ifdef CONFIG_TDLS
2248 if (bss)
2249 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2250 bss->ie_len);
2251#endif /* CONFIG_TDLS */
2252
Hai Shalomc3565922019-10-28 11:58:20 -07002253#ifdef CONFIG_MBO
2254 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2255#endif /* CONFIG_MBO */
2256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002257 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002258 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259 sme_authenticate(wpa_s, bss, ssid);
2260 return;
2261 }
2262
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002263 if (wpa_s->connect_work) {
2264 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2265 return;
2266 }
2267
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002268 if (radio_work_pending(wpa_s, "connect")) {
2269 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2270 return;
2271 }
2272
Dmitry Shmidt29333592017-01-09 12:27:11 -08002273#ifdef CONFIG_SME
2274 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2275 /* Clear possibly set auth_alg, if any, from last attempt. */
2276 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2277 }
2278#endif /* CONFIG_SME */
2279
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002280 wpas_abort_ongoing_scan(wpa_s);
2281
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002282 cwork = os_zalloc(sizeof(*cwork));
2283 if (cwork == NULL)
2284 return;
2285
2286 cwork->bss = bss;
2287 cwork->ssid = ssid;
2288
2289 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2290 wpas_start_assoc_cb, cwork) < 0) {
2291 os_free(cwork);
2292 }
2293}
2294
2295
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002296static int bss_is_ibss(struct wpa_bss *bss)
2297{
2298 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2299 IEEE80211_CAP_IBSS;
2300}
2301
2302
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002303static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2304 const struct wpa_ssid *ssid)
2305{
2306 enum hostapd_hw_mode hw_mode;
2307 struct hostapd_hw_modes *mode = NULL;
2308 u8 channel;
2309 int i;
2310
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002311 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2312 if (hw_mode == NUM_HOSTAPD_MODES)
2313 return 0;
2314 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2315 if (wpa_s->hw.modes[i].mode == hw_mode) {
2316 mode = &wpa_s->hw.modes[i];
2317 break;
2318 }
2319 }
2320
2321 if (!mode)
2322 return 0;
2323
2324 return mode->vht_capab != 0;
2325}
2326
2327
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002328void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2329 const struct wpa_ssid *ssid,
2330 struct hostapd_freq_params *freq)
2331{
Hai Shalom81f62d82019-07-22 12:10:00 -07002332 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002333 enum hostapd_hw_mode hw_mode;
2334 struct hostapd_hw_modes *mode = NULL;
2335 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2336 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002337 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002338 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2339 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002340 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002341 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002342 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002343 int chwidth, seg0, seg1;
2344 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002345 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002346
2347 freq->freq = ssid->frequency;
2348
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002349 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2350 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2351
2352 if (ssid->mode != WPAS_MODE_IBSS)
2353 break;
2354
2355 /* Don't adjust control freq in case of fixed_freq */
2356 if (ssid->fixed_freq)
2357 break;
2358
2359 if (!bss_is_ibss(bss))
2360 continue;
2361
2362 if (ssid->ssid_len == bss->ssid_len &&
2363 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2364 wpa_printf(MSG_DEBUG,
2365 "IBSS already found in scan results, adjust control freq: %d",
2366 bss->freq);
2367 freq->freq = bss->freq;
2368 obss_scan = 0;
2369 break;
2370 }
2371 }
2372
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002373 /* For IBSS check HT_IBSS flag */
2374 if (ssid->mode == WPAS_MODE_IBSS &&
2375 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2376 return;
2377
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002378 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2379 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2380 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2381 wpa_printf(MSG_DEBUG,
2382 "IBSS: WEP/TKIP detected, do not try to enable HT");
2383 return;
2384 }
2385
2386 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002387 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2388 if (wpa_s->hw.modes[i].mode == hw_mode) {
2389 mode = &wpa_s->hw.modes[i];
2390 break;
2391 }
2392 }
2393
2394 if (!mode)
2395 return;
2396
Hai Shalomc3565922019-10-28 11:58:20 -07002397 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2398 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002399
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002400#ifdef CONFIG_HT_OVERRIDES
2401 if (ssid->disable_ht) {
2402 freq->ht_enabled = 0;
2403 return;
2404 }
2405#endif /* CONFIG_HT_OVERRIDES */
2406
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002407 freq->ht_enabled = ht_supported(mode);
2408 if (!freq->ht_enabled)
2409 return;
2410
Hai Shalomc3565922019-10-28 11:58:20 -07002411 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2412 if (is_24ghz)
2413 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002414#ifdef CONFIG_HE_OVERRIDES
2415 if (is_24ghz && ssid->disable_he)
2416 freq->he_enabled = 0;
2417#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002418
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002419 /* Setup higher BW only for 5 GHz */
2420 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2421 return;
2422
2423 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2424 pri_chan = &mode->channels[chan_idx];
2425 if (pri_chan->chan == channel)
2426 break;
2427 pri_chan = NULL;
2428 }
2429 if (!pri_chan)
2430 return;
2431
2432 /* Check primary channel flags */
2433 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2434 return;
2435
Hai Shalom74f70d42019-02-11 14:42:39 -08002436 freq->channel = pri_chan->chan;
2437
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002438#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002439 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002440#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002441 if (ssid->disable_vht)
2442 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002443#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002444 goto skip_ht40;
2445 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002446#endif /* CONFIG_HT_OVERRIDES */
2447
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002448 /* Check/setup HT40+/HT40- */
2449 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2450 if (ht40plus[j] == channel) {
2451 ht40 = 1;
2452 break;
2453 }
2454 }
2455
2456 /* Find secondary channel */
2457 for (i = 0; i < mode->num_channels; i++) {
2458 sec_chan = &mode->channels[i];
2459 if (sec_chan->chan == channel + ht40 * 4)
2460 break;
2461 sec_chan = NULL;
2462 }
2463 if (!sec_chan)
2464 return;
2465
2466 /* Check secondary channel flags */
2467 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2468 return;
2469
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002470 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002471 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2472 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002473 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002474 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2475 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002476 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002477 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002478
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002479 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002480 struct wpa_scan_results *scan_res;
2481
2482 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2483 if (scan_res == NULL) {
2484 /* Back to HT20 */
2485 freq->sec_channel_offset = 0;
2486 return;
2487 }
2488
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002489 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002490 switch (res) {
2491 case 0:
2492 /* Back to HT20 */
2493 freq->sec_channel_offset = 0;
2494 break;
2495 case 1:
2496 /* Configuration allowed */
2497 break;
2498 case 2:
2499 /* Switch pri/sec channels */
2500 freq->freq = hw_get_freq(mode, sec_chan->chan);
2501 freq->sec_channel_offset = -freq->sec_channel_offset;
2502 freq->channel = sec_chan->chan;
2503 break;
2504 default:
2505 freq->sec_channel_offset = 0;
2506 break;
2507 }
2508
2509 wpa_scan_results_free(scan_res);
2510 }
2511
Hai Shalom74f70d42019-02-11 14:42:39 -08002512#ifdef CONFIG_HT_OVERRIDES
2513skip_ht40:
2514#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002515 wpa_printf(MSG_DEBUG,
2516 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2517 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002518
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002519 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002520 return;
2521
2522 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002523 if (ssid->mode == WPAS_MODE_IBSS &&
2524 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002525 return;
2526
2527 vht_freq = *freq;
2528
Paul Stewart092955c2017-02-06 09:13:09 -08002529#ifdef CONFIG_VHT_OVERRIDES
2530 if (ssid->disable_vht) {
2531 freq->vht_enabled = 0;
2532 return;
2533 }
2534#endif /* CONFIG_VHT_OVERRIDES */
2535
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002536 vht_freq.vht_enabled = vht_supported(mode);
2537 if (!vht_freq.vht_enabled)
2538 return;
2539
Hai Shalomfdcde762020-04-02 11:19:20 -07002540 /* Enable HE with VHT for 5 GHz */
2541 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002542
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002543 /* setup center_freq1, bandwidth */
2544 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2545 if (freq->channel >= vht80[j] &&
2546 freq->channel < vht80[j] + 16)
2547 break;
2548 }
2549
2550 if (j == ARRAY_SIZE(vht80))
2551 return;
2552
2553 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2554 struct hostapd_channel_data *chan;
2555
2556 chan = hw_get_channel_chan(mode, i, NULL);
2557 if (!chan)
2558 return;
2559
2560 /* Back to HT configuration if channel not usable */
2561 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2562 return;
2563 }
2564
Hai Shalom81f62d82019-07-22 12:10:00 -07002565 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002566 seg0 = vht80[j] + 6;
2567 seg1 = 0;
2568
Hai Shalom81f62d82019-07-22 12:10:00 -07002569 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002570 /* setup center_freq2, bandwidth */
2571 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2572 /* Only accept 80 MHz segments separated by a gap */
2573 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2574 continue;
2575 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2576 struct hostapd_channel_data *chan;
2577
2578 chan = hw_get_channel_chan(mode, i, NULL);
2579 if (!chan)
2580 continue;
2581
2582 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2583 HOSTAPD_CHAN_NO_IR |
2584 HOSTAPD_CHAN_RADAR))
2585 continue;
2586
2587 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002588 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002589 vht_caps |=
2590 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2591 seg1 = vht80[k] + 6;
2592 }
2593
Hai Shalom81f62d82019-07-22 12:10:00 -07002594 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002595 break;
2596 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002597 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002598 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002599 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002600 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2601 seg0 = 50;
2602 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002603 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002604 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2605 seg0 = 114;
2606 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002607 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2608 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002609 seg0 = vht80[j] + 2;
2610#ifdef CONFIG_HT_OVERRIDES
2611 if (ssid->disable_ht40)
2612 seg0 = 0;
2613#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002614 }
2615
Hai Shalomfdcde762020-04-02 11:19:20 -07002616#ifdef CONFIG_HE_OVERRIDES
2617 if (ssid->disable_he) {
2618 vht_freq.he_enabled = 0;
2619 freq->he_enabled = 0;
2620 }
2621#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002622 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002623 freq->channel, ssid->enable_edmg,
2624 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002625 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002626 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002627 chwidth, seg0, seg1, vht_caps,
2628 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002629 return;
2630
2631 *freq = vht_freq;
2632
2633 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2634 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002635}
2636
2637
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002638#ifdef CONFIG_FILS
2639static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2640 size_t ie_buf_len)
2641{
2642 struct fils_hlp_req *req;
2643 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2644 const u8 *pos;
2645 u8 *buf = ie_buf;
2646
2647 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2648 list) {
2649 rem_len = ie_buf_len - ie_len;
2650 pos = wpabuf_head(req->pkt);
2651 hdr_len = 1 + 2 * ETH_ALEN + 6;
2652 hlp_len = wpabuf_len(req->pkt);
2653
2654 if (rem_len < 2 + hdr_len + hlp_len) {
2655 wpa_printf(MSG_ERROR,
2656 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2657 (unsigned long) rem_len,
2658 (unsigned long) (2 + hdr_len + hlp_len));
2659 break;
2660 }
2661
2662 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2663 /* Element ID */
2664 *buf++ = WLAN_EID_EXTENSION;
2665 /* Length */
2666 *buf++ = len;
2667 /* Element ID Extension */
2668 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2669 /* Destination MAC address */
2670 os_memcpy(buf, req->dst, ETH_ALEN);
2671 buf += ETH_ALEN;
2672 /* Source MAC address */
2673 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2674 buf += ETH_ALEN;
2675 /* LLC/SNAP Header */
2676 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2677 buf += 6;
2678 /* HLP Packet */
2679 os_memcpy(buf, pos, len - hdr_len);
2680 buf += len - hdr_len;
2681 pos += len - hdr_len;
2682
2683 hlp_len -= len - hdr_len;
2684 ie_len += 2 + len;
2685 rem_len -= 2 + len;
2686
2687 while (hlp_len) {
2688 len = (hlp_len > 255) ? 255 : hlp_len;
2689 if (rem_len < 2 + len)
2690 break;
2691 *buf++ = WLAN_EID_FRAGMENT;
2692 *buf++ = len;
2693 os_memcpy(buf, pos, len);
2694 buf += len;
2695 pos += len;
2696
2697 hlp_len -= len;
2698 ie_len += 2 + len;
2699 rem_len -= 2 + len;
2700 }
2701 }
2702
2703 return ie_len;
2704}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002705
2706
2707int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2708{
2709 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2710 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2711 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2712 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2713}
2714
2715
2716int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2717{
2718#ifdef CONFIG_FILS_SK_PFS
2719 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2720 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2721#else /* CONFIG_FILS_SK_PFS */
2722 return 0;
2723#endif /* CONFIG_FILS_SK_PFS */
2724}
2725
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002726#endif /* CONFIG_FILS */
2727
2728
2729static u8 * wpas_populate_assoc_ies(
2730 struct wpa_supplicant *wpa_s,
2731 struct wpa_bss *bss, struct wpa_ssid *ssid,
2732 struct wpa_driver_associate_params *params,
2733 enum wpa_drv_update_connect_params_mask *mask)
2734{
2735 u8 *wpa_ie;
2736 size_t max_wpa_ie_len = 500;
2737 size_t wpa_ie_len;
2738 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002739#ifdef CONFIG_MBO
2740 const u8 *mbo_ie;
2741#endif
Hai Shalom5f92bc92019-04-18 11:54:11 -07002742#ifdef CONFIG_SAE
2743 int sae_pmksa_cached = 0;
2744#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002745#ifdef CONFIG_FILS
2746 const u8 *realm, *username, *rrk;
2747 size_t realm_len, username_len, rrk_len;
2748 u16 next_seq_num;
2749 struct fils_hlp_req *req;
2750
2751 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2752 list) {
2753 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2754 2 + 2 * wpabuf_len(req->pkt) / 255;
2755 }
2756#endif /* CONFIG_FILS */
2757
2758 wpa_ie = os_malloc(max_wpa_ie_len);
2759 if (!wpa_ie) {
2760 wpa_printf(MSG_ERROR,
2761 "Failed to allocate connect IE buffer for %lu bytes",
2762 (unsigned long) max_wpa_ie_len);
2763 return NULL;
2764 }
2765
2766 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2767 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2768 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2769 int try_opportunistic;
2770 const u8 *cache_id = NULL;
2771
2772 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2773 wpa_s->conf->okc :
2774 ssid->proactive_key_caching) &&
2775 (ssid->proto & WPA_PROTO_RSN);
2776#ifdef CONFIG_FILS
2777 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2778 cache_id = wpa_bss_get_fils_cache_id(bss);
2779#endif /* CONFIG_FILS */
2780 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2781 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002782 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002783 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Hai Shalom5f92bc92019-04-18 11:54:11 -07002784#ifdef CONFIG_SAE
2785 sae_pmksa_cached = 1;
2786#endif /* CONFIG_SAE */
2787 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002788 wpa_ie_len = max_wpa_ie_len;
2789 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2790 wpa_ie, &wpa_ie_len)) {
2791 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2792 "key management and encryption suites");
2793 os_free(wpa_ie);
2794 return NULL;
2795 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002796#ifdef CONFIG_HS20
2797 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2798 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2799 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2800 wpa_ie_len = max_wpa_ie_len;
2801 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2802 wpa_ie, &wpa_ie_len)) {
2803 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2804 "key management and encryption suites");
2805 os_free(wpa_ie);
2806 return NULL;
2807 }
2808#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002809 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2810 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2811 /*
2812 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2813 * use non-WPA since the scan results did not indicate that the
2814 * AP is using WPA or WPA2.
2815 */
2816 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2817 wpa_ie_len = 0;
2818 wpa_s->wpa_proto = 0;
2819 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2820 wpa_ie_len = max_wpa_ie_len;
2821 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2822 wpa_ie, &wpa_ie_len)) {
2823 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2824 "key management and encryption suites (no "
2825 "scan results)");
2826 os_free(wpa_ie);
2827 return NULL;
2828 }
2829#ifdef CONFIG_WPS
2830 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2831 struct wpabuf *wps_ie;
2832 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2833 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2834 wpa_ie_len = wpabuf_len(wps_ie);
2835 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2836 } else
2837 wpa_ie_len = 0;
2838 wpabuf_free(wps_ie);
2839 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2840 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2841 params->wps = WPS_MODE_PRIVACY;
2842 else
2843 params->wps = WPS_MODE_OPEN;
2844 wpa_s->wpa_proto = 0;
2845#endif /* CONFIG_WPS */
2846 } else {
2847 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2848 wpa_ie_len = 0;
2849 wpa_s->wpa_proto = 0;
2850 }
2851
2852#ifdef IEEE8021X_EAPOL
2853 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2854 if (ssid->leap) {
2855 if (ssid->non_leap == 0)
2856 algs = WPA_AUTH_ALG_LEAP;
2857 else
2858 algs |= WPA_AUTH_ALG_LEAP;
2859 }
2860 }
2861
2862#ifdef CONFIG_FILS
2863 /* Clear FILS association */
2864 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2865
2866 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2867 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2868 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2869 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002870 &next_seq_num, &rrk, &rrk_len) == 0 &&
2871 (!wpa_s->last_con_fail_realm ||
2872 wpa_s->last_con_fail_realm_len != realm_len ||
2873 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002874 algs = WPA_AUTH_ALG_FILS;
2875 params->fils_erp_username = username;
2876 params->fils_erp_username_len = username_len;
2877 params->fils_erp_realm = realm;
2878 params->fils_erp_realm_len = realm_len;
2879 params->fils_erp_next_seq_num = next_seq_num;
2880 params->fils_erp_rrk = rrk;
2881 params->fils_erp_rrk_len = rrk_len;
2882
2883 if (mask)
2884 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2885 }
2886#endif /* CONFIG_FILS */
2887#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002888#ifdef CONFIG_SAE
2889 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2890 algs = WPA_AUTH_ALG_SAE;
2891#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002892
2893 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2894 if (ssid->auth_alg) {
2895 algs = ssid->auth_alg;
2896 wpa_dbg(wpa_s, MSG_DEBUG,
2897 "Overriding auth_alg selection: 0x%x", algs);
2898 }
2899
Hai Shalom5f92bc92019-04-18 11:54:11 -07002900#ifdef CONFIG_SAE
2901 if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
2902 wpa_dbg(wpa_s, MSG_DEBUG,
2903 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2904 algs = WPA_AUTH_ALG_OPEN;
2905 }
2906#endif /* CONFIG_SAE */
2907
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002908#ifdef CONFIG_P2P
2909 if (wpa_s->global->p2p) {
2910 u8 *pos;
2911 size_t len;
2912 int res;
2913 pos = wpa_ie + wpa_ie_len;
2914 len = max_wpa_ie_len - wpa_ie_len;
2915 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2916 ssid->p2p_group);
2917 if (res >= 0)
2918 wpa_ie_len += res;
2919 }
2920
2921 wpa_s->cross_connect_disallowed = 0;
2922 if (bss) {
2923 struct wpabuf *p2p;
2924 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2925 if (p2p) {
2926 wpa_s->cross_connect_disallowed =
2927 p2p_get_cross_connect_disallowed(p2p);
2928 wpabuf_free(p2p);
2929 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2930 "connection",
2931 wpa_s->cross_connect_disallowed ?
2932 "disallows" : "allows");
2933 }
2934 }
2935
2936 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2937#endif /* CONFIG_P2P */
2938
2939 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002940 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002941 wpa_ie + wpa_ie_len,
2942 max_wpa_ie_len -
2943 wpa_ie_len);
2944 }
2945
2946 /*
2947 * Workaround: Add Extended Capabilities element only if the AP
2948 * included this element in Beacon/Probe Response frames. Some older
2949 * APs seem to have interoperability issues if this element is
2950 * included, so while the standard may require us to include the
2951 * element in all cases, it is justifiable to skip it to avoid
2952 * interoperability issues.
2953 */
2954 if (ssid->p2p_group)
2955 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2956 else
2957 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2958
2959 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2960 u8 ext_capab[18];
2961 int ext_capab_len;
2962 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2963 sizeof(ext_capab));
2964 if (ext_capab_len > 0 &&
2965 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2966 u8 *pos = wpa_ie;
2967 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2968 pos += 2 + pos[1];
2969 os_memmove(pos + ext_capab_len, pos,
2970 wpa_ie_len - (pos - wpa_ie));
2971 wpa_ie_len += ext_capab_len;
2972 os_memcpy(pos, ext_capab, ext_capab_len);
2973 }
2974 }
2975
2976#ifdef CONFIG_HS20
2977 if (is_hs20_network(wpa_s, ssid, bss)) {
2978 struct wpabuf *hs20;
2979
Roshan Pius3a1667e2018-07-03 15:17:14 -07002980 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002981 if (hs20) {
2982 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2983 size_t len;
2984
Hai Shalom74f70d42019-02-11 14:42:39 -08002985 wpas_hs20_add_indication(hs20, pps_mo_id,
2986 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002987 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002988 len = max_wpa_ie_len - wpa_ie_len;
2989 if (wpabuf_len(hs20) <= len) {
2990 os_memcpy(wpa_ie + wpa_ie_len,
2991 wpabuf_head(hs20), wpabuf_len(hs20));
2992 wpa_ie_len += wpabuf_len(hs20);
2993 }
2994 wpabuf_free(hs20);
2995
2996 hs20_configure_frame_filters(wpa_s);
2997 }
2998 }
2999#endif /* CONFIG_HS20 */
3000
3001 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3002 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3003 size_t len;
3004
3005 len = max_wpa_ie_len - wpa_ie_len;
3006 if (wpabuf_len(buf) <= len) {
3007 os_memcpy(wpa_ie + wpa_ie_len,
3008 wpabuf_head(buf), wpabuf_len(buf));
3009 wpa_ie_len += wpabuf_len(buf);
3010 }
3011 }
3012
3013#ifdef CONFIG_FST
3014 if (wpa_s->fst_ies) {
3015 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3016
3017 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3018 os_memcpy(wpa_ie + wpa_ie_len,
3019 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3020 wpa_ie_len += fst_ies_len;
3021 }
3022 }
3023#endif /* CONFIG_FST */
3024
3025#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003026 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003027 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003028 int len;
3029
3030 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003031 max_wpa_ie_len - wpa_ie_len,
3032 !!mbo_attr_from_mbo_ie(mbo_ie,
3033 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003034 if (len >= 0)
3035 wpa_ie_len += len;
3036 }
3037#endif /* CONFIG_MBO */
3038
3039#ifdef CONFIG_FILS
3040 if (algs == WPA_AUTH_ALG_FILS) {
3041 size_t len;
3042
3043 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3044 max_wpa_ie_len - wpa_ie_len);
3045 wpa_ie_len += len;
3046 }
3047#endif /* CONFIG_FILS */
3048
3049#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003050#ifdef CONFIG_TESTING_OPTIONS
3051 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3052 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3053 } else
3054#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003055 if (algs == WPA_AUTH_ALG_OPEN &&
3056 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3057 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003058 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003059
Roshan Pius3a1667e2018-07-03 15:17:14 -07003060 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003061 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003062 } else if (wpa_s->assoc_status_code ==
3063 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003064 if (wpa_s->last_owe_group == 19)
3065 group = 20;
3066 else if (wpa_s->last_owe_group == 20)
3067 group = 21;
3068 else
3069 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003070 } else {
3071 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003072 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003073
Roshan Pius3a1667e2018-07-03 15:17:14 -07003074 wpa_s->last_owe_group = group;
3075 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003076 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3077 if (owe_ie &&
3078 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3079 os_memcpy(wpa_ie + wpa_ie_len,
3080 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3081 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003082 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003083 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003084 }
3085#endif /* CONFIG_OWE */
3086
Hai Shalom021b0b52019-04-10 11:17:58 -07003087#ifdef CONFIG_DPP2
3088 if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003089 ssid->dpp_netaccesskey &&
3090 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003091 dpp_pfs_free(wpa_s->dpp_pfs);
3092 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3093 ssid->dpp_netaccesskey_len);
3094 if (!wpa_s->dpp_pfs) {
3095 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3096 /* Try to continue without PFS */
3097 goto pfs_fail;
3098 }
3099 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3100 max_wpa_ie_len - wpa_ie_len) {
3101 os_memcpy(wpa_ie + wpa_ie_len,
3102 wpabuf_head(wpa_s->dpp_pfs->ie),
3103 wpabuf_len(wpa_s->dpp_pfs->ie));
3104 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3105 }
3106 }
3107pfs_fail:
3108#endif /* CONFIG_DPP2 */
3109
Roshan Pius3a1667e2018-07-03 15:17:14 -07003110#ifdef CONFIG_IEEE80211R
3111 /*
3112 * Add MDIE under these conditions: the network profile allows FT,
3113 * the AP supports FT, and the mobility domain ID matches.
3114 */
3115 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3116 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3117
3118 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3119 size_t len = 0;
3120 const u8 *md = mdie + 2;
3121 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3122
3123 if (os_memcmp(md, wpa_md,
3124 MOBILITY_DOMAIN_ID_LEN) == 0) {
3125 /* Add mobility domain IE */
3126 len = wpa_ft_add_mdie(
3127 wpa_s->wpa, wpa_ie + wpa_ie_len,
3128 max_wpa_ie_len - wpa_ie_len, mdie);
3129 wpa_ie_len += len;
3130 }
3131#ifdef CONFIG_SME
3132 if (len > 0 && wpa_s->sme.ft_used &&
3133 wpa_sm_has_ptk(wpa_s->wpa)) {
3134 wpa_dbg(wpa_s, MSG_DEBUG,
3135 "SME: Trying to use FT over-the-air");
3136 algs |= WPA_AUTH_ALG_FT;
3137 }
3138#endif /* CONFIG_SME */
3139 }
3140 }
3141#endif /* CONFIG_IEEE80211R */
3142
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003143#ifdef CONFIG_TESTING_OPTIONS
3144 if (wpa_s->rsnxe_override_assoc &&
3145 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3146 max_wpa_ie_len - wpa_ie_len) {
3147 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3148 os_memcpy(wpa_ie + wpa_ie_len,
3149 wpabuf_head(wpa_s->rsnxe_override_assoc),
3150 wpabuf_len(wpa_s->rsnxe_override_assoc));
3151 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3152 } else
3153#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003154 if (wpa_s->rsnxe_len > 0 &&
3155 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3156 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3157 wpa_ie_len += wpa_s->rsnxe_len;
3158 }
3159
Hai Shalom74f70d42019-02-11 14:42:39 -08003160 if (ssid->multi_ap_backhaul_sta) {
3161 size_t multi_ap_ie_len;
3162
3163 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3164 max_wpa_ie_len - wpa_ie_len,
3165 MULTI_AP_BACKHAUL_STA);
3166 if (multi_ap_ie_len == 0) {
3167 wpa_printf(MSG_ERROR,
3168 "Multi-AP: Failed to build Multi-AP IE");
3169 os_free(wpa_ie);
3170 return NULL;
3171 }
3172 wpa_ie_len += multi_ap_ie_len;
3173 }
3174
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003175 params->wpa_ie = wpa_ie;
3176 params->wpa_ie_len = wpa_ie_len;
3177 params->auth_alg = algs;
3178 if (mask)
3179 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3180
3181 return wpa_ie;
3182}
3183
3184
Hai Shalomc3565922019-10-28 11:58:20 -07003185#ifdef CONFIG_OWE
3186static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3187{
3188 struct wpa_driver_associate_params params;
3189 u8 *wpa_ie;
3190
3191 os_memset(&params, 0, sizeof(params));
3192 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3193 wpa_s->current_ssid, &params, NULL);
3194 if (!wpa_ie)
3195 return;
3196
3197 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3198 os_free(wpa_ie);
3199}
3200#endif /* CONFIG_OWE */
3201
3202
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003203#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3204static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3205{
3206 struct wpa_driver_associate_params params;
3207 enum wpa_drv_update_connect_params_mask mask = 0;
3208 u8 *wpa_ie;
3209
3210 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3211 return; /* nothing to do */
3212
3213 os_memset(&params, 0, sizeof(params));
3214 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3215 wpa_s->current_ssid, &params, &mask);
3216 if (!wpa_ie)
3217 return;
3218
3219 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3220 os_free(wpa_ie);
3221 return;
3222 }
3223
3224 wpa_s->auth_alg = params.auth_alg;
3225 wpa_drv_update_connect_params(wpa_s, &params, mask);
3226 os_free(wpa_ie);
3227}
3228#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3229
3230
Hai Shalomc3565922019-10-28 11:58:20 -07003231static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3232{
3233 if (!edmg_ie || edmg_ie[1] < 6)
3234 return 0;
3235 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3236}
3237
3238
3239static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3240{
3241 if (!edmg_ie || edmg_ie[1] < 6)
3242 return 0;
3243 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3244}
3245
3246
3247/* Returns the intersection of two EDMG configurations.
3248 * Note: The current implementation is limited to CB2 only (CB1 included),
3249 * i.e., the implementation supports up to 2 contiguous channels.
3250 * For supporting non-contiguous (aggregated) channels and for supporting
3251 * CB3 and above, this function will need to be extended.
3252 */
3253static struct ieee80211_edmg_config
3254get_edmg_intersection(struct ieee80211_edmg_config a,
3255 struct ieee80211_edmg_config b,
3256 u8 primary_channel)
3257{
3258 struct ieee80211_edmg_config result;
3259 int i, contiguous = 0;
3260 int max_contiguous = 0;
3261
3262 result.channels = b.channels & a.channels;
3263 if (!result.channels) {
3264 wpa_printf(MSG_DEBUG,
3265 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3266 a.channels, b.channels);
3267 goto fail;
3268 }
3269
3270 if (!(result.channels & BIT(primary_channel - 1))) {
3271 wpa_printf(MSG_DEBUG,
3272 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3273 primary_channel, result.channels);
3274 goto fail;
3275 }
3276
3277 /* Find max contiguous channels */
3278 for (i = 0; i < 6; i++) {
3279 if (result.channels & BIT(i))
3280 contiguous++;
3281 else
3282 contiguous = 0;
3283
3284 if (contiguous > max_contiguous)
3285 max_contiguous = contiguous;
3286 }
3287
3288 /* Assuming AP and STA supports ONLY contiguous channels,
3289 * bw configuration can have value between 4-7.
3290 */
3291 if ((b.bw_config < a.bw_config))
3292 result.bw_config = b.bw_config;
3293 else
3294 result.bw_config = a.bw_config;
3295
3296 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3297 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3298 wpa_printf(MSG_DEBUG,
3299 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3300 max_contiguous);
3301 goto fail;
3302 }
3303
3304 return result;
3305
3306fail:
3307 result.channels = 0;
3308 result.bw_config = 0;
3309 return result;
3310}
3311
3312
3313static struct ieee80211_edmg_config
3314get_supported_edmg(struct wpa_supplicant *wpa_s,
3315 struct hostapd_freq_params *freq,
3316 struct ieee80211_edmg_config request_edmg)
3317{
3318 enum hostapd_hw_mode hw_mode;
3319 struct hostapd_hw_modes *mode = NULL;
3320 u8 primary_channel;
3321
3322 if (!wpa_s->hw.modes)
3323 goto fail;
3324
3325 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3326 if (hw_mode == NUM_HOSTAPD_MODES)
3327 goto fail;
3328
Hai Shalomfdcde762020-04-02 11:19:20 -07003329 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003330 if (!mode)
3331 goto fail;
3332
3333 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3334
3335fail:
3336 request_edmg.channels = 0;
3337 request_edmg.bw_config = 0;
3338 return request_edmg;
3339}
3340
3341
Hai Shalom021b0b52019-04-10 11:17:58 -07003342#ifdef CONFIG_MBO
3343void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3344{
3345 struct wpa_driver_associate_params params;
3346 u8 *wpa_ie;
3347
3348 /*
3349 * Update MBO connect params only in case of change of MBO attributes
3350 * when connected, if the AP support MBO.
3351 */
3352
3353 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3354 !wpa_s->current_bss ||
3355 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3356 return;
3357
3358 os_memset(&params, 0, sizeof(params));
3359 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3360 wpa_s->current_ssid, &params, NULL);
3361 if (!wpa_ie)
3362 return;
3363
3364 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3365 os_free(wpa_ie);
3366}
3367#endif /* CONFIG_MBO */
3368
3369
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003370static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3371{
3372 struct wpa_connect_work *cwork = work->ctx;
3373 struct wpa_bss *bss = cwork->bss;
3374 struct wpa_ssid *ssid = cwork->ssid;
3375 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003376 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003377 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003378 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003379 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003380 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003381#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003382 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003383#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003384 int assoc_failed = 0;
3385 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003386 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003387#ifdef CONFIG_HT_OVERRIDES
3388 struct ieee80211_ht_capabilities htcaps;
3389 struct ieee80211_ht_capabilities htcaps_mask;
3390#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003391#ifdef CONFIG_VHT_OVERRIDES
3392 struct ieee80211_vht_capabilities vhtcaps;
3393 struct ieee80211_vht_capabilities vhtcaps_mask;
3394#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003395
3396 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003397 if (work->started) {
3398 wpa_s->connect_work = NULL;
3399
3400 /* cancel possible auth. timeout */
3401 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3402 NULL);
3403 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003404 wpas_connect_work_free(cwork);
3405 return;
3406 }
3407
3408 wpa_s->connect_work = work;
3409
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003410 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3411 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003412 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3413 wpas_connect_work_done(wpa_s);
3414 return;
3415 }
3416
Dmitry Shmidte4663042016-04-04 10:07:49 -07003417 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003418 os_memset(&params, 0, sizeof(params));
3419 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003420 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003421 if (bss &&
3422 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003423#ifdef CONFIG_IEEE80211R
3424 const u8 *ie, *md = NULL;
3425#endif /* CONFIG_IEEE80211R */
3426 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3427 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3428 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3429 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3430 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3431 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3432 if (bssid_changed)
3433 wpas_notify_bssid_changed(wpa_s);
3434#ifdef CONFIG_IEEE80211R
3435 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3436 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3437 md = ie + 2;
3438 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3439 if (md) {
3440 /* Prepare for the next transition */
3441 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3442 }
3443#endif /* CONFIG_IEEE80211R */
3444#ifdef CONFIG_WPS
3445 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3446 wpa_s->conf->ap_scan == 2 &&
3447 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3448 /* Use ap_scan==1 style network selection to find the network
3449 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003450 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003451 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003452 wpa_s->reassociate = 1;
3453 wpa_supplicant_req_scan(wpa_s, 0, 0);
3454 return;
3455#endif /* CONFIG_WPS */
3456 } else {
3457 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3458 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003459 if (bss)
3460 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3461 else
3462 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003464 if (!wpa_s->pno)
3465 wpa_supplicant_cancel_sched_scan(wpa_s);
3466
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003467 wpa_supplicant_cancel_scan(wpa_s);
3468
3469 /* Starting new association, so clear the possibly used WPA IE from the
3470 * previous association. */
3471 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003472 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3473 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003474
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003475 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3476 if (!wpa_ie) {
3477 wpas_connect_work_done(wpa_s);
3478 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003479 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003480
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003481 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3482 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003483 cipher_pairwise = wpa_s->pairwise_cipher;
3484 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003485 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003486 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3487 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3488 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3489 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003490#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491 if (wpa_set_wep_keys(wpa_s, ssid)) {
3492 use_crypt = 1;
3493 wep_keys_set = 1;
3494 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003495#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003496 }
3497 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3498 use_crypt = 0;
3499
3500#ifdef IEEE8021X_EAPOL
3501 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3502 if ((ssid->eapol_flags &
3503 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3504 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3505 !wep_keys_set) {
3506 use_crypt = 0;
3507 } else {
3508 /* Assume that dynamic WEP-104 keys will be used and
3509 * set cipher suites in order for drivers to expect
3510 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003511 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003512 }
3513 }
3514#endif /* IEEE8021X_EAPOL */
3515
3516 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3517 /* Set the key before (and later after) association */
3518 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3519 }
3520
3521 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3522 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003523 params.ssid = bss->ssid;
3524 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003525 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3526 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003527 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3528 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003529 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003530 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003531 ssid->bssid_set,
3532 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003533 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003534 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003535 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003536 params.bssid_hint = bss->bssid;
3537 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003538 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003539 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003540 if (ssid->bssid_hint_set)
3541 params.bssid_hint = ssid->bssid_hint;
3542
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003543 params.ssid = ssid->ssid;
3544 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003545 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003546 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003547
3548 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3549 wpa_s->conf->ap_scan == 2) {
3550 params.bssid = ssid->bssid;
3551 params.fixed_bssid = 1;
3552 }
3553
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003554 /* Initial frequency for IBSS/mesh */
3555 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003556 ssid->frequency > 0 && params.freq.freq == 0)
3557 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003558
3559 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003560 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003561 if (ssid->beacon_int)
3562 params.beacon_int = ssid->beacon_int;
3563 else
3564 params.beacon_int = wpa_s->conf->beacon_int;
3565 }
3566
Hai Shalomc3565922019-10-28 11:58:20 -07003567 if (bss && ssid->enable_edmg)
3568 edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len,
3569 WLAN_EID_EXT_EDMG_OPERATION);
3570 else
3571 edmg_ie_oper = NULL;
3572
3573 if (edmg_ie_oper) {
3574 params.freq.edmg.channels =
3575 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3576 params.freq.edmg.bw_config =
3577 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3578 wpa_printf(MSG_DEBUG,
3579 "AP supports EDMG channels 0x%x, bw_config %d",
3580 params.freq.edmg.channels,
3581 params.freq.edmg.bw_config);
3582
3583 /* User may ask for specific EDMG channel for EDMG connection
3584 * (must be supported by AP)
3585 */
3586 if (ssid->edmg_channel) {
3587 struct ieee80211_edmg_config configured_edmg;
3588 enum hostapd_hw_mode hw_mode;
3589 u8 primary_channel;
3590
3591 hw_mode = ieee80211_freq_to_chan(bss->freq,
3592 &primary_channel);
3593 if (hw_mode == NUM_HOSTAPD_MODES)
3594 goto edmg_fail;
3595
3596 hostapd_encode_edmg_chan(ssid->enable_edmg,
3597 ssid->edmg_channel,
3598 primary_channel,
3599 &configured_edmg);
3600
3601 if (ieee802_edmg_is_allowed(params.freq.edmg,
3602 configured_edmg)) {
3603 params.freq.edmg = configured_edmg;
3604 wpa_printf(MSG_DEBUG,
3605 "Use EDMG channel %d for connection",
3606 ssid->edmg_channel);
3607 } else {
3608 edmg_fail:
3609 params.freq.edmg.channels = 0;
3610 params.freq.edmg.bw_config = 0;
3611 wpa_printf(MSG_WARNING,
3612 "EDMG channel %d not supported by AP, fallback to DMG",
3613 ssid->edmg_channel);
3614 }
3615 }
3616
3617 if (params.freq.edmg.channels) {
3618 wpa_printf(MSG_DEBUG,
3619 "EDMG before: channels 0x%x, bw_config %d",
3620 params.freq.edmg.channels,
3621 params.freq.edmg.bw_config);
3622 params.freq.edmg = get_supported_edmg(wpa_s,
3623 &params.freq,
3624 params.freq.edmg);
3625 wpa_printf(MSG_DEBUG,
3626 "EDMG after: channels 0x%x, bw_config %d",
3627 params.freq.edmg.channels,
3628 params.freq.edmg.bw_config);
3629 }
3630 }
3631
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003632 params.pairwise_suite = cipher_pairwise;
3633 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003634 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003635 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003636 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003637 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003638 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003639 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003640#ifdef CONFIG_WEP
3641 {
3642 int i;
3643
3644 for (i = 0; i < NUM_WEP_KEYS; i++) {
3645 if (ssid->wep_key_len[i])
3646 params.wep_key[i] = ssid->wep_key[i];
3647 params.wep_key_len[i] = ssid->wep_key_len[i];
3648 }
3649 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003650 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003651#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652
Hai Shalom74f70d42019-02-11 14:42:39 -08003653 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003654 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3655 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003656 params.passphrase = ssid->passphrase;
3657 if (ssid->psk_set)
3658 params.psk = ssid->psk;
3659 }
3660
Hai Shalom74f70d42019-02-11 14:42:39 -08003661 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3662 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3663 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3664 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3665 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003666 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003667
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003668 if (wpa_s->conf->key_mgmt_offload) {
3669 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3670 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003671 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3672 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003673 params.req_key_mgmt_offload =
3674 ssid->proactive_key_caching < 0 ?
3675 wpa_s->conf->okc : ssid->proactive_key_caching;
3676 else
3677 params.req_key_mgmt_offload = 1;
3678
3679 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3680 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3681 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3682 ssid->psk_set)
3683 params.psk = ssid->psk;
3684 }
3685
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003686 params.drop_unencrypted = use_crypt;
3687
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003688 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003689 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003690 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3691 struct wpa_ie_data ie;
3692 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3693 ie.capabilities &
3694 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3695 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3696 "MFP: require MFP");
3697 params.mgmt_frame_protection =
3698 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003699#ifdef CONFIG_OWE
3700 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3701 !ssid->owe_only) {
3702 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3703#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003704 }
3705 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003707 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003709 if (wpa_s->p2pdev->set_sta_uapsd)
3710 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003711 else
3712 params.uapsd = -1;
3713
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003714#ifdef CONFIG_HT_OVERRIDES
3715 os_memset(&htcaps, 0, sizeof(htcaps));
3716 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3717 params.htcaps = (u8 *) &htcaps;
3718 params.htcaps_mask = (u8 *) &htcaps_mask;
3719 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3720#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003721#ifdef CONFIG_VHT_OVERRIDES
3722 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3723 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3724 params.vhtcaps = &vhtcaps;
3725 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003726 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003727#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003728#ifdef CONFIG_HE_OVERRIDES
3729 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3730#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003731
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003732#ifdef CONFIG_P2P
3733 /*
3734 * If multi-channel concurrency is not supported, check for any
3735 * frequency conflict. In case of any frequency conflict, remove the
3736 * least prioritized connection.
3737 */
3738 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003739 int freq, num;
3740 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003741 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003742 wpa_printf(MSG_DEBUG,
3743 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003744 freq, params.freq.freq);
3745 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003746 wpa_s, params.freq.freq, ssid) < 0) {
3747 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003748 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003749 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003750 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003751 }
3752 }
3753#endif /* CONFIG_P2P */
3754
Dmitry Shmidte4663042016-04-04 10:07:49 -07003755 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3756 wpa_s->current_ssid)
3757 params.prev_bssid = prev_bssid;
3758
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003759 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003760 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003761 if (ret < 0) {
3762 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3763 "failed");
3764 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3765 /*
3766 * The driver is known to mean what is saying, so we
3767 * can stop right here; the association will not
3768 * succeed.
3769 */
3770 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003771 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003772 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3773 return;
3774 }
3775 /* try to continue anyway; new association will be tried again
3776 * after timeout */
3777 assoc_failed = 1;
3778 }
3779
3780 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3781 /* Set the key after the association just in case association
3782 * cleared the previously configured key. */
3783 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3784 /* No need to timeout authentication since there is no key
3785 * management. */
3786 wpa_supplicant_cancel_auth_timeout(wpa_s);
3787 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3788#ifdef CONFIG_IBSS_RSN
3789 } else if (ssid->mode == WPAS_MODE_IBSS &&
3790 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3791 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3792 /*
3793 * RSN IBSS authentication is per-STA and we can disable the
3794 * per-BSSID authentication.
3795 */
3796 wpa_supplicant_cancel_auth_timeout(wpa_s);
3797#endif /* CONFIG_IBSS_RSN */
3798 } else {
3799 /* Timeout for IEEE 802.11 authentication and association */
3800 int timeout = 60;
3801
3802 if (assoc_failed) {
3803 /* give IBSS a bit more time */
3804 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3805 } else if (wpa_s->conf->ap_scan == 1) {
3806 /* give IBSS a bit more time */
3807 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3808 }
3809 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3810 }
3811
Hai Shalomfdcde762020-04-02 11:19:20 -07003812#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003813 if (wep_keys_set &&
3814 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003815 /* Set static WEP keys again */
3816 wpa_set_wep_keys(wpa_s, ssid);
3817 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003818#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003819
3820 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3821 /*
3822 * Do not allow EAP session resumption between different
3823 * network configurations.
3824 */
3825 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3826 }
3827 old_ssid = wpa_s->current_ssid;
3828 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003829
3830 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003831 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003832#ifdef CONFIG_HS20
3833 hs20_configure_frame_filters(wpa_s);
3834#endif /* CONFIG_HS20 */
3835 }
3836
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003837 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3838 wpa_supplicant_initiate_eapol(wpa_s);
3839 if (old_ssid != wpa_s->current_ssid)
3840 wpas_notify_network_changed(wpa_s);
3841}
3842
3843
3844static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3845 const u8 *addr)
3846{
3847 struct wpa_ssid *old_ssid;
3848
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003849 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003850 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003851 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003852 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003853 wpa_sm_set_config(wpa_s->wpa, NULL);
3854 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3855 if (old_ssid != wpa_s->current_ssid)
3856 wpas_notify_network_changed(wpa_s);
3857 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3858}
3859
3860
3861/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003862 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3863 * @wpa_s: Pointer to wpa_supplicant data
3864 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3865 *
3866 * This function is used to request %wpa_supplicant to deauthenticate from the
3867 * current AP.
3868 */
3869void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003870 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003871{
3872 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003873 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003874 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003875
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003876 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003877 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003878 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003879 reason_code, reason2str(reason_code),
3880 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003881
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003882 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3883 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3884 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003885 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003886 else if (!is_zero_ether_addr(wpa_s->bssid))
3887 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003888 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3889 /*
3890 * When using driver-based BSS selection, we may not know the
3891 * BSSID with which we are currently trying to associate. We
3892 * need to notify the driver of this disconnection even in such
3893 * a case, so use the all zeros address here.
3894 */
3895 addr = wpa_s->bssid;
3896 zero_addr = 1;
3897 }
3898
Hai Shalom74f70d42019-02-11 14:42:39 -08003899 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3900 wpa_s->enabled_4addr_mode = 0;
3901
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003902#ifdef CONFIG_TDLS
3903 wpa_tdls_teardown_peers(wpa_s->wpa);
3904#endif /* CONFIG_TDLS */
3905
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003906#ifdef CONFIG_MESH
3907 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003908 struct mesh_conf *mconf;
3909
3910 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003911 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3912 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003913 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3914 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003915 wpa_supplicant_leave_mesh(wpa_s);
3916 }
3917#endif /* CONFIG_MESH */
3918
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003919 if (addr) {
3920 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003921 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07003922 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003923 event.deauth_info.locally_generated = 1;
3924 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003925 if (zero_addr)
3926 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003927 }
3928
3929 wpa_supplicant_clear_connection(wpa_s, addr);
3930}
3931
Hai Shalomfdcde762020-04-02 11:19:20 -07003932
3933void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
3934{
3935 wpa_s->own_reconnect_req = 1;
3936 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
3937
3938}
3939
3940
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003941static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3942 struct wpa_ssid *ssid)
3943{
3944 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3945 return;
3946
3947 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003948 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003949 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3950 wpas_notify_network_enabled_changed(wpa_s, ssid);
3951
3952 /*
3953 * Try to reassociate since there is no current configuration and a new
3954 * network was made available.
3955 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003956 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003957 wpa_s->reassociate = 1;
3958}
3959
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003960
Roshan Pius950bec92016-07-19 09:49:24 -07003961/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003962 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003963 * @wpa_s: wpa_supplicant structure for a network interface
3964 * Returns: The new network configuration or %NULL if operation failed
3965 *
3966 * This function performs the following operations:
3967 * 1. Adds a new network.
3968 * 2. Send network addition notification.
3969 * 3. Marks the network disabled.
3970 * 4. Set network default parameters.
3971 */
3972struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3973{
3974 struct wpa_ssid *ssid;
3975
3976 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003977 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003978 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003979 wpas_notify_network_added(wpa_s, ssid);
3980 ssid->disabled = 1;
3981 wpa_config_set_network_defaults(ssid);
3982
3983 return ssid;
3984}
3985
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003986
Roshan Pius950bec92016-07-19 09:49:24 -07003987/**
3988 * wpa_supplicant_remove_network - Remove a configured network based on id
3989 * @wpa_s: wpa_supplicant structure for a network interface
3990 * @id: Unique network id to search for
3991 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3992 * could not be removed
3993 *
3994 * This function performs the following operations:
3995 * 1. Removes the network.
3996 * 2. Send network removal notification.
3997 * 3. Update internal state machines.
3998 * 4. Stop any running sched scans.
3999 */
4000int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4001{
4002 struct wpa_ssid *ssid;
4003 int was_disabled;
4004
4005 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004006 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004007 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004008 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004009
4010 if (wpa_s->last_ssid == ssid)
4011 wpa_s->last_ssid = NULL;
4012
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004013 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004014#ifdef CONFIG_SME
4015 wpa_s->sme.prev_bssid_set = 0;
4016#endif /* CONFIG_SME */
4017 /*
4018 * Invalidate the EAP session cache if the current or
4019 * previously used network is removed.
4020 */
4021 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4022 }
4023
4024 if (ssid == wpa_s->current_ssid) {
4025 wpa_sm_set_config(wpa_s->wpa, NULL);
4026 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4027
4028 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4029 wpa_s->own_disconnect_req = 1;
4030 wpa_supplicant_deauthenticate(wpa_s,
4031 WLAN_REASON_DEAUTH_LEAVING);
4032 }
4033
4034 was_disabled = ssid->disabled;
4035
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004036 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004037 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004038
4039 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004040 wpa_printf(MSG_DEBUG,
4041 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004042 wpa_supplicant_cancel_sched_scan(wpa_s);
4043 wpa_supplicant_req_scan(wpa_s, 0, 0);
4044 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004045
Roshan Pius950bec92016-07-19 09:49:24 -07004046 return 0;
4047}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004048
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004049
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004050/**
4051 * wpa_supplicant_enable_network - Mark a configured network as enabled
4052 * @wpa_s: wpa_supplicant structure for a network interface
4053 * @ssid: wpa_ssid structure for a configured network or %NULL
4054 *
4055 * Enables the specified network or all networks if no network specified.
4056 */
4057void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4058 struct wpa_ssid *ssid)
4059{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004060 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004061 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4062 wpa_supplicant_enable_one_network(wpa_s, ssid);
4063 } else
4064 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004065
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004066 if (wpa_s->reassociate && !wpa_s->disconnected &&
4067 (!wpa_s->current_ssid ||
4068 wpa_s->wpa_state == WPA_DISCONNECTED ||
4069 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004070 if (wpa_s->sched_scanning) {
4071 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4072 "new network to scan filters");
4073 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004074 }
4075
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004076 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4077 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004078 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004079 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004080 }
4081}
4082
4083
4084/**
4085 * wpa_supplicant_disable_network - Mark a configured network as disabled
4086 * @wpa_s: wpa_supplicant structure for a network interface
4087 * @ssid: wpa_ssid structure for a configured network or %NULL
4088 *
4089 * Disables the specified network or all networks if no network specified.
4090 */
4091void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4092 struct wpa_ssid *ssid)
4093{
4094 struct wpa_ssid *other_ssid;
4095 int was_disabled;
4096
4097 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004098 if (wpa_s->sched_scanning)
4099 wpa_supplicant_cancel_sched_scan(wpa_s);
4100
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004101 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4102 other_ssid = other_ssid->next) {
4103 was_disabled = other_ssid->disabled;
4104 if (was_disabled == 2)
4105 continue; /* do not change persistent P2P group
4106 * data */
4107
4108 other_ssid->disabled = 1;
4109
4110 if (was_disabled != other_ssid->disabled)
4111 wpas_notify_network_enabled_changed(
4112 wpa_s, other_ssid);
4113 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004114 if (wpa_s->current_ssid) {
4115 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4116 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004117 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004118 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004119 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004120 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004121 if (ssid == wpa_s->current_ssid) {
4122 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4123 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004124 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004125 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004126 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004127
4128 was_disabled = ssid->disabled;
4129
4130 ssid->disabled = 1;
4131
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004132 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004133 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004134 if (wpa_s->sched_scanning) {
4135 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4136 "to remove network from filters");
4137 wpa_supplicant_cancel_sched_scan(wpa_s);
4138 wpa_supplicant_req_scan(wpa_s, 0, 0);
4139 }
4140 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004141 }
4142}
4143
4144
4145/**
4146 * wpa_supplicant_select_network - Attempt association with a network
4147 * @wpa_s: wpa_supplicant structure for a network interface
4148 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4149 */
4150void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4151 struct wpa_ssid *ssid)
4152{
4153
4154 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004155 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004156
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004157 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004158 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4159 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004160 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004161 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004162 disconnected = 1;
4163 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004164
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004165 if (ssid)
4166 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4167
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004168 /*
4169 * Mark all other networks disabled or mark all networks enabled if no
4170 * network specified.
4171 */
4172 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4173 other_ssid = other_ssid->next) {
4174 int was_disabled = other_ssid->disabled;
4175 if (was_disabled == 2)
4176 continue; /* do not change persistent P2P group data */
4177
4178 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004179 if (was_disabled && !other_ssid->disabled)
4180 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004181
4182 if (was_disabled != other_ssid->disabled)
4183 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4184 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004185
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004186 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4187 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004188 /* We are already associated with the selected network */
4189 wpa_printf(MSG_DEBUG, "Already associated with the "
4190 "selected network - do nothing");
4191 return;
4192 }
4193
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004194 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004195 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004196 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004197 wpa_s->connect_without_scan =
4198 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004199
4200 /*
4201 * Don't optimize next scan freqs since a new ESS has been
4202 * selected.
4203 */
4204 os_free(wpa_s->next_scan_freqs);
4205 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004206 } else {
4207 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004208 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004209
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004210 wpa_s->disconnected = 0;
4211 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004212 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004213 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004214 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004215 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004216 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4217 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004218
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004219 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004220 wpa_supplicant_fast_associate(wpa_s) != 1) {
4221 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004222 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004223 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004224 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004225
4226 if (ssid)
4227 wpas_notify_network_selected(wpa_s, ssid);
4228}
4229
4230
4231/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004232 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4233 * @wpa_s: wpa_supplicant structure for a network interface
4234 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4235 * @pkcs11_module_path: PKCS #11 module path or NULL
4236 * Returns: 0 on success; -1 on failure
4237 *
4238 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4239 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4240 * module path fails the paths will be reset to the default value (NULL).
4241 */
4242int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4243 const char *pkcs11_engine_path,
4244 const char *pkcs11_module_path)
4245{
4246 char *pkcs11_engine_path_copy = NULL;
4247 char *pkcs11_module_path_copy = NULL;
4248
4249 if (pkcs11_engine_path != NULL) {
4250 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4251 if (pkcs11_engine_path_copy == NULL)
4252 return -1;
4253 }
4254 if (pkcs11_module_path != NULL) {
4255 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004256 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004257 os_free(pkcs11_engine_path_copy);
4258 return -1;
4259 }
4260 }
4261
4262 os_free(wpa_s->conf->pkcs11_engine_path);
4263 os_free(wpa_s->conf->pkcs11_module_path);
4264 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4265 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4266
4267 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4268 eapol_sm_deinit(wpa_s->eapol);
4269 wpa_s->eapol = NULL;
4270 if (wpa_supplicant_init_eapol(wpa_s)) {
4271 /* Error -> Reset paths to the default value (NULL) once. */
4272 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4273 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4274 NULL);
4275
4276 return -1;
4277 }
4278 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4279
4280 return 0;
4281}
4282
4283
4284/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4286 * @wpa_s: wpa_supplicant structure for a network interface
4287 * @ap_scan: AP scan mode
4288 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4289 *
4290 */
4291int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4292{
4293
4294 int old_ap_scan;
4295
4296 if (ap_scan < 0 || ap_scan > 2)
4297 return -1;
4298
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004299 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4300 wpa_printf(MSG_INFO,
4301 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4302 }
4303
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004304#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004305 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4306 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4307 wpa_s->wpa_state < WPA_COMPLETED) {
4308 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4309 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004310 return 0;
4311 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004312#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004314 old_ap_scan = wpa_s->conf->ap_scan;
4315 wpa_s->conf->ap_scan = ap_scan;
4316
4317 if (old_ap_scan != wpa_s->conf->ap_scan)
4318 wpas_notify_ap_scan_changed(wpa_s);
4319
4320 return 0;
4321}
4322
4323
4324/**
4325 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4326 * @wpa_s: wpa_supplicant structure for a network interface
4327 * @expire_age: Expiration age in seconds
4328 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4329 *
4330 */
4331int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4332 unsigned int bss_expire_age)
4333{
4334 if (bss_expire_age < 10) {
4335 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4336 bss_expire_age);
4337 return -1;
4338 }
4339 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4340 bss_expire_age);
4341 wpa_s->conf->bss_expiration_age = bss_expire_age;
4342
4343 return 0;
4344}
4345
4346
4347/**
4348 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4349 * @wpa_s: wpa_supplicant structure for a network interface
4350 * @expire_count: number of scans after which an unseen BSS is reclaimed
4351 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4352 *
4353 */
4354int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4355 unsigned int bss_expire_count)
4356{
4357 if (bss_expire_count < 1) {
4358 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4359 bss_expire_count);
4360 return -1;
4361 }
4362 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4363 bss_expire_count);
4364 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4365
4366 return 0;
4367}
4368
4369
4370/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004371 * wpa_supplicant_set_scan_interval - Set scan interval
4372 * @wpa_s: wpa_supplicant structure for a network interface
4373 * @scan_interval: scan interval in seconds
4374 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4375 *
4376 */
4377int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4378 int scan_interval)
4379{
4380 if (scan_interval < 0) {
4381 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4382 scan_interval);
4383 return -1;
4384 }
4385 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4386 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004387 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004388
4389 return 0;
4390}
4391
4392
4393/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004394 * wpa_supplicant_set_debug_params - Set global debug params
4395 * @global: wpa_global structure
4396 * @debug_level: debug level
4397 * @debug_timestamp: determines if show timestamp in debug data
4398 * @debug_show_keys: determines if show keys in debug data
4399 * Returns: 0 if succeed or -1 if debug_level has wrong value
4400 */
4401int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4402 int debug_timestamp, int debug_show_keys)
4403{
4404
4405 int old_level, old_timestamp, old_show_keys;
4406
4407 /* check for allowed debuglevels */
4408 if (debug_level != MSG_EXCESSIVE &&
4409 debug_level != MSG_MSGDUMP &&
4410 debug_level != MSG_DEBUG &&
4411 debug_level != MSG_INFO &&
4412 debug_level != MSG_WARNING &&
4413 debug_level != MSG_ERROR)
4414 return -1;
4415
4416 old_level = wpa_debug_level;
4417 old_timestamp = wpa_debug_timestamp;
4418 old_show_keys = wpa_debug_show_keys;
4419
4420 wpa_debug_level = debug_level;
4421 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4422 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4423
4424 if (wpa_debug_level != old_level)
4425 wpas_notify_debug_level_changed(global);
4426 if (wpa_debug_timestamp != old_timestamp)
4427 wpas_notify_debug_timestamp_changed(global);
4428 if (wpa_debug_show_keys != old_show_keys)
4429 wpas_notify_debug_show_keys_changed(global);
4430
4431 return 0;
4432}
4433
4434
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004435#ifdef CONFIG_OWE
4436static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4437 const u8 *entry_ssid, size_t entry_ssid_len)
4438{
4439 const u8 *owe, *pos, *end;
4440 u8 ssid_len;
4441 struct wpa_bss *bss;
4442
4443 /* Check network profile SSID aganst the SSID in the
4444 * OWE Transition Mode element. */
4445
4446 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4447 if (!bss)
4448 return 0;
4449
4450 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4451 if (!owe)
4452 return 0;
4453
4454 pos = owe + 6;
4455 end = owe + 2 + owe[1];
4456
4457 if (end - pos < ETH_ALEN + 1)
4458 return 0;
4459 pos += ETH_ALEN;
4460 ssid_len = *pos++;
4461 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4462 return 0;
4463
4464 return entry_ssid_len == ssid_len &&
4465 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4466}
4467#endif /* CONFIG_OWE */
4468
4469
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004470/**
4471 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4472 * @wpa_s: Pointer to wpa_supplicant data
4473 * Returns: A pointer to the current network structure or %NULL on failure
4474 */
4475struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4476{
4477 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004478 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004479 int res;
4480 size_t ssid_len;
4481 u8 bssid[ETH_ALEN];
4482 int wired;
4483
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004484 res = wpa_drv_get_ssid(wpa_s, ssid);
4485 if (res < 0) {
4486 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4487 "driver");
4488 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004489 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004490 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004491
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004492 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004493 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4494 "driver");
4495 return NULL;
4496 }
4497
4498 wired = wpa_s->conf->ap_scan == 0 &&
4499 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4500
4501 entry = wpa_s->conf->ssid;
4502 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004503 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004504 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004505 (!entry->ssid ||
4506 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4507 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004508 (!entry->bssid_set ||
4509 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4510 return entry;
4511#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004512 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004513 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4514 (entry->ssid == NULL || entry->ssid_len == 0) &&
4515 (!entry->bssid_set ||
4516 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4517 return entry;
4518#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004519
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004520#ifdef CONFIG_OWE
4521 if (!wpas_network_disabled(wpa_s, entry) &&
4522 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4523 entry->ssid_len) &&
4524 (!entry->bssid_set ||
4525 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4526 return entry;
4527#endif /* CONFIG_OWE */
4528
Dmitry Shmidt04949592012-07-19 12:16:46 -07004529 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004530 entry->ssid_len == 0 &&
4531 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4532 return entry;
4533
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004534 entry = entry->next;
4535 }
4536
4537 return NULL;
4538}
4539
4540
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004541static int select_driver(struct wpa_supplicant *wpa_s, int i)
4542{
4543 struct wpa_global *global = wpa_s->global;
4544
4545 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004546 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004547 if (global->drv_priv[i] == NULL) {
4548 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4549 "'%s'", wpa_drivers[i]->name);
4550 return -1;
4551 }
4552 }
4553
4554 wpa_s->driver = wpa_drivers[i];
4555 wpa_s->global_drv_priv = global->drv_priv[i];
4556
4557 return 0;
4558}
4559
4560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004561static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4562 const char *name)
4563{
4564 int i;
4565 size_t len;
4566 const char *pos, *driver = name;
4567
4568 if (wpa_s == NULL)
4569 return -1;
4570
4571 if (wpa_drivers[0] == NULL) {
4572 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4573 "wpa_supplicant");
4574 return -1;
4575 }
4576
4577 if (name == NULL) {
4578 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004579 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004580 }
4581
4582 do {
4583 pos = os_strchr(driver, ',');
4584 if (pos)
4585 len = pos - driver;
4586 else
4587 len = os_strlen(driver);
4588
4589 for (i = 0; wpa_drivers[i]; i++) {
4590 if (os_strlen(wpa_drivers[i]->name) == len &&
4591 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004592 0) {
4593 /* First driver that succeeds wins */
4594 if (select_driver(wpa_s, i) == 0)
4595 return 0;
4596 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004597 }
4598
4599 driver = pos + 1;
4600 } while (pos);
4601
4602 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4603 return -1;
4604}
4605
4606
4607/**
4608 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4609 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4610 * with struct wpa_driver_ops::init()
4611 * @src_addr: Source address of the EAPOL frame
4612 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4613 * @len: Length of the EAPOL data
4614 *
4615 * This function is called for each received EAPOL frame. Most driver
4616 * interfaces rely on more generic OS mechanism for receiving frames through
4617 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4618 * take care of received EAPOL frames and deliver them to the core supplicant
4619 * code by calling this function.
4620 */
4621void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4622 const u8 *buf, size_t len)
4623{
4624 struct wpa_supplicant *wpa_s = ctx;
4625
4626 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4627 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4628
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004629#ifdef CONFIG_TESTING_OPTIONS
4630 if (wpa_s->ignore_auth_resp) {
4631 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4632 return;
4633 }
4634#endif /* CONFIG_TESTING_OPTIONS */
4635
Jouni Malinena05074c2012-12-21 21:35:35 +02004636 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4637 (wpa_s->last_eapol_matches_bssid &&
4638#ifdef CONFIG_AP
4639 !wpa_s->ap_iface &&
4640#endif /* CONFIG_AP */
4641 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642 /*
4643 * There is possible race condition between receiving the
4644 * association event and the EAPOL frame since they are coming
4645 * through different paths from the driver. In order to avoid
4646 * issues in trying to process the EAPOL frame before receiving
4647 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004648 * the association event is received. This may also be needed in
4649 * driver-based roaming case, so also use src_addr != BSSID as a
4650 * trigger if we have previously confirmed that the
4651 * Authenticator uses BSSID as the src_addr (which is not the
4652 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004653 */
4654 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004655 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4656 wpa_supplicant_state_txt(wpa_s->wpa_state),
4657 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004658 wpabuf_free(wpa_s->pending_eapol_rx);
4659 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4660 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004661 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004662 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4663 ETH_ALEN);
4664 }
4665 return;
4666 }
4667
Jouni Malinena05074c2012-12-21 21:35:35 +02004668 wpa_s->last_eapol_matches_bssid =
4669 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4670
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004671#ifdef CONFIG_AP
4672 if (wpa_s->ap_iface) {
4673 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4674 return;
4675 }
4676#endif /* CONFIG_AP */
4677
4678 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4679 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4680 "no key management is configured");
4681 return;
4682 }
4683
4684 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004685 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004686 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4687 wpa_s->wpa_state != WPA_COMPLETED) &&
4688 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004689 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004690 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004691 int timeout = 10;
4692
4693 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4694 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4695 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4696 /* Use longer timeout for IEEE 802.1X/EAP */
4697 timeout = 70;
4698 }
4699
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004700#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004701 if (wpa_s->current_ssid && wpa_s->current_bss &&
4702 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4703 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4704 /*
4705 * Use shorter timeout if going through WPS AP iteration
4706 * for PIN config method with an AP that does not
4707 * advertise Selected Registrar.
4708 */
4709 struct wpabuf *wps_ie;
4710
4711 wps_ie = wpa_bss_get_vendor_ie_multi(
4712 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4713 if (wps_ie &&
4714 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4715 timeout = 10;
4716 wpabuf_free(wps_ie);
4717 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004718#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004719
4720 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004721 }
4722 wpa_s->eapol_received++;
4723
4724 if (wpa_s->countermeasures) {
4725 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4726 "EAPOL packet");
4727 return;
4728 }
4729
4730#ifdef CONFIG_IBSS_RSN
4731 if (wpa_s->current_ssid &&
4732 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4733 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4734 return;
4735 }
4736#endif /* CONFIG_IBSS_RSN */
4737
4738 /* Source address of the incoming EAPOL frame could be compared to the
4739 * current BSSID. However, it is possible that a centralized
4740 * Authenticator could be using another MAC address than the BSSID of
4741 * an AP, so just allow any address to be used for now. The replies are
4742 * still sent to the current BSSID (if available), though. */
4743
4744 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4745 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004746 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4747 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004748 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4749 return;
4750 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004751 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004752 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4753 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4754 /*
4755 * Set portValid = TRUE here since we are going to skip 4-way
4756 * handshake processing which would normally set portValid. We
4757 * need this to allow the EAPOL state machines to be completed
4758 * without going through EAPOL-Key handshake.
4759 */
4760 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
4761 }
4762}
4763
4764
Hai Shalomb755a2a2020-04-23 21:49:02 -07004765static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
4766{
4767 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
4768 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
4769}
4770
4771
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004772int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004773{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004774 if ((!wpa_s->p2p_mgmt ||
4775 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4776 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004777 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004778 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4779 wpa_drv_get_mac_addr(wpa_s),
4780 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07004781 wpas_eapol_needs_l2_packet(wpa_s) ?
4782 wpa_supplicant_rx_eapol : NULL,
4783 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004784 if (wpa_s->l2 == NULL)
4785 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004786
4787 if (l2_packet_set_packet_filter(wpa_s->l2,
4788 L2_PACKET_FILTER_PKTTYPE))
4789 wpa_dbg(wpa_s, MSG_DEBUG,
4790 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07004791
4792 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4793 wpa_msg(wpa_s, MSG_ERROR,
4794 "Failed to get own L2 address");
4795 return -1;
4796 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004797 } else {
4798 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4799 if (addr)
4800 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4801 }
4802
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004803 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004804 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004805
Hai Shalomc3565922019-10-28 11:58:20 -07004806#ifdef CONFIG_FST
4807 if (wpa_s->fst)
4808 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4809#endif /* CONFIG_FST */
4810
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004811 return 0;
4812}
4813
4814
Dmitry Shmidt04949592012-07-19 12:16:46 -07004815static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4816 const u8 *buf, size_t len)
4817{
4818 struct wpa_supplicant *wpa_s = ctx;
4819 const struct l2_ethhdr *eth;
4820
4821 if (len < sizeof(*eth))
4822 return;
4823 eth = (const struct l2_ethhdr *) buf;
4824
4825 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4826 !(eth->h_dest[0] & 0x01)) {
4827 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4828 " (bridge - not for this interface - ignore)",
4829 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4830 return;
4831 }
4832
4833 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4834 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4835 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4836 len - sizeof(*eth));
4837}
4838
4839
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004840/**
4841 * wpa_supplicant_driver_init - Initialize driver interface parameters
4842 * @wpa_s: Pointer to wpa_supplicant data
4843 * Returns: 0 on success, -1 on failure
4844 *
4845 * This function is called to initialize driver interface parameters.
4846 * wpa_drv_init() must have been called before this function to initialize the
4847 * driver interface.
4848 */
4849int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4850{
4851 static int interface_count = 0;
4852
4853 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4854 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004855
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004856 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4857 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004858 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004859 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4860
Hai Shalomb755a2a2020-04-23 21:49:02 -07004861 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004862 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4863 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004864 wpa_s->l2_br = l2_packet_init_bridge(
4865 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4866 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004867 if (wpa_s->l2_br == NULL) {
4868 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4869 "connection for the bridge interface '%s'",
4870 wpa_s->bridge_ifname);
4871 return -1;
4872 }
4873 }
4874
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004875 if (wpa_s->conf->ap_scan == 2 &&
4876 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4877 wpa_printf(MSG_INFO,
4878 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4879 }
4880
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004881 wpa_clear_keys(wpa_s, NULL);
4882
4883 /* Make sure that TKIP countermeasures are not left enabled (could
4884 * happen if wpa_supplicant is killed during countermeasures. */
4885 wpa_drv_set_countermeasures(wpa_s, 0);
4886
4887 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4888 wpa_drv_flush_pmkid(wpa_s);
4889
4890 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004891 wpa_s->prev_scan_wildcard = 0;
4892
Dmitry Shmidt04949592012-07-19 12:16:46 -07004893 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004894 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4895 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4896 interface_count = 0;
4897 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004898#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004899 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004900 wpa_supplicant_delayed_sched_scan(wpa_s,
4901 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004902 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004903 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004904 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004905#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004906 interface_count++;
4907 } else
4908 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4909
4910 return 0;
4911}
4912
4913
4914static int wpa_supplicant_daemon(const char *pid_file)
4915{
4916 wpa_printf(MSG_DEBUG, "Daemonize..");
4917 return os_daemonize(pid_file);
4918}
4919
4920
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004921static struct wpa_supplicant *
4922wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004923{
4924 struct wpa_supplicant *wpa_s;
4925
4926 wpa_s = os_zalloc(sizeof(*wpa_s));
4927 if (wpa_s == NULL)
4928 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004929 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004930 wpa_s->scan_interval = 5;
4931 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004932 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004933 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004934 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004935
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004936 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004937 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07004938#ifdef CONFIG_TESTING_OPTIONS
4939 dl_list_init(&wpa_s->drv_signal_override);
4940#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004941
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004942 return wpa_s;
4943}
4944
4945
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004946#ifdef CONFIG_HT_OVERRIDES
4947
4948static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4949 struct ieee80211_ht_capabilities *htcaps,
4950 struct ieee80211_ht_capabilities *htcaps_mask,
4951 const char *ht_mcs)
4952{
4953 /* parse ht_mcs into hex array */
4954 int i;
4955 const char *tmp = ht_mcs;
4956 char *end = NULL;
4957
4958 /* If ht_mcs is null, do not set anything */
4959 if (!ht_mcs)
4960 return 0;
4961
4962 /* This is what we are setting in the kernel */
4963 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4964
4965 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4966
4967 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004968 long v;
4969
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004970 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004971 v = strtol(tmp, &end, 16);
4972
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004973 if (errno == 0) {
4974 wpa_msg(wpa_s, MSG_DEBUG,
4975 "htcap value[%i]: %ld end: %p tmp: %p",
4976 i, v, end, tmp);
4977 if (end == tmp)
4978 break;
4979
4980 htcaps->supported_mcs_set[i] = v;
4981 tmp = end;
4982 } else {
4983 wpa_msg(wpa_s, MSG_ERROR,
4984 "Failed to parse ht-mcs: %s, error: %s\n",
4985 ht_mcs, strerror(errno));
4986 return -1;
4987 }
4988 }
4989
4990 /*
4991 * If we were able to parse any values, then set mask for the MCS set.
4992 */
4993 if (i) {
4994 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4995 IEEE80211_HT_MCS_MASK_LEN - 1);
4996 /* skip the 3 reserved bits */
4997 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4998 0x1f;
4999 }
5000
5001 return 0;
5002}
5003
5004
5005static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5006 struct ieee80211_ht_capabilities *htcaps,
5007 struct ieee80211_ht_capabilities *htcaps_mask,
5008 int disabled)
5009{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005010 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005011
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005012 if (disabled == -1)
5013 return 0;
5014
Hai Shalom74f70d42019-02-11 14:42:39 -08005015 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5016
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005017 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5018 htcaps_mask->ht_capabilities_info |= msk;
5019 if (disabled)
5020 htcaps->ht_capabilities_info &= msk;
5021 else
5022 htcaps->ht_capabilities_info |= msk;
5023
5024 return 0;
5025}
5026
5027
5028static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5029 struct ieee80211_ht_capabilities *htcaps,
5030 struct ieee80211_ht_capabilities *htcaps_mask,
5031 int factor)
5032{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005033 if (factor == -1)
5034 return 0;
5035
Hai Shalom74f70d42019-02-11 14:42:39 -08005036 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5037
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005038 if (factor < 0 || factor > 3) {
5039 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5040 "Must be 0-3 or -1", factor);
5041 return -EINVAL;
5042 }
5043
5044 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5045 htcaps->a_mpdu_params &= ~0x3;
5046 htcaps->a_mpdu_params |= factor & 0x3;
5047
5048 return 0;
5049}
5050
5051
5052static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5053 struct ieee80211_ht_capabilities *htcaps,
5054 struct ieee80211_ht_capabilities *htcaps_mask,
5055 int density)
5056{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005057 if (density == -1)
5058 return 0;
5059
Hai Shalom74f70d42019-02-11 14:42:39 -08005060 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5061
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005062 if (density < 0 || density > 7) {
5063 wpa_msg(wpa_s, MSG_ERROR,
5064 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5065 density);
5066 return -EINVAL;
5067 }
5068
5069 htcaps_mask->a_mpdu_params |= 0x1C;
5070 htcaps->a_mpdu_params &= ~(0x1C);
5071 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5072
5073 return 0;
5074}
5075
5076
5077static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5078 struct ieee80211_ht_capabilities *htcaps,
5079 struct ieee80211_ht_capabilities *htcaps_mask,
5080 int disabled)
5081{
Hai Shalom74f70d42019-02-11 14:42:39 -08005082 if (disabled)
5083 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005084
Paul Stewart092955c2017-02-06 09:13:09 -08005085 set_disable_ht40(htcaps, disabled);
5086 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005087
5088 return 0;
5089}
5090
5091
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005092static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5093 struct ieee80211_ht_capabilities *htcaps,
5094 struct ieee80211_ht_capabilities *htcaps_mask,
5095 int disabled)
5096{
5097 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005098 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5099 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005100
Hai Shalom74f70d42019-02-11 14:42:39 -08005101 if (disabled)
5102 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005103
5104 if (disabled)
5105 htcaps->ht_capabilities_info &= ~msk;
5106 else
5107 htcaps->ht_capabilities_info |= msk;
5108
5109 htcaps_mask->ht_capabilities_info |= msk;
5110
5111 return 0;
5112}
5113
5114
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005115static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5116 struct ieee80211_ht_capabilities *htcaps,
5117 struct ieee80211_ht_capabilities *htcaps_mask,
5118 int disabled)
5119{
5120 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005121 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005122
Hai Shalom74f70d42019-02-11 14:42:39 -08005123 if (disabled)
5124 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005125
5126 if (disabled)
5127 htcaps->ht_capabilities_info &= ~msk;
5128 else
5129 htcaps->ht_capabilities_info |= msk;
5130
5131 htcaps_mask->ht_capabilities_info |= msk;
5132
5133 return 0;
5134}
5135
5136
Hai Shalom74f70d42019-02-11 14:42:39 -08005137static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5138 struct ieee80211_ht_capabilities *htcaps,
5139 struct ieee80211_ht_capabilities *htcaps_mask,
5140 int tx_stbc)
5141{
5142 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5143
5144 if (tx_stbc == -1)
5145 return 0;
5146
5147 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5148
5149 if (tx_stbc < 0 || tx_stbc > 1) {
5150 wpa_msg(wpa_s, MSG_ERROR,
5151 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5152 return -EINVAL;
5153 }
5154
5155 htcaps_mask->ht_capabilities_info |= msk;
5156 htcaps->ht_capabilities_info &= ~msk;
5157 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5158
5159 return 0;
5160}
5161
5162
5163static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5164 struct ieee80211_ht_capabilities *htcaps,
5165 struct ieee80211_ht_capabilities *htcaps_mask,
5166 int rx_stbc)
5167{
5168 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5169
5170 if (rx_stbc == -1)
5171 return 0;
5172
5173 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5174
5175 if (rx_stbc < 0 || rx_stbc > 3) {
5176 wpa_msg(wpa_s, MSG_ERROR,
5177 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5178 return -EINVAL;
5179 }
5180
5181 htcaps_mask->ht_capabilities_info |= msk;
5182 htcaps->ht_capabilities_info &= ~msk;
5183 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5184
5185 return 0;
5186}
5187
5188
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005189void wpa_supplicant_apply_ht_overrides(
5190 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5191 struct wpa_driver_associate_params *params)
5192{
5193 struct ieee80211_ht_capabilities *htcaps;
5194 struct ieee80211_ht_capabilities *htcaps_mask;
5195
5196 if (!ssid)
5197 return;
5198
5199 params->disable_ht = ssid->disable_ht;
5200 if (!params->htcaps || !params->htcaps_mask)
5201 return;
5202
5203 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5204 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5205 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5206 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5207 ssid->disable_max_amsdu);
5208 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5209 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5210 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005211 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005212 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005213 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5214 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005215
5216 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005217 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005218 htcaps->ht_capabilities_info |= bit;
5219 htcaps_mask->ht_capabilities_info |= bit;
5220 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005221}
5222
5223#endif /* CONFIG_HT_OVERRIDES */
5224
5225
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005226#ifdef CONFIG_VHT_OVERRIDES
5227void wpa_supplicant_apply_vht_overrides(
5228 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5229 struct wpa_driver_associate_params *params)
5230{
5231 struct ieee80211_vht_capabilities *vhtcaps;
5232 struct ieee80211_vht_capabilities *vhtcaps_mask;
5233
5234 if (!ssid)
5235 return;
5236
5237 params->disable_vht = ssid->disable_vht;
5238
5239 vhtcaps = (void *) params->vhtcaps;
5240 vhtcaps_mask = (void *) params->vhtcaps_mask;
5241
5242 if (!vhtcaps || !vhtcaps_mask)
5243 return;
5244
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005245 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5246 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005247
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005248#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005249 if (ssid->disable_sgi) {
5250 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5251 VHT_CAP_SHORT_GI_160);
5252 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5253 VHT_CAP_SHORT_GI_160);
5254 wpa_msg(wpa_s, MSG_DEBUG,
5255 "disable-sgi override specified, vht-caps: 0x%x",
5256 vhtcaps->vht_capabilities_info);
5257 }
5258
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005259 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005260 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5261 int max_ampdu;
5262
5263 max_ampdu = (ssid->vht_capa &
5264 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5265 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005266
5267 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5268 wpa_set_ampdu_factor(wpa_s,
5269 (void *) params->htcaps,
5270 (void *) params->htcaps_mask,
5271 max_ampdu);
5272 }
5273#endif /* CONFIG_HT_OVERRIDES */
5274
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005275#define OVERRIDE_MCS(i) \
5276 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5277 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005278 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005279 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005280 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5281 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005282 } \
5283 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5284 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005285 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005286 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005287 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5288 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005289 }
5290
5291 OVERRIDE_MCS(1);
5292 OVERRIDE_MCS(2);
5293 OVERRIDE_MCS(3);
5294 OVERRIDE_MCS(4);
5295 OVERRIDE_MCS(5);
5296 OVERRIDE_MCS(6);
5297 OVERRIDE_MCS(7);
5298 OVERRIDE_MCS(8);
5299}
5300#endif /* CONFIG_VHT_OVERRIDES */
5301
5302
Hai Shalomfdcde762020-04-02 11:19:20 -07005303#ifdef CONFIG_HE_OVERRIDES
5304void wpa_supplicant_apply_he_overrides(
5305 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5306 struct wpa_driver_associate_params *params)
5307{
5308 if (!ssid)
5309 return;
5310
5311 params->disable_he = ssid->disable_he;
5312}
5313#endif /* CONFIG_HE_OVERRIDES */
5314
5315
Dmitry Shmidt04949592012-07-19 12:16:46 -07005316static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5317{
5318#ifdef PCSC_FUNCS
5319 size_t len;
5320
5321 if (!wpa_s->conf->pcsc_reader)
5322 return 0;
5323
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005324 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005325 if (!wpa_s->scard)
5326 return 1;
5327
5328 if (wpa_s->conf->pcsc_pin &&
5329 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5330 scard_deinit(wpa_s->scard);
5331 wpa_s->scard = NULL;
5332 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5333 return -1;
5334 }
5335
5336 len = sizeof(wpa_s->imsi) - 1;
5337 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5338 scard_deinit(wpa_s->scard);
5339 wpa_s->scard = NULL;
5340 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5341 return -1;
5342 }
5343 wpa_s->imsi[len] = '\0';
5344
5345 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5346
5347 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5348 wpa_s->imsi, wpa_s->mnc_len);
5349
5350 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5351 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5352#endif /* PCSC_FUNCS */
5353
5354 return 0;
5355}
5356
5357
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005358int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5359{
5360 char *val, *pos;
5361
5362 ext_password_deinit(wpa_s->ext_pw);
5363 wpa_s->ext_pw = NULL;
5364 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5365
5366 if (!wpa_s->conf->ext_password_backend)
5367 return 0;
5368
5369 val = os_strdup(wpa_s->conf->ext_password_backend);
5370 if (val == NULL)
5371 return -1;
5372 pos = os_strchr(val, ':');
5373 if (pos)
5374 *pos++ = '\0';
5375
5376 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5377
5378 wpa_s->ext_pw = ext_password_init(val, pos);
5379 os_free(val);
5380 if (wpa_s->ext_pw == NULL) {
5381 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5382 return -1;
5383 }
5384 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5385
5386 return 0;
5387}
5388
5389
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005390#ifdef CONFIG_FST
5391
5392static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5393{
5394 struct wpa_supplicant *wpa_s = ctx;
5395
5396 return (is_zero_ether_addr(wpa_s->bssid) ||
5397 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5398}
5399
5400
5401static void wpas_fst_get_channel_info_cb(void *ctx,
5402 enum hostapd_hw_mode *hw_mode,
5403 u8 *channel)
5404{
5405 struct wpa_supplicant *wpa_s = ctx;
5406
5407 if (wpa_s->current_bss) {
5408 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5409 channel);
5410 } else if (wpa_s->hw.num_modes) {
5411 *hw_mode = wpa_s->hw.modes[0].mode;
5412 } else {
5413 WPA_ASSERT(0);
5414 *hw_mode = 0;
5415 }
5416}
5417
5418
5419static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5420{
5421 struct wpa_supplicant *wpa_s = ctx;
5422
5423 *modes = wpa_s->hw.modes;
5424 return wpa_s->hw.num_modes;
5425}
5426
5427
5428static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5429{
5430 struct wpa_supplicant *wpa_s = ctx;
5431
5432 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5433 wpa_s->fst_ies = fst_ies;
5434}
5435
5436
5437static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5438{
5439 struct wpa_supplicant *wpa_s = ctx;
5440
Paul Stewart092955c2017-02-06 09:13:09 -08005441 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5442 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5443 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5444 return -1;
5445 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005446 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005447 wpa_s->own_addr, wpa_s->bssid,
5448 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005449 0);
5450}
5451
5452
5453static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5454{
5455 struct wpa_supplicant *wpa_s = ctx;
5456
5457 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5458 return wpa_s->received_mb_ies;
5459}
5460
5461
5462static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5463 const u8 *buf, size_t size)
5464{
5465 struct wpa_supplicant *wpa_s = ctx;
5466 struct mb_ies_info info;
5467
5468 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5469
5470 if (!mb_ies_info_by_ies(&info, buf, size)) {
5471 wpabuf_free(wpa_s->received_mb_ies);
5472 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5473 }
5474}
5475
5476
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005477static const u8 * wpas_fst_get_peer_first(void *ctx,
5478 struct fst_get_peer_ctx **get_ctx,
5479 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005480{
5481 struct wpa_supplicant *wpa_s = ctx;
5482
5483 *get_ctx = NULL;
5484 if (!is_zero_ether_addr(wpa_s->bssid))
5485 return (wpa_s->received_mb_ies || !mb_only) ?
5486 wpa_s->bssid : NULL;
5487 return NULL;
5488}
5489
5490
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005491static const u8 * wpas_fst_get_peer_next(void *ctx,
5492 struct fst_get_peer_ctx **get_ctx,
5493 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005494{
5495 return NULL;
5496}
5497
5498void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5499 struct fst_wpa_obj *iface_obj)
5500{
5501 iface_obj->ctx = wpa_s;
5502 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5503 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5504 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5505 iface_obj->set_ies = wpas_fst_set_ies_cb;
5506 iface_obj->send_action = wpas_fst_send_action_cb;
5507 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5508 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5509 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5510 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5511}
5512#endif /* CONFIG_FST */
5513
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005514static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005515 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005516{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005517 struct wowlan_triggers *triggers;
5518 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005519
5520 if (!wpa_s->conf->wowlan_triggers)
5521 return 0;
5522
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005523 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5524 if (triggers) {
5525 ret = wpa_drv_wowlan(wpa_s, triggers);
5526 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005527 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005528 return ret;
5529}
5530
5531
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005532enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005533{
5534 if (freq < 3000)
5535 return BAND_2_4_GHZ;
5536 if (freq > 50000)
5537 return BAND_60_GHZ;
5538 return BAND_5_GHZ;
5539}
5540
5541
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005542unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005543{
5544 int i;
5545 unsigned int band = 0;
5546
5547 if (freqs) {
5548 /* freqs are specified for the radio work */
5549 for (i = 0; freqs[i]; i++)
5550 band |= wpas_freq_to_band(freqs[i]);
5551 } else {
5552 /*
5553 * freqs are not specified, implies all
5554 * the supported freqs by HW
5555 */
5556 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5557 if (wpa_s->hw.modes[i].num_channels != 0) {
5558 if (wpa_s->hw.modes[i].mode ==
5559 HOSTAPD_MODE_IEEE80211B ||
5560 wpa_s->hw.modes[i].mode ==
5561 HOSTAPD_MODE_IEEE80211G)
5562 band |= BAND_2_4_GHZ;
5563 else if (wpa_s->hw.modes[i].mode ==
5564 HOSTAPD_MODE_IEEE80211A)
5565 band |= BAND_5_GHZ;
5566 else if (wpa_s->hw.modes[i].mode ==
5567 HOSTAPD_MODE_IEEE80211AD)
5568 band |= BAND_60_GHZ;
5569 else if (wpa_s->hw.modes[i].mode ==
5570 HOSTAPD_MODE_IEEE80211ANY)
5571 band = BAND_2_4_GHZ | BAND_5_GHZ |
5572 BAND_60_GHZ;
5573 }
5574 }
5575 }
5576
5577 return band;
5578}
5579
5580
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005581static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5582 const char *rn)
5583{
5584 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5585 struct wpa_radio *radio;
5586
5587 while (rn && iface) {
5588 radio = iface->radio;
5589 if (radio && os_strcmp(rn, radio->name) == 0) {
5590 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5591 wpa_s->ifname, rn);
5592 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5593 return radio;
5594 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005595
5596 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005597 }
5598
5599 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5600 wpa_s->ifname, rn ? rn : "N/A");
5601 radio = os_zalloc(sizeof(*radio));
5602 if (radio == NULL)
5603 return NULL;
5604
5605 if (rn)
5606 os_strlcpy(radio->name, rn, sizeof(radio->name));
5607 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005608 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005609 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5610
5611 return radio;
5612}
5613
5614
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005615static void radio_work_free(struct wpa_radio_work *work)
5616{
5617 if (work->wpa_s->scan_work == work) {
5618 /* This should not really happen. */
5619 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5620 work->type, work, work->started);
5621 work->wpa_s->scan_work = NULL;
5622 }
5623
5624#ifdef CONFIG_P2P
5625 if (work->wpa_s->p2p_scan_work == work) {
5626 /* This should not really happen. */
5627 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5628 work->type, work, work->started);
5629 work->wpa_s->p2p_scan_work = NULL;
5630 }
5631#endif /* CONFIG_P2P */
5632
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005633 if (work->started) {
5634 work->wpa_s->radio->num_active_works--;
5635 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005636 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005637 work->type, work,
5638 work->wpa_s->radio->num_active_works);
5639 }
5640
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005641 dl_list_del(&work->list);
5642 os_free(work);
5643}
5644
5645
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005646static int radio_work_is_connect(struct wpa_radio_work *work)
5647{
5648 return os_strcmp(work->type, "sme-connect") == 0 ||
5649 os_strcmp(work->type, "connect") == 0;
5650}
5651
5652
5653static int radio_work_is_scan(struct wpa_radio_work *work)
5654{
5655 return os_strcmp(work->type, "scan") == 0 ||
5656 os_strcmp(work->type, "p2p-scan") == 0;
5657}
5658
5659
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005660static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5661{
5662 struct wpa_radio_work *active_work = NULL;
5663 struct wpa_radio_work *tmp;
5664
5665 /* Get the active work to know the type and band. */
5666 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5667 if (tmp->started) {
5668 active_work = tmp;
5669 break;
5670 }
5671 }
5672
5673 if (!active_work) {
5674 /* No active work, start one */
5675 radio->num_active_works = 0;
5676 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5677 list) {
5678 if (os_strcmp(tmp->type, "scan") == 0 &&
5679 radio->external_scan_running &&
5680 (((struct wpa_driver_scan_params *)
5681 tmp->ctx)->only_new_results ||
5682 tmp->wpa_s->clear_driver_scan_cache))
5683 continue;
5684 return tmp;
5685 }
5686 return NULL;
5687 }
5688
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005689 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005690 /*
5691 * If the active work is either connect or sme-connect,
5692 * do not parallelize them with other radio works.
5693 */
5694 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5695 "Do not parallelize radio work with %s",
5696 active_work->type);
5697 return NULL;
5698 }
5699
5700 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5701 if (tmp->started)
5702 continue;
5703
5704 /*
5705 * If connect or sme-connect are enqueued, parallelize only
5706 * those operations ahead of them in the queue.
5707 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005708 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005709 break;
5710
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005711 /* Serialize parallel scan and p2p_scan operations on the same
5712 * interface since the driver_nl80211 mechanism for tracking
5713 * scan cookies does not yet have support for this. */
5714 if (active_work->wpa_s == tmp->wpa_s &&
5715 radio_work_is_scan(active_work) &&
5716 radio_work_is_scan(tmp)) {
5717 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5718 "Do not start work '%s' when another work '%s' is already scheduled",
5719 tmp->type, active_work->type);
5720 continue;
5721 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005722 /*
5723 * Check that the radio works are distinct and
5724 * on different bands.
5725 */
5726 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5727 (active_work->bands != tmp->bands)) {
5728 /*
5729 * If a scan has to be scheduled through nl80211 scan
5730 * interface and if an external scan is already running,
5731 * do not schedule the scan since it is likely to get
5732 * rejected by kernel.
5733 */
5734 if (os_strcmp(tmp->type, "scan") == 0 &&
5735 radio->external_scan_running &&
5736 (((struct wpa_driver_scan_params *)
5737 tmp->ctx)->only_new_results ||
5738 tmp->wpa_s->clear_driver_scan_cache))
5739 continue;
5740
5741 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5742 "active_work:%s new_work:%s",
5743 active_work->type, tmp->type);
5744 return tmp;
5745 }
5746 }
5747
5748 /* Did not find a radio work to schedule in parallel. */
5749 return NULL;
5750}
5751
5752
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005753static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5754{
5755 struct wpa_radio *radio = eloop_ctx;
5756 struct wpa_radio_work *work;
5757 struct os_reltime now, diff;
5758 struct wpa_supplicant *wpa_s;
5759
5760 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005761 if (work == NULL) {
5762 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005763 return;
5764 }
5765
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005766 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5767 radio_list);
5768
5769 if (!(wpa_s &&
5770 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5771 if (work->started)
5772 return; /* already started and still in progress */
5773
5774 if (wpa_s && wpa_s->radio->external_scan_running) {
5775 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5776 return;
5777 }
5778 } else {
5779 work = NULL;
5780 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5781 /* get the work to schedule next */
5782 work = radio_work_get_next_work(radio);
5783 }
5784 if (!work)
5785 return;
5786 }
5787
5788 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005789 os_get_reltime(&now);
5790 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005791 wpa_dbg(wpa_s, MSG_DEBUG,
5792 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005793 work->type, work, diff.sec, diff.usec);
5794 work->started = 1;
5795 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005796 radio->num_active_works++;
5797
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005798 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005799
5800 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5801 radio->num_active_works < MAX_ACTIVE_WORKS)
5802 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005803}
5804
5805
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005806/*
5807 * This function removes both started and pending radio works running on
5808 * the provided interface's radio.
5809 * Prior to the removal of the radio work, its callback (cb) is called with
5810 * deinit set to be 1. Each work's callback is responsible for clearing its
5811 * internal data and restoring to a correct state.
5812 * @wpa_s: wpa_supplicant data
5813 * @type: type of works to be removed
5814 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5815 * this interface's works.
5816 */
5817void radio_remove_works(struct wpa_supplicant *wpa_s,
5818 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005819{
5820 struct wpa_radio_work *work, *tmp;
5821 struct wpa_radio *radio = wpa_s->radio;
5822
5823 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5824 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005825 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005826 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005827
5828 /* skip other ifaces' works */
5829 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005830 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005831
5832 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5833 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005834 work->cb(work, 1);
5835 radio_work_free(work);
5836 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005837
5838 /* in case we removed the started work */
5839 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005840}
5841
5842
Roshan Pius3a1667e2018-07-03 15:17:14 -07005843void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5844{
5845 struct wpa_radio_work *work;
5846 struct wpa_radio *radio = wpa_s->radio;
5847
5848 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5849 if (work->ctx != ctx)
5850 continue;
5851 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5852 work->type, work, work->started ? " (started)" : "");
5853 radio_work_free(work);
5854 break;
5855 }
5856}
5857
5858
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005859static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5860{
5861 struct wpa_radio *radio = wpa_s->radio;
5862
5863 if (!radio)
5864 return;
5865
5866 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5867 wpa_s->ifname, radio->name);
5868 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005869 radio_remove_works(wpa_s, NULL, 0);
5870 wpa_s->radio = NULL;
5871 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005872 return; /* Interfaces remain for this radio */
5873
5874 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005875 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005876 os_free(radio);
5877}
5878
5879
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005880void radio_work_check_next(struct wpa_supplicant *wpa_s)
5881{
5882 struct wpa_radio *radio = wpa_s->radio;
5883
5884 if (dl_list_empty(&radio->work))
5885 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005886 if (wpa_s->ext_work_in_progress) {
5887 wpa_printf(MSG_DEBUG,
5888 "External radio work in progress - delay start of pending item");
5889 return;
5890 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005891 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5892 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5893}
5894
5895
5896/**
5897 * radio_add_work - Add a radio work item
5898 * @wpa_s: Pointer to wpa_supplicant data
5899 * @freq: Frequency of the offchannel operation in MHz or 0
5900 * @type: Unique identifier for each type of work
5901 * @next: Force as the next work to be executed
5902 * @cb: Callback function for indicating when radio is available
5903 * @ctx: Context pointer for the work (work->ctx in cb())
5904 * Returns: 0 on success, -1 on failure
5905 *
5906 * This function is used to request time for an operation that requires
5907 * exclusive radio control. Once the radio is available, the registered callback
5908 * function will be called. radio_work_done() must be called once the exclusive
5909 * radio operation has been completed, so that the radio is freed for other
5910 * operations. The special case of deinit=1 is used to free the context data
5911 * during interface removal. That does not allow the callback function to start
5912 * the radio operation, i.e., it must free any resources allocated for the radio
5913 * work and return.
5914 *
5915 * The @freq parameter can be used to indicate a single channel on which the
5916 * offchannel operation will occur. This may allow multiple radio work
5917 * operations to be performed in parallel if they apply for the same channel.
5918 * Setting this to 0 indicates that the work item may use multiple channels or
5919 * requires exclusive control of the radio.
5920 */
5921int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5922 const char *type, int next,
5923 void (*cb)(struct wpa_radio_work *work, int deinit),
5924 void *ctx)
5925{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005926 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005927 struct wpa_radio_work *work;
5928 int was_empty;
5929
5930 work = os_zalloc(sizeof(*work));
5931 if (work == NULL)
5932 return -1;
5933 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5934 os_get_reltime(&work->time);
5935 work->freq = freq;
5936 work->type = type;
5937 work->wpa_s = wpa_s;
5938 work->cb = cb;
5939 work->ctx = ctx;
5940
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005941 if (freq)
5942 work->bands = wpas_freq_to_band(freq);
5943 else if (os_strcmp(type, "scan") == 0 ||
5944 os_strcmp(type, "p2p-scan") == 0)
5945 work->bands = wpas_get_bands(wpa_s,
5946 ((struct wpa_driver_scan_params *)
5947 ctx)->freqs);
5948 else
5949 work->bands = wpas_get_bands(wpa_s, NULL);
5950
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005951 was_empty = dl_list_empty(&wpa_s->radio->work);
5952 if (next)
5953 dl_list_add(&wpa_s->radio->work, &work->list);
5954 else
5955 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5956 if (was_empty) {
5957 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5958 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005959 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5960 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5961 wpa_dbg(wpa_s, MSG_DEBUG,
5962 "Try to schedule a radio work (num_active_works=%u)",
5963 radio->num_active_works);
5964 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005965 }
5966
5967 return 0;
5968}
5969
5970
5971/**
5972 * radio_work_done - Indicate that a radio work item has been completed
5973 * @work: Completed work
5974 *
5975 * This function is called once the callback function registered with
5976 * radio_add_work() has completed its work.
5977 */
5978void radio_work_done(struct wpa_radio_work *work)
5979{
5980 struct wpa_supplicant *wpa_s = work->wpa_s;
5981 struct os_reltime now, diff;
5982 unsigned int started = work->started;
5983
5984 os_get_reltime(&now);
5985 os_reltime_sub(&now, &work->time, &diff);
5986 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5987 work->type, work, started ? "done" : "canceled",
5988 diff.sec, diff.usec);
5989 radio_work_free(work);
5990 if (started)
5991 radio_work_check_next(wpa_s);
5992}
5993
5994
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005995struct wpa_radio_work *
5996radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005997{
5998 struct wpa_radio_work *work;
5999 struct wpa_radio *radio = wpa_s->radio;
6000
6001 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6002 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006003 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006004 }
6005
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006006 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006007}
6008
6009
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006010static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006011 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006012{
6013 const char *ifname, *driver, *rn;
6014
6015 driver = iface->driver;
6016next_driver:
6017 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6018 return -1;
6019
6020 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6021 if (wpa_s->drv_priv == NULL) {
6022 const char *pos;
6023 pos = driver ? os_strchr(driver, ',') : NULL;
6024 if (pos) {
6025 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6026 "driver interface - try next driver wrapper");
6027 driver = pos + 1;
6028 goto next_driver;
6029 }
6030 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
6031 "interface");
6032 return -1;
6033 }
6034 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6035 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6036 "driver_param '%s'", wpa_s->conf->driver_param);
6037 return -1;
6038 }
6039
6040 ifname = wpa_drv_get_ifname(wpa_s);
6041 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6042 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6043 "interface name with '%s'", ifname);
6044 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6045 }
6046
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006047 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006048 if (rn && rn[0] == '\0')
6049 rn = NULL;
6050
6051 wpa_s->radio = radio_add_interface(wpa_s, rn);
6052 if (wpa_s->radio == NULL)
6053 return -1;
6054
6055 return 0;
6056}
6057
6058
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006059#ifdef CONFIG_GAS_SERVER
6060
6061static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6062 unsigned int freq, const u8 *dst,
6063 const u8 *src, const u8 *bssid,
6064 const u8 *data, size_t data_len,
6065 enum offchannel_send_action_result result)
6066{
6067 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6068 " result=%s",
6069 freq, MAC2STR(dst),
6070 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6071 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6072 "FAILED"));
6073 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6074 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6075}
6076
6077
6078static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6079 struct wpabuf *buf, unsigned int wait_time)
6080{
6081 struct wpa_supplicant *wpa_s = ctx;
6082 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6083
6084 if (wait_time > wpa_s->max_remain_on_chan)
6085 wait_time = wpa_s->max_remain_on_chan;
6086
6087 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6088 wpabuf_head(buf), wpabuf_len(buf),
6089 wait_time, wpas_gas_server_tx_status, 0);
6090}
6091
6092#endif /* CONFIG_GAS_SERVER */
6093
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006094static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006095 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006096{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006097 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006098 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006099 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006100
6101 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6102 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6103 iface->confname ? iface->confname : "N/A",
6104 iface->driver ? iface->driver : "default",
6105 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6106 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6107
6108 if (iface->confname) {
6109#ifdef CONFIG_BACKEND_FILE
6110 wpa_s->confname = os_rel2abs_path(iface->confname);
6111 if (wpa_s->confname == NULL) {
6112 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6113 "for configuration file '%s'.",
6114 iface->confname);
6115 return -1;
6116 }
6117 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6118 iface->confname, wpa_s->confname);
6119#else /* CONFIG_BACKEND_FILE */
6120 wpa_s->confname = os_strdup(iface->confname);
6121#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006122 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006123 if (wpa_s->conf == NULL) {
6124 wpa_printf(MSG_ERROR, "Failed to read or parse "
6125 "configuration '%s'.", wpa_s->confname);
6126 return -1;
6127 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006128 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006129 if (wpa_s->confanother &&
6130 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6131 wpa_printf(MSG_ERROR,
6132 "Failed to read or parse configuration '%s'.",
6133 wpa_s->confanother);
6134 return -1;
6135 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006136
6137 /*
6138 * Override ctrl_interface and driver_param if set on command
6139 * line.
6140 */
6141 if (iface->ctrl_interface) {
6142 os_free(wpa_s->conf->ctrl_interface);
6143 wpa_s->conf->ctrl_interface =
6144 os_strdup(iface->ctrl_interface);
6145 }
6146
6147 if (iface->driver_param) {
6148 os_free(wpa_s->conf->driver_param);
6149 wpa_s->conf->driver_param =
6150 os_strdup(iface->driver_param);
6151 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006152
6153 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6154 os_free(wpa_s->conf->ctrl_interface);
6155 wpa_s->conf->ctrl_interface = NULL;
6156 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006157 } else
6158 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6159 iface->driver_param);
6160
6161 if (wpa_s->conf == NULL) {
6162 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6163 return -1;
6164 }
6165
6166 if (iface->ifname == NULL) {
6167 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6168 return -1;
6169 }
6170 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6171 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6172 iface->ifname);
6173 return -1;
6174 }
6175 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
6176
6177 if (iface->bridge_ifname) {
6178 if (os_strlen(iface->bridge_ifname) >=
6179 sizeof(wpa_s->bridge_ifname)) {
6180 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6181 "name '%s'.", iface->bridge_ifname);
6182 return -1;
6183 }
6184 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6185 sizeof(wpa_s->bridge_ifname));
6186 }
6187
6188 /* RSNA Supplicant Key Management - INITIALIZE */
6189 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
6190 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
6191
6192 /* Initialize driver interface and register driver event handler before
6193 * L2 receive handler so that association events are processed before
6194 * EAPOL-Key packets if both become available for the same select()
6195 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006196 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006197 return -1;
6198
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006199 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6200 return -1;
6201
6202 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6203 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6204 NULL);
6205 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6206
6207 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6208 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6209 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6210 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6211 "dot11RSNAConfigPMKLifetime");
6212 return -1;
6213 }
6214
6215 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6216 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6217 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6218 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6219 "dot11RSNAConfigPMKReauthThreshold");
6220 return -1;
6221 }
6222
6223 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6224 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6225 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6226 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6227 "dot11RSNAConfigSATimeout");
6228 return -1;
6229 }
6230
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006231 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6232 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006233 &wpa_s->hw.flags,
6234 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006235 if (wpa_s->hw.modes) {
6236 u16 i;
6237
6238 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6239 if (wpa_s->hw.modes[i].vht_capab) {
6240 wpa_s->hw_capab = CAPAB_VHT;
6241 break;
6242 }
6243
6244 if (wpa_s->hw.modes[i].ht_capab &
6245 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6246 wpa_s->hw_capab = CAPAB_HT40;
6247 else if (wpa_s->hw.modes[i].ht_capab &&
6248 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6249 wpa_s->hw_capab = CAPAB_HT;
6250 }
6251 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006252
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006253 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6254 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006255 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006256 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006257 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006258 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006259 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006260 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006261 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006262 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006263 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6264 wpa_s->max_sched_scan_plan_interval =
6265 capa.max_sched_scan_plan_interval;
6266 wpa_s->max_sched_scan_plan_iterations =
6267 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006268 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6269 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006270 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6271 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006272 wpa_s->extended_capa = capa.extended_capa;
6273 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6274 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006275 wpa_s->num_multichan_concurrent =
6276 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006277 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6278
6279 if (capa.mac_addr_rand_scan_supported)
6280 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6281 if (wpa_s->sched_scan_supported &&
6282 capa.mac_addr_rand_sched_scan_supported)
6283 wpa_s->mac_addr_rand_supported |=
6284 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006285
6286 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6287 if (wpa_s->extended_capa &&
6288 wpa_s->extended_capa_len >= 3 &&
6289 wpa_s->extended_capa[2] & 0x40)
6290 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006291 }
6292 if (wpa_s->max_remain_on_chan == 0)
6293 wpa_s->max_remain_on_chan = 1000;
6294
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006295 /*
6296 * Only take p2p_mgmt parameters when P2P Device is supported.
6297 * Doing it here as it determines whether l2_packet_init() will be done
6298 * during wpa_supplicant_driver_init().
6299 */
6300 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6301 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006302
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006303 if (wpa_s->num_multichan_concurrent == 0)
6304 wpa_s->num_multichan_concurrent = 1;
6305
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006306 if (wpa_supplicant_driver_init(wpa_s) < 0)
6307 return -1;
6308
6309#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006310 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006311 return -1;
6312#endif /* CONFIG_TDLS */
6313
6314 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6315 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6316 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6317 return -1;
6318 }
6319
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006320#ifdef CONFIG_FST
6321 if (wpa_s->conf->fst_group_id) {
6322 struct fst_iface_cfg cfg;
6323 struct fst_wpa_obj iface_obj;
6324
6325 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6326 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6327 sizeof(cfg.group_id));
6328 cfg.priority = wpa_s->conf->fst_priority;
6329 cfg.llt = wpa_s->conf->fst_llt;
6330
6331 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6332 &iface_obj, &cfg);
6333 if (!wpa_s->fst) {
6334 wpa_msg(wpa_s, MSG_ERROR,
6335 "FST: Cannot attach iface %s to group %s",
6336 wpa_s->ifname, cfg.group_id);
6337 return -1;
6338 }
6339 }
6340#endif /* CONFIG_FST */
6341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006342 if (wpas_wps_init(wpa_s))
6343 return -1;
6344
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006345#ifdef CONFIG_GAS_SERVER
6346 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6347 if (!wpa_s->gas_server) {
6348 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6349 return -1;
6350 }
6351#endif /* CONFIG_GAS_SERVER */
6352
6353#ifdef CONFIG_DPP
6354 if (wpas_dpp_init(wpa_s) < 0)
6355 return -1;
6356#endif /* CONFIG_DPP */
6357
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006358 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6359 return -1;
6360 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6361
6362 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6363 if (wpa_s->ctrl_iface == NULL) {
6364 wpa_printf(MSG_ERROR,
6365 "Failed to initialize control interface '%s'.\n"
6366 "You may have another wpa_supplicant process "
6367 "already running or the file was\n"
6368 "left by an unclean termination of wpa_supplicant "
6369 "in which case you will need\n"
6370 "to manually remove this file before starting "
6371 "wpa_supplicant again.\n",
6372 wpa_s->conf->ctrl_interface);
6373 return -1;
6374 }
6375
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006376 wpa_s->gas = gas_query_init(wpa_s);
6377 if (wpa_s->gas == NULL) {
6378 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6379 return -1;
6380 }
6381
Roshan Pius3a1667e2018-07-03 15:17:14 -07006382 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6383 wpa_s->p2p_mgmt) &&
6384 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006385 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6386 return -1;
6387 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006388
6389 if (wpa_bss_init(wpa_s) < 0)
6390 return -1;
6391
Paul Stewart092955c2017-02-06 09:13:09 -08006392#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6393#ifdef CONFIG_MESH
6394 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6395#endif /* CONFIG_MESH */
6396#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6397
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006398 /*
6399 * Set Wake-on-WLAN triggers, if configured.
6400 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6401 * have effect anyway when the interface is down).
6402 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006403 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006404 return -1;
6405
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006406#ifdef CONFIG_EAP_PROXY
6407{
6408 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006409 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6410 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006411 if (wpa_s->mnc_len > 0) {
6412 wpa_s->imsi[len] = '\0';
6413 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6414 wpa_s->imsi, wpa_s->mnc_len);
6415 } else {
6416 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6417 }
6418}
6419#endif /* CONFIG_EAP_PROXY */
6420
Dmitry Shmidt04949592012-07-19 12:16:46 -07006421 if (pcsc_reader_init(wpa_s) < 0)
6422 return -1;
6423
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006424 if (wpas_init_ext_pw(wpa_s) < 0)
6425 return -1;
6426
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006427 wpas_rrm_reset(wpa_s);
6428
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006429 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6430
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006431#ifdef CONFIG_HS20
6432 hs20_init(wpa_s);
6433#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006434#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006435 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006436 if ((wpa_s->conf->oce & OCE_STA) &&
6437 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6438 wpa_s->enable_oce = OCE_STA;
6439 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6440 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6441 /* TODO: Need to add STA-CFON support */
6442 wpa_printf(MSG_ERROR,
6443 "OCE STA-CFON feature is not yet supported");
6444 }
6445 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006446 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6447#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006448
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006449 wpa_supplicant_set_default_scan_ies(wpa_s);
6450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006451 return 0;
6452}
6453
6454
6455static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006456 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006457{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006458 struct wpa_global *global = wpa_s->global;
6459 struct wpa_supplicant *iface, *prev;
6460
6461 if (wpa_s == wpa_s->parent)
6462 wpas_p2p_group_remove(wpa_s, "*");
6463
6464 iface = global->ifaces;
6465 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006466 if (iface->p2pdev == wpa_s)
6467 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006468 if (iface == wpa_s || iface->parent != wpa_s) {
6469 iface = iface->next;
6470 continue;
6471 }
6472 wpa_printf(MSG_DEBUG,
6473 "Remove remaining child interface %s from parent %s",
6474 iface->ifname, wpa_s->ifname);
6475 prev = iface;
6476 iface = iface->next;
6477 wpa_supplicant_remove_iface(global, prev, terminate);
6478 }
6479
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006480 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006481 if (wpa_s->drv_priv) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006482 /* Don't deauthenticate if WoWLAN is enabled */
6483 if (!wpa_drv_get_wowlan(wpa_s)) {
6484 wpa_supplicant_deauthenticate(
6485 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006486
Hai Shalomfdcde762020-04-02 11:19:20 -07006487 wpa_drv_set_countermeasures(wpa_s, 0);
6488 wpa_clear_keys(wpa_s, NULL);
6489 } else {
6490 wpa_msg(wpa_s, MSG_INFO,
6491 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6492 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006493 }
6494
6495 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006496 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006497
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006498 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006499 radio_remove_interface(wpa_s);
6500
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006501#ifdef CONFIG_FST
6502 if (wpa_s->fst) {
6503 fst_detach(wpa_s->fst);
6504 wpa_s->fst = NULL;
6505 }
6506 if (wpa_s->received_mb_ies) {
6507 wpabuf_free(wpa_s->received_mb_ies);
6508 wpa_s->received_mb_ies = NULL;
6509 }
6510#endif /* CONFIG_FST */
6511
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006512 if (wpa_s->drv_priv)
6513 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006514
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006515 if (notify)
6516 wpas_notify_iface_removed(wpa_s);
6517
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006518 if (terminate)
6519 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006520
6521 if (wpa_s->ctrl_iface) {
6522 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6523 wpa_s->ctrl_iface = NULL;
6524 }
6525
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006526#ifdef CONFIG_MESH
6527 if (wpa_s->ifmsh) {
6528 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6529 wpa_s->ifmsh = NULL;
6530 }
6531#endif /* CONFIG_MESH */
6532
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006533 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006534 wpa_config_free(wpa_s->conf);
6535 wpa_s->conf = NULL;
6536 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006537
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006538 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006539 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006540
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006541 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006542}
6543
6544
Dmitry Shmidte4663042016-04-04 10:07:49 -07006545#ifdef CONFIG_MATCH_IFACE
6546
6547/**
6548 * wpa_supplicant_match_iface - Match an interface description to a name
6549 * @global: Pointer to global data from wpa_supplicant_init()
6550 * @ifname: Name of the interface to match
6551 * Returns: Pointer to the created interface description or %NULL on failure
6552 */
6553struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6554 const char *ifname)
6555{
6556 int i;
6557 struct wpa_interface *iface, *miface;
6558
6559 for (i = 0; i < global->params.match_iface_count; i++) {
6560 miface = &global->params.match_ifaces[i];
6561 if (!miface->ifname ||
6562 fnmatch(miface->ifname, ifname, 0) == 0) {
6563 iface = os_zalloc(sizeof(*iface));
6564 if (!iface)
6565 return NULL;
6566 *iface = *miface;
6567 iface->ifname = ifname;
6568 return iface;
6569 }
6570 }
6571
6572 return NULL;
6573}
6574
6575
6576/**
6577 * wpa_supplicant_match_existing - Match existing interfaces
6578 * @global: Pointer to global data from wpa_supplicant_init()
6579 * Returns: 0 on success, -1 on failure
6580 */
6581static int wpa_supplicant_match_existing(struct wpa_global *global)
6582{
6583 struct if_nameindex *ifi, *ifp;
6584 struct wpa_supplicant *wpa_s;
6585 struct wpa_interface *iface;
6586
6587 ifp = if_nameindex();
6588 if (!ifp) {
6589 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6590 return -1;
6591 }
6592
6593 for (ifi = ifp; ifi->if_name; ifi++) {
6594 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6595 if (wpa_s)
6596 continue;
6597 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6598 if (iface) {
6599 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6600 os_free(iface);
6601 if (wpa_s)
6602 wpa_s->matched = 1;
6603 }
6604 }
6605
6606 if_freenameindex(ifp);
6607 return 0;
6608}
6609
6610#endif /* CONFIG_MATCH_IFACE */
6611
6612
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006613/**
6614 * wpa_supplicant_add_iface - Add a new network interface
6615 * @global: Pointer to global data from wpa_supplicant_init()
6616 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006617 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006618 * Returns: Pointer to the created interface or %NULL on failure
6619 *
6620 * This function is used to add new network interfaces for %wpa_supplicant.
6621 * This can be called before wpa_supplicant_run() to add interfaces before the
6622 * main event loop has been started. In addition, new interfaces can be added
6623 * dynamically while %wpa_supplicant is already running. This could happen,
6624 * e.g., when a hotplug network adapter is inserted.
6625 */
6626struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006627 struct wpa_interface *iface,
6628 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006629{
6630 struct wpa_supplicant *wpa_s;
6631 struct wpa_interface t_iface;
6632 struct wpa_ssid *ssid;
6633
6634 if (global == NULL || iface == NULL)
6635 return NULL;
6636
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006637 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006638 if (wpa_s == NULL)
6639 return NULL;
6640
6641 wpa_s->global = global;
6642
6643 t_iface = *iface;
6644 if (global->params.override_driver) {
6645 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6646 "('%s' -> '%s')",
6647 iface->driver, global->params.override_driver);
6648 t_iface.driver = global->params.override_driver;
6649 }
6650 if (global->params.override_ctrl_interface) {
6651 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6652 "ctrl_interface ('%s' -> '%s')",
6653 iface->ctrl_interface,
6654 global->params.override_ctrl_interface);
6655 t_iface.ctrl_interface =
6656 global->params.override_ctrl_interface;
6657 }
6658 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6659 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6660 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006661 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006662 return NULL;
6663 }
6664
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006665 /* Notify the control interfaces about new iface */
6666 if (wpas_notify_iface_added(wpa_s)) {
6667 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6668 return NULL;
6669 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006670
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006671 /* Notify the control interfaces about new networks for non p2p mgmt
6672 * ifaces. */
6673 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006674 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6675 wpas_notify_network_added(wpa_s, ssid);
6676 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006677
6678 wpa_s->next = global->ifaces;
6679 global->ifaces = wpa_s;
6680
6681 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006682 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006683
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006684#ifdef CONFIG_P2P
6685 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006686 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006687 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006688 wpas_p2p_add_p2pdev_interface(
6689 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006690 wpa_printf(MSG_INFO,
6691 "P2P: Failed to enable P2P Device interface");
6692 /* Try to continue without. P2P will be disabled. */
6693 }
6694#endif /* CONFIG_P2P */
6695
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006696 return wpa_s;
6697}
6698
6699
6700/**
6701 * wpa_supplicant_remove_iface - Remove a network interface
6702 * @global: Pointer to global data from wpa_supplicant_init()
6703 * @wpa_s: Pointer to the network interface to be removed
6704 * Returns: 0 if interface was removed, -1 if interface was not found
6705 *
6706 * This function can be used to dynamically remove network interfaces from
6707 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6708 * addition, this function is used to remove all remaining interfaces when
6709 * %wpa_supplicant is terminated.
6710 */
6711int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006712 struct wpa_supplicant *wpa_s,
6713 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006714{
6715 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006716#ifdef CONFIG_MESH
6717 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6718 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006719 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006720#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006721
6722 /* Remove interface from the global list of interfaces */
6723 prev = global->ifaces;
6724 if (prev == wpa_s) {
6725 global->ifaces = wpa_s->next;
6726 } else {
6727 while (prev && prev->next != wpa_s)
6728 prev = prev->next;
6729 if (prev == NULL)
6730 return -1;
6731 prev->next = wpa_s->next;
6732 }
6733
6734 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6735
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006736#ifdef CONFIG_MESH
6737 if (mesh_if_created) {
6738 ifname = os_strdup(wpa_s->ifname);
6739 if (ifname == NULL) {
6740 wpa_dbg(wpa_s, MSG_ERROR,
6741 "mesh: Failed to malloc ifname");
6742 return -1;
6743 }
6744 }
6745#endif /* CONFIG_MESH */
6746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006747 if (global->p2p_group_formation == wpa_s)
6748 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006749 if (global->p2p_invite_group == wpa_s)
6750 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006751 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006752
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006753#ifdef CONFIG_MESH
6754 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006755 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006756 os_free(ifname);
6757 }
6758#endif /* CONFIG_MESH */
6759
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006760 return 0;
6761}
6762
6763
6764/**
6765 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6766 * @wpa_s: Pointer to the network interface
6767 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6768 */
6769const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6770{
6771 const char *eapol_method;
6772
6773 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6774 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6775 return "NO-EAP";
6776 }
6777
6778 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6779 if (eapol_method == NULL)
6780 return "UNKNOWN-EAP";
6781
6782 return eapol_method;
6783}
6784
6785
6786/**
6787 * wpa_supplicant_get_iface - Get a new network interface
6788 * @global: Pointer to global data from wpa_supplicant_init()
6789 * @ifname: Interface name
6790 * Returns: Pointer to the interface or %NULL if not found
6791 */
6792struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6793 const char *ifname)
6794{
6795 struct wpa_supplicant *wpa_s;
6796
6797 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6798 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6799 return wpa_s;
6800 }
6801 return NULL;
6802}
6803
6804
6805#ifndef CONFIG_NO_WPA_MSG
6806static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6807{
6808 struct wpa_supplicant *wpa_s = ctx;
6809 if (wpa_s == NULL)
6810 return NULL;
6811 return wpa_s->ifname;
6812}
6813#endif /* CONFIG_NO_WPA_MSG */
6814
6815
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006816#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6817#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6818#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6819
6820/* Periodic cleanup tasks */
6821static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6822{
6823 struct wpa_global *global = eloop_ctx;
6824 struct wpa_supplicant *wpa_s;
6825
6826 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6827 wpas_periodic, global, NULL);
6828
6829#ifdef CONFIG_P2P
6830 if (global->p2p)
6831 p2p_expire_peers(global->p2p);
6832#endif /* CONFIG_P2P */
6833
6834 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6835 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6836#ifdef CONFIG_AP
6837 ap_periodic(wpa_s);
6838#endif /* CONFIG_AP */
6839 }
6840}
6841
6842
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006843/**
6844 * wpa_supplicant_init - Initialize %wpa_supplicant
6845 * @params: Parameters for %wpa_supplicant
6846 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6847 *
6848 * This function is used to initialize %wpa_supplicant. After successful
6849 * initialization, the returned data pointer can be used to add and remove
6850 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6851 */
6852struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6853{
6854 struct wpa_global *global;
6855 int ret, i;
6856
6857 if (params == NULL)
6858 return NULL;
6859
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006860#ifdef CONFIG_DRIVER_NDIS
6861 {
6862 void driver_ndis_init_ops(void);
6863 driver_ndis_init_ops();
6864 }
6865#endif /* CONFIG_DRIVER_NDIS */
6866
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006867#ifndef CONFIG_NO_WPA_MSG
6868 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6869#endif /* CONFIG_NO_WPA_MSG */
6870
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006871 if (params->wpa_debug_file_path)
6872 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07006873 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006874 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006875 if (params->wpa_debug_syslog)
6876 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006877 if (params->wpa_debug_tracing) {
6878 ret = wpa_debug_open_linux_tracing();
6879 if (ret) {
6880 wpa_printf(MSG_ERROR,
6881 "Failed to enable trace logging");
6882 return NULL;
6883 }
6884 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006885
6886 ret = eap_register_methods();
6887 if (ret) {
6888 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6889 if (ret == -2)
6890 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6891 "the same EAP type.");
6892 return NULL;
6893 }
6894
6895 global = os_zalloc(sizeof(*global));
6896 if (global == NULL)
6897 return NULL;
6898 dl_list_init(&global->p2p_srv_bonjour);
6899 dl_list_init(&global->p2p_srv_upnp);
6900 global->params.daemonize = params->daemonize;
6901 global->params.wait_for_monitor = params->wait_for_monitor;
6902 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6903 if (params->pid_file)
6904 global->params.pid_file = os_strdup(params->pid_file);
6905 if (params->ctrl_interface)
6906 global->params.ctrl_interface =
6907 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006908 if (params->ctrl_interface_group)
6909 global->params.ctrl_interface_group =
6910 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006911 if (params->override_driver)
6912 global->params.override_driver =
6913 os_strdup(params->override_driver);
6914 if (params->override_ctrl_interface)
6915 global->params.override_ctrl_interface =
6916 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006917#ifdef CONFIG_MATCH_IFACE
6918 global->params.match_iface_count = params->match_iface_count;
6919 if (params->match_iface_count) {
6920 global->params.match_ifaces =
6921 os_calloc(params->match_iface_count,
6922 sizeof(struct wpa_interface));
6923 os_memcpy(global->params.match_ifaces,
6924 params->match_ifaces,
6925 params->match_iface_count *
6926 sizeof(struct wpa_interface));
6927 }
6928#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006929#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006930 if (params->conf_p2p_dev)
6931 global->params.conf_p2p_dev =
6932 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006933#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006934 wpa_debug_level = global->params.wpa_debug_level =
6935 params->wpa_debug_level;
6936 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6937 params->wpa_debug_show_keys;
6938 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6939 params->wpa_debug_timestamp;
6940
Hai Shalomfdcde762020-04-02 11:19:20 -07006941 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006942
6943 if (eloop_init()) {
6944 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6945 wpa_supplicant_deinit(global);
6946 return NULL;
6947 }
6948
Jouni Malinen75ecf522011-06-27 15:19:46 -07006949 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006950
6951 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6952 if (global->ctrl_iface == NULL) {
6953 wpa_supplicant_deinit(global);
6954 return NULL;
6955 }
6956
6957 if (wpas_notify_supplicant_initialized(global)) {
6958 wpa_supplicant_deinit(global);
6959 return NULL;
6960 }
6961
6962 for (i = 0; wpa_drivers[i]; i++)
6963 global->drv_count++;
6964 if (global->drv_count == 0) {
6965 wpa_printf(MSG_ERROR, "No drivers enabled");
6966 wpa_supplicant_deinit(global);
6967 return NULL;
6968 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006969 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006970 if (global->drv_priv == NULL) {
6971 wpa_supplicant_deinit(global);
6972 return NULL;
6973 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006974
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006975#ifdef CONFIG_WIFI_DISPLAY
6976 if (wifi_display_init(global) < 0) {
6977 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6978 wpa_supplicant_deinit(global);
6979 return NULL;
6980 }
6981#endif /* CONFIG_WIFI_DISPLAY */
6982
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006983 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6984 wpas_periodic, global, NULL);
6985
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006986 return global;
6987}
6988
6989
6990/**
6991 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6992 * @global: Pointer to global data from wpa_supplicant_init()
6993 * Returns: 0 after successful event loop run, -1 on failure
6994 *
6995 * This function starts the main event loop and continues running as long as
6996 * there are any remaining events. In most cases, this function is running as
6997 * long as the %wpa_supplicant process in still in use.
6998 */
6999int wpa_supplicant_run(struct wpa_global *global)
7000{
7001 struct wpa_supplicant *wpa_s;
7002
7003 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007004 (wpa_supplicant_daemon(global->params.pid_file) ||
7005 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007006 return -1;
7007
Dmitry Shmidte4663042016-04-04 10:07:49 -07007008#ifdef CONFIG_MATCH_IFACE
7009 if (wpa_supplicant_match_existing(global))
7010 return -1;
7011#endif
7012
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007013 if (global->params.wait_for_monitor) {
7014 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007015 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007016 wpa_supplicant_ctrl_iface_wait(
7017 wpa_s->ctrl_iface);
7018 }
7019
7020 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7021 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7022
7023 eloop_run();
7024
7025 return 0;
7026}
7027
7028
7029/**
7030 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7031 * @global: Pointer to global data from wpa_supplicant_init()
7032 *
7033 * This function is called to deinitialize %wpa_supplicant and to free all
7034 * allocated resources. Remaining network interfaces will also be removed.
7035 */
7036void wpa_supplicant_deinit(struct wpa_global *global)
7037{
7038 int i;
7039
7040 if (global == NULL)
7041 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007042
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007043 eloop_cancel_timeout(wpas_periodic, global, NULL);
7044
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007045#ifdef CONFIG_WIFI_DISPLAY
7046 wifi_display_deinit(global);
7047#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007048
7049 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007050 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007051
7052 if (global->ctrl_iface)
7053 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7054
7055 wpas_notify_supplicant_deinitialized(global);
7056
7057 eap_peer_unregister_methods();
7058#ifdef CONFIG_AP
7059 eap_server_unregister_methods();
7060#endif /* CONFIG_AP */
7061
7062 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7063 if (!global->drv_priv[i])
7064 continue;
7065 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7066 }
7067 os_free(global->drv_priv);
7068
7069 random_deinit();
7070
7071 eloop_destroy();
7072
7073 if (global->params.pid_file) {
7074 os_daemonize_terminate(global->params.pid_file);
7075 os_free(global->params.pid_file);
7076 }
7077 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007078 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007079 os_free(global->params.override_driver);
7080 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007081#ifdef CONFIG_MATCH_IFACE
7082 os_free(global->params.match_ifaces);
7083#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007084#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007085 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007086#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007087
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007088 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007089 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007090 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007091
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007092 os_free(global);
7093 wpa_debug_close_syslog();
7094 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007095 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007096}
7097
7098
7099void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7100{
7101 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7102 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7103 char country[3];
7104 country[0] = wpa_s->conf->country[0];
7105 country[1] = wpa_s->conf->country[1];
7106 country[2] = '\0';
7107 if (wpa_drv_set_country(wpa_s, country) < 0) {
7108 wpa_printf(MSG_ERROR, "Failed to set country code "
7109 "'%s'", country);
7110 }
7111 }
7112
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007113 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7114 wpas_init_ext_pw(wpa_s);
7115
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007116 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7117 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7118
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007119 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7120 struct wpa_driver_capa capa;
7121 int res = wpa_drv_get_capa(wpa_s, &capa);
7122
7123 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7124 wpa_printf(MSG_ERROR,
7125 "Failed to update wowlan_triggers to '%s'",
7126 wpa_s->conf->wowlan_triggers);
7127 }
7128
Hai Shalom81f62d82019-07-22 12:10:00 -07007129 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7130 wpa_supplicant_set_default_scan_ies(wpa_s);
7131
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007132#ifdef CONFIG_WPS
7133 wpas_wps_update_config(wpa_s);
7134#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007135 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007136 wpa_s->conf->changed_parameters = 0;
7137}
7138
7139
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007140void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007141{
7142 int i;
7143
7144 for (i = 0; i < *num_freqs; i++) {
7145 if (freqs[i] == freq)
7146 return;
7147 }
7148
7149 freqs[*num_freqs] = freq;
7150 (*num_freqs)++;
7151}
7152
7153
7154static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7155{
7156 struct wpa_bss *bss, *cbss;
7157 const int max_freqs = 10;
7158 int *freqs;
7159 int num_freqs = 0;
7160
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007161 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007162 if (freqs == NULL)
7163 return NULL;
7164
7165 cbss = wpa_s->current_bss;
7166
7167 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7168 if (bss == cbss)
7169 continue;
7170 if (bss->ssid_len == cbss->ssid_len &&
7171 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
7172 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
7173 add_freq(freqs, &num_freqs, bss->freq);
7174 if (num_freqs == max_freqs)
7175 break;
7176 }
7177 }
7178
7179 if (num_freqs == 0) {
7180 os_free(freqs);
7181 freqs = NULL;
7182 }
7183
7184 return freqs;
7185}
7186
7187
7188void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7189{
7190 int timeout;
7191 int count;
7192 int *freqs = NULL;
7193
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007194 wpas_connect_work_done(wpa_s);
7195
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007196 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007197 * Remove possible authentication timeout since the connection failed.
7198 */
7199 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7200
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007201 /*
7202 * There is no point in blacklisting the AP if this event is
7203 * generated based on local request to disconnect.
7204 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007205 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007206 wpa_s->own_disconnect_req = 0;
7207 wpa_dbg(wpa_s, MSG_DEBUG,
7208 "Ignore connection failure due to local request to disconnect");
7209 return;
7210 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007211 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007212 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7213 "indication since interface has been put into "
7214 "disconnected state");
7215 return;
7216 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007217 if (wpa_s->auto_reconnect_disabled) {
7218 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7219 "indication since auto connect is disabled");
7220 return;
7221 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007222
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007223 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007224 * Add the failed BSSID into the blacklist and speed up next scan
7225 * attempt if there could be other APs that could accept association.
7226 * The current blacklist count indicates how many times we have tried
7227 * connecting to this AP and multiple attempts mean that other APs are
7228 * either not available or has already been tried, so that we can start
7229 * increasing the delay here to avoid constant scanning.
7230 */
7231 count = wpa_blacklist_add(wpa_s, bssid);
7232 if (count == 1 && wpa_s->current_bss) {
7233 /*
7234 * This BSS was not in the blacklist before. If there is
7235 * another BSS available for the same ESS, we should try that
7236 * next. Otherwise, we may as well try this one once more
7237 * before allowing other, likely worse, ESSes to be considered.
7238 */
7239 freqs = get_bss_freqs_in_ess(wpa_s);
7240 if (freqs) {
7241 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7242 "has been seen; try it next");
7243 wpa_blacklist_add(wpa_s, bssid);
7244 /*
7245 * On the next scan, go through only the known channels
7246 * used in this ESS based on previous scans to speed up
7247 * common load balancing use case.
7248 */
7249 os_free(wpa_s->next_scan_freqs);
7250 wpa_s->next_scan_freqs = freqs;
7251 }
7252 }
7253
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007254 /*
7255 * Add previous failure count in case the temporary blacklist was
7256 * cleared due to no other BSSes being available.
7257 */
7258 count += wpa_s->extra_blacklist_count;
7259
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007260 if (count > 3 && wpa_s->current_ssid) {
7261 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7262 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007263 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007264 }
7265
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007266 switch (count) {
7267 case 1:
7268 timeout = 100;
7269 break;
7270 case 2:
7271 timeout = 500;
7272 break;
7273 case 3:
7274 timeout = 1000;
7275 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007276 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007277 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007278 break;
7279 default:
7280 timeout = 10000;
7281 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007282 }
7283
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007284 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
7285 "ms", count, timeout);
7286
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007287 /*
7288 * TODO: if more than one possible AP is available in scan results,
7289 * could try the other ones before requesting a new scan.
7290 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007291
7292 /* speed up the connection attempt with normal scan */
7293 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007294 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7295 1000 * (timeout % 1000));
7296}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007297
7298
Hai Shalomce48b4a2018-09-05 11:41:35 -07007299#ifdef CONFIG_FILS
7300void fils_connection_failure(struct wpa_supplicant *wpa_s)
7301{
7302 struct wpa_ssid *ssid = wpa_s->current_ssid;
7303 const u8 *realm, *username, *rrk;
7304 size_t realm_len, username_len, rrk_len;
7305 u16 next_seq_num;
7306
7307 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7308 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7309 &username, &username_len,
7310 &realm, &realm_len, &next_seq_num,
7311 &rrk, &rrk_len) != 0 ||
7312 !realm)
7313 return;
7314
7315 wpa_hexdump_ascii(MSG_DEBUG,
7316 "FILS: Store last connection failure realm",
7317 realm, realm_len);
7318 os_free(wpa_s->last_con_fail_realm);
7319 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7320 if (wpa_s->last_con_fail_realm) {
7321 wpa_s->last_con_fail_realm_len = realm_len;
7322 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7323 }
7324}
7325#endif /* CONFIG_FILS */
7326
7327
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007328int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7329{
7330 return wpa_s->conf->ap_scan == 2 ||
7331 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7332}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007333
Dmitry Shmidt04949592012-07-19 12:16:46 -07007334
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007335#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007336int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7337 struct wpa_ssid *ssid,
7338 const char *field,
7339 const char *value)
7340{
7341#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007342 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007343
7344 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7345 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7346 (const u8 *) value, os_strlen(value));
7347
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007348 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007349 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007350#else /* IEEE8021X_EAPOL */
7351 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7352 return -1;
7353#endif /* IEEE8021X_EAPOL */
7354}
7355
7356int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7357 struct wpa_ssid *ssid,
7358 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007359 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007360{
7361#ifdef IEEE8021X_EAPOL
7362 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007363 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007364
7365 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007366 case WPA_CTRL_REQ_EAP_IDENTITY:
7367 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007368 os_free(eap->imsi_identity);
7369 if (value == NULL)
7370 return -1;
7371 identity = os_strchr(value, ':');
7372 if (identity == NULL) {
7373 /* plain identity */
7374 eap->identity = (u8 *)os_strdup(value);
7375 eap->identity_len = os_strlen(value);
7376 } else {
7377 /* have both plain identity and encrypted identity */
7378 imsi_identity = value;
7379 *identity++ = '\0';
7380 /* plain identity */
7381 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7382 eap->imsi_identity_len = strlen(imsi_identity);
7383 /* encrypted identity */
7384 eap->identity = (u8 *)dup_binstr(identity,
7385 value_len - strlen(imsi_identity) - 1);
7386 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7387 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007388 eap->pending_req_identity = 0;
7389 if (ssid == wpa_s->current_ssid)
7390 wpa_s->reassociate = 1;
7391 break;
7392 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007393 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007394 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007395 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007396 eap->pending_req_password = 0;
7397 if (ssid == wpa_s->current_ssid)
7398 wpa_s->reassociate = 1;
7399 break;
7400 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007401 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007402 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007403 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007404 eap->pending_req_new_password = 0;
7405 if (ssid == wpa_s->current_ssid)
7406 wpa_s->reassociate = 1;
7407 break;
7408 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007409 str_clear_free(eap->cert.pin);
7410 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007411 eap->pending_req_pin = 0;
7412 if (ssid == wpa_s->current_ssid)
7413 wpa_s->reassociate = 1;
7414 break;
7415 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007416 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007417 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007418 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007419 os_free(eap->pending_req_otp);
7420 eap->pending_req_otp = NULL;
7421 eap->pending_req_otp_len = 0;
7422 break;
7423 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007424 str_clear_free(eap->cert.private_key_passwd);
7425 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007426 eap->pending_req_passphrase = 0;
7427 if (ssid == wpa_s->current_ssid)
7428 wpa_s->reassociate = 1;
7429 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007430 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007431 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007432 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007433 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007434 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007435 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7436 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7437 return -1;
7438 ssid->mem_only_psk = 1;
7439 if (ssid->passphrase)
7440 wpa_config_update_psk(ssid);
7441 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7442 wpa_supplicant_req_scan(wpa_s, 0, 0);
7443 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007444 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7445 if (eap->pending_ext_cert_check != PENDING_CHECK)
7446 return -1;
7447 if (os_strcmp(value, "good") == 0)
7448 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7449 else if (os_strcmp(value, "bad") == 0)
7450 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7451 else
7452 return -1;
7453 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007454 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007455 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007456 return -1;
7457 }
7458
7459 return 0;
7460#else /* IEEE8021X_EAPOL */
7461 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7462 return -1;
7463#endif /* IEEE8021X_EAPOL */
7464}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007465#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007466
7467
7468int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7469{
Hai Shalomfdcde762020-04-02 11:19:20 -07007470#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007471 int i;
7472 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007473#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007474
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007475 if (wpa_s->p2p_mgmt)
7476 return 1; /* no normal network profiles on p2p_mgmt interface */
7477
Dmitry Shmidt04949592012-07-19 12:16:46 -07007478 if (ssid == NULL)
7479 return 1;
7480
7481 if (ssid->disabled)
7482 return 1;
7483
Hai Shalomfdcde762020-04-02 11:19:20 -07007484#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007485 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007486 drv_enc = wpa_s->drv_enc;
7487 else
7488 drv_enc = (unsigned int) -1;
7489
7490 for (i = 0; i < NUM_WEP_KEYS; i++) {
7491 size_t len = ssid->wep_key_len[i];
7492 if (len == 0)
7493 continue;
7494 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7495 continue;
7496 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7497 continue;
7498 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7499 continue;
7500 return 1; /* invalid WEP key */
7501 }
Hai Shalomfdcde762020-04-02 11:19:20 -07007502#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007503
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007504 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007505 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007506 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007507 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007508 return 1;
7509
Dmitry Shmidt04949592012-07-19 12:16:46 -07007510 return 0;
7511}
7512
7513
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007514int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7515{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007516 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7517 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7518 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7519 /*
7520 * Driver does not support BIP -- ignore pmf=1 default
7521 * since the connection with PMF would fail and the
7522 * configuration does not require PMF to be enabled.
7523 */
7524 return NO_MGMT_FRAME_PROTECTION;
7525 }
7526
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007527 if (ssid &&
7528 (ssid->key_mgmt &
7529 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7530 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7531 /*
7532 * Do not use the default PMF value for non-RSN networks
7533 * since PMF is available only with RSN and pmf=2
7534 * configuration would otherwise prevent connections to
7535 * all open networks.
7536 */
7537 return NO_MGMT_FRAME_PROTECTION;
7538 }
7539
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007540 return wpa_s->conf->pmf;
7541 }
7542
7543 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007544}
7545
7546
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007547int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007548{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007549 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007550 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007551 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007552 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007553 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007554}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007555
7556
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007557void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007558{
7559 struct wpa_ssid *ssid = wpa_s->current_ssid;
7560 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007561 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007562
7563 if (ssid == NULL) {
7564 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7565 "SSID block");
7566 return;
7567 }
7568
7569 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7570 return;
7571
7572 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007573
7574#ifdef CONFIG_P2P
7575 if (ssid->p2p_group &&
7576 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7577 /*
7578 * Skip the wait time since there is a short timeout on the
7579 * connection to a P2P group.
7580 */
7581 return;
7582 }
7583#endif /* CONFIG_P2P */
7584
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007585 if (ssid->auth_failures > 50)
7586 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007587 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007588 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007589 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007590 dur = 90;
7591 else if (ssid->auth_failures > 3)
7592 dur = 60;
7593 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007594 dur = 30;
7595 else if (ssid->auth_failures > 1)
7596 dur = 20;
7597 else
7598 dur = 10;
7599
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007600 if (ssid->auth_failures > 1 &&
7601 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7602 dur += os_random() % (ssid->auth_failures * 10);
7603
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007604 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007605 if (now.sec + dur <= ssid->disabled_until.sec)
7606 return;
7607
7608 ssid->disabled_until.sec = now.sec + dur;
7609
7610 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007611 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007612 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007613 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007614}
7615
7616
7617void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7618 struct wpa_ssid *ssid, int clear_failures)
7619{
7620 if (ssid == NULL)
7621 return;
7622
7623 if (ssid->disabled_until.sec) {
7624 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7625 "id=%d ssid=\"%s\"",
7626 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7627 }
7628 ssid->disabled_until.sec = 0;
7629 ssid->disabled_until.usec = 0;
7630 if (clear_failures)
7631 ssid->auth_failures = 0;
7632}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007633
7634
7635int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7636{
7637 size_t i;
7638
7639 if (wpa_s->disallow_aps_bssid == NULL)
7640 return 0;
7641
7642 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7643 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7644 bssid, ETH_ALEN) == 0)
7645 return 1;
7646 }
7647
7648 return 0;
7649}
7650
7651
7652int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7653 size_t ssid_len)
7654{
7655 size_t i;
7656
7657 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7658 return 0;
7659
7660 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7661 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7662 if (ssid_len == s->ssid_len &&
7663 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7664 return 1;
7665 }
7666
7667 return 0;
7668}
7669
7670
7671/**
7672 * wpas_request_connection - Request a new connection
7673 * @wpa_s: Pointer to the network interface
7674 *
7675 * This function is used to request a new connection to be found. It will mark
7676 * the interface to allow reassociation and request a new scan to find a
7677 * suitable network to connect to.
7678 */
7679void wpas_request_connection(struct wpa_supplicant *wpa_s)
7680{
7681 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007682 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007683 wpa_supplicant_reinit_autoscan(wpa_s);
7684 wpa_s->extra_blacklist_count = 0;
7685 wpa_s->disconnected = 0;
7686 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007687 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007688
7689 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7690 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007691 else
7692 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007693}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007694
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007695
Roshan Pius02242d72016-08-09 15:31:48 -07007696/**
7697 * wpas_request_disconnection - Request disconnection
7698 * @wpa_s: Pointer to the network interface
7699 *
7700 * This function is used to request disconnection from the currently connected
7701 * network. This will stop any ongoing scans and initiate deauthentication.
7702 */
7703void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7704{
7705#ifdef CONFIG_SME
7706 wpa_s->sme.prev_bssid_set = 0;
7707#endif /* CONFIG_SME */
7708 wpa_s->reassociate = 0;
7709 wpa_s->disconnected = 1;
7710 wpa_supplicant_cancel_sched_scan(wpa_s);
7711 wpa_supplicant_cancel_scan(wpa_s);
7712 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7713 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007714 radio_remove_works(wpa_s, "connect", 0);
7715 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007716}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007717
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007718
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007719void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7720 struct wpa_used_freq_data *freqs_data,
7721 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007722{
7723 unsigned int i;
7724
7725 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7726 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007727 for (i = 0; i < len; i++) {
7728 struct wpa_used_freq_data *cur = &freqs_data[i];
7729 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7730 i, cur->freq, cur->flags);
7731 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007732}
7733
7734
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007735/*
7736 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007737 * are using the same radio as the current interface, and in addition, get
7738 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007739 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007740int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7741 struct wpa_used_freq_data *freqs_data,
7742 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007743{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007744 struct wpa_supplicant *ifs;
7745 u8 bssid[ETH_ALEN];
7746 int freq;
7747 unsigned int idx = 0, i;
7748
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007749 wpa_dbg(wpa_s, MSG_DEBUG,
7750 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007751 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007752
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007753 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7754 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007755 if (idx == len)
7756 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007757
7758 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7759 continue;
7760
7761 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007762 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7763 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007764 freq = ifs->current_ssid->frequency;
7765 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7766 freq = ifs->assoc_freq;
7767 else
7768 continue;
7769
7770 /* Hold only distinct freqs */
7771 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007772 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007773 break;
7774
7775 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007776 freqs_data[idx++].freq = freq;
7777
7778 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007779 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007780 WPA_FREQ_USED_BY_P2P_CLIENT :
7781 WPA_FREQ_USED_BY_INFRA_STATION;
7782 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007783 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007784
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007785 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007786 return idx;
7787}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007788
7789
7790/*
7791 * Find the operating frequencies of any of the virtual interfaces that
7792 * are using the same radio as the current interface.
7793 */
7794int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7795 int *freq_array, unsigned int len)
7796{
7797 struct wpa_used_freq_data *freqs_data;
7798 int num, i;
7799
7800 os_memset(freq_array, 0, sizeof(int) * len);
7801
7802 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7803 if (!freqs_data)
7804 return -1;
7805
7806 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7807 for (i = 0; i < num; i++)
7808 freq_array[i] = freqs_data[i].freq;
7809
7810 os_free(freqs_data);
7811
7812 return num;
7813}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007814
7815
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007816struct wpa_supplicant *
7817wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7818{
7819 switch (frame) {
7820#ifdef CONFIG_P2P
7821 case VENDOR_ELEM_PROBE_REQ_P2P:
7822 case VENDOR_ELEM_PROBE_RESP_P2P:
7823 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7824 case VENDOR_ELEM_BEACON_P2P_GO:
7825 case VENDOR_ELEM_P2P_PD_REQ:
7826 case VENDOR_ELEM_P2P_PD_RESP:
7827 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7828 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7829 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7830 case VENDOR_ELEM_P2P_INV_REQ:
7831 case VENDOR_ELEM_P2P_INV_RESP:
7832 case VENDOR_ELEM_P2P_ASSOC_REQ:
7833 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007834 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007835#endif /* CONFIG_P2P */
7836 default:
7837 return wpa_s;
7838 }
7839}
7840
7841
7842void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7843{
7844 unsigned int i;
7845 char buf[30];
7846
7847 wpa_printf(MSG_DEBUG, "Update vendor elements");
7848
7849 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7850 if (wpa_s->vendor_elem[i]) {
7851 int res;
7852
7853 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7854 if (!os_snprintf_error(sizeof(buf), res)) {
7855 wpa_hexdump_buf(MSG_DEBUG, buf,
7856 wpa_s->vendor_elem[i]);
7857 }
7858 }
7859 }
7860
7861#ifdef CONFIG_P2P
7862 if (wpa_s->parent == wpa_s &&
7863 wpa_s->global->p2p &&
7864 !wpa_s->global->p2p_disabled)
7865 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7866#endif /* CONFIG_P2P */
7867}
7868
7869
7870int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7871 const u8 *elem, size_t len)
7872{
7873 u8 *ie, *end;
7874
7875 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7876 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7877
7878 for (; ie + 1 < end; ie += 2 + ie[1]) {
7879 if (ie + len > end)
7880 break;
7881 if (os_memcmp(ie, elem, len) != 0)
7882 continue;
7883
7884 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7885 wpabuf_free(wpa_s->vendor_elem[frame]);
7886 wpa_s->vendor_elem[frame] = NULL;
7887 } else {
7888 os_memmove(ie, ie + len, end - (ie + len));
7889 wpa_s->vendor_elem[frame]->used -= len;
7890 }
7891 wpas_vendor_elem_update(wpa_s);
7892 return 0;
7893 }
7894
7895 return -1;
7896}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007897
7898
7899struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07007900 u16 num_modes, enum hostapd_hw_mode mode,
7901 int is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007902{
7903 u16 i;
7904
7905 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007906 if (modes[i].mode != mode ||
7907 !modes[i].num_channels || !modes[i].channels)
7908 continue;
7909 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
7910 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007911 return &modes[i];
7912 }
7913
7914 return NULL;
7915}
7916
7917
7918static struct
7919wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7920 const u8 *bssid)
7921{
7922 struct wpa_bss_tmp_disallowed *bss;
7923
7924 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7925 struct wpa_bss_tmp_disallowed, list) {
7926 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7927 return bss;
7928 }
7929
7930 return NULL;
7931}
7932
7933
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007934static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7935{
7936 struct wpa_bss_tmp_disallowed *tmp;
7937 unsigned int num_bssid = 0;
7938 u8 *bssids;
7939 int ret;
7940
7941 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7942 if (!bssids)
7943 return -1;
7944 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7945 struct wpa_bss_tmp_disallowed, list) {
7946 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7947 ETH_ALEN);
7948 num_bssid++;
7949 }
7950 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7951 os_free(bssids);
7952 return ret;
7953}
7954
7955
7956static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7957{
7958 struct wpa_supplicant *wpa_s = eloop_ctx;
7959 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7960
7961 /* Make sure the bss is not already freed */
7962 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7963 struct wpa_bss_tmp_disallowed, list) {
7964 if (bss == tmp) {
7965 dl_list_del(&tmp->list);
7966 os_free(tmp);
7967 wpa_set_driver_tmp_disallow_list(wpa_s);
7968 break;
7969 }
7970 }
7971}
7972
7973
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007974void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08007975 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007976{
7977 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007978
7979 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7980 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007981 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08007982 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007983 }
7984
7985 bss = os_malloc(sizeof(*bss));
7986 if (!bss) {
7987 wpa_printf(MSG_DEBUG,
7988 "Failed to allocate memory for temp disallow BSS");
7989 return;
7990 }
7991
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007992 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7993 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007994 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08007995
7996finish:
7997 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007998 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7999 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008000}
8001
8002
Hai Shalom74f70d42019-02-11 14:42:39 -08008003int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8004 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008005{
Hai Shalom74f70d42019-02-11 14:42:39 -08008006 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008007
8008 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8009 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008010 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8011 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008012 break;
8013 }
8014 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008015 if (!disallowed)
8016 return 0;
8017
8018 if (disallowed->rssi_threshold != 0 &&
8019 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008020 return 0;
8021
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008022 return 1;
8023}
Hai Shalom81f62d82019-07-22 12:10:00 -07008024
8025
8026int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8027 unsigned int type, const u8 *addr,
8028 const u8 *mask)
8029{
8030 if ((addr && !mask) || (!addr && mask)) {
8031 wpa_printf(MSG_INFO,
8032 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8033 return -1;
8034 }
8035
8036 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8037 wpa_printf(MSG_INFO,
8038 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8039 return -1;
8040 }
8041
8042 if (type & MAC_ADDR_RAND_SCAN) {
8043 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8044 addr, mask))
8045 return -1;
8046 }
8047
8048 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8049 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8050 addr, mask))
8051 return -1;
8052
8053 if (wpa_s->sched_scanning && !wpa_s->pno)
8054 wpas_scan_restart_sched_scan(wpa_s);
8055 }
8056
8057 if (type & MAC_ADDR_RAND_PNO) {
8058 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8059 addr, mask))
8060 return -1;
8061
8062 if (wpa_s->pno) {
8063 wpas_stop_pno(wpa_s);
8064 wpas_start_pno(wpa_s);
8065 }
8066 }
8067
8068 return 0;
8069}
8070
8071
8072int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8073 unsigned int type)
8074{
8075 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8076 if (wpa_s->pno) {
8077 if (type & MAC_ADDR_RAND_PNO) {
8078 wpas_stop_pno(wpa_s);
8079 wpas_start_pno(wpa_s);
8080 }
8081 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8082 wpas_scan_restart_sched_scan(wpa_s);
8083 }
8084
8085 return 0;
8086}
Hai Shalomfdcde762020-04-02 11:19:20 -07008087
8088
8089int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8090 struct wpa_signal_info *si)
8091{
8092 int res;
8093
8094 if (!wpa_s->driver->signal_poll)
8095 return -1;
8096
8097 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8098
8099#ifdef CONFIG_TESTING_OPTIONS
8100 if (res == 0) {
8101 struct driver_signal_override *dso;
8102
8103 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8104 struct driver_signal_override, list) {
8105 if (os_memcmp(wpa_s->bssid, dso->bssid,
8106 ETH_ALEN) != 0)
8107 continue;
8108 wpa_printf(MSG_DEBUG,
8109 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8110 si->current_signal,
8111 dso->si_current_signal,
8112 si->avg_signal,
8113 dso->si_avg_signal,
8114 si->avg_beacon_signal,
8115 dso->si_avg_beacon_signal,
8116 si->current_noise,
8117 dso->si_current_noise);
8118 si->current_signal = dso->si_current_signal;
8119 si->avg_signal = dso->si_avg_signal;
8120 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8121 si->current_noise = dso->si_current_noise;
8122 break;
8123 }
8124 }
8125#endif /* CONFIG_TESTING_OPTIONS */
8126
8127 return res;
8128}
8129
8130
8131struct wpa_scan_results *
8132wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8133{
8134 struct wpa_scan_results *scan_res;
8135#ifdef CONFIG_TESTING_OPTIONS
8136 size_t idx;
8137#endif /* CONFIG_TESTING_OPTIONS */
8138
8139 if (!wpa_s->driver->get_scan_results2)
8140 return NULL;
8141
8142 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8143
8144#ifdef CONFIG_TESTING_OPTIONS
8145 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8146 struct driver_signal_override *dso;
8147 struct wpa_scan_res *res = scan_res->res[idx];
8148
8149 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8150 struct driver_signal_override, list) {
8151 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8152 continue;
8153 wpa_printf(MSG_DEBUG,
8154 "Override driver scan signal level %d->%d for "
8155 MACSTR,
8156 res->level, dso->scan_level,
8157 MAC2STR(res->bssid));
8158 res->flags |= WPA_SCAN_QUAL_INVALID;
8159 if (dso->scan_level < 0)
8160 res->flags |= WPA_SCAN_LEVEL_DBM;
8161 else
8162 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8163 res->level = dso->scan_level;
8164 break;
8165 }
8166 }
8167#endif /* CONFIG_TESTING_OPTIONS */
8168
8169 return scan_res;
8170}