blob: d4294966a49cc0665338afa32ad28f4c68a9f311 [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);
1643
1644 /* Extended Key ID is only supported in infrastructure BSS so far */
1645 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1646 (ssid->proto & WPA_PROTO_RSN) &&
1647 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1648 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1649 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1650 int use_ext_key_id = 0;
1651
1652 wpa_msg(wpa_s, MSG_DEBUG,
1653 "WPA: Enable Extended Key ID support");
1654 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1655 wpa_s->conf->extended_key_id);
1656 if (bss_rsn &&
1657 wpa_s->conf->extended_key_id &&
1658 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1659 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1660 use_ext_key_id = 1;
1661 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1662 use_ext_key_id);
1663 } else {
1664 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1665 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1666 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001667
1668 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1669 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1670 return -1;
1671 }
1672
Hai Shalomc3565922019-10-28 11:58:20 -07001673 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1674 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1675 &wpa_s->rsnxe_len)) {
1676 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1677 return -1;
1678 }
1679
Hai Shalom021b0b52019-04-10 11:17:58 -07001680 if (0) {
1681#ifdef CONFIG_DPP
1682 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1683 /* Use PMK from DPP network introduction (PMKSA entry) */
1684 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1685#endif /* CONFIG_DPP */
1686 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001687 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001688 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001689
Roshan Pius3a1667e2018-07-03 15:17:14 -07001690 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1691 WPA_KEY_MGMT_FT_PSK |
1692 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1693
1694 if (ssid->psk_set && !sae_only) {
1695 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1696 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001697 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1698 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001699 psk_set = 1;
1700 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001701
Roshan Pius3a1667e2018-07-03 15:17:14 -07001702 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1703 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001704 psk_set = 1;
1705
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001706#ifndef CONFIG_NO_PBKDF2
1707 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001708 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001709 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001710 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1711 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001712 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1713 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001714 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001715 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001716 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001717 }
1718#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001719#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001720 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001721 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1722 ssid->ext_psk);
1723 char pw_str[64 + 1];
1724 u8 psk[PMK_LEN];
1725
1726 if (pw == NULL) {
1727 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1728 "found from external storage");
1729 return -1;
1730 }
1731
1732 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1733 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1734 "PSK length %d in external storage",
1735 (int) wpabuf_len(pw));
1736 ext_password_free(pw);
1737 return -1;
1738 }
1739
1740 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1741 pw_str[wpabuf_len(pw)] = '\0';
1742
1743#ifndef CONFIG_NO_PBKDF2
1744 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1745 {
1746 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1747 4096, psk, PMK_LEN);
1748 os_memset(pw_str, 0, sizeof(pw_str));
1749 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1750 "external passphrase)",
1751 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001752 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1753 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001754 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001755 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001756 } else
1757#endif /* CONFIG_NO_PBKDF2 */
1758 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1759 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1760 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1761 "Invalid PSK hex string");
1762 os_memset(pw_str, 0, sizeof(pw_str));
1763 ext_password_free(pw);
1764 return -1;
1765 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001766 wpa_hexdump_key(MSG_MSGDUMP,
1767 "PSK (from external PSK)",
1768 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001769 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1770 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001771 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001772 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001773 } else {
1774 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1775 "PSK available");
1776 os_memset(pw_str, 0, sizeof(pw_str));
1777 ext_password_free(pw);
1778 return -1;
1779 }
1780
1781 os_memset(pw_str, 0, sizeof(pw_str));
1782 ext_password_free(pw);
1783 }
1784#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001785
1786 if (!psk_set) {
1787 wpa_msg(wpa_s, MSG_INFO,
1788 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001789 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001790 return -1;
1791 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001792#ifdef CONFIG_OWE
1793 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1794 /* OWE Diffie-Hellman exchange in (Re)Association
1795 * Request/Response frames set the PMK, so do not override it
1796 * here. */
1797#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001798 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001799 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1800
Hai Shalomfdcde762020-04-02 11:19:20 -07001801 if (ssid->mode != WPAS_MODE_IBSS &&
1802 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1803 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1804 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1805 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1806 wpa_msg(wpa_s, MSG_INFO,
1807 "Disable PTK0 rekey support - replaced with reconnect");
1808 wpa_s->deny_ptk0_rekey = 1;
1809 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1810 } else {
1811 wpa_s->deny_ptk0_rekey = 0;
1812 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1813 }
1814
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001815 return 0;
1816}
1817
1818
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001819static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1820{
1821 *pos = 0x00;
1822
1823 switch (idx) {
1824 case 0: /* Bits 0-7 */
1825 break;
1826 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001827 if (wpa_s->conf->coloc_intf_reporting) {
1828 /* Bit 13 - Collocated Interference Reporting */
1829 *pos |= 0x20;
1830 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001831 break;
1832 case 2: /* Bits 16-23 */
1833#ifdef CONFIG_WNM
1834 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001835 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001836 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001837#endif /* CONFIG_WNM */
1838 break;
1839 case 3: /* Bits 24-31 */
1840#ifdef CONFIG_WNM
1841 *pos |= 0x02; /* Bit 25 - SSID List */
1842#endif /* CONFIG_WNM */
1843#ifdef CONFIG_INTERWORKING
1844 if (wpa_s->conf->interworking)
1845 *pos |= 0x80; /* Bit 31 - Interworking */
1846#endif /* CONFIG_INTERWORKING */
1847 break;
1848 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001849#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001850 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001851 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001852#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001853 break;
1854 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001855#ifdef CONFIG_HS20
1856 if (wpa_s->conf->hs20)
1857 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1858#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001859#ifdef CONFIG_MBO
1860 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1861#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001862 break;
1863 case 6: /* Bits 48-55 */
1864 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001865 case 7: /* Bits 56-63 */
1866 break;
1867 case 8: /* Bits 64-71 */
1868 if (wpa_s->conf->ftm_responder)
1869 *pos |= 0x40; /* Bit 70 - FTM responder */
1870 if (wpa_s->conf->ftm_initiator)
1871 *pos |= 0x80; /* Bit 71 - FTM initiator */
1872 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001873 case 9: /* Bits 72-79 */
1874#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001875 if (!wpa_s->disable_fils)
1876 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001877#endif /* CONFIG_FILS */
1878 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001879 }
1880}
1881
1882
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001883int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001884{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001885 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001886 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001887
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001888 if (len < wpa_s->extended_capa_len)
1889 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001890 if (buflen < (size_t) len + 2) {
1891 wpa_printf(MSG_INFO,
1892 "Not enough room for building extended capabilities element");
1893 return -1;
1894 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001895
1896 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001897 *pos++ = len;
1898 for (i = 0; i < len; i++, pos++) {
1899 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001900
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001901 if (i < wpa_s->extended_capa_len) {
1902 *pos &= ~wpa_s->extended_capa_mask[i];
1903 *pos |= wpa_s->extended_capa[i];
1904 }
1905 }
1906
1907 while (len > 0 && buf[1 + len] == 0) {
1908 len--;
1909 buf[1] = len;
1910 }
1911 if (len == 0)
1912 return 0;
1913
1914 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001915}
1916
1917
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001918static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1919 struct wpa_bss *test_bss)
1920{
1921 struct wpa_bss *bss;
1922
1923 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1924 if (bss == test_bss)
1925 return 1;
1926 }
1927
1928 return 0;
1929}
1930
1931
1932static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1933 struct wpa_ssid *test_ssid)
1934{
1935 struct wpa_ssid *ssid;
1936
1937 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1938 if (ssid == test_ssid)
1939 return 1;
1940 }
1941
1942 return 0;
1943}
1944
1945
1946int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1947 struct wpa_ssid *test_ssid)
1948{
1949 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1950 return 0;
1951
1952 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1953}
1954
1955
1956void wpas_connect_work_free(struct wpa_connect_work *cwork)
1957{
1958 if (cwork == NULL)
1959 return;
1960 os_free(cwork);
1961}
1962
1963
1964void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1965{
1966 struct wpa_connect_work *cwork;
1967 struct wpa_radio_work *work = wpa_s->connect_work;
1968
1969 if (!work)
1970 return;
1971
1972 wpa_s->connect_work = NULL;
1973 cwork = work->ctx;
1974 work->ctx = NULL;
1975 wpas_connect_work_free(cwork);
1976 radio_work_done(work);
1977}
1978
1979
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001980int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1981{
1982 struct os_reltime now;
1983 u8 addr[ETH_ALEN];
1984
1985 os_get_reltime(&now);
1986 if (wpa_s->last_mac_addr_style == style &&
1987 wpa_s->last_mac_addr_change.sec != 0 &&
1988 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1989 wpa_s->conf->rand_addr_lifetime)) {
1990 wpa_msg(wpa_s, MSG_DEBUG,
1991 "Previously selected random MAC address has not yet expired");
1992 return 0;
1993 }
1994
1995 switch (style) {
1996 case 1:
1997 if (random_mac_addr(addr) < 0)
1998 return -1;
1999 break;
2000 case 2:
2001 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2002 if (random_mac_addr_keep_oui(addr) < 0)
2003 return -1;
2004 break;
2005 default:
2006 return -1;
2007 }
2008
2009 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2010 wpa_msg(wpa_s, MSG_INFO,
2011 "Failed to set random MAC address");
2012 return -1;
2013 }
2014
2015 os_get_reltime(&wpa_s->last_mac_addr_change);
2016 wpa_s->mac_addr_changed = 1;
2017 wpa_s->last_mac_addr_style = style;
2018
2019 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2020 wpa_msg(wpa_s, MSG_INFO,
2021 "Could not update MAC address information");
2022 return -1;
2023 }
2024
2025 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2026 MAC2STR(addr));
2027
2028 return 0;
2029}
2030
2031
2032int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2033{
2034 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2035 !wpa_s->conf->preassoc_mac_addr)
2036 return 0;
2037
2038 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2039}
2040
2041
Hai Shalomc3565922019-10-28 11:58:20 -07002042static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2043{
2044#ifdef CONFIG_SAE
2045 int *groups = conf->sae_groups;
2046 int default_groups[] = { 19, 20, 21, 0 };
2047 const char *password;
2048
2049 if (!groups || groups[0] <= 0)
2050 groups = default_groups;
2051
2052 password = ssid->sae_password;
2053 if (!password)
2054 password = ssid->passphrase;
2055
Hai Shalomfdcde762020-04-02 11:19:20 -07002056 if ((conf->sae_pwe == 0 && !ssid->sae_password_id) || !password ||
2057 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002058 /* PT derivation not needed */
2059 sae_deinit_pt(ssid->pt);
2060 ssid->pt = NULL;
2061 return;
2062 }
2063
2064 if (ssid->pt)
2065 return; /* PT already derived */
2066 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2067 (const u8 *) password, os_strlen(password),
2068 ssid->sae_password_id);
2069#endif /* CONFIG_SAE */
2070}
2071
2072
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002073static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2074{
2075#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2076 os_free(wpa_s->sme.sae_rejected_groups);
2077 wpa_s->sme.sae_rejected_groups = NULL;
2078#ifdef CONFIG_TESTING_OPTIONS
2079 if (wpa_s->extra_sae_rejected_groups) {
2080 int i, *groups = wpa_s->extra_sae_rejected_groups;
2081
2082 for (i = 0; groups[i]; i++) {
2083 wpa_printf(MSG_DEBUG,
2084 "TESTING: Indicate rejection of an extra SAE group %d",
2085 groups[i]);
2086 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2087 groups[i]);
2088 }
2089 }
2090#endif /* CONFIG_TESTING_OPTIONS */
2091#endif /* CONFIG_SAE && CONFIG_SME */
2092}
2093
2094
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002095static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2096
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097/**
2098 * wpa_supplicant_associate - Request association
2099 * @wpa_s: Pointer to wpa_supplicant data
2100 * @bss: Scan results for the selected BSS, or %NULL if not available
2101 * @ssid: Configuration data for the selected network
2102 *
2103 * This function is used to request %wpa_supplicant to associate with a BSS.
2104 */
2105void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2106 struct wpa_bss *bss, struct wpa_ssid *ssid)
2107{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002108 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002109 int rand_style;
2110
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002111 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002112 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002113
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002114 /*
2115 * If we are starting a new connection, any previously pending EAPOL
2116 * RX cannot be valid anymore.
2117 */
2118 wpabuf_free(wpa_s->pending_eapol_rx);
2119 wpa_s->pending_eapol_rx = NULL;
2120
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002121 if (ssid->mac_addr == -1)
2122 rand_style = wpa_s->conf->mac_addr;
2123 else
2124 rand_style = ssid->mac_addr;
2125
Hai Shalomfdcde762020-04-02 11:19:20 -07002126 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002127 wmm_ac_clear_saved_tspecs(wpa_s);
2128 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002129 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002130#ifdef CONFIG_TESTING_OPTIONS
2131 wpa_s->testing_resend_assoc = 0;
2132#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002133
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002134 if (wpa_s->last_ssid == ssid) {
2135 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002136 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002137 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2138 wmm_ac_save_tspecs(wpa_s);
2139 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002140 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2141 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002142 }
Hai Shalomc3565922019-10-28 11:58:20 -07002143 } else {
2144#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002145 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002146 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2147#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002148 }
2149
2150 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002151 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2152 return;
2153 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002154 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002155 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2156 wpa_msg(wpa_s, MSG_INFO,
2157 "Could not restore permanent MAC address");
2158 return;
2159 }
2160 wpa_s->mac_addr_changed = 0;
2161 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2162 wpa_msg(wpa_s, MSG_INFO,
2163 "Could not update MAC address information");
2164 return;
2165 }
2166 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2167 }
2168 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169
2170#ifdef CONFIG_IBSS_RSN
2171 ibss_rsn_deinit(wpa_s->ibss_rsn);
2172 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002173#else /* CONFIG_IBSS_RSN */
2174 if (ssid->mode == WPAS_MODE_IBSS &&
2175 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2176 wpa_msg(wpa_s, MSG_INFO,
2177 "IBSS RSN not supported in the build");
2178 return;
2179 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002180#endif /* CONFIG_IBSS_RSN */
2181
2182 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2183 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2184#ifdef CONFIG_AP
2185 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2186 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2187 "mode");
2188 return;
2189 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002190 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2191 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002192 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2193 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002194 return;
2195 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002196 wpa_s->current_bss = bss;
2197#else /* CONFIG_AP */
2198 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2199 "the build");
2200#endif /* CONFIG_AP */
2201 return;
2202 }
2203
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002204 if (ssid->mode == WPAS_MODE_MESH) {
2205#ifdef CONFIG_MESH
2206 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2207 wpa_msg(wpa_s, MSG_INFO,
2208 "Driver does not support mesh mode");
2209 return;
2210 }
2211 if (bss)
2212 ssid->frequency = bss->freq;
2213 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2214 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2215 return;
2216 }
2217 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002218 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
2219 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
2220 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002221 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002222#else /* CONFIG_MESH */
2223 wpa_msg(wpa_s, MSG_ERROR,
2224 "mesh mode support not included in the build");
2225#endif /* CONFIG_MESH */
2226 return;
2227 }
2228
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002229 /*
2230 * Set WPA state machine configuration to match the selected network now
2231 * so that the information is available before wpas_start_assoc_cb()
2232 * gets called. This is needed at least for RSN pre-authentication where
2233 * candidate APs are added to a list based on scan result processing
2234 * before completion of the first association.
2235 */
2236 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2237
2238#ifdef CONFIG_DPP
2239 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2240 return;
2241#endif /* CONFIG_DPP */
2242
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002243#ifdef CONFIG_TDLS
2244 if (bss)
2245 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2246 bss->ie_len);
2247#endif /* CONFIG_TDLS */
2248
Hai Shalomc3565922019-10-28 11:58:20 -07002249#ifdef CONFIG_MBO
2250 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2251#endif /* CONFIG_MBO */
2252
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002253 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002254 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002255 sme_authenticate(wpa_s, bss, ssid);
2256 return;
2257 }
2258
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002259 if (wpa_s->connect_work) {
2260 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2261 return;
2262 }
2263
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002264 if (radio_work_pending(wpa_s, "connect")) {
2265 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2266 return;
2267 }
2268
Dmitry Shmidt29333592017-01-09 12:27:11 -08002269#ifdef CONFIG_SME
2270 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2271 /* Clear possibly set auth_alg, if any, from last attempt. */
2272 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2273 }
2274#endif /* CONFIG_SME */
2275
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002276 wpas_abort_ongoing_scan(wpa_s);
2277
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002278 cwork = os_zalloc(sizeof(*cwork));
2279 if (cwork == NULL)
2280 return;
2281
2282 cwork->bss = bss;
2283 cwork->ssid = ssid;
2284
2285 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2286 wpas_start_assoc_cb, cwork) < 0) {
2287 os_free(cwork);
2288 }
2289}
2290
2291
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002292static int bss_is_ibss(struct wpa_bss *bss)
2293{
2294 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2295 IEEE80211_CAP_IBSS;
2296}
2297
2298
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002299static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2300 const struct wpa_ssid *ssid)
2301{
2302 enum hostapd_hw_mode hw_mode;
2303 struct hostapd_hw_modes *mode = NULL;
2304 u8 channel;
2305 int i;
2306
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002307 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2308 if (hw_mode == NUM_HOSTAPD_MODES)
2309 return 0;
2310 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2311 if (wpa_s->hw.modes[i].mode == hw_mode) {
2312 mode = &wpa_s->hw.modes[i];
2313 break;
2314 }
2315 }
2316
2317 if (!mode)
2318 return 0;
2319
2320 return mode->vht_capab != 0;
2321}
2322
2323
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002324void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2325 const struct wpa_ssid *ssid,
2326 struct hostapd_freq_params *freq)
2327{
Hai Shalom81f62d82019-07-22 12:10:00 -07002328 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002329 enum hostapd_hw_mode hw_mode;
2330 struct hostapd_hw_modes *mode = NULL;
2331 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2332 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002333 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002334 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2335 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002336 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002337 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002338 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002339 int chwidth, seg0, seg1;
2340 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002341 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002342
2343 freq->freq = ssid->frequency;
2344
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002345 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2346 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2347
2348 if (ssid->mode != WPAS_MODE_IBSS)
2349 break;
2350
2351 /* Don't adjust control freq in case of fixed_freq */
2352 if (ssid->fixed_freq)
2353 break;
2354
2355 if (!bss_is_ibss(bss))
2356 continue;
2357
2358 if (ssid->ssid_len == bss->ssid_len &&
2359 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2360 wpa_printf(MSG_DEBUG,
2361 "IBSS already found in scan results, adjust control freq: %d",
2362 bss->freq);
2363 freq->freq = bss->freq;
2364 obss_scan = 0;
2365 break;
2366 }
2367 }
2368
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002369 /* For IBSS check HT_IBSS flag */
2370 if (ssid->mode == WPAS_MODE_IBSS &&
2371 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2372 return;
2373
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002374 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2375 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2376 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2377 wpa_printf(MSG_DEBUG,
2378 "IBSS: WEP/TKIP detected, do not try to enable HT");
2379 return;
2380 }
2381
2382 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002383 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2384 if (wpa_s->hw.modes[i].mode == hw_mode) {
2385 mode = &wpa_s->hw.modes[i];
2386 break;
2387 }
2388 }
2389
2390 if (!mode)
2391 return;
2392
Hai Shalomc3565922019-10-28 11:58:20 -07002393 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2394 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002395
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002396#ifdef CONFIG_HT_OVERRIDES
2397 if (ssid->disable_ht) {
2398 freq->ht_enabled = 0;
2399 return;
2400 }
2401#endif /* CONFIG_HT_OVERRIDES */
2402
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002403 freq->ht_enabled = ht_supported(mode);
2404 if (!freq->ht_enabled)
2405 return;
2406
Hai Shalomc3565922019-10-28 11:58:20 -07002407 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2408 if (is_24ghz)
2409 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002410#ifdef CONFIG_HE_OVERRIDES
2411 if (is_24ghz && ssid->disable_he)
2412 freq->he_enabled = 0;
2413#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002414
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002415 /* Setup higher BW only for 5 GHz */
2416 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2417 return;
2418
2419 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2420 pri_chan = &mode->channels[chan_idx];
2421 if (pri_chan->chan == channel)
2422 break;
2423 pri_chan = NULL;
2424 }
2425 if (!pri_chan)
2426 return;
2427
2428 /* Check primary channel flags */
2429 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2430 return;
2431
Hai Shalom74f70d42019-02-11 14:42:39 -08002432 freq->channel = pri_chan->chan;
2433
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002434#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002435 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002436#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002437 if (ssid->disable_vht)
2438 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002439#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002440 goto skip_ht40;
2441 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002442#endif /* CONFIG_HT_OVERRIDES */
2443
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002444 /* Check/setup HT40+/HT40- */
2445 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2446 if (ht40plus[j] == channel) {
2447 ht40 = 1;
2448 break;
2449 }
2450 }
2451
2452 /* Find secondary channel */
2453 for (i = 0; i < mode->num_channels; i++) {
2454 sec_chan = &mode->channels[i];
2455 if (sec_chan->chan == channel + ht40 * 4)
2456 break;
2457 sec_chan = NULL;
2458 }
2459 if (!sec_chan)
2460 return;
2461
2462 /* Check secondary channel flags */
2463 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2464 return;
2465
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002466 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002467 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2468 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002469 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002470 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2471 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002472 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002473 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002474
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002475 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002476 struct wpa_scan_results *scan_res;
2477
2478 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2479 if (scan_res == NULL) {
2480 /* Back to HT20 */
2481 freq->sec_channel_offset = 0;
2482 return;
2483 }
2484
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002485 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002486 switch (res) {
2487 case 0:
2488 /* Back to HT20 */
2489 freq->sec_channel_offset = 0;
2490 break;
2491 case 1:
2492 /* Configuration allowed */
2493 break;
2494 case 2:
2495 /* Switch pri/sec channels */
2496 freq->freq = hw_get_freq(mode, sec_chan->chan);
2497 freq->sec_channel_offset = -freq->sec_channel_offset;
2498 freq->channel = sec_chan->chan;
2499 break;
2500 default:
2501 freq->sec_channel_offset = 0;
2502 break;
2503 }
2504
2505 wpa_scan_results_free(scan_res);
2506 }
2507
Hai Shalom74f70d42019-02-11 14:42:39 -08002508#ifdef CONFIG_HT_OVERRIDES
2509skip_ht40:
2510#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002511 wpa_printf(MSG_DEBUG,
2512 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2513 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002514
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002515 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002516 return;
2517
2518 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002519 if (ssid->mode == WPAS_MODE_IBSS &&
2520 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002521 return;
2522
2523 vht_freq = *freq;
2524
Paul Stewart092955c2017-02-06 09:13:09 -08002525#ifdef CONFIG_VHT_OVERRIDES
2526 if (ssid->disable_vht) {
2527 freq->vht_enabled = 0;
2528 return;
2529 }
2530#endif /* CONFIG_VHT_OVERRIDES */
2531
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002532 vht_freq.vht_enabled = vht_supported(mode);
2533 if (!vht_freq.vht_enabled)
2534 return;
2535
Hai Shalomfdcde762020-04-02 11:19:20 -07002536 /* Enable HE with VHT for 5 GHz */
2537 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002538
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002539 /* setup center_freq1, bandwidth */
2540 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2541 if (freq->channel >= vht80[j] &&
2542 freq->channel < vht80[j] + 16)
2543 break;
2544 }
2545
2546 if (j == ARRAY_SIZE(vht80))
2547 return;
2548
2549 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2550 struct hostapd_channel_data *chan;
2551
2552 chan = hw_get_channel_chan(mode, i, NULL);
2553 if (!chan)
2554 return;
2555
2556 /* Back to HT configuration if channel not usable */
2557 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2558 return;
2559 }
2560
Hai Shalom81f62d82019-07-22 12:10:00 -07002561 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002562 seg0 = vht80[j] + 6;
2563 seg1 = 0;
2564
Hai Shalom81f62d82019-07-22 12:10:00 -07002565 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002566 /* setup center_freq2, bandwidth */
2567 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2568 /* Only accept 80 MHz segments separated by a gap */
2569 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2570 continue;
2571 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2572 struct hostapd_channel_data *chan;
2573
2574 chan = hw_get_channel_chan(mode, i, NULL);
2575 if (!chan)
2576 continue;
2577
2578 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2579 HOSTAPD_CHAN_NO_IR |
2580 HOSTAPD_CHAN_RADAR))
2581 continue;
2582
2583 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002584 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002585 vht_caps |=
2586 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2587 seg1 = vht80[k] + 6;
2588 }
2589
Hai Shalom81f62d82019-07-22 12:10:00 -07002590 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002591 break;
2592 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002593 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002594 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002595 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002596 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2597 seg0 = 50;
2598 } else if (freq->freq == 5520) {
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 = 114;
2602 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002603 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2604 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002605 seg0 = vht80[j] + 2;
2606#ifdef CONFIG_HT_OVERRIDES
2607 if (ssid->disable_ht40)
2608 seg0 = 0;
2609#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002610 }
2611
Hai Shalomfdcde762020-04-02 11:19:20 -07002612#ifdef CONFIG_HE_OVERRIDES
2613 if (ssid->disable_he) {
2614 vht_freq.he_enabled = 0;
2615 freq->he_enabled = 0;
2616 }
2617#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002618 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002619 freq->channel, ssid->enable_edmg,
2620 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002621 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002622 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002623 chwidth, seg0, seg1, vht_caps,
2624 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002625 return;
2626
2627 *freq = vht_freq;
2628
2629 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2630 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002631}
2632
2633
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002634#ifdef CONFIG_FILS
2635static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2636 size_t ie_buf_len)
2637{
2638 struct fils_hlp_req *req;
2639 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2640 const u8 *pos;
2641 u8 *buf = ie_buf;
2642
2643 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2644 list) {
2645 rem_len = ie_buf_len - ie_len;
2646 pos = wpabuf_head(req->pkt);
2647 hdr_len = 1 + 2 * ETH_ALEN + 6;
2648 hlp_len = wpabuf_len(req->pkt);
2649
2650 if (rem_len < 2 + hdr_len + hlp_len) {
2651 wpa_printf(MSG_ERROR,
2652 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2653 (unsigned long) rem_len,
2654 (unsigned long) (2 + hdr_len + hlp_len));
2655 break;
2656 }
2657
2658 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2659 /* Element ID */
2660 *buf++ = WLAN_EID_EXTENSION;
2661 /* Length */
2662 *buf++ = len;
2663 /* Element ID Extension */
2664 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2665 /* Destination MAC address */
2666 os_memcpy(buf, req->dst, ETH_ALEN);
2667 buf += ETH_ALEN;
2668 /* Source MAC address */
2669 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2670 buf += ETH_ALEN;
2671 /* LLC/SNAP Header */
2672 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2673 buf += 6;
2674 /* HLP Packet */
2675 os_memcpy(buf, pos, len - hdr_len);
2676 buf += len - hdr_len;
2677 pos += len - hdr_len;
2678
2679 hlp_len -= len - hdr_len;
2680 ie_len += 2 + len;
2681 rem_len -= 2 + len;
2682
2683 while (hlp_len) {
2684 len = (hlp_len > 255) ? 255 : hlp_len;
2685 if (rem_len < 2 + len)
2686 break;
2687 *buf++ = WLAN_EID_FRAGMENT;
2688 *buf++ = len;
2689 os_memcpy(buf, pos, len);
2690 buf += len;
2691 pos += len;
2692
2693 hlp_len -= len;
2694 ie_len += 2 + len;
2695 rem_len -= 2 + len;
2696 }
2697 }
2698
2699 return ie_len;
2700}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002701
2702
2703int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2704{
2705 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2706 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2707 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2708 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2709}
2710
2711
2712int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2713{
2714#ifdef CONFIG_FILS_SK_PFS
2715 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2716 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2717#else /* CONFIG_FILS_SK_PFS */
2718 return 0;
2719#endif /* CONFIG_FILS_SK_PFS */
2720}
2721
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002722#endif /* CONFIG_FILS */
2723
2724
2725static u8 * wpas_populate_assoc_ies(
2726 struct wpa_supplicant *wpa_s,
2727 struct wpa_bss *bss, struct wpa_ssid *ssid,
2728 struct wpa_driver_associate_params *params,
2729 enum wpa_drv_update_connect_params_mask *mask)
2730{
2731 u8 *wpa_ie;
2732 size_t max_wpa_ie_len = 500;
2733 size_t wpa_ie_len;
2734 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002735#ifdef CONFIG_MBO
2736 const u8 *mbo_ie;
2737#endif
Hai Shalom5f92bc92019-04-18 11:54:11 -07002738#ifdef CONFIG_SAE
2739 int sae_pmksa_cached = 0;
2740#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002741#ifdef CONFIG_FILS
2742 const u8 *realm, *username, *rrk;
2743 size_t realm_len, username_len, rrk_len;
2744 u16 next_seq_num;
2745 struct fils_hlp_req *req;
2746
2747 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2748 list) {
2749 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2750 2 + 2 * wpabuf_len(req->pkt) / 255;
2751 }
2752#endif /* CONFIG_FILS */
2753
2754 wpa_ie = os_malloc(max_wpa_ie_len);
2755 if (!wpa_ie) {
2756 wpa_printf(MSG_ERROR,
2757 "Failed to allocate connect IE buffer for %lu bytes",
2758 (unsigned long) max_wpa_ie_len);
2759 return NULL;
2760 }
2761
2762 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2763 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2764 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2765 int try_opportunistic;
2766 const u8 *cache_id = NULL;
2767
2768 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2769 wpa_s->conf->okc :
2770 ssid->proactive_key_caching) &&
2771 (ssid->proto & WPA_PROTO_RSN);
2772#ifdef CONFIG_FILS
2773 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2774 cache_id = wpa_bss_get_fils_cache_id(bss);
2775#endif /* CONFIG_FILS */
2776 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2777 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002778 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002779 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Hai Shalom5f92bc92019-04-18 11:54:11 -07002780#ifdef CONFIG_SAE
2781 sae_pmksa_cached = 1;
2782#endif /* CONFIG_SAE */
2783 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002784 wpa_ie_len = max_wpa_ie_len;
2785 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2786 wpa_ie, &wpa_ie_len)) {
2787 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2788 "key management and encryption suites");
2789 os_free(wpa_ie);
2790 return NULL;
2791 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002792#ifdef CONFIG_HS20
2793 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2794 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2795 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2796 wpa_ie_len = max_wpa_ie_len;
2797 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2798 wpa_ie, &wpa_ie_len)) {
2799 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2800 "key management and encryption suites");
2801 os_free(wpa_ie);
2802 return NULL;
2803 }
2804#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002805 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2806 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2807 /*
2808 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2809 * use non-WPA since the scan results did not indicate that the
2810 * AP is using WPA or WPA2.
2811 */
2812 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2813 wpa_ie_len = 0;
2814 wpa_s->wpa_proto = 0;
2815 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2816 wpa_ie_len = max_wpa_ie_len;
2817 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2818 wpa_ie, &wpa_ie_len)) {
2819 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2820 "key management and encryption suites (no "
2821 "scan results)");
2822 os_free(wpa_ie);
2823 return NULL;
2824 }
2825#ifdef CONFIG_WPS
2826 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2827 struct wpabuf *wps_ie;
2828 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2829 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2830 wpa_ie_len = wpabuf_len(wps_ie);
2831 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2832 } else
2833 wpa_ie_len = 0;
2834 wpabuf_free(wps_ie);
2835 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2836 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2837 params->wps = WPS_MODE_PRIVACY;
2838 else
2839 params->wps = WPS_MODE_OPEN;
2840 wpa_s->wpa_proto = 0;
2841#endif /* CONFIG_WPS */
2842 } else {
2843 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2844 wpa_ie_len = 0;
2845 wpa_s->wpa_proto = 0;
2846 }
2847
2848#ifdef IEEE8021X_EAPOL
2849 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2850 if (ssid->leap) {
2851 if (ssid->non_leap == 0)
2852 algs = WPA_AUTH_ALG_LEAP;
2853 else
2854 algs |= WPA_AUTH_ALG_LEAP;
2855 }
2856 }
2857
2858#ifdef CONFIG_FILS
2859 /* Clear FILS association */
2860 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2861
2862 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2863 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2864 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2865 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002866 &next_seq_num, &rrk, &rrk_len) == 0 &&
2867 (!wpa_s->last_con_fail_realm ||
2868 wpa_s->last_con_fail_realm_len != realm_len ||
2869 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002870 algs = WPA_AUTH_ALG_FILS;
2871 params->fils_erp_username = username;
2872 params->fils_erp_username_len = username_len;
2873 params->fils_erp_realm = realm;
2874 params->fils_erp_realm_len = realm_len;
2875 params->fils_erp_next_seq_num = next_seq_num;
2876 params->fils_erp_rrk = rrk;
2877 params->fils_erp_rrk_len = rrk_len;
2878
2879 if (mask)
2880 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2881 }
2882#endif /* CONFIG_FILS */
2883#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002884#ifdef CONFIG_SAE
2885 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2886 algs = WPA_AUTH_ALG_SAE;
2887#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002888
2889 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2890 if (ssid->auth_alg) {
2891 algs = ssid->auth_alg;
2892 wpa_dbg(wpa_s, MSG_DEBUG,
2893 "Overriding auth_alg selection: 0x%x", algs);
2894 }
2895
Hai Shalom5f92bc92019-04-18 11:54:11 -07002896#ifdef CONFIG_SAE
2897 if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
2898 wpa_dbg(wpa_s, MSG_DEBUG,
2899 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2900 algs = WPA_AUTH_ALG_OPEN;
2901 }
2902#endif /* CONFIG_SAE */
2903
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002904#ifdef CONFIG_P2P
2905 if (wpa_s->global->p2p) {
2906 u8 *pos;
2907 size_t len;
2908 int res;
2909 pos = wpa_ie + wpa_ie_len;
2910 len = max_wpa_ie_len - wpa_ie_len;
2911 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2912 ssid->p2p_group);
2913 if (res >= 0)
2914 wpa_ie_len += res;
2915 }
2916
2917 wpa_s->cross_connect_disallowed = 0;
2918 if (bss) {
2919 struct wpabuf *p2p;
2920 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2921 if (p2p) {
2922 wpa_s->cross_connect_disallowed =
2923 p2p_get_cross_connect_disallowed(p2p);
2924 wpabuf_free(p2p);
2925 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2926 "connection",
2927 wpa_s->cross_connect_disallowed ?
2928 "disallows" : "allows");
2929 }
2930 }
2931
2932 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2933#endif /* CONFIG_P2P */
2934
2935 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002936 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002937 wpa_ie + wpa_ie_len,
2938 max_wpa_ie_len -
2939 wpa_ie_len);
2940 }
2941
2942 /*
2943 * Workaround: Add Extended Capabilities element only if the AP
2944 * included this element in Beacon/Probe Response frames. Some older
2945 * APs seem to have interoperability issues if this element is
2946 * included, so while the standard may require us to include the
2947 * element in all cases, it is justifiable to skip it to avoid
2948 * interoperability issues.
2949 */
2950 if (ssid->p2p_group)
2951 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2952 else
2953 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2954
2955 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2956 u8 ext_capab[18];
2957 int ext_capab_len;
2958 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2959 sizeof(ext_capab));
2960 if (ext_capab_len > 0 &&
2961 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2962 u8 *pos = wpa_ie;
2963 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2964 pos += 2 + pos[1];
2965 os_memmove(pos + ext_capab_len, pos,
2966 wpa_ie_len - (pos - wpa_ie));
2967 wpa_ie_len += ext_capab_len;
2968 os_memcpy(pos, ext_capab, ext_capab_len);
2969 }
2970 }
2971
2972#ifdef CONFIG_HS20
2973 if (is_hs20_network(wpa_s, ssid, bss)) {
2974 struct wpabuf *hs20;
2975
Roshan Pius3a1667e2018-07-03 15:17:14 -07002976 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002977 if (hs20) {
2978 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2979 size_t len;
2980
Hai Shalom74f70d42019-02-11 14:42:39 -08002981 wpas_hs20_add_indication(hs20, pps_mo_id,
2982 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002983 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002984 len = max_wpa_ie_len - wpa_ie_len;
2985 if (wpabuf_len(hs20) <= len) {
2986 os_memcpy(wpa_ie + wpa_ie_len,
2987 wpabuf_head(hs20), wpabuf_len(hs20));
2988 wpa_ie_len += wpabuf_len(hs20);
2989 }
2990 wpabuf_free(hs20);
2991
2992 hs20_configure_frame_filters(wpa_s);
2993 }
2994 }
2995#endif /* CONFIG_HS20 */
2996
2997 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2998 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2999 size_t len;
3000
3001 len = max_wpa_ie_len - wpa_ie_len;
3002 if (wpabuf_len(buf) <= len) {
3003 os_memcpy(wpa_ie + wpa_ie_len,
3004 wpabuf_head(buf), wpabuf_len(buf));
3005 wpa_ie_len += wpabuf_len(buf);
3006 }
3007 }
3008
3009#ifdef CONFIG_FST
3010 if (wpa_s->fst_ies) {
3011 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3012
3013 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3014 os_memcpy(wpa_ie + wpa_ie_len,
3015 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3016 wpa_ie_len += fst_ies_len;
3017 }
3018 }
3019#endif /* CONFIG_FST */
3020
3021#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003022 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003023 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003024 int len;
3025
3026 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003027 max_wpa_ie_len - wpa_ie_len,
3028 !!mbo_attr_from_mbo_ie(mbo_ie,
3029 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003030 if (len >= 0)
3031 wpa_ie_len += len;
3032 }
3033#endif /* CONFIG_MBO */
3034
3035#ifdef CONFIG_FILS
3036 if (algs == WPA_AUTH_ALG_FILS) {
3037 size_t len;
3038
3039 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3040 max_wpa_ie_len - wpa_ie_len);
3041 wpa_ie_len += len;
3042 }
3043#endif /* CONFIG_FILS */
3044
3045#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003046#ifdef CONFIG_TESTING_OPTIONS
3047 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3048 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3049 } else
3050#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003051 if (algs == WPA_AUTH_ALG_OPEN &&
3052 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3053 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003054 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003055
Roshan Pius3a1667e2018-07-03 15:17:14 -07003056 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003057 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003058 } else if (wpa_s->assoc_status_code ==
3059 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003060 if (wpa_s->last_owe_group == 19)
3061 group = 20;
3062 else if (wpa_s->last_owe_group == 20)
3063 group = 21;
3064 else
3065 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003066 } else {
3067 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003068 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003069
Roshan Pius3a1667e2018-07-03 15:17:14 -07003070 wpa_s->last_owe_group = group;
3071 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003072 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3073 if (owe_ie &&
3074 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3075 os_memcpy(wpa_ie + wpa_ie_len,
3076 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3077 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003078 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003079 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003080 }
3081#endif /* CONFIG_OWE */
3082
Hai Shalom021b0b52019-04-10 11:17:58 -07003083#ifdef CONFIG_DPP2
3084 if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003085 ssid->dpp_netaccesskey &&
3086 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003087 dpp_pfs_free(wpa_s->dpp_pfs);
3088 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3089 ssid->dpp_netaccesskey_len);
3090 if (!wpa_s->dpp_pfs) {
3091 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3092 /* Try to continue without PFS */
3093 goto pfs_fail;
3094 }
3095 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3096 max_wpa_ie_len - wpa_ie_len) {
3097 os_memcpy(wpa_ie + wpa_ie_len,
3098 wpabuf_head(wpa_s->dpp_pfs->ie),
3099 wpabuf_len(wpa_s->dpp_pfs->ie));
3100 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3101 }
3102 }
3103pfs_fail:
3104#endif /* CONFIG_DPP2 */
3105
Roshan Pius3a1667e2018-07-03 15:17:14 -07003106#ifdef CONFIG_IEEE80211R
3107 /*
3108 * Add MDIE under these conditions: the network profile allows FT,
3109 * the AP supports FT, and the mobility domain ID matches.
3110 */
3111 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3112 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3113
3114 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3115 size_t len = 0;
3116 const u8 *md = mdie + 2;
3117 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3118
3119 if (os_memcmp(md, wpa_md,
3120 MOBILITY_DOMAIN_ID_LEN) == 0) {
3121 /* Add mobility domain IE */
3122 len = wpa_ft_add_mdie(
3123 wpa_s->wpa, wpa_ie + wpa_ie_len,
3124 max_wpa_ie_len - wpa_ie_len, mdie);
3125 wpa_ie_len += len;
3126 }
3127#ifdef CONFIG_SME
3128 if (len > 0 && wpa_s->sme.ft_used &&
3129 wpa_sm_has_ptk(wpa_s->wpa)) {
3130 wpa_dbg(wpa_s, MSG_DEBUG,
3131 "SME: Trying to use FT over-the-air");
3132 algs |= WPA_AUTH_ALG_FT;
3133 }
3134#endif /* CONFIG_SME */
3135 }
3136 }
3137#endif /* CONFIG_IEEE80211R */
3138
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003139#ifdef CONFIG_TESTING_OPTIONS
3140 if (wpa_s->rsnxe_override_assoc &&
3141 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3142 max_wpa_ie_len - wpa_ie_len) {
3143 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3144 os_memcpy(wpa_ie + wpa_ie_len,
3145 wpabuf_head(wpa_s->rsnxe_override_assoc),
3146 wpabuf_len(wpa_s->rsnxe_override_assoc));
3147 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3148 } else
3149#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003150 if (wpa_s->rsnxe_len > 0 &&
3151 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3152 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3153 wpa_ie_len += wpa_s->rsnxe_len;
3154 }
3155
Hai Shalom74f70d42019-02-11 14:42:39 -08003156 if (ssid->multi_ap_backhaul_sta) {
3157 size_t multi_ap_ie_len;
3158
3159 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3160 max_wpa_ie_len - wpa_ie_len,
3161 MULTI_AP_BACKHAUL_STA);
3162 if (multi_ap_ie_len == 0) {
3163 wpa_printf(MSG_ERROR,
3164 "Multi-AP: Failed to build Multi-AP IE");
3165 os_free(wpa_ie);
3166 return NULL;
3167 }
3168 wpa_ie_len += multi_ap_ie_len;
3169 }
3170
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003171 params->wpa_ie = wpa_ie;
3172 params->wpa_ie_len = wpa_ie_len;
3173 params->auth_alg = algs;
3174 if (mask)
3175 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3176
3177 return wpa_ie;
3178}
3179
3180
Hai Shalomc3565922019-10-28 11:58:20 -07003181#ifdef CONFIG_OWE
3182static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3183{
3184 struct wpa_driver_associate_params params;
3185 u8 *wpa_ie;
3186
3187 os_memset(&params, 0, sizeof(params));
3188 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3189 wpa_s->current_ssid, &params, NULL);
3190 if (!wpa_ie)
3191 return;
3192
3193 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3194 os_free(wpa_ie);
3195}
3196#endif /* CONFIG_OWE */
3197
3198
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003199#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3200static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3201{
3202 struct wpa_driver_associate_params params;
3203 enum wpa_drv_update_connect_params_mask mask = 0;
3204 u8 *wpa_ie;
3205
3206 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3207 return; /* nothing to do */
3208
3209 os_memset(&params, 0, sizeof(params));
3210 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3211 wpa_s->current_ssid, &params, &mask);
3212 if (!wpa_ie)
3213 return;
3214
3215 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3216 os_free(wpa_ie);
3217 return;
3218 }
3219
3220 wpa_s->auth_alg = params.auth_alg;
3221 wpa_drv_update_connect_params(wpa_s, &params, mask);
3222 os_free(wpa_ie);
3223}
3224#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3225
3226
Hai Shalomc3565922019-10-28 11:58:20 -07003227static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3228{
3229 if (!edmg_ie || edmg_ie[1] < 6)
3230 return 0;
3231 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3232}
3233
3234
3235static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3236{
3237 if (!edmg_ie || edmg_ie[1] < 6)
3238 return 0;
3239 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3240}
3241
3242
3243/* Returns the intersection of two EDMG configurations.
3244 * Note: The current implementation is limited to CB2 only (CB1 included),
3245 * i.e., the implementation supports up to 2 contiguous channels.
3246 * For supporting non-contiguous (aggregated) channels and for supporting
3247 * CB3 and above, this function will need to be extended.
3248 */
3249static struct ieee80211_edmg_config
3250get_edmg_intersection(struct ieee80211_edmg_config a,
3251 struct ieee80211_edmg_config b,
3252 u8 primary_channel)
3253{
3254 struct ieee80211_edmg_config result;
3255 int i, contiguous = 0;
3256 int max_contiguous = 0;
3257
3258 result.channels = b.channels & a.channels;
3259 if (!result.channels) {
3260 wpa_printf(MSG_DEBUG,
3261 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3262 a.channels, b.channels);
3263 goto fail;
3264 }
3265
3266 if (!(result.channels & BIT(primary_channel - 1))) {
3267 wpa_printf(MSG_DEBUG,
3268 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3269 primary_channel, result.channels);
3270 goto fail;
3271 }
3272
3273 /* Find max contiguous channels */
3274 for (i = 0; i < 6; i++) {
3275 if (result.channels & BIT(i))
3276 contiguous++;
3277 else
3278 contiguous = 0;
3279
3280 if (contiguous > max_contiguous)
3281 max_contiguous = contiguous;
3282 }
3283
3284 /* Assuming AP and STA supports ONLY contiguous channels,
3285 * bw configuration can have value between 4-7.
3286 */
3287 if ((b.bw_config < a.bw_config))
3288 result.bw_config = b.bw_config;
3289 else
3290 result.bw_config = a.bw_config;
3291
3292 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3293 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3294 wpa_printf(MSG_DEBUG,
3295 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3296 max_contiguous);
3297 goto fail;
3298 }
3299
3300 return result;
3301
3302fail:
3303 result.channels = 0;
3304 result.bw_config = 0;
3305 return result;
3306}
3307
3308
3309static struct ieee80211_edmg_config
3310get_supported_edmg(struct wpa_supplicant *wpa_s,
3311 struct hostapd_freq_params *freq,
3312 struct ieee80211_edmg_config request_edmg)
3313{
3314 enum hostapd_hw_mode hw_mode;
3315 struct hostapd_hw_modes *mode = NULL;
3316 u8 primary_channel;
3317
3318 if (!wpa_s->hw.modes)
3319 goto fail;
3320
3321 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3322 if (hw_mode == NUM_HOSTAPD_MODES)
3323 goto fail;
3324
Hai Shalomfdcde762020-04-02 11:19:20 -07003325 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003326 if (!mode)
3327 goto fail;
3328
3329 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3330
3331fail:
3332 request_edmg.channels = 0;
3333 request_edmg.bw_config = 0;
3334 return request_edmg;
3335}
3336
3337
Hai Shalom021b0b52019-04-10 11:17:58 -07003338#ifdef CONFIG_MBO
3339void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3340{
3341 struct wpa_driver_associate_params params;
3342 u8 *wpa_ie;
3343
3344 /*
3345 * Update MBO connect params only in case of change of MBO attributes
3346 * when connected, if the AP support MBO.
3347 */
3348
3349 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3350 !wpa_s->current_bss ||
3351 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3352 return;
3353
3354 os_memset(&params, 0, sizeof(params));
3355 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3356 wpa_s->current_ssid, &params, NULL);
3357 if (!wpa_ie)
3358 return;
3359
3360 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3361 os_free(wpa_ie);
3362}
3363#endif /* CONFIG_MBO */
3364
3365
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003366static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3367{
3368 struct wpa_connect_work *cwork = work->ctx;
3369 struct wpa_bss *bss = cwork->bss;
3370 struct wpa_ssid *ssid = cwork->ssid;
3371 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003372 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003373 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003374 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003375 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003376 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003377#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003378 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003379#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003380 int assoc_failed = 0;
3381 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003382 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003383#ifdef CONFIG_HT_OVERRIDES
3384 struct ieee80211_ht_capabilities htcaps;
3385 struct ieee80211_ht_capabilities htcaps_mask;
3386#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003387#ifdef CONFIG_VHT_OVERRIDES
3388 struct ieee80211_vht_capabilities vhtcaps;
3389 struct ieee80211_vht_capabilities vhtcaps_mask;
3390#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003391
3392 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003393 if (work->started) {
3394 wpa_s->connect_work = NULL;
3395
3396 /* cancel possible auth. timeout */
3397 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3398 NULL);
3399 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003400 wpas_connect_work_free(cwork);
3401 return;
3402 }
3403
3404 wpa_s->connect_work = work;
3405
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003406 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3407 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003408 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3409 wpas_connect_work_done(wpa_s);
3410 return;
3411 }
3412
Dmitry Shmidte4663042016-04-04 10:07:49 -07003413 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003414 os_memset(&params, 0, sizeof(params));
3415 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003416 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003417 if (bss &&
3418 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003419#ifdef CONFIG_IEEE80211R
3420 const u8 *ie, *md = NULL;
3421#endif /* CONFIG_IEEE80211R */
3422 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3423 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3424 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3425 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3426 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3427 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3428 if (bssid_changed)
3429 wpas_notify_bssid_changed(wpa_s);
3430#ifdef CONFIG_IEEE80211R
3431 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3432 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3433 md = ie + 2;
3434 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3435 if (md) {
3436 /* Prepare for the next transition */
3437 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3438 }
3439#endif /* CONFIG_IEEE80211R */
3440#ifdef CONFIG_WPS
3441 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3442 wpa_s->conf->ap_scan == 2 &&
3443 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3444 /* Use ap_scan==1 style network selection to find the network
3445 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003446 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003447 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003448 wpa_s->reassociate = 1;
3449 wpa_supplicant_req_scan(wpa_s, 0, 0);
3450 return;
3451#endif /* CONFIG_WPS */
3452 } else {
3453 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3454 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003455 if (bss)
3456 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3457 else
3458 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003459 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003460 if (!wpa_s->pno)
3461 wpa_supplicant_cancel_sched_scan(wpa_s);
3462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463 wpa_supplicant_cancel_scan(wpa_s);
3464
3465 /* Starting new association, so clear the possibly used WPA IE from the
3466 * previous association. */
3467 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003468 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3469 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003470
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003471 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3472 if (!wpa_ie) {
3473 wpas_connect_work_done(wpa_s);
3474 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003475 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003476
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3478 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003479 cipher_pairwise = wpa_s->pairwise_cipher;
3480 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003481 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003482 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3483 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3484 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3485 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003486#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003487 if (wpa_set_wep_keys(wpa_s, ssid)) {
3488 use_crypt = 1;
3489 wep_keys_set = 1;
3490 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003491#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003492 }
3493 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3494 use_crypt = 0;
3495
3496#ifdef IEEE8021X_EAPOL
3497 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3498 if ((ssid->eapol_flags &
3499 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3500 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3501 !wep_keys_set) {
3502 use_crypt = 0;
3503 } else {
3504 /* Assume that dynamic WEP-104 keys will be used and
3505 * set cipher suites in order for drivers to expect
3506 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003507 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003508 }
3509 }
3510#endif /* IEEE8021X_EAPOL */
3511
3512 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3513 /* Set the key before (and later after) association */
3514 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3515 }
3516
3517 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3518 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003519 params.ssid = bss->ssid;
3520 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003521 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3522 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003523 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3524 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003525 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003526 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003527 ssid->bssid_set,
3528 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003529 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003530 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003531 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003532 params.bssid_hint = bss->bssid;
3533 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003534 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003535 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003536 if (ssid->bssid_hint_set)
3537 params.bssid_hint = ssid->bssid_hint;
3538
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003539 params.ssid = ssid->ssid;
3540 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003541 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003542 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003543
3544 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3545 wpa_s->conf->ap_scan == 2) {
3546 params.bssid = ssid->bssid;
3547 params.fixed_bssid = 1;
3548 }
3549
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003550 /* Initial frequency for IBSS/mesh */
3551 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003552 ssid->frequency > 0 && params.freq.freq == 0)
3553 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003554
3555 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003556 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003557 if (ssid->beacon_int)
3558 params.beacon_int = ssid->beacon_int;
3559 else
3560 params.beacon_int = wpa_s->conf->beacon_int;
3561 }
3562
Hai Shalomc3565922019-10-28 11:58:20 -07003563 if (bss && ssid->enable_edmg)
3564 edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len,
3565 WLAN_EID_EXT_EDMG_OPERATION);
3566 else
3567 edmg_ie_oper = NULL;
3568
3569 if (edmg_ie_oper) {
3570 params.freq.edmg.channels =
3571 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3572 params.freq.edmg.bw_config =
3573 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3574 wpa_printf(MSG_DEBUG,
3575 "AP supports EDMG channels 0x%x, bw_config %d",
3576 params.freq.edmg.channels,
3577 params.freq.edmg.bw_config);
3578
3579 /* User may ask for specific EDMG channel for EDMG connection
3580 * (must be supported by AP)
3581 */
3582 if (ssid->edmg_channel) {
3583 struct ieee80211_edmg_config configured_edmg;
3584 enum hostapd_hw_mode hw_mode;
3585 u8 primary_channel;
3586
3587 hw_mode = ieee80211_freq_to_chan(bss->freq,
3588 &primary_channel);
3589 if (hw_mode == NUM_HOSTAPD_MODES)
3590 goto edmg_fail;
3591
3592 hostapd_encode_edmg_chan(ssid->enable_edmg,
3593 ssid->edmg_channel,
3594 primary_channel,
3595 &configured_edmg);
3596
3597 if (ieee802_edmg_is_allowed(params.freq.edmg,
3598 configured_edmg)) {
3599 params.freq.edmg = configured_edmg;
3600 wpa_printf(MSG_DEBUG,
3601 "Use EDMG channel %d for connection",
3602 ssid->edmg_channel);
3603 } else {
3604 edmg_fail:
3605 params.freq.edmg.channels = 0;
3606 params.freq.edmg.bw_config = 0;
3607 wpa_printf(MSG_WARNING,
3608 "EDMG channel %d not supported by AP, fallback to DMG",
3609 ssid->edmg_channel);
3610 }
3611 }
3612
3613 if (params.freq.edmg.channels) {
3614 wpa_printf(MSG_DEBUG,
3615 "EDMG before: channels 0x%x, bw_config %d",
3616 params.freq.edmg.channels,
3617 params.freq.edmg.bw_config);
3618 params.freq.edmg = get_supported_edmg(wpa_s,
3619 &params.freq,
3620 params.freq.edmg);
3621 wpa_printf(MSG_DEBUG,
3622 "EDMG after: channels 0x%x, bw_config %d",
3623 params.freq.edmg.channels,
3624 params.freq.edmg.bw_config);
3625 }
3626 }
3627
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003628 params.pairwise_suite = cipher_pairwise;
3629 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003630 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003631 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003632 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003633 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003634 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003635 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003636#ifdef CONFIG_WEP
3637 {
3638 int i;
3639
3640 for (i = 0; i < NUM_WEP_KEYS; i++) {
3641 if (ssid->wep_key_len[i])
3642 params.wep_key[i] = ssid->wep_key[i];
3643 params.wep_key_len[i] = ssid->wep_key_len[i];
3644 }
3645 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003647#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003648
Hai Shalom74f70d42019-02-11 14:42:39 -08003649 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003650 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3651 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652 params.passphrase = ssid->passphrase;
3653 if (ssid->psk_set)
3654 params.psk = ssid->psk;
3655 }
3656
Hai Shalom74f70d42019-02-11 14:42:39 -08003657 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3658 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3659 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3660 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3661 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003662 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003663
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003664 if (wpa_s->conf->key_mgmt_offload) {
3665 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3666 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003667 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3668 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003669 params.req_key_mgmt_offload =
3670 ssid->proactive_key_caching < 0 ?
3671 wpa_s->conf->okc : ssid->proactive_key_caching;
3672 else
3673 params.req_key_mgmt_offload = 1;
3674
3675 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3676 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3677 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3678 ssid->psk_set)
3679 params.psk = ssid->psk;
3680 }
3681
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003682 params.drop_unencrypted = use_crypt;
3683
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003684 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003685 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003686 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3687 struct wpa_ie_data ie;
3688 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3689 ie.capabilities &
3690 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3691 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3692 "MFP: require MFP");
3693 params.mgmt_frame_protection =
3694 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003695#ifdef CONFIG_OWE
3696 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3697 !ssid->owe_only) {
3698 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3699#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003700 }
3701 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003702
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003703 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003704
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003705 if (wpa_s->p2pdev->set_sta_uapsd)
3706 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003707 else
3708 params.uapsd = -1;
3709
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003710#ifdef CONFIG_HT_OVERRIDES
3711 os_memset(&htcaps, 0, sizeof(htcaps));
3712 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3713 params.htcaps = (u8 *) &htcaps;
3714 params.htcaps_mask = (u8 *) &htcaps_mask;
3715 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3716#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003717#ifdef CONFIG_VHT_OVERRIDES
3718 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3719 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3720 params.vhtcaps = &vhtcaps;
3721 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003722 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003723#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003724#ifdef CONFIG_HE_OVERRIDES
3725 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3726#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003727
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003728#ifdef CONFIG_P2P
3729 /*
3730 * If multi-channel concurrency is not supported, check for any
3731 * frequency conflict. In case of any frequency conflict, remove the
3732 * least prioritized connection.
3733 */
3734 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003735 int freq, num;
3736 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003737 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003738 wpa_printf(MSG_DEBUG,
3739 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003740 freq, params.freq.freq);
3741 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003742 wpa_s, params.freq.freq, ssid) < 0) {
3743 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003744 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003745 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003746 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003747 }
3748 }
3749#endif /* CONFIG_P2P */
3750
Dmitry Shmidte4663042016-04-04 10:07:49 -07003751 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3752 wpa_s->current_ssid)
3753 params.prev_bssid = prev_bssid;
3754
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003755 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003756 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003757 if (ret < 0) {
3758 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3759 "failed");
3760 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3761 /*
3762 * The driver is known to mean what is saying, so we
3763 * can stop right here; the association will not
3764 * succeed.
3765 */
3766 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003767 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003768 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3769 return;
3770 }
3771 /* try to continue anyway; new association will be tried again
3772 * after timeout */
3773 assoc_failed = 1;
3774 }
3775
3776 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3777 /* Set the key after the association just in case association
3778 * cleared the previously configured key. */
3779 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3780 /* No need to timeout authentication since there is no key
3781 * management. */
3782 wpa_supplicant_cancel_auth_timeout(wpa_s);
3783 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3784#ifdef CONFIG_IBSS_RSN
3785 } else if (ssid->mode == WPAS_MODE_IBSS &&
3786 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3787 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3788 /*
3789 * RSN IBSS authentication is per-STA and we can disable the
3790 * per-BSSID authentication.
3791 */
3792 wpa_supplicant_cancel_auth_timeout(wpa_s);
3793#endif /* CONFIG_IBSS_RSN */
3794 } else {
3795 /* Timeout for IEEE 802.11 authentication and association */
3796 int timeout = 60;
3797
3798 if (assoc_failed) {
3799 /* give IBSS a bit more time */
3800 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3801 } else if (wpa_s->conf->ap_scan == 1) {
3802 /* give IBSS a bit more time */
3803 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3804 }
3805 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3806 }
3807
Hai Shalomfdcde762020-04-02 11:19:20 -07003808#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003809 if (wep_keys_set &&
3810 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003811 /* Set static WEP keys again */
3812 wpa_set_wep_keys(wpa_s, ssid);
3813 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003814#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003815
3816 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3817 /*
3818 * Do not allow EAP session resumption between different
3819 * network configurations.
3820 */
3821 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3822 }
3823 old_ssid = wpa_s->current_ssid;
3824 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003825
3826 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003827 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003828#ifdef CONFIG_HS20
3829 hs20_configure_frame_filters(wpa_s);
3830#endif /* CONFIG_HS20 */
3831 }
3832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003833 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3834 wpa_supplicant_initiate_eapol(wpa_s);
3835 if (old_ssid != wpa_s->current_ssid)
3836 wpas_notify_network_changed(wpa_s);
3837}
3838
3839
3840static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3841 const u8 *addr)
3842{
3843 struct wpa_ssid *old_ssid;
3844
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003845 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003846 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003847 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003848 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003849 wpa_sm_set_config(wpa_s->wpa, NULL);
3850 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3851 if (old_ssid != wpa_s->current_ssid)
3852 wpas_notify_network_changed(wpa_s);
3853 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3854}
3855
3856
3857/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003858 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3859 * @wpa_s: Pointer to wpa_supplicant data
3860 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3861 *
3862 * This function is used to request %wpa_supplicant to deauthenticate from the
3863 * current AP.
3864 */
3865void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003866 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003867{
3868 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003869 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003870 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003871
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003872 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003873 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003874 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003875 reason_code, reason2str(reason_code),
3876 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003877
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003878 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3879 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3880 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003881 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003882 else if (!is_zero_ether_addr(wpa_s->bssid))
3883 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003884 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3885 /*
3886 * When using driver-based BSS selection, we may not know the
3887 * BSSID with which we are currently trying to associate. We
3888 * need to notify the driver of this disconnection even in such
3889 * a case, so use the all zeros address here.
3890 */
3891 addr = wpa_s->bssid;
3892 zero_addr = 1;
3893 }
3894
Hai Shalom74f70d42019-02-11 14:42:39 -08003895 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3896 wpa_s->enabled_4addr_mode = 0;
3897
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003898#ifdef CONFIG_TDLS
3899 wpa_tdls_teardown_peers(wpa_s->wpa);
3900#endif /* CONFIG_TDLS */
3901
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003902#ifdef CONFIG_MESH
3903 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003904 struct mesh_conf *mconf;
3905
3906 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003907 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3908 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003909 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3910 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003911 wpa_supplicant_leave_mesh(wpa_s);
3912 }
3913#endif /* CONFIG_MESH */
3914
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003915 if (addr) {
3916 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003917 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07003918 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003919 event.deauth_info.locally_generated = 1;
3920 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003921 if (zero_addr)
3922 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 }
3924
3925 wpa_supplicant_clear_connection(wpa_s, addr);
3926}
3927
Hai Shalomfdcde762020-04-02 11:19:20 -07003928
3929void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
3930{
3931 wpa_s->own_reconnect_req = 1;
3932 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
3933
3934}
3935
3936
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003937static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3938 struct wpa_ssid *ssid)
3939{
3940 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3941 return;
3942
3943 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003944 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003945 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3946 wpas_notify_network_enabled_changed(wpa_s, ssid);
3947
3948 /*
3949 * Try to reassociate since there is no current configuration and a new
3950 * network was made available.
3951 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003952 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003953 wpa_s->reassociate = 1;
3954}
3955
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003956
Roshan Pius950bec92016-07-19 09:49:24 -07003957/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003958 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003959 * @wpa_s: wpa_supplicant structure for a network interface
3960 * Returns: The new network configuration or %NULL if operation failed
3961 *
3962 * This function performs the following operations:
3963 * 1. Adds a new network.
3964 * 2. Send network addition notification.
3965 * 3. Marks the network disabled.
3966 * 4. Set network default parameters.
3967 */
3968struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3969{
3970 struct wpa_ssid *ssid;
3971
3972 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003973 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003974 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003975 wpas_notify_network_added(wpa_s, ssid);
3976 ssid->disabled = 1;
3977 wpa_config_set_network_defaults(ssid);
3978
3979 return ssid;
3980}
3981
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003982
Roshan Pius950bec92016-07-19 09:49:24 -07003983/**
3984 * wpa_supplicant_remove_network - Remove a configured network based on id
3985 * @wpa_s: wpa_supplicant structure for a network interface
3986 * @id: Unique network id to search for
3987 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3988 * could not be removed
3989 *
3990 * This function performs the following operations:
3991 * 1. Removes the network.
3992 * 2. Send network removal notification.
3993 * 3. Update internal state machines.
3994 * 4. Stop any running sched scans.
3995 */
3996int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
3997{
3998 struct wpa_ssid *ssid;
3999 int was_disabled;
4000
4001 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004002 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004003 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004004 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004005
4006 if (wpa_s->last_ssid == ssid)
4007 wpa_s->last_ssid = NULL;
4008
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004009 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004010#ifdef CONFIG_SME
4011 wpa_s->sme.prev_bssid_set = 0;
4012#endif /* CONFIG_SME */
4013 /*
4014 * Invalidate the EAP session cache if the current or
4015 * previously used network is removed.
4016 */
4017 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4018 }
4019
4020 if (ssid == wpa_s->current_ssid) {
4021 wpa_sm_set_config(wpa_s->wpa, NULL);
4022 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4023
4024 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4025 wpa_s->own_disconnect_req = 1;
4026 wpa_supplicant_deauthenticate(wpa_s,
4027 WLAN_REASON_DEAUTH_LEAVING);
4028 }
4029
4030 was_disabled = ssid->disabled;
4031
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004032 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004033 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004034
4035 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004036 wpa_printf(MSG_DEBUG,
4037 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004038 wpa_supplicant_cancel_sched_scan(wpa_s);
4039 wpa_supplicant_req_scan(wpa_s, 0, 0);
4040 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004041
Roshan Pius950bec92016-07-19 09:49:24 -07004042 return 0;
4043}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004044
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004045
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004046/**
4047 * wpa_supplicant_enable_network - Mark a configured network as enabled
4048 * @wpa_s: wpa_supplicant structure for a network interface
4049 * @ssid: wpa_ssid structure for a configured network or %NULL
4050 *
4051 * Enables the specified network or all networks if no network specified.
4052 */
4053void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4054 struct wpa_ssid *ssid)
4055{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004056 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004057 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4058 wpa_supplicant_enable_one_network(wpa_s, ssid);
4059 } else
4060 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004061
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004062 if (wpa_s->reassociate && !wpa_s->disconnected &&
4063 (!wpa_s->current_ssid ||
4064 wpa_s->wpa_state == WPA_DISCONNECTED ||
4065 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004066 if (wpa_s->sched_scanning) {
4067 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4068 "new network to scan filters");
4069 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004070 }
4071
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004072 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4073 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004074 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004075 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004076 }
4077}
4078
4079
4080/**
4081 * wpa_supplicant_disable_network - Mark a configured network as disabled
4082 * @wpa_s: wpa_supplicant structure for a network interface
4083 * @ssid: wpa_ssid structure for a configured network or %NULL
4084 *
4085 * Disables the specified network or all networks if no network specified.
4086 */
4087void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4088 struct wpa_ssid *ssid)
4089{
4090 struct wpa_ssid *other_ssid;
4091 int was_disabled;
4092
4093 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004094 if (wpa_s->sched_scanning)
4095 wpa_supplicant_cancel_sched_scan(wpa_s);
4096
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004097 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4098 other_ssid = other_ssid->next) {
4099 was_disabled = other_ssid->disabled;
4100 if (was_disabled == 2)
4101 continue; /* do not change persistent P2P group
4102 * data */
4103
4104 other_ssid->disabled = 1;
4105
4106 if (was_disabled != other_ssid->disabled)
4107 wpas_notify_network_enabled_changed(
4108 wpa_s, other_ssid);
4109 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004110 if (wpa_s->current_ssid) {
4111 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4112 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004113 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004114 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004115 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004117 if (ssid == wpa_s->current_ssid) {
4118 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4119 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004120 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004121 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004122 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004123
4124 was_disabled = ssid->disabled;
4125
4126 ssid->disabled = 1;
4127
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004128 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004129 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004130 if (wpa_s->sched_scanning) {
4131 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4132 "to remove network from filters");
4133 wpa_supplicant_cancel_sched_scan(wpa_s);
4134 wpa_supplicant_req_scan(wpa_s, 0, 0);
4135 }
4136 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004137 }
4138}
4139
4140
4141/**
4142 * wpa_supplicant_select_network - Attempt association with a network
4143 * @wpa_s: wpa_supplicant structure for a network interface
4144 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4145 */
4146void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4147 struct wpa_ssid *ssid)
4148{
4149
4150 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004151 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004152
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004153 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004154 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4155 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004156 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004157 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004158 disconnected = 1;
4159 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004161 if (ssid)
4162 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4163
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004164 /*
4165 * Mark all other networks disabled or mark all networks enabled if no
4166 * network specified.
4167 */
4168 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4169 other_ssid = other_ssid->next) {
4170 int was_disabled = other_ssid->disabled;
4171 if (was_disabled == 2)
4172 continue; /* do not change persistent P2P group data */
4173
4174 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004175 if (was_disabled && !other_ssid->disabled)
4176 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004177
4178 if (was_disabled != other_ssid->disabled)
4179 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4180 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004181
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004182 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4183 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004184 /* We are already associated with the selected network */
4185 wpa_printf(MSG_DEBUG, "Already associated with the "
4186 "selected network - do nothing");
4187 return;
4188 }
4189
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004190 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004191 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004192 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004193 wpa_s->connect_without_scan =
4194 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004195
4196 /*
4197 * Don't optimize next scan freqs since a new ESS has been
4198 * selected.
4199 */
4200 os_free(wpa_s->next_scan_freqs);
4201 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004202 } else {
4203 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004204 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004205
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004206 wpa_s->disconnected = 0;
4207 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004208 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004209 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004210 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004211 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004212 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4213 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004214
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004215 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004216 wpa_supplicant_fast_associate(wpa_s) != 1) {
4217 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004218 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004219 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004220 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004221
4222 if (ssid)
4223 wpas_notify_network_selected(wpa_s, ssid);
4224}
4225
4226
4227/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004228 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4229 * @wpa_s: wpa_supplicant structure for a network interface
4230 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4231 * @pkcs11_module_path: PKCS #11 module path or NULL
4232 * Returns: 0 on success; -1 on failure
4233 *
4234 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4235 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4236 * module path fails the paths will be reset to the default value (NULL).
4237 */
4238int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4239 const char *pkcs11_engine_path,
4240 const char *pkcs11_module_path)
4241{
4242 char *pkcs11_engine_path_copy = NULL;
4243 char *pkcs11_module_path_copy = NULL;
4244
4245 if (pkcs11_engine_path != NULL) {
4246 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4247 if (pkcs11_engine_path_copy == NULL)
4248 return -1;
4249 }
4250 if (pkcs11_module_path != NULL) {
4251 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004252 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004253 os_free(pkcs11_engine_path_copy);
4254 return -1;
4255 }
4256 }
4257
4258 os_free(wpa_s->conf->pkcs11_engine_path);
4259 os_free(wpa_s->conf->pkcs11_module_path);
4260 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4261 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4262
4263 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4264 eapol_sm_deinit(wpa_s->eapol);
4265 wpa_s->eapol = NULL;
4266 if (wpa_supplicant_init_eapol(wpa_s)) {
4267 /* Error -> Reset paths to the default value (NULL) once. */
4268 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4269 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4270 NULL);
4271
4272 return -1;
4273 }
4274 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4275
4276 return 0;
4277}
4278
4279
4280/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004281 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4282 * @wpa_s: wpa_supplicant structure for a network interface
4283 * @ap_scan: AP scan mode
4284 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4285 *
4286 */
4287int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4288{
4289
4290 int old_ap_scan;
4291
4292 if (ap_scan < 0 || ap_scan > 2)
4293 return -1;
4294
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004295 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4296 wpa_printf(MSG_INFO,
4297 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4298 }
4299
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004300#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004301 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4302 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4303 wpa_s->wpa_state < WPA_COMPLETED) {
4304 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4305 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004306 return 0;
4307 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004308#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004309
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004310 old_ap_scan = wpa_s->conf->ap_scan;
4311 wpa_s->conf->ap_scan = ap_scan;
4312
4313 if (old_ap_scan != wpa_s->conf->ap_scan)
4314 wpas_notify_ap_scan_changed(wpa_s);
4315
4316 return 0;
4317}
4318
4319
4320/**
4321 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4322 * @wpa_s: wpa_supplicant structure for a network interface
4323 * @expire_age: Expiration age in seconds
4324 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4325 *
4326 */
4327int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4328 unsigned int bss_expire_age)
4329{
4330 if (bss_expire_age < 10) {
4331 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4332 bss_expire_age);
4333 return -1;
4334 }
4335 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4336 bss_expire_age);
4337 wpa_s->conf->bss_expiration_age = bss_expire_age;
4338
4339 return 0;
4340}
4341
4342
4343/**
4344 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4345 * @wpa_s: wpa_supplicant structure for a network interface
4346 * @expire_count: number of scans after which an unseen BSS is reclaimed
4347 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4348 *
4349 */
4350int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4351 unsigned int bss_expire_count)
4352{
4353 if (bss_expire_count < 1) {
4354 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4355 bss_expire_count);
4356 return -1;
4357 }
4358 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4359 bss_expire_count);
4360 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4361
4362 return 0;
4363}
4364
4365
4366/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004367 * wpa_supplicant_set_scan_interval - Set scan interval
4368 * @wpa_s: wpa_supplicant structure for a network interface
4369 * @scan_interval: scan interval in seconds
4370 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4371 *
4372 */
4373int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4374 int scan_interval)
4375{
4376 if (scan_interval < 0) {
4377 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4378 scan_interval);
4379 return -1;
4380 }
4381 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4382 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004383 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004384
4385 return 0;
4386}
4387
4388
4389/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004390 * wpa_supplicant_set_debug_params - Set global debug params
4391 * @global: wpa_global structure
4392 * @debug_level: debug level
4393 * @debug_timestamp: determines if show timestamp in debug data
4394 * @debug_show_keys: determines if show keys in debug data
4395 * Returns: 0 if succeed or -1 if debug_level has wrong value
4396 */
4397int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4398 int debug_timestamp, int debug_show_keys)
4399{
4400
4401 int old_level, old_timestamp, old_show_keys;
4402
4403 /* check for allowed debuglevels */
4404 if (debug_level != MSG_EXCESSIVE &&
4405 debug_level != MSG_MSGDUMP &&
4406 debug_level != MSG_DEBUG &&
4407 debug_level != MSG_INFO &&
4408 debug_level != MSG_WARNING &&
4409 debug_level != MSG_ERROR)
4410 return -1;
4411
4412 old_level = wpa_debug_level;
4413 old_timestamp = wpa_debug_timestamp;
4414 old_show_keys = wpa_debug_show_keys;
4415
4416 wpa_debug_level = debug_level;
4417 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4418 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4419
4420 if (wpa_debug_level != old_level)
4421 wpas_notify_debug_level_changed(global);
4422 if (wpa_debug_timestamp != old_timestamp)
4423 wpas_notify_debug_timestamp_changed(global);
4424 if (wpa_debug_show_keys != old_show_keys)
4425 wpas_notify_debug_show_keys_changed(global);
4426
4427 return 0;
4428}
4429
4430
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004431#ifdef CONFIG_OWE
4432static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4433 const u8 *entry_ssid, size_t entry_ssid_len)
4434{
4435 const u8 *owe, *pos, *end;
4436 u8 ssid_len;
4437 struct wpa_bss *bss;
4438
4439 /* Check network profile SSID aganst the SSID in the
4440 * OWE Transition Mode element. */
4441
4442 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4443 if (!bss)
4444 return 0;
4445
4446 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4447 if (!owe)
4448 return 0;
4449
4450 pos = owe + 6;
4451 end = owe + 2 + owe[1];
4452
4453 if (end - pos < ETH_ALEN + 1)
4454 return 0;
4455 pos += ETH_ALEN;
4456 ssid_len = *pos++;
4457 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4458 return 0;
4459
4460 return entry_ssid_len == ssid_len &&
4461 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4462}
4463#endif /* CONFIG_OWE */
4464
4465
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004466/**
4467 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4468 * @wpa_s: Pointer to wpa_supplicant data
4469 * Returns: A pointer to the current network structure or %NULL on failure
4470 */
4471struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4472{
4473 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004474 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004475 int res;
4476 size_t ssid_len;
4477 u8 bssid[ETH_ALEN];
4478 int wired;
4479
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004480 res = wpa_drv_get_ssid(wpa_s, ssid);
4481 if (res < 0) {
4482 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4483 "driver");
4484 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004485 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004486 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004487
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004488 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004489 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4490 "driver");
4491 return NULL;
4492 }
4493
4494 wired = wpa_s->conf->ap_scan == 0 &&
4495 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4496
4497 entry = wpa_s->conf->ssid;
4498 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004499 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004500 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004501 (!entry->ssid ||
4502 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4503 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004504 (!entry->bssid_set ||
4505 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4506 return entry;
4507#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004508 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004509 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4510 (entry->ssid == NULL || entry->ssid_len == 0) &&
4511 (!entry->bssid_set ||
4512 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4513 return entry;
4514#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004515
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004516#ifdef CONFIG_OWE
4517 if (!wpas_network_disabled(wpa_s, entry) &&
4518 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4519 entry->ssid_len) &&
4520 (!entry->bssid_set ||
4521 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4522 return entry;
4523#endif /* CONFIG_OWE */
4524
Dmitry Shmidt04949592012-07-19 12:16:46 -07004525 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004526 entry->ssid_len == 0 &&
4527 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4528 return entry;
4529
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004530 entry = entry->next;
4531 }
4532
4533 return NULL;
4534}
4535
4536
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004537static int select_driver(struct wpa_supplicant *wpa_s, int i)
4538{
4539 struct wpa_global *global = wpa_s->global;
4540
4541 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004542 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004543 if (global->drv_priv[i] == NULL) {
4544 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4545 "'%s'", wpa_drivers[i]->name);
4546 return -1;
4547 }
4548 }
4549
4550 wpa_s->driver = wpa_drivers[i];
4551 wpa_s->global_drv_priv = global->drv_priv[i];
4552
4553 return 0;
4554}
4555
4556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4558 const char *name)
4559{
4560 int i;
4561 size_t len;
4562 const char *pos, *driver = name;
4563
4564 if (wpa_s == NULL)
4565 return -1;
4566
4567 if (wpa_drivers[0] == NULL) {
4568 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4569 "wpa_supplicant");
4570 return -1;
4571 }
4572
4573 if (name == NULL) {
4574 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004575 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004576 }
4577
4578 do {
4579 pos = os_strchr(driver, ',');
4580 if (pos)
4581 len = pos - driver;
4582 else
4583 len = os_strlen(driver);
4584
4585 for (i = 0; wpa_drivers[i]; i++) {
4586 if (os_strlen(wpa_drivers[i]->name) == len &&
4587 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004588 0) {
4589 /* First driver that succeeds wins */
4590 if (select_driver(wpa_s, i) == 0)
4591 return 0;
4592 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004593 }
4594
4595 driver = pos + 1;
4596 } while (pos);
4597
4598 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4599 return -1;
4600}
4601
4602
4603/**
4604 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4605 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4606 * with struct wpa_driver_ops::init()
4607 * @src_addr: Source address of the EAPOL frame
4608 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4609 * @len: Length of the EAPOL data
4610 *
4611 * This function is called for each received EAPOL frame. Most driver
4612 * interfaces rely on more generic OS mechanism for receiving frames through
4613 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4614 * take care of received EAPOL frames and deliver them to the core supplicant
4615 * code by calling this function.
4616 */
4617void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4618 const u8 *buf, size_t len)
4619{
4620 struct wpa_supplicant *wpa_s = ctx;
4621
4622 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4623 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4624
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004625#ifdef CONFIG_TESTING_OPTIONS
4626 if (wpa_s->ignore_auth_resp) {
4627 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4628 return;
4629 }
4630#endif /* CONFIG_TESTING_OPTIONS */
4631
Jouni Malinena05074c2012-12-21 21:35:35 +02004632 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4633 (wpa_s->last_eapol_matches_bssid &&
4634#ifdef CONFIG_AP
4635 !wpa_s->ap_iface &&
4636#endif /* CONFIG_AP */
4637 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004638 /*
4639 * There is possible race condition between receiving the
4640 * association event and the EAPOL frame since they are coming
4641 * through different paths from the driver. In order to avoid
4642 * issues in trying to process the EAPOL frame before receiving
4643 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004644 * the association event is received. This may also be needed in
4645 * driver-based roaming case, so also use src_addr != BSSID as a
4646 * trigger if we have previously confirmed that the
4647 * Authenticator uses BSSID as the src_addr (which is not the
4648 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004649 */
4650 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004651 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4652 wpa_supplicant_state_txt(wpa_s->wpa_state),
4653 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004654 wpabuf_free(wpa_s->pending_eapol_rx);
4655 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4656 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004657 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004658 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4659 ETH_ALEN);
4660 }
4661 return;
4662 }
4663
Jouni Malinena05074c2012-12-21 21:35:35 +02004664 wpa_s->last_eapol_matches_bssid =
4665 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4666
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004667#ifdef CONFIG_AP
4668 if (wpa_s->ap_iface) {
4669 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4670 return;
4671 }
4672#endif /* CONFIG_AP */
4673
4674 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4675 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4676 "no key management is configured");
4677 return;
4678 }
4679
4680 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004681 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004682 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4683 wpa_s->wpa_state != WPA_COMPLETED) &&
4684 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004685 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004686 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004687 int timeout = 10;
4688
4689 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4690 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4691 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4692 /* Use longer timeout for IEEE 802.1X/EAP */
4693 timeout = 70;
4694 }
4695
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004696#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004697 if (wpa_s->current_ssid && wpa_s->current_bss &&
4698 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4699 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4700 /*
4701 * Use shorter timeout if going through WPS AP iteration
4702 * for PIN config method with an AP that does not
4703 * advertise Selected Registrar.
4704 */
4705 struct wpabuf *wps_ie;
4706
4707 wps_ie = wpa_bss_get_vendor_ie_multi(
4708 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4709 if (wps_ie &&
4710 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4711 timeout = 10;
4712 wpabuf_free(wps_ie);
4713 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004714#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004715
4716 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004717 }
4718 wpa_s->eapol_received++;
4719
4720 if (wpa_s->countermeasures) {
4721 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4722 "EAPOL packet");
4723 return;
4724 }
4725
4726#ifdef CONFIG_IBSS_RSN
4727 if (wpa_s->current_ssid &&
4728 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4729 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4730 return;
4731 }
4732#endif /* CONFIG_IBSS_RSN */
4733
4734 /* Source address of the incoming EAPOL frame could be compared to the
4735 * current BSSID. However, it is possible that a centralized
4736 * Authenticator could be using another MAC address than the BSSID of
4737 * an AP, so just allow any address to be used for now. The replies are
4738 * still sent to the current BSSID (if available), though. */
4739
4740 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4741 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004742 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4743 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004744 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4745 return;
4746 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004747 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004748 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4749 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4750 /*
4751 * Set portValid = TRUE here since we are going to skip 4-way
4752 * handshake processing which would normally set portValid. We
4753 * need this to allow the EAPOL state machines to be completed
4754 * without going through EAPOL-Key handshake.
4755 */
4756 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
4757 }
4758}
4759
4760
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004761int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004762{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004763 if ((!wpa_s->p2p_mgmt ||
4764 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4765 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004766 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004767 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4768 wpa_drv_get_mac_addr(wpa_s),
4769 ETH_P_EAPOL,
4770 wpa_supplicant_rx_eapol, wpa_s, 0);
4771 if (wpa_s->l2 == NULL)
4772 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004773
4774 if (l2_packet_set_packet_filter(wpa_s->l2,
4775 L2_PACKET_FILTER_PKTTYPE))
4776 wpa_dbg(wpa_s, MSG_DEBUG,
4777 "Failed to attach pkt_type filter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004778 } else {
4779 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4780 if (addr)
4781 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4782 }
4783
4784 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4785 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
4786 return -1;
4787 }
4788
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004789 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004790 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004791
Hai Shalomc3565922019-10-28 11:58:20 -07004792#ifdef CONFIG_FST
4793 if (wpa_s->fst)
4794 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4795#endif /* CONFIG_FST */
4796
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004797 return 0;
4798}
4799
4800
Dmitry Shmidt04949592012-07-19 12:16:46 -07004801static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4802 const u8 *buf, size_t len)
4803{
4804 struct wpa_supplicant *wpa_s = ctx;
4805 const struct l2_ethhdr *eth;
4806
4807 if (len < sizeof(*eth))
4808 return;
4809 eth = (const struct l2_ethhdr *) buf;
4810
4811 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4812 !(eth->h_dest[0] & 0x01)) {
4813 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4814 " (bridge - not for this interface - ignore)",
4815 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4816 return;
4817 }
4818
4819 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4820 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4821 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4822 len - sizeof(*eth));
4823}
4824
4825
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004826/**
4827 * wpa_supplicant_driver_init - Initialize driver interface parameters
4828 * @wpa_s: Pointer to wpa_supplicant data
4829 * Returns: 0 on success, -1 on failure
4830 *
4831 * This function is called to initialize driver interface parameters.
4832 * wpa_drv_init() must have been called before this function to initialize the
4833 * driver interface.
4834 */
4835int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4836{
4837 static int interface_count = 0;
4838
4839 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4840 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004841
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004842 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4843 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004844 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004845 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4846
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004847 if (wpa_s->bridge_ifname[0]) {
4848 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4849 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004850 wpa_s->l2_br = l2_packet_init_bridge(
4851 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4852 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004853 if (wpa_s->l2_br == NULL) {
4854 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4855 "connection for the bridge interface '%s'",
4856 wpa_s->bridge_ifname);
4857 return -1;
4858 }
4859 }
4860
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004861 if (wpa_s->conf->ap_scan == 2 &&
4862 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4863 wpa_printf(MSG_INFO,
4864 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4865 }
4866
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004867 wpa_clear_keys(wpa_s, NULL);
4868
4869 /* Make sure that TKIP countermeasures are not left enabled (could
4870 * happen if wpa_supplicant is killed during countermeasures. */
4871 wpa_drv_set_countermeasures(wpa_s, 0);
4872
4873 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4874 wpa_drv_flush_pmkid(wpa_s);
4875
4876 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004877 wpa_s->prev_scan_wildcard = 0;
4878
Dmitry Shmidt04949592012-07-19 12:16:46 -07004879 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004880 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4881 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4882 interface_count = 0;
4883 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004884#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004885 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004886 wpa_supplicant_delayed_sched_scan(wpa_s,
4887 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004888 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004889 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004890 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004891#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004892 interface_count++;
4893 } else
4894 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4895
4896 return 0;
4897}
4898
4899
4900static int wpa_supplicant_daemon(const char *pid_file)
4901{
4902 wpa_printf(MSG_DEBUG, "Daemonize..");
4903 return os_daemonize(pid_file);
4904}
4905
4906
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004907static struct wpa_supplicant *
4908wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004909{
4910 struct wpa_supplicant *wpa_s;
4911
4912 wpa_s = os_zalloc(sizeof(*wpa_s));
4913 if (wpa_s == NULL)
4914 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004915 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004916 wpa_s->scan_interval = 5;
4917 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004918 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004919 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004920 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004921
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004922 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004923 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07004924#ifdef CONFIG_TESTING_OPTIONS
4925 dl_list_init(&wpa_s->drv_signal_override);
4926#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004927
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004928 return wpa_s;
4929}
4930
4931
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004932#ifdef CONFIG_HT_OVERRIDES
4933
4934static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4935 struct ieee80211_ht_capabilities *htcaps,
4936 struct ieee80211_ht_capabilities *htcaps_mask,
4937 const char *ht_mcs)
4938{
4939 /* parse ht_mcs into hex array */
4940 int i;
4941 const char *tmp = ht_mcs;
4942 char *end = NULL;
4943
4944 /* If ht_mcs is null, do not set anything */
4945 if (!ht_mcs)
4946 return 0;
4947
4948 /* This is what we are setting in the kernel */
4949 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4950
4951 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4952
4953 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004954 long v;
4955
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004956 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004957 v = strtol(tmp, &end, 16);
4958
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004959 if (errno == 0) {
4960 wpa_msg(wpa_s, MSG_DEBUG,
4961 "htcap value[%i]: %ld end: %p tmp: %p",
4962 i, v, end, tmp);
4963 if (end == tmp)
4964 break;
4965
4966 htcaps->supported_mcs_set[i] = v;
4967 tmp = end;
4968 } else {
4969 wpa_msg(wpa_s, MSG_ERROR,
4970 "Failed to parse ht-mcs: %s, error: %s\n",
4971 ht_mcs, strerror(errno));
4972 return -1;
4973 }
4974 }
4975
4976 /*
4977 * If we were able to parse any values, then set mask for the MCS set.
4978 */
4979 if (i) {
4980 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4981 IEEE80211_HT_MCS_MASK_LEN - 1);
4982 /* skip the 3 reserved bits */
4983 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4984 0x1f;
4985 }
4986
4987 return 0;
4988}
4989
4990
4991static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4992 struct ieee80211_ht_capabilities *htcaps,
4993 struct ieee80211_ht_capabilities *htcaps_mask,
4994 int disabled)
4995{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004996 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004997
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004998 if (disabled == -1)
4999 return 0;
5000
Hai Shalom74f70d42019-02-11 14:42:39 -08005001 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5002
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005003 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5004 htcaps_mask->ht_capabilities_info |= msk;
5005 if (disabled)
5006 htcaps->ht_capabilities_info &= msk;
5007 else
5008 htcaps->ht_capabilities_info |= msk;
5009
5010 return 0;
5011}
5012
5013
5014static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5015 struct ieee80211_ht_capabilities *htcaps,
5016 struct ieee80211_ht_capabilities *htcaps_mask,
5017 int factor)
5018{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005019 if (factor == -1)
5020 return 0;
5021
Hai Shalom74f70d42019-02-11 14:42:39 -08005022 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5023
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005024 if (factor < 0 || factor > 3) {
5025 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5026 "Must be 0-3 or -1", factor);
5027 return -EINVAL;
5028 }
5029
5030 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5031 htcaps->a_mpdu_params &= ~0x3;
5032 htcaps->a_mpdu_params |= factor & 0x3;
5033
5034 return 0;
5035}
5036
5037
5038static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5039 struct ieee80211_ht_capabilities *htcaps,
5040 struct ieee80211_ht_capabilities *htcaps_mask,
5041 int density)
5042{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005043 if (density == -1)
5044 return 0;
5045
Hai Shalom74f70d42019-02-11 14:42:39 -08005046 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5047
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005048 if (density < 0 || density > 7) {
5049 wpa_msg(wpa_s, MSG_ERROR,
5050 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5051 density);
5052 return -EINVAL;
5053 }
5054
5055 htcaps_mask->a_mpdu_params |= 0x1C;
5056 htcaps->a_mpdu_params &= ~(0x1C);
5057 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5058
5059 return 0;
5060}
5061
5062
5063static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5064 struct ieee80211_ht_capabilities *htcaps,
5065 struct ieee80211_ht_capabilities *htcaps_mask,
5066 int disabled)
5067{
Hai Shalom74f70d42019-02-11 14:42:39 -08005068 if (disabled)
5069 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005070
Paul Stewart092955c2017-02-06 09:13:09 -08005071 set_disable_ht40(htcaps, disabled);
5072 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005073
5074 return 0;
5075}
5076
5077
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005078static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5079 struct ieee80211_ht_capabilities *htcaps,
5080 struct ieee80211_ht_capabilities *htcaps_mask,
5081 int disabled)
5082{
5083 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005084 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5085 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005086
Hai Shalom74f70d42019-02-11 14:42:39 -08005087 if (disabled)
5088 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005089
5090 if (disabled)
5091 htcaps->ht_capabilities_info &= ~msk;
5092 else
5093 htcaps->ht_capabilities_info |= msk;
5094
5095 htcaps_mask->ht_capabilities_info |= msk;
5096
5097 return 0;
5098}
5099
5100
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005101static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5102 struct ieee80211_ht_capabilities *htcaps,
5103 struct ieee80211_ht_capabilities *htcaps_mask,
5104 int disabled)
5105{
5106 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005107 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005108
Hai Shalom74f70d42019-02-11 14:42:39 -08005109 if (disabled)
5110 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005111
5112 if (disabled)
5113 htcaps->ht_capabilities_info &= ~msk;
5114 else
5115 htcaps->ht_capabilities_info |= msk;
5116
5117 htcaps_mask->ht_capabilities_info |= msk;
5118
5119 return 0;
5120}
5121
5122
Hai Shalom74f70d42019-02-11 14:42:39 -08005123static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5124 struct ieee80211_ht_capabilities *htcaps,
5125 struct ieee80211_ht_capabilities *htcaps_mask,
5126 int tx_stbc)
5127{
5128 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5129
5130 if (tx_stbc == -1)
5131 return 0;
5132
5133 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5134
5135 if (tx_stbc < 0 || tx_stbc > 1) {
5136 wpa_msg(wpa_s, MSG_ERROR,
5137 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5138 return -EINVAL;
5139 }
5140
5141 htcaps_mask->ht_capabilities_info |= msk;
5142 htcaps->ht_capabilities_info &= ~msk;
5143 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5144
5145 return 0;
5146}
5147
5148
5149static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5150 struct ieee80211_ht_capabilities *htcaps,
5151 struct ieee80211_ht_capabilities *htcaps_mask,
5152 int rx_stbc)
5153{
5154 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5155
5156 if (rx_stbc == -1)
5157 return 0;
5158
5159 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5160
5161 if (rx_stbc < 0 || rx_stbc > 3) {
5162 wpa_msg(wpa_s, MSG_ERROR,
5163 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5164 return -EINVAL;
5165 }
5166
5167 htcaps_mask->ht_capabilities_info |= msk;
5168 htcaps->ht_capabilities_info &= ~msk;
5169 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5170
5171 return 0;
5172}
5173
5174
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005175void wpa_supplicant_apply_ht_overrides(
5176 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5177 struct wpa_driver_associate_params *params)
5178{
5179 struct ieee80211_ht_capabilities *htcaps;
5180 struct ieee80211_ht_capabilities *htcaps_mask;
5181
5182 if (!ssid)
5183 return;
5184
5185 params->disable_ht = ssid->disable_ht;
5186 if (!params->htcaps || !params->htcaps_mask)
5187 return;
5188
5189 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5190 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5191 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5192 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5193 ssid->disable_max_amsdu);
5194 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5195 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5196 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005197 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005198 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005199 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5200 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005201
5202 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005203 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005204 htcaps->ht_capabilities_info |= bit;
5205 htcaps_mask->ht_capabilities_info |= bit;
5206 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005207}
5208
5209#endif /* CONFIG_HT_OVERRIDES */
5210
5211
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005212#ifdef CONFIG_VHT_OVERRIDES
5213void wpa_supplicant_apply_vht_overrides(
5214 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5215 struct wpa_driver_associate_params *params)
5216{
5217 struct ieee80211_vht_capabilities *vhtcaps;
5218 struct ieee80211_vht_capabilities *vhtcaps_mask;
5219
5220 if (!ssid)
5221 return;
5222
5223 params->disable_vht = ssid->disable_vht;
5224
5225 vhtcaps = (void *) params->vhtcaps;
5226 vhtcaps_mask = (void *) params->vhtcaps_mask;
5227
5228 if (!vhtcaps || !vhtcaps_mask)
5229 return;
5230
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005231 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5232 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005233
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005234#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005235 if (ssid->disable_sgi) {
5236 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5237 VHT_CAP_SHORT_GI_160);
5238 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5239 VHT_CAP_SHORT_GI_160);
5240 wpa_msg(wpa_s, MSG_DEBUG,
5241 "disable-sgi override specified, vht-caps: 0x%x",
5242 vhtcaps->vht_capabilities_info);
5243 }
5244
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005245 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005246 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5247 int max_ampdu;
5248
5249 max_ampdu = (ssid->vht_capa &
5250 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5251 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005252
5253 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5254 wpa_set_ampdu_factor(wpa_s,
5255 (void *) params->htcaps,
5256 (void *) params->htcaps_mask,
5257 max_ampdu);
5258 }
5259#endif /* CONFIG_HT_OVERRIDES */
5260
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005261#define OVERRIDE_MCS(i) \
5262 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5263 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005264 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005265 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005266 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5267 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005268 } \
5269 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5270 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005271 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005272 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005273 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5274 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005275 }
5276
5277 OVERRIDE_MCS(1);
5278 OVERRIDE_MCS(2);
5279 OVERRIDE_MCS(3);
5280 OVERRIDE_MCS(4);
5281 OVERRIDE_MCS(5);
5282 OVERRIDE_MCS(6);
5283 OVERRIDE_MCS(7);
5284 OVERRIDE_MCS(8);
5285}
5286#endif /* CONFIG_VHT_OVERRIDES */
5287
5288
Hai Shalomfdcde762020-04-02 11:19:20 -07005289#ifdef CONFIG_HE_OVERRIDES
5290void wpa_supplicant_apply_he_overrides(
5291 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5292 struct wpa_driver_associate_params *params)
5293{
5294 if (!ssid)
5295 return;
5296
5297 params->disable_he = ssid->disable_he;
5298}
5299#endif /* CONFIG_HE_OVERRIDES */
5300
5301
Dmitry Shmidt04949592012-07-19 12:16:46 -07005302static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5303{
5304#ifdef PCSC_FUNCS
5305 size_t len;
5306
5307 if (!wpa_s->conf->pcsc_reader)
5308 return 0;
5309
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005310 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005311 if (!wpa_s->scard)
5312 return 1;
5313
5314 if (wpa_s->conf->pcsc_pin &&
5315 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5316 scard_deinit(wpa_s->scard);
5317 wpa_s->scard = NULL;
5318 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5319 return -1;
5320 }
5321
5322 len = sizeof(wpa_s->imsi) - 1;
5323 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5324 scard_deinit(wpa_s->scard);
5325 wpa_s->scard = NULL;
5326 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5327 return -1;
5328 }
5329 wpa_s->imsi[len] = '\0';
5330
5331 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5332
5333 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5334 wpa_s->imsi, wpa_s->mnc_len);
5335
5336 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5337 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5338#endif /* PCSC_FUNCS */
5339
5340 return 0;
5341}
5342
5343
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005344int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5345{
5346 char *val, *pos;
5347
5348 ext_password_deinit(wpa_s->ext_pw);
5349 wpa_s->ext_pw = NULL;
5350 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5351
5352 if (!wpa_s->conf->ext_password_backend)
5353 return 0;
5354
5355 val = os_strdup(wpa_s->conf->ext_password_backend);
5356 if (val == NULL)
5357 return -1;
5358 pos = os_strchr(val, ':');
5359 if (pos)
5360 *pos++ = '\0';
5361
5362 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5363
5364 wpa_s->ext_pw = ext_password_init(val, pos);
5365 os_free(val);
5366 if (wpa_s->ext_pw == NULL) {
5367 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5368 return -1;
5369 }
5370 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5371
5372 return 0;
5373}
5374
5375
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005376#ifdef CONFIG_FST
5377
5378static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5379{
5380 struct wpa_supplicant *wpa_s = ctx;
5381
5382 return (is_zero_ether_addr(wpa_s->bssid) ||
5383 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5384}
5385
5386
5387static void wpas_fst_get_channel_info_cb(void *ctx,
5388 enum hostapd_hw_mode *hw_mode,
5389 u8 *channel)
5390{
5391 struct wpa_supplicant *wpa_s = ctx;
5392
5393 if (wpa_s->current_bss) {
5394 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5395 channel);
5396 } else if (wpa_s->hw.num_modes) {
5397 *hw_mode = wpa_s->hw.modes[0].mode;
5398 } else {
5399 WPA_ASSERT(0);
5400 *hw_mode = 0;
5401 }
5402}
5403
5404
5405static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5406{
5407 struct wpa_supplicant *wpa_s = ctx;
5408
5409 *modes = wpa_s->hw.modes;
5410 return wpa_s->hw.num_modes;
5411}
5412
5413
5414static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5415{
5416 struct wpa_supplicant *wpa_s = ctx;
5417
5418 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5419 wpa_s->fst_ies = fst_ies;
5420}
5421
5422
5423static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5424{
5425 struct wpa_supplicant *wpa_s = ctx;
5426
Paul Stewart092955c2017-02-06 09:13:09 -08005427 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5428 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5429 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5430 return -1;
5431 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005432 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005433 wpa_s->own_addr, wpa_s->bssid,
5434 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005435 0);
5436}
5437
5438
5439static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5440{
5441 struct wpa_supplicant *wpa_s = ctx;
5442
5443 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5444 return wpa_s->received_mb_ies;
5445}
5446
5447
5448static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5449 const u8 *buf, size_t size)
5450{
5451 struct wpa_supplicant *wpa_s = ctx;
5452 struct mb_ies_info info;
5453
5454 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5455
5456 if (!mb_ies_info_by_ies(&info, buf, size)) {
5457 wpabuf_free(wpa_s->received_mb_ies);
5458 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5459 }
5460}
5461
5462
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005463static const u8 * wpas_fst_get_peer_first(void *ctx,
5464 struct fst_get_peer_ctx **get_ctx,
5465 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005466{
5467 struct wpa_supplicant *wpa_s = ctx;
5468
5469 *get_ctx = NULL;
5470 if (!is_zero_ether_addr(wpa_s->bssid))
5471 return (wpa_s->received_mb_ies || !mb_only) ?
5472 wpa_s->bssid : NULL;
5473 return NULL;
5474}
5475
5476
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005477static const u8 * wpas_fst_get_peer_next(void *ctx,
5478 struct fst_get_peer_ctx **get_ctx,
5479 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005480{
5481 return NULL;
5482}
5483
5484void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5485 struct fst_wpa_obj *iface_obj)
5486{
5487 iface_obj->ctx = wpa_s;
5488 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5489 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5490 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5491 iface_obj->set_ies = wpas_fst_set_ies_cb;
5492 iface_obj->send_action = wpas_fst_send_action_cb;
5493 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5494 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5495 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5496 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5497}
5498#endif /* CONFIG_FST */
5499
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005500static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005501 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005502{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005503 struct wowlan_triggers *triggers;
5504 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005505
5506 if (!wpa_s->conf->wowlan_triggers)
5507 return 0;
5508
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005509 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5510 if (triggers) {
5511 ret = wpa_drv_wowlan(wpa_s, triggers);
5512 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005513 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005514 return ret;
5515}
5516
5517
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005518enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005519{
5520 if (freq < 3000)
5521 return BAND_2_4_GHZ;
5522 if (freq > 50000)
5523 return BAND_60_GHZ;
5524 return BAND_5_GHZ;
5525}
5526
5527
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005528unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005529{
5530 int i;
5531 unsigned int band = 0;
5532
5533 if (freqs) {
5534 /* freqs are specified for the radio work */
5535 for (i = 0; freqs[i]; i++)
5536 band |= wpas_freq_to_band(freqs[i]);
5537 } else {
5538 /*
5539 * freqs are not specified, implies all
5540 * the supported freqs by HW
5541 */
5542 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5543 if (wpa_s->hw.modes[i].num_channels != 0) {
5544 if (wpa_s->hw.modes[i].mode ==
5545 HOSTAPD_MODE_IEEE80211B ||
5546 wpa_s->hw.modes[i].mode ==
5547 HOSTAPD_MODE_IEEE80211G)
5548 band |= BAND_2_4_GHZ;
5549 else if (wpa_s->hw.modes[i].mode ==
5550 HOSTAPD_MODE_IEEE80211A)
5551 band |= BAND_5_GHZ;
5552 else if (wpa_s->hw.modes[i].mode ==
5553 HOSTAPD_MODE_IEEE80211AD)
5554 band |= BAND_60_GHZ;
5555 else if (wpa_s->hw.modes[i].mode ==
5556 HOSTAPD_MODE_IEEE80211ANY)
5557 band = BAND_2_4_GHZ | BAND_5_GHZ |
5558 BAND_60_GHZ;
5559 }
5560 }
5561 }
5562
5563 return band;
5564}
5565
5566
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005567static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5568 const char *rn)
5569{
5570 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5571 struct wpa_radio *radio;
5572
5573 while (rn && iface) {
5574 radio = iface->radio;
5575 if (radio && os_strcmp(rn, radio->name) == 0) {
5576 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5577 wpa_s->ifname, rn);
5578 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5579 return radio;
5580 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005581
5582 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005583 }
5584
5585 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5586 wpa_s->ifname, rn ? rn : "N/A");
5587 radio = os_zalloc(sizeof(*radio));
5588 if (radio == NULL)
5589 return NULL;
5590
5591 if (rn)
5592 os_strlcpy(radio->name, rn, sizeof(radio->name));
5593 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005594 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005595 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5596
5597 return radio;
5598}
5599
5600
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005601static void radio_work_free(struct wpa_radio_work *work)
5602{
5603 if (work->wpa_s->scan_work == work) {
5604 /* This should not really happen. */
5605 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5606 work->type, work, work->started);
5607 work->wpa_s->scan_work = NULL;
5608 }
5609
5610#ifdef CONFIG_P2P
5611 if (work->wpa_s->p2p_scan_work == work) {
5612 /* This should not really happen. */
5613 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5614 work->type, work, work->started);
5615 work->wpa_s->p2p_scan_work = NULL;
5616 }
5617#endif /* CONFIG_P2P */
5618
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005619 if (work->started) {
5620 work->wpa_s->radio->num_active_works--;
5621 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005622 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005623 work->type, work,
5624 work->wpa_s->radio->num_active_works);
5625 }
5626
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005627 dl_list_del(&work->list);
5628 os_free(work);
5629}
5630
5631
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005632static int radio_work_is_connect(struct wpa_radio_work *work)
5633{
5634 return os_strcmp(work->type, "sme-connect") == 0 ||
5635 os_strcmp(work->type, "connect") == 0;
5636}
5637
5638
5639static int radio_work_is_scan(struct wpa_radio_work *work)
5640{
5641 return os_strcmp(work->type, "scan") == 0 ||
5642 os_strcmp(work->type, "p2p-scan") == 0;
5643}
5644
5645
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005646static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5647{
5648 struct wpa_radio_work *active_work = NULL;
5649 struct wpa_radio_work *tmp;
5650
5651 /* Get the active work to know the type and band. */
5652 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5653 if (tmp->started) {
5654 active_work = tmp;
5655 break;
5656 }
5657 }
5658
5659 if (!active_work) {
5660 /* No active work, start one */
5661 radio->num_active_works = 0;
5662 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5663 list) {
5664 if (os_strcmp(tmp->type, "scan") == 0 &&
5665 radio->external_scan_running &&
5666 (((struct wpa_driver_scan_params *)
5667 tmp->ctx)->only_new_results ||
5668 tmp->wpa_s->clear_driver_scan_cache))
5669 continue;
5670 return tmp;
5671 }
5672 return NULL;
5673 }
5674
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005675 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005676 /*
5677 * If the active work is either connect or sme-connect,
5678 * do not parallelize them with other radio works.
5679 */
5680 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5681 "Do not parallelize radio work with %s",
5682 active_work->type);
5683 return NULL;
5684 }
5685
5686 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5687 if (tmp->started)
5688 continue;
5689
5690 /*
5691 * If connect or sme-connect are enqueued, parallelize only
5692 * those operations ahead of them in the queue.
5693 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005694 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005695 break;
5696
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005697 /* Serialize parallel scan and p2p_scan operations on the same
5698 * interface since the driver_nl80211 mechanism for tracking
5699 * scan cookies does not yet have support for this. */
5700 if (active_work->wpa_s == tmp->wpa_s &&
5701 radio_work_is_scan(active_work) &&
5702 radio_work_is_scan(tmp)) {
5703 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5704 "Do not start work '%s' when another work '%s' is already scheduled",
5705 tmp->type, active_work->type);
5706 continue;
5707 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005708 /*
5709 * Check that the radio works are distinct and
5710 * on different bands.
5711 */
5712 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5713 (active_work->bands != tmp->bands)) {
5714 /*
5715 * If a scan has to be scheduled through nl80211 scan
5716 * interface and if an external scan is already running,
5717 * do not schedule the scan since it is likely to get
5718 * rejected by kernel.
5719 */
5720 if (os_strcmp(tmp->type, "scan") == 0 &&
5721 radio->external_scan_running &&
5722 (((struct wpa_driver_scan_params *)
5723 tmp->ctx)->only_new_results ||
5724 tmp->wpa_s->clear_driver_scan_cache))
5725 continue;
5726
5727 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5728 "active_work:%s new_work:%s",
5729 active_work->type, tmp->type);
5730 return tmp;
5731 }
5732 }
5733
5734 /* Did not find a radio work to schedule in parallel. */
5735 return NULL;
5736}
5737
5738
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005739static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5740{
5741 struct wpa_radio *radio = eloop_ctx;
5742 struct wpa_radio_work *work;
5743 struct os_reltime now, diff;
5744 struct wpa_supplicant *wpa_s;
5745
5746 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005747 if (work == NULL) {
5748 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005749 return;
5750 }
5751
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005752 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5753 radio_list);
5754
5755 if (!(wpa_s &&
5756 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5757 if (work->started)
5758 return; /* already started and still in progress */
5759
5760 if (wpa_s && wpa_s->radio->external_scan_running) {
5761 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5762 return;
5763 }
5764 } else {
5765 work = NULL;
5766 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5767 /* get the work to schedule next */
5768 work = radio_work_get_next_work(radio);
5769 }
5770 if (!work)
5771 return;
5772 }
5773
5774 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005775 os_get_reltime(&now);
5776 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005777 wpa_dbg(wpa_s, MSG_DEBUG,
5778 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005779 work->type, work, diff.sec, diff.usec);
5780 work->started = 1;
5781 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005782 radio->num_active_works++;
5783
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005784 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005785
5786 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5787 radio->num_active_works < MAX_ACTIVE_WORKS)
5788 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005789}
5790
5791
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005792/*
5793 * This function removes both started and pending radio works running on
5794 * the provided interface's radio.
5795 * Prior to the removal of the radio work, its callback (cb) is called with
5796 * deinit set to be 1. Each work's callback is responsible for clearing its
5797 * internal data and restoring to a correct state.
5798 * @wpa_s: wpa_supplicant data
5799 * @type: type of works to be removed
5800 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5801 * this interface's works.
5802 */
5803void radio_remove_works(struct wpa_supplicant *wpa_s,
5804 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005805{
5806 struct wpa_radio_work *work, *tmp;
5807 struct wpa_radio *radio = wpa_s->radio;
5808
5809 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5810 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005811 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005812 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005813
5814 /* skip other ifaces' works */
5815 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005816 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005817
5818 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5819 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005820 work->cb(work, 1);
5821 radio_work_free(work);
5822 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005823
5824 /* in case we removed the started work */
5825 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005826}
5827
5828
Roshan Pius3a1667e2018-07-03 15:17:14 -07005829void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5830{
5831 struct wpa_radio_work *work;
5832 struct wpa_radio *radio = wpa_s->radio;
5833
5834 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5835 if (work->ctx != ctx)
5836 continue;
5837 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5838 work->type, work, work->started ? " (started)" : "");
5839 radio_work_free(work);
5840 break;
5841 }
5842}
5843
5844
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005845static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5846{
5847 struct wpa_radio *radio = wpa_s->radio;
5848
5849 if (!radio)
5850 return;
5851
5852 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5853 wpa_s->ifname, radio->name);
5854 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005855 radio_remove_works(wpa_s, NULL, 0);
5856 wpa_s->radio = NULL;
5857 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005858 return; /* Interfaces remain for this radio */
5859
5860 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005861 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005862 os_free(radio);
5863}
5864
5865
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005866void radio_work_check_next(struct wpa_supplicant *wpa_s)
5867{
5868 struct wpa_radio *radio = wpa_s->radio;
5869
5870 if (dl_list_empty(&radio->work))
5871 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005872 if (wpa_s->ext_work_in_progress) {
5873 wpa_printf(MSG_DEBUG,
5874 "External radio work in progress - delay start of pending item");
5875 return;
5876 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005877 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5878 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5879}
5880
5881
5882/**
5883 * radio_add_work - Add a radio work item
5884 * @wpa_s: Pointer to wpa_supplicant data
5885 * @freq: Frequency of the offchannel operation in MHz or 0
5886 * @type: Unique identifier for each type of work
5887 * @next: Force as the next work to be executed
5888 * @cb: Callback function for indicating when radio is available
5889 * @ctx: Context pointer for the work (work->ctx in cb())
5890 * Returns: 0 on success, -1 on failure
5891 *
5892 * This function is used to request time for an operation that requires
5893 * exclusive radio control. Once the radio is available, the registered callback
5894 * function will be called. radio_work_done() must be called once the exclusive
5895 * radio operation has been completed, so that the radio is freed for other
5896 * operations. The special case of deinit=1 is used to free the context data
5897 * during interface removal. That does not allow the callback function to start
5898 * the radio operation, i.e., it must free any resources allocated for the radio
5899 * work and return.
5900 *
5901 * The @freq parameter can be used to indicate a single channel on which the
5902 * offchannel operation will occur. This may allow multiple radio work
5903 * operations to be performed in parallel if they apply for the same channel.
5904 * Setting this to 0 indicates that the work item may use multiple channels or
5905 * requires exclusive control of the radio.
5906 */
5907int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5908 const char *type, int next,
5909 void (*cb)(struct wpa_radio_work *work, int deinit),
5910 void *ctx)
5911{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005912 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005913 struct wpa_radio_work *work;
5914 int was_empty;
5915
5916 work = os_zalloc(sizeof(*work));
5917 if (work == NULL)
5918 return -1;
5919 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5920 os_get_reltime(&work->time);
5921 work->freq = freq;
5922 work->type = type;
5923 work->wpa_s = wpa_s;
5924 work->cb = cb;
5925 work->ctx = ctx;
5926
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005927 if (freq)
5928 work->bands = wpas_freq_to_band(freq);
5929 else if (os_strcmp(type, "scan") == 0 ||
5930 os_strcmp(type, "p2p-scan") == 0)
5931 work->bands = wpas_get_bands(wpa_s,
5932 ((struct wpa_driver_scan_params *)
5933 ctx)->freqs);
5934 else
5935 work->bands = wpas_get_bands(wpa_s, NULL);
5936
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005937 was_empty = dl_list_empty(&wpa_s->radio->work);
5938 if (next)
5939 dl_list_add(&wpa_s->radio->work, &work->list);
5940 else
5941 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5942 if (was_empty) {
5943 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5944 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005945 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5946 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5947 wpa_dbg(wpa_s, MSG_DEBUG,
5948 "Try to schedule a radio work (num_active_works=%u)",
5949 radio->num_active_works);
5950 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005951 }
5952
5953 return 0;
5954}
5955
5956
5957/**
5958 * radio_work_done - Indicate that a radio work item has been completed
5959 * @work: Completed work
5960 *
5961 * This function is called once the callback function registered with
5962 * radio_add_work() has completed its work.
5963 */
5964void radio_work_done(struct wpa_radio_work *work)
5965{
5966 struct wpa_supplicant *wpa_s = work->wpa_s;
5967 struct os_reltime now, diff;
5968 unsigned int started = work->started;
5969
5970 os_get_reltime(&now);
5971 os_reltime_sub(&now, &work->time, &diff);
5972 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5973 work->type, work, started ? "done" : "canceled",
5974 diff.sec, diff.usec);
5975 radio_work_free(work);
5976 if (started)
5977 radio_work_check_next(wpa_s);
5978}
5979
5980
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005981struct wpa_radio_work *
5982radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005983{
5984 struct wpa_radio_work *work;
5985 struct wpa_radio *radio = wpa_s->radio;
5986
5987 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5988 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005989 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005990 }
5991
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005992 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005993}
5994
5995
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005996static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005997 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005998{
5999 const char *ifname, *driver, *rn;
6000
6001 driver = iface->driver;
6002next_driver:
6003 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6004 return -1;
6005
6006 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6007 if (wpa_s->drv_priv == NULL) {
6008 const char *pos;
6009 pos = driver ? os_strchr(driver, ',') : NULL;
6010 if (pos) {
6011 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6012 "driver interface - try next driver wrapper");
6013 driver = pos + 1;
6014 goto next_driver;
6015 }
6016 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
6017 "interface");
6018 return -1;
6019 }
6020 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6021 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6022 "driver_param '%s'", wpa_s->conf->driver_param);
6023 return -1;
6024 }
6025
6026 ifname = wpa_drv_get_ifname(wpa_s);
6027 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6028 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6029 "interface name with '%s'", ifname);
6030 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6031 }
6032
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006033 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006034 if (rn && rn[0] == '\0')
6035 rn = NULL;
6036
6037 wpa_s->radio = radio_add_interface(wpa_s, rn);
6038 if (wpa_s->radio == NULL)
6039 return -1;
6040
6041 return 0;
6042}
6043
6044
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006045#ifdef CONFIG_GAS_SERVER
6046
6047static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6048 unsigned int freq, const u8 *dst,
6049 const u8 *src, const u8 *bssid,
6050 const u8 *data, size_t data_len,
6051 enum offchannel_send_action_result result)
6052{
6053 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6054 " result=%s",
6055 freq, MAC2STR(dst),
6056 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6057 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6058 "FAILED"));
6059 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6060 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6061}
6062
6063
6064static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6065 struct wpabuf *buf, unsigned int wait_time)
6066{
6067 struct wpa_supplicant *wpa_s = ctx;
6068 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6069
6070 if (wait_time > wpa_s->max_remain_on_chan)
6071 wait_time = wpa_s->max_remain_on_chan;
6072
6073 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6074 wpabuf_head(buf), wpabuf_len(buf),
6075 wait_time, wpas_gas_server_tx_status, 0);
6076}
6077
6078#endif /* CONFIG_GAS_SERVER */
6079
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006080static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006081 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006082{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006083 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006084 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006085 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006086
6087 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6088 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6089 iface->confname ? iface->confname : "N/A",
6090 iface->driver ? iface->driver : "default",
6091 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6092 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6093
6094 if (iface->confname) {
6095#ifdef CONFIG_BACKEND_FILE
6096 wpa_s->confname = os_rel2abs_path(iface->confname);
6097 if (wpa_s->confname == NULL) {
6098 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6099 "for configuration file '%s'.",
6100 iface->confname);
6101 return -1;
6102 }
6103 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6104 iface->confname, wpa_s->confname);
6105#else /* CONFIG_BACKEND_FILE */
6106 wpa_s->confname = os_strdup(iface->confname);
6107#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006108 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006109 if (wpa_s->conf == NULL) {
6110 wpa_printf(MSG_ERROR, "Failed to read or parse "
6111 "configuration '%s'.", wpa_s->confname);
6112 return -1;
6113 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006114 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006115 if (wpa_s->confanother &&
6116 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6117 wpa_printf(MSG_ERROR,
6118 "Failed to read or parse configuration '%s'.",
6119 wpa_s->confanother);
6120 return -1;
6121 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006122
6123 /*
6124 * Override ctrl_interface and driver_param if set on command
6125 * line.
6126 */
6127 if (iface->ctrl_interface) {
6128 os_free(wpa_s->conf->ctrl_interface);
6129 wpa_s->conf->ctrl_interface =
6130 os_strdup(iface->ctrl_interface);
6131 }
6132
6133 if (iface->driver_param) {
6134 os_free(wpa_s->conf->driver_param);
6135 wpa_s->conf->driver_param =
6136 os_strdup(iface->driver_param);
6137 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006138
6139 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6140 os_free(wpa_s->conf->ctrl_interface);
6141 wpa_s->conf->ctrl_interface = NULL;
6142 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006143 } else
6144 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6145 iface->driver_param);
6146
6147 if (wpa_s->conf == NULL) {
6148 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6149 return -1;
6150 }
6151
6152 if (iface->ifname == NULL) {
6153 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6154 return -1;
6155 }
6156 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6157 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6158 iface->ifname);
6159 return -1;
6160 }
6161 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
6162
6163 if (iface->bridge_ifname) {
6164 if (os_strlen(iface->bridge_ifname) >=
6165 sizeof(wpa_s->bridge_ifname)) {
6166 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6167 "name '%s'.", iface->bridge_ifname);
6168 return -1;
6169 }
6170 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6171 sizeof(wpa_s->bridge_ifname));
6172 }
6173
6174 /* RSNA Supplicant Key Management - INITIALIZE */
6175 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
6176 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
6177
6178 /* Initialize driver interface and register driver event handler before
6179 * L2 receive handler so that association events are processed before
6180 * EAPOL-Key packets if both become available for the same select()
6181 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006182 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006183 return -1;
6184
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006185 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6186 return -1;
6187
6188 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6189 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6190 NULL);
6191 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6192
6193 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6194 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6195 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6196 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6197 "dot11RSNAConfigPMKLifetime");
6198 return -1;
6199 }
6200
6201 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6202 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6203 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6204 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6205 "dot11RSNAConfigPMKReauthThreshold");
6206 return -1;
6207 }
6208
6209 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6210 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6211 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6212 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6213 "dot11RSNAConfigSATimeout");
6214 return -1;
6215 }
6216
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006217 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6218 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006219 &wpa_s->hw.flags,
6220 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006221 if (wpa_s->hw.modes) {
6222 u16 i;
6223
6224 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6225 if (wpa_s->hw.modes[i].vht_capab) {
6226 wpa_s->hw_capab = CAPAB_VHT;
6227 break;
6228 }
6229
6230 if (wpa_s->hw.modes[i].ht_capab &
6231 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6232 wpa_s->hw_capab = CAPAB_HT40;
6233 else if (wpa_s->hw.modes[i].ht_capab &&
6234 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6235 wpa_s->hw_capab = CAPAB_HT;
6236 }
6237 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006238
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006239 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6240 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006241 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006242 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006243 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006244 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006245 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006246 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006247 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006248 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6249 wpa_s->max_sched_scan_plan_interval =
6250 capa.max_sched_scan_plan_interval;
6251 wpa_s->max_sched_scan_plan_iterations =
6252 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006253 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6254 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006255 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6256 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006257 wpa_s->extended_capa = capa.extended_capa;
6258 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6259 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006260 wpa_s->num_multichan_concurrent =
6261 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006262 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6263
6264 if (capa.mac_addr_rand_scan_supported)
6265 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6266 if (wpa_s->sched_scan_supported &&
6267 capa.mac_addr_rand_sched_scan_supported)
6268 wpa_s->mac_addr_rand_supported |=
6269 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006270
6271 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6272 if (wpa_s->extended_capa &&
6273 wpa_s->extended_capa_len >= 3 &&
6274 wpa_s->extended_capa[2] & 0x40)
6275 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006276 }
6277 if (wpa_s->max_remain_on_chan == 0)
6278 wpa_s->max_remain_on_chan = 1000;
6279
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006280 /*
6281 * Only take p2p_mgmt parameters when P2P Device is supported.
6282 * Doing it here as it determines whether l2_packet_init() will be done
6283 * during wpa_supplicant_driver_init().
6284 */
6285 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6286 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006287
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006288 if (wpa_s->num_multichan_concurrent == 0)
6289 wpa_s->num_multichan_concurrent = 1;
6290
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006291 if (wpa_supplicant_driver_init(wpa_s) < 0)
6292 return -1;
6293
6294#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006295 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006296 return -1;
6297#endif /* CONFIG_TDLS */
6298
6299 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6300 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6301 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6302 return -1;
6303 }
6304
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006305#ifdef CONFIG_FST
6306 if (wpa_s->conf->fst_group_id) {
6307 struct fst_iface_cfg cfg;
6308 struct fst_wpa_obj iface_obj;
6309
6310 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6311 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6312 sizeof(cfg.group_id));
6313 cfg.priority = wpa_s->conf->fst_priority;
6314 cfg.llt = wpa_s->conf->fst_llt;
6315
6316 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6317 &iface_obj, &cfg);
6318 if (!wpa_s->fst) {
6319 wpa_msg(wpa_s, MSG_ERROR,
6320 "FST: Cannot attach iface %s to group %s",
6321 wpa_s->ifname, cfg.group_id);
6322 return -1;
6323 }
6324 }
6325#endif /* CONFIG_FST */
6326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006327 if (wpas_wps_init(wpa_s))
6328 return -1;
6329
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006330#ifdef CONFIG_GAS_SERVER
6331 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6332 if (!wpa_s->gas_server) {
6333 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6334 return -1;
6335 }
6336#endif /* CONFIG_GAS_SERVER */
6337
6338#ifdef CONFIG_DPP
6339 if (wpas_dpp_init(wpa_s) < 0)
6340 return -1;
6341#endif /* CONFIG_DPP */
6342
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006343 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6344 return -1;
6345 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6346
6347 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6348 if (wpa_s->ctrl_iface == NULL) {
6349 wpa_printf(MSG_ERROR,
6350 "Failed to initialize control interface '%s'.\n"
6351 "You may have another wpa_supplicant process "
6352 "already running or the file was\n"
6353 "left by an unclean termination of wpa_supplicant "
6354 "in which case you will need\n"
6355 "to manually remove this file before starting "
6356 "wpa_supplicant again.\n",
6357 wpa_s->conf->ctrl_interface);
6358 return -1;
6359 }
6360
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006361 wpa_s->gas = gas_query_init(wpa_s);
6362 if (wpa_s->gas == NULL) {
6363 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6364 return -1;
6365 }
6366
Roshan Pius3a1667e2018-07-03 15:17:14 -07006367 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6368 wpa_s->p2p_mgmt) &&
6369 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006370 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6371 return -1;
6372 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006373
6374 if (wpa_bss_init(wpa_s) < 0)
6375 return -1;
6376
Paul Stewart092955c2017-02-06 09:13:09 -08006377#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6378#ifdef CONFIG_MESH
6379 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6380#endif /* CONFIG_MESH */
6381#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6382
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006383 /*
6384 * Set Wake-on-WLAN triggers, if configured.
6385 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6386 * have effect anyway when the interface is down).
6387 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006388 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006389 return -1;
6390
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006391#ifdef CONFIG_EAP_PROXY
6392{
6393 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006394 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6395 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006396 if (wpa_s->mnc_len > 0) {
6397 wpa_s->imsi[len] = '\0';
6398 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6399 wpa_s->imsi, wpa_s->mnc_len);
6400 } else {
6401 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6402 }
6403}
6404#endif /* CONFIG_EAP_PROXY */
6405
Dmitry Shmidt04949592012-07-19 12:16:46 -07006406 if (pcsc_reader_init(wpa_s) < 0)
6407 return -1;
6408
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006409 if (wpas_init_ext_pw(wpa_s) < 0)
6410 return -1;
6411
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006412 wpas_rrm_reset(wpa_s);
6413
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006414 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6415
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006416#ifdef CONFIG_HS20
6417 hs20_init(wpa_s);
6418#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006419#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006420 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006421 if ((wpa_s->conf->oce & OCE_STA) &&
6422 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6423 wpa_s->enable_oce = OCE_STA;
6424 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6425 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6426 /* TODO: Need to add STA-CFON support */
6427 wpa_printf(MSG_ERROR,
6428 "OCE STA-CFON feature is not yet supported");
6429 }
6430 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006431 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6432#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006433
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006434 wpa_supplicant_set_default_scan_ies(wpa_s);
6435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006436 return 0;
6437}
6438
6439
6440static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006441 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006442{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006443 struct wpa_global *global = wpa_s->global;
6444 struct wpa_supplicant *iface, *prev;
6445
6446 if (wpa_s == wpa_s->parent)
6447 wpas_p2p_group_remove(wpa_s, "*");
6448
6449 iface = global->ifaces;
6450 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006451 if (iface->p2pdev == wpa_s)
6452 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006453 if (iface == wpa_s || iface->parent != wpa_s) {
6454 iface = iface->next;
6455 continue;
6456 }
6457 wpa_printf(MSG_DEBUG,
6458 "Remove remaining child interface %s from parent %s",
6459 iface->ifname, wpa_s->ifname);
6460 prev = iface;
6461 iface = iface->next;
6462 wpa_supplicant_remove_iface(global, prev, terminate);
6463 }
6464
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006465 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006466 if (wpa_s->drv_priv) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006467 /* Don't deauthenticate if WoWLAN is enabled */
6468 if (!wpa_drv_get_wowlan(wpa_s)) {
6469 wpa_supplicant_deauthenticate(
6470 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006471
Hai Shalomfdcde762020-04-02 11:19:20 -07006472 wpa_drv_set_countermeasures(wpa_s, 0);
6473 wpa_clear_keys(wpa_s, NULL);
6474 } else {
6475 wpa_msg(wpa_s, MSG_INFO,
6476 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6477 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006478 }
6479
6480 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006481 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006482
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006483 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006484 radio_remove_interface(wpa_s);
6485
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006486#ifdef CONFIG_FST
6487 if (wpa_s->fst) {
6488 fst_detach(wpa_s->fst);
6489 wpa_s->fst = NULL;
6490 }
6491 if (wpa_s->received_mb_ies) {
6492 wpabuf_free(wpa_s->received_mb_ies);
6493 wpa_s->received_mb_ies = NULL;
6494 }
6495#endif /* CONFIG_FST */
6496
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006497 if (wpa_s->drv_priv)
6498 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006499
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006500 if (notify)
6501 wpas_notify_iface_removed(wpa_s);
6502
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006503 if (terminate)
6504 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006505
6506 if (wpa_s->ctrl_iface) {
6507 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6508 wpa_s->ctrl_iface = NULL;
6509 }
6510
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006511#ifdef CONFIG_MESH
6512 if (wpa_s->ifmsh) {
6513 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6514 wpa_s->ifmsh = NULL;
6515 }
6516#endif /* CONFIG_MESH */
6517
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006518 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006519 wpa_config_free(wpa_s->conf);
6520 wpa_s->conf = NULL;
6521 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006522
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006523 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006524 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006525
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006526 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006527}
6528
6529
Dmitry Shmidte4663042016-04-04 10:07:49 -07006530#ifdef CONFIG_MATCH_IFACE
6531
6532/**
6533 * wpa_supplicant_match_iface - Match an interface description to a name
6534 * @global: Pointer to global data from wpa_supplicant_init()
6535 * @ifname: Name of the interface to match
6536 * Returns: Pointer to the created interface description or %NULL on failure
6537 */
6538struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6539 const char *ifname)
6540{
6541 int i;
6542 struct wpa_interface *iface, *miface;
6543
6544 for (i = 0; i < global->params.match_iface_count; i++) {
6545 miface = &global->params.match_ifaces[i];
6546 if (!miface->ifname ||
6547 fnmatch(miface->ifname, ifname, 0) == 0) {
6548 iface = os_zalloc(sizeof(*iface));
6549 if (!iface)
6550 return NULL;
6551 *iface = *miface;
6552 iface->ifname = ifname;
6553 return iface;
6554 }
6555 }
6556
6557 return NULL;
6558}
6559
6560
6561/**
6562 * wpa_supplicant_match_existing - Match existing interfaces
6563 * @global: Pointer to global data from wpa_supplicant_init()
6564 * Returns: 0 on success, -1 on failure
6565 */
6566static int wpa_supplicant_match_existing(struct wpa_global *global)
6567{
6568 struct if_nameindex *ifi, *ifp;
6569 struct wpa_supplicant *wpa_s;
6570 struct wpa_interface *iface;
6571
6572 ifp = if_nameindex();
6573 if (!ifp) {
6574 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6575 return -1;
6576 }
6577
6578 for (ifi = ifp; ifi->if_name; ifi++) {
6579 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6580 if (wpa_s)
6581 continue;
6582 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6583 if (iface) {
6584 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6585 os_free(iface);
6586 if (wpa_s)
6587 wpa_s->matched = 1;
6588 }
6589 }
6590
6591 if_freenameindex(ifp);
6592 return 0;
6593}
6594
6595#endif /* CONFIG_MATCH_IFACE */
6596
6597
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006598/**
6599 * wpa_supplicant_add_iface - Add a new network interface
6600 * @global: Pointer to global data from wpa_supplicant_init()
6601 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006602 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006603 * Returns: Pointer to the created interface or %NULL on failure
6604 *
6605 * This function is used to add new network interfaces for %wpa_supplicant.
6606 * This can be called before wpa_supplicant_run() to add interfaces before the
6607 * main event loop has been started. In addition, new interfaces can be added
6608 * dynamically while %wpa_supplicant is already running. This could happen,
6609 * e.g., when a hotplug network adapter is inserted.
6610 */
6611struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006612 struct wpa_interface *iface,
6613 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006614{
6615 struct wpa_supplicant *wpa_s;
6616 struct wpa_interface t_iface;
6617 struct wpa_ssid *ssid;
6618
6619 if (global == NULL || iface == NULL)
6620 return NULL;
6621
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006622 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006623 if (wpa_s == NULL)
6624 return NULL;
6625
6626 wpa_s->global = global;
6627
6628 t_iface = *iface;
6629 if (global->params.override_driver) {
6630 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6631 "('%s' -> '%s')",
6632 iface->driver, global->params.override_driver);
6633 t_iface.driver = global->params.override_driver;
6634 }
6635 if (global->params.override_ctrl_interface) {
6636 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6637 "ctrl_interface ('%s' -> '%s')",
6638 iface->ctrl_interface,
6639 global->params.override_ctrl_interface);
6640 t_iface.ctrl_interface =
6641 global->params.override_ctrl_interface;
6642 }
6643 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6644 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6645 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006646 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006647 return NULL;
6648 }
6649
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006650 /* Notify the control interfaces about new iface */
6651 if (wpas_notify_iface_added(wpa_s)) {
6652 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6653 return NULL;
6654 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006655
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006656 /* Notify the control interfaces about new networks for non p2p mgmt
6657 * ifaces. */
6658 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006659 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6660 wpas_notify_network_added(wpa_s, ssid);
6661 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006662
6663 wpa_s->next = global->ifaces;
6664 global->ifaces = wpa_s;
6665
6666 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006667 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006668
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006669#ifdef CONFIG_P2P
6670 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006671 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006672 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006673 wpas_p2p_add_p2pdev_interface(
6674 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006675 wpa_printf(MSG_INFO,
6676 "P2P: Failed to enable P2P Device interface");
6677 /* Try to continue without. P2P will be disabled. */
6678 }
6679#endif /* CONFIG_P2P */
6680
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006681 return wpa_s;
6682}
6683
6684
6685/**
6686 * wpa_supplicant_remove_iface - Remove a network interface
6687 * @global: Pointer to global data from wpa_supplicant_init()
6688 * @wpa_s: Pointer to the network interface to be removed
6689 * Returns: 0 if interface was removed, -1 if interface was not found
6690 *
6691 * This function can be used to dynamically remove network interfaces from
6692 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6693 * addition, this function is used to remove all remaining interfaces when
6694 * %wpa_supplicant is terminated.
6695 */
6696int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006697 struct wpa_supplicant *wpa_s,
6698 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006699{
6700 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006701#ifdef CONFIG_MESH
6702 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6703 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006704 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006705#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006706
6707 /* Remove interface from the global list of interfaces */
6708 prev = global->ifaces;
6709 if (prev == wpa_s) {
6710 global->ifaces = wpa_s->next;
6711 } else {
6712 while (prev && prev->next != wpa_s)
6713 prev = prev->next;
6714 if (prev == NULL)
6715 return -1;
6716 prev->next = wpa_s->next;
6717 }
6718
6719 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6720
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006721#ifdef CONFIG_MESH
6722 if (mesh_if_created) {
6723 ifname = os_strdup(wpa_s->ifname);
6724 if (ifname == NULL) {
6725 wpa_dbg(wpa_s, MSG_ERROR,
6726 "mesh: Failed to malloc ifname");
6727 return -1;
6728 }
6729 }
6730#endif /* CONFIG_MESH */
6731
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006732 if (global->p2p_group_formation == wpa_s)
6733 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006734 if (global->p2p_invite_group == wpa_s)
6735 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006736 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006737
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006738#ifdef CONFIG_MESH
6739 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006740 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006741 os_free(ifname);
6742 }
6743#endif /* CONFIG_MESH */
6744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006745 return 0;
6746}
6747
6748
6749/**
6750 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6751 * @wpa_s: Pointer to the network interface
6752 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6753 */
6754const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6755{
6756 const char *eapol_method;
6757
6758 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6759 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6760 return "NO-EAP";
6761 }
6762
6763 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6764 if (eapol_method == NULL)
6765 return "UNKNOWN-EAP";
6766
6767 return eapol_method;
6768}
6769
6770
6771/**
6772 * wpa_supplicant_get_iface - Get a new network interface
6773 * @global: Pointer to global data from wpa_supplicant_init()
6774 * @ifname: Interface name
6775 * Returns: Pointer to the interface or %NULL if not found
6776 */
6777struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6778 const char *ifname)
6779{
6780 struct wpa_supplicant *wpa_s;
6781
6782 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6783 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6784 return wpa_s;
6785 }
6786 return NULL;
6787}
6788
6789
6790#ifndef CONFIG_NO_WPA_MSG
6791static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6792{
6793 struct wpa_supplicant *wpa_s = ctx;
6794 if (wpa_s == NULL)
6795 return NULL;
6796 return wpa_s->ifname;
6797}
6798#endif /* CONFIG_NO_WPA_MSG */
6799
6800
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006801#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6802#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6803#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6804
6805/* Periodic cleanup tasks */
6806static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6807{
6808 struct wpa_global *global = eloop_ctx;
6809 struct wpa_supplicant *wpa_s;
6810
6811 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6812 wpas_periodic, global, NULL);
6813
6814#ifdef CONFIG_P2P
6815 if (global->p2p)
6816 p2p_expire_peers(global->p2p);
6817#endif /* CONFIG_P2P */
6818
6819 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6820 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6821#ifdef CONFIG_AP
6822 ap_periodic(wpa_s);
6823#endif /* CONFIG_AP */
6824 }
6825}
6826
6827
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006828/**
6829 * wpa_supplicant_init - Initialize %wpa_supplicant
6830 * @params: Parameters for %wpa_supplicant
6831 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6832 *
6833 * This function is used to initialize %wpa_supplicant. After successful
6834 * initialization, the returned data pointer can be used to add and remove
6835 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6836 */
6837struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6838{
6839 struct wpa_global *global;
6840 int ret, i;
6841
6842 if (params == NULL)
6843 return NULL;
6844
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006845#ifdef CONFIG_DRIVER_NDIS
6846 {
6847 void driver_ndis_init_ops(void);
6848 driver_ndis_init_ops();
6849 }
6850#endif /* CONFIG_DRIVER_NDIS */
6851
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006852#ifndef CONFIG_NO_WPA_MSG
6853 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6854#endif /* CONFIG_NO_WPA_MSG */
6855
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006856 if (params->wpa_debug_file_path)
6857 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07006858 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006859 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006860 if (params->wpa_debug_syslog)
6861 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006862 if (params->wpa_debug_tracing) {
6863 ret = wpa_debug_open_linux_tracing();
6864 if (ret) {
6865 wpa_printf(MSG_ERROR,
6866 "Failed to enable trace logging");
6867 return NULL;
6868 }
6869 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006870
6871 ret = eap_register_methods();
6872 if (ret) {
6873 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6874 if (ret == -2)
6875 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6876 "the same EAP type.");
6877 return NULL;
6878 }
6879
6880 global = os_zalloc(sizeof(*global));
6881 if (global == NULL)
6882 return NULL;
6883 dl_list_init(&global->p2p_srv_bonjour);
6884 dl_list_init(&global->p2p_srv_upnp);
6885 global->params.daemonize = params->daemonize;
6886 global->params.wait_for_monitor = params->wait_for_monitor;
6887 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6888 if (params->pid_file)
6889 global->params.pid_file = os_strdup(params->pid_file);
6890 if (params->ctrl_interface)
6891 global->params.ctrl_interface =
6892 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006893 if (params->ctrl_interface_group)
6894 global->params.ctrl_interface_group =
6895 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006896 if (params->override_driver)
6897 global->params.override_driver =
6898 os_strdup(params->override_driver);
6899 if (params->override_ctrl_interface)
6900 global->params.override_ctrl_interface =
6901 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006902#ifdef CONFIG_MATCH_IFACE
6903 global->params.match_iface_count = params->match_iface_count;
6904 if (params->match_iface_count) {
6905 global->params.match_ifaces =
6906 os_calloc(params->match_iface_count,
6907 sizeof(struct wpa_interface));
6908 os_memcpy(global->params.match_ifaces,
6909 params->match_ifaces,
6910 params->match_iface_count *
6911 sizeof(struct wpa_interface));
6912 }
6913#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006914#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006915 if (params->conf_p2p_dev)
6916 global->params.conf_p2p_dev =
6917 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006918#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006919 wpa_debug_level = global->params.wpa_debug_level =
6920 params->wpa_debug_level;
6921 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6922 params->wpa_debug_show_keys;
6923 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6924 params->wpa_debug_timestamp;
6925
Hai Shalomfdcde762020-04-02 11:19:20 -07006926 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006927
6928 if (eloop_init()) {
6929 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6930 wpa_supplicant_deinit(global);
6931 return NULL;
6932 }
6933
Jouni Malinen75ecf522011-06-27 15:19:46 -07006934 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006935
6936 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6937 if (global->ctrl_iface == NULL) {
6938 wpa_supplicant_deinit(global);
6939 return NULL;
6940 }
6941
6942 if (wpas_notify_supplicant_initialized(global)) {
6943 wpa_supplicant_deinit(global);
6944 return NULL;
6945 }
6946
6947 for (i = 0; wpa_drivers[i]; i++)
6948 global->drv_count++;
6949 if (global->drv_count == 0) {
6950 wpa_printf(MSG_ERROR, "No drivers enabled");
6951 wpa_supplicant_deinit(global);
6952 return NULL;
6953 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006954 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006955 if (global->drv_priv == NULL) {
6956 wpa_supplicant_deinit(global);
6957 return NULL;
6958 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006959
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006960#ifdef CONFIG_WIFI_DISPLAY
6961 if (wifi_display_init(global) < 0) {
6962 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6963 wpa_supplicant_deinit(global);
6964 return NULL;
6965 }
6966#endif /* CONFIG_WIFI_DISPLAY */
6967
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006968 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6969 wpas_periodic, global, NULL);
6970
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006971 return global;
6972}
6973
6974
6975/**
6976 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6977 * @global: Pointer to global data from wpa_supplicant_init()
6978 * Returns: 0 after successful event loop run, -1 on failure
6979 *
6980 * This function starts the main event loop and continues running as long as
6981 * there are any remaining events. In most cases, this function is running as
6982 * long as the %wpa_supplicant process in still in use.
6983 */
6984int wpa_supplicant_run(struct wpa_global *global)
6985{
6986 struct wpa_supplicant *wpa_s;
6987
6988 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006989 (wpa_supplicant_daemon(global->params.pid_file) ||
6990 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006991 return -1;
6992
Dmitry Shmidte4663042016-04-04 10:07:49 -07006993#ifdef CONFIG_MATCH_IFACE
6994 if (wpa_supplicant_match_existing(global))
6995 return -1;
6996#endif
6997
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006998 if (global->params.wait_for_monitor) {
6999 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007000 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007001 wpa_supplicant_ctrl_iface_wait(
7002 wpa_s->ctrl_iface);
7003 }
7004
7005 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7006 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7007
7008 eloop_run();
7009
7010 return 0;
7011}
7012
7013
7014/**
7015 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7016 * @global: Pointer to global data from wpa_supplicant_init()
7017 *
7018 * This function is called to deinitialize %wpa_supplicant and to free all
7019 * allocated resources. Remaining network interfaces will also be removed.
7020 */
7021void wpa_supplicant_deinit(struct wpa_global *global)
7022{
7023 int i;
7024
7025 if (global == NULL)
7026 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007027
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007028 eloop_cancel_timeout(wpas_periodic, global, NULL);
7029
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007030#ifdef CONFIG_WIFI_DISPLAY
7031 wifi_display_deinit(global);
7032#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007033
7034 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007035 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007036
7037 if (global->ctrl_iface)
7038 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7039
7040 wpas_notify_supplicant_deinitialized(global);
7041
7042 eap_peer_unregister_methods();
7043#ifdef CONFIG_AP
7044 eap_server_unregister_methods();
7045#endif /* CONFIG_AP */
7046
7047 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7048 if (!global->drv_priv[i])
7049 continue;
7050 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7051 }
7052 os_free(global->drv_priv);
7053
7054 random_deinit();
7055
7056 eloop_destroy();
7057
7058 if (global->params.pid_file) {
7059 os_daemonize_terminate(global->params.pid_file);
7060 os_free(global->params.pid_file);
7061 }
7062 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007063 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007064 os_free(global->params.override_driver);
7065 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007066#ifdef CONFIG_MATCH_IFACE
7067 os_free(global->params.match_ifaces);
7068#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007069#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007070 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007071#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007072
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007073 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007074 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007075 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007076
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007077 os_free(global);
7078 wpa_debug_close_syslog();
7079 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007080 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007081}
7082
7083
7084void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7085{
7086 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7087 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7088 char country[3];
7089 country[0] = wpa_s->conf->country[0];
7090 country[1] = wpa_s->conf->country[1];
7091 country[2] = '\0';
7092 if (wpa_drv_set_country(wpa_s, country) < 0) {
7093 wpa_printf(MSG_ERROR, "Failed to set country code "
7094 "'%s'", country);
7095 }
7096 }
7097
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007098 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7099 wpas_init_ext_pw(wpa_s);
7100
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007101 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7102 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7103
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007104 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7105 struct wpa_driver_capa capa;
7106 int res = wpa_drv_get_capa(wpa_s, &capa);
7107
7108 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7109 wpa_printf(MSG_ERROR,
7110 "Failed to update wowlan_triggers to '%s'",
7111 wpa_s->conf->wowlan_triggers);
7112 }
7113
Hai Shalom81f62d82019-07-22 12:10:00 -07007114 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7115 wpa_supplicant_set_default_scan_ies(wpa_s);
7116
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007117#ifdef CONFIG_WPS
7118 wpas_wps_update_config(wpa_s);
7119#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007120 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007121 wpa_s->conf->changed_parameters = 0;
7122}
7123
7124
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007125void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007126{
7127 int i;
7128
7129 for (i = 0; i < *num_freqs; i++) {
7130 if (freqs[i] == freq)
7131 return;
7132 }
7133
7134 freqs[*num_freqs] = freq;
7135 (*num_freqs)++;
7136}
7137
7138
7139static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7140{
7141 struct wpa_bss *bss, *cbss;
7142 const int max_freqs = 10;
7143 int *freqs;
7144 int num_freqs = 0;
7145
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007146 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007147 if (freqs == NULL)
7148 return NULL;
7149
7150 cbss = wpa_s->current_bss;
7151
7152 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7153 if (bss == cbss)
7154 continue;
7155 if (bss->ssid_len == cbss->ssid_len &&
7156 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
7157 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
7158 add_freq(freqs, &num_freqs, bss->freq);
7159 if (num_freqs == max_freqs)
7160 break;
7161 }
7162 }
7163
7164 if (num_freqs == 0) {
7165 os_free(freqs);
7166 freqs = NULL;
7167 }
7168
7169 return freqs;
7170}
7171
7172
7173void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7174{
7175 int timeout;
7176 int count;
7177 int *freqs = NULL;
7178
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007179 wpas_connect_work_done(wpa_s);
7180
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007181 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007182 * Remove possible authentication timeout since the connection failed.
7183 */
7184 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7185
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007186 /*
7187 * There is no point in blacklisting the AP if this event is
7188 * generated based on local request to disconnect.
7189 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007190 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007191 wpa_s->own_disconnect_req = 0;
7192 wpa_dbg(wpa_s, MSG_DEBUG,
7193 "Ignore connection failure due to local request to disconnect");
7194 return;
7195 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007196 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007197 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7198 "indication since interface has been put into "
7199 "disconnected state");
7200 return;
7201 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007202 if (wpa_s->auto_reconnect_disabled) {
7203 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7204 "indication since auto connect is disabled");
7205 return;
7206 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007207
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007208 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007209 * Add the failed BSSID into the blacklist and speed up next scan
7210 * attempt if there could be other APs that could accept association.
7211 * The current blacklist count indicates how many times we have tried
7212 * connecting to this AP and multiple attempts mean that other APs are
7213 * either not available or has already been tried, so that we can start
7214 * increasing the delay here to avoid constant scanning.
7215 */
7216 count = wpa_blacklist_add(wpa_s, bssid);
7217 if (count == 1 && wpa_s->current_bss) {
7218 /*
7219 * This BSS was not in the blacklist before. If there is
7220 * another BSS available for the same ESS, we should try that
7221 * next. Otherwise, we may as well try this one once more
7222 * before allowing other, likely worse, ESSes to be considered.
7223 */
7224 freqs = get_bss_freqs_in_ess(wpa_s);
7225 if (freqs) {
7226 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7227 "has been seen; try it next");
7228 wpa_blacklist_add(wpa_s, bssid);
7229 /*
7230 * On the next scan, go through only the known channels
7231 * used in this ESS based on previous scans to speed up
7232 * common load balancing use case.
7233 */
7234 os_free(wpa_s->next_scan_freqs);
7235 wpa_s->next_scan_freqs = freqs;
7236 }
7237 }
7238
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007239 /*
7240 * Add previous failure count in case the temporary blacklist was
7241 * cleared due to no other BSSes being available.
7242 */
7243 count += wpa_s->extra_blacklist_count;
7244
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007245 if (count > 3 && wpa_s->current_ssid) {
7246 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7247 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007248 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007249 }
7250
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007251 switch (count) {
7252 case 1:
7253 timeout = 100;
7254 break;
7255 case 2:
7256 timeout = 500;
7257 break;
7258 case 3:
7259 timeout = 1000;
7260 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007261 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007262 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007263 break;
7264 default:
7265 timeout = 10000;
7266 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007267 }
7268
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007269 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
7270 "ms", count, timeout);
7271
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007272 /*
7273 * TODO: if more than one possible AP is available in scan results,
7274 * could try the other ones before requesting a new scan.
7275 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007276
7277 /* speed up the connection attempt with normal scan */
7278 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007279 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7280 1000 * (timeout % 1000));
7281}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007282
7283
Hai Shalomce48b4a2018-09-05 11:41:35 -07007284#ifdef CONFIG_FILS
7285void fils_connection_failure(struct wpa_supplicant *wpa_s)
7286{
7287 struct wpa_ssid *ssid = wpa_s->current_ssid;
7288 const u8 *realm, *username, *rrk;
7289 size_t realm_len, username_len, rrk_len;
7290 u16 next_seq_num;
7291
7292 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7293 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7294 &username, &username_len,
7295 &realm, &realm_len, &next_seq_num,
7296 &rrk, &rrk_len) != 0 ||
7297 !realm)
7298 return;
7299
7300 wpa_hexdump_ascii(MSG_DEBUG,
7301 "FILS: Store last connection failure realm",
7302 realm, realm_len);
7303 os_free(wpa_s->last_con_fail_realm);
7304 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7305 if (wpa_s->last_con_fail_realm) {
7306 wpa_s->last_con_fail_realm_len = realm_len;
7307 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7308 }
7309}
7310#endif /* CONFIG_FILS */
7311
7312
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007313int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7314{
7315 return wpa_s->conf->ap_scan == 2 ||
7316 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7317}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007318
Dmitry Shmidt04949592012-07-19 12:16:46 -07007319
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007320#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007321int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7322 struct wpa_ssid *ssid,
7323 const char *field,
7324 const char *value)
7325{
7326#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007327 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007328
7329 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7330 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7331 (const u8 *) value, os_strlen(value));
7332
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007333 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007334 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007335#else /* IEEE8021X_EAPOL */
7336 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7337 return -1;
7338#endif /* IEEE8021X_EAPOL */
7339}
7340
7341int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7342 struct wpa_ssid *ssid,
7343 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007344 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007345{
7346#ifdef IEEE8021X_EAPOL
7347 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007348 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007349
7350 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007351 case WPA_CTRL_REQ_EAP_IDENTITY:
7352 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007353 os_free(eap->imsi_identity);
7354 if (value == NULL)
7355 return -1;
7356 identity = os_strchr(value, ':');
7357 if (identity == NULL) {
7358 /* plain identity */
7359 eap->identity = (u8 *)os_strdup(value);
7360 eap->identity_len = os_strlen(value);
7361 } else {
7362 /* have both plain identity and encrypted identity */
7363 imsi_identity = value;
7364 *identity++ = '\0';
7365 /* plain identity */
7366 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7367 eap->imsi_identity_len = strlen(imsi_identity);
7368 /* encrypted identity */
7369 eap->identity = (u8 *)dup_binstr(identity,
7370 value_len - strlen(imsi_identity) - 1);
7371 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7372 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007373 eap->pending_req_identity = 0;
7374 if (ssid == wpa_s->current_ssid)
7375 wpa_s->reassociate = 1;
7376 break;
7377 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007378 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007379 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007380 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007381 eap->pending_req_password = 0;
7382 if (ssid == wpa_s->current_ssid)
7383 wpa_s->reassociate = 1;
7384 break;
7385 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007386 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007387 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007388 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007389 eap->pending_req_new_password = 0;
7390 if (ssid == wpa_s->current_ssid)
7391 wpa_s->reassociate = 1;
7392 break;
7393 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007394 str_clear_free(eap->cert.pin);
7395 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007396 eap->pending_req_pin = 0;
7397 if (ssid == wpa_s->current_ssid)
7398 wpa_s->reassociate = 1;
7399 break;
7400 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007401 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007402 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007403 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007404 os_free(eap->pending_req_otp);
7405 eap->pending_req_otp = NULL;
7406 eap->pending_req_otp_len = 0;
7407 break;
7408 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007409 str_clear_free(eap->cert.private_key_passwd);
7410 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007411 eap->pending_req_passphrase = 0;
7412 if (ssid == wpa_s->current_ssid)
7413 wpa_s->reassociate = 1;
7414 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007415 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007416 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007417 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007418 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007419 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007420 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7421 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7422 return -1;
7423 ssid->mem_only_psk = 1;
7424 if (ssid->passphrase)
7425 wpa_config_update_psk(ssid);
7426 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7427 wpa_supplicant_req_scan(wpa_s, 0, 0);
7428 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007429 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7430 if (eap->pending_ext_cert_check != PENDING_CHECK)
7431 return -1;
7432 if (os_strcmp(value, "good") == 0)
7433 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7434 else if (os_strcmp(value, "bad") == 0)
7435 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7436 else
7437 return -1;
7438 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007439 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007440 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007441 return -1;
7442 }
7443
7444 return 0;
7445#else /* IEEE8021X_EAPOL */
7446 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7447 return -1;
7448#endif /* IEEE8021X_EAPOL */
7449}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007450#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007451
7452
7453int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7454{
Hai Shalomfdcde762020-04-02 11:19:20 -07007455#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007456 int i;
7457 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007458#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007459
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007460 if (wpa_s->p2p_mgmt)
7461 return 1; /* no normal network profiles on p2p_mgmt interface */
7462
Dmitry Shmidt04949592012-07-19 12:16:46 -07007463 if (ssid == NULL)
7464 return 1;
7465
7466 if (ssid->disabled)
7467 return 1;
7468
Hai Shalomfdcde762020-04-02 11:19:20 -07007469#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007470 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007471 drv_enc = wpa_s->drv_enc;
7472 else
7473 drv_enc = (unsigned int) -1;
7474
7475 for (i = 0; i < NUM_WEP_KEYS; i++) {
7476 size_t len = ssid->wep_key_len[i];
7477 if (len == 0)
7478 continue;
7479 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7480 continue;
7481 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7482 continue;
7483 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7484 continue;
7485 return 1; /* invalid WEP key */
7486 }
Hai Shalomfdcde762020-04-02 11:19:20 -07007487#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007488
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007489 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007490 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007491 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007492 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007493 return 1;
7494
Dmitry Shmidt04949592012-07-19 12:16:46 -07007495 return 0;
7496}
7497
7498
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007499int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7500{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007501 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7502 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7503 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7504 /*
7505 * Driver does not support BIP -- ignore pmf=1 default
7506 * since the connection with PMF would fail and the
7507 * configuration does not require PMF to be enabled.
7508 */
7509 return NO_MGMT_FRAME_PROTECTION;
7510 }
7511
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007512 if (ssid &&
7513 (ssid->key_mgmt &
7514 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7515 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7516 /*
7517 * Do not use the default PMF value for non-RSN networks
7518 * since PMF is available only with RSN and pmf=2
7519 * configuration would otherwise prevent connections to
7520 * all open networks.
7521 */
7522 return NO_MGMT_FRAME_PROTECTION;
7523 }
7524
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007525 return wpa_s->conf->pmf;
7526 }
7527
7528 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007529}
7530
7531
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007532int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007533{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007534 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007535 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007536 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007537 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007538 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007539}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007540
7541
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007542void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007543{
7544 struct wpa_ssid *ssid = wpa_s->current_ssid;
7545 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007546 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007547
7548 if (ssid == NULL) {
7549 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7550 "SSID block");
7551 return;
7552 }
7553
7554 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7555 return;
7556
7557 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007558
7559#ifdef CONFIG_P2P
7560 if (ssid->p2p_group &&
7561 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7562 /*
7563 * Skip the wait time since there is a short timeout on the
7564 * connection to a P2P group.
7565 */
7566 return;
7567 }
7568#endif /* CONFIG_P2P */
7569
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007570 if (ssid->auth_failures > 50)
7571 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007572 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007573 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007574 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007575 dur = 90;
7576 else if (ssid->auth_failures > 3)
7577 dur = 60;
7578 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007579 dur = 30;
7580 else if (ssid->auth_failures > 1)
7581 dur = 20;
7582 else
7583 dur = 10;
7584
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007585 if (ssid->auth_failures > 1 &&
7586 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7587 dur += os_random() % (ssid->auth_failures * 10);
7588
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007589 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007590 if (now.sec + dur <= ssid->disabled_until.sec)
7591 return;
7592
7593 ssid->disabled_until.sec = now.sec + dur;
7594
7595 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007596 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007597 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007598 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007599}
7600
7601
7602void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7603 struct wpa_ssid *ssid, int clear_failures)
7604{
7605 if (ssid == NULL)
7606 return;
7607
7608 if (ssid->disabled_until.sec) {
7609 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7610 "id=%d ssid=\"%s\"",
7611 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7612 }
7613 ssid->disabled_until.sec = 0;
7614 ssid->disabled_until.usec = 0;
7615 if (clear_failures)
7616 ssid->auth_failures = 0;
7617}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007618
7619
7620int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7621{
7622 size_t i;
7623
7624 if (wpa_s->disallow_aps_bssid == NULL)
7625 return 0;
7626
7627 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7628 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7629 bssid, ETH_ALEN) == 0)
7630 return 1;
7631 }
7632
7633 return 0;
7634}
7635
7636
7637int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7638 size_t ssid_len)
7639{
7640 size_t i;
7641
7642 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7643 return 0;
7644
7645 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7646 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7647 if (ssid_len == s->ssid_len &&
7648 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7649 return 1;
7650 }
7651
7652 return 0;
7653}
7654
7655
7656/**
7657 * wpas_request_connection - Request a new connection
7658 * @wpa_s: Pointer to the network interface
7659 *
7660 * This function is used to request a new connection to be found. It will mark
7661 * the interface to allow reassociation and request a new scan to find a
7662 * suitable network to connect to.
7663 */
7664void wpas_request_connection(struct wpa_supplicant *wpa_s)
7665{
7666 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007667 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007668 wpa_supplicant_reinit_autoscan(wpa_s);
7669 wpa_s->extra_blacklist_count = 0;
7670 wpa_s->disconnected = 0;
7671 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007672 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007673
7674 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7675 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007676 else
7677 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007678}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007679
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007680
Roshan Pius02242d72016-08-09 15:31:48 -07007681/**
7682 * wpas_request_disconnection - Request disconnection
7683 * @wpa_s: Pointer to the network interface
7684 *
7685 * This function is used to request disconnection from the currently connected
7686 * network. This will stop any ongoing scans and initiate deauthentication.
7687 */
7688void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7689{
7690#ifdef CONFIG_SME
7691 wpa_s->sme.prev_bssid_set = 0;
7692#endif /* CONFIG_SME */
7693 wpa_s->reassociate = 0;
7694 wpa_s->disconnected = 1;
7695 wpa_supplicant_cancel_sched_scan(wpa_s);
7696 wpa_supplicant_cancel_scan(wpa_s);
7697 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7698 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007699 radio_remove_works(wpa_s, "connect", 0);
7700 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007701}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007702
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007703
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007704void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7705 struct wpa_used_freq_data *freqs_data,
7706 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007707{
7708 unsigned int i;
7709
7710 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7711 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007712 for (i = 0; i < len; i++) {
7713 struct wpa_used_freq_data *cur = &freqs_data[i];
7714 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7715 i, cur->freq, cur->flags);
7716 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007717}
7718
7719
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007720/*
7721 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007722 * are using the same radio as the current interface, and in addition, get
7723 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007724 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007725int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7726 struct wpa_used_freq_data *freqs_data,
7727 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007728{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007729 struct wpa_supplicant *ifs;
7730 u8 bssid[ETH_ALEN];
7731 int freq;
7732 unsigned int idx = 0, i;
7733
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007734 wpa_dbg(wpa_s, MSG_DEBUG,
7735 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007736 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007737
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007738 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7739 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007740 if (idx == len)
7741 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007742
7743 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7744 continue;
7745
7746 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007747 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7748 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007749 freq = ifs->current_ssid->frequency;
7750 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7751 freq = ifs->assoc_freq;
7752 else
7753 continue;
7754
7755 /* Hold only distinct freqs */
7756 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007757 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007758 break;
7759
7760 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007761 freqs_data[idx++].freq = freq;
7762
7763 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007764 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007765 WPA_FREQ_USED_BY_P2P_CLIENT :
7766 WPA_FREQ_USED_BY_INFRA_STATION;
7767 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007768 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007769
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007770 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007771 return idx;
7772}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007773
7774
7775/*
7776 * Find the operating frequencies of any of the virtual interfaces that
7777 * are using the same radio as the current interface.
7778 */
7779int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7780 int *freq_array, unsigned int len)
7781{
7782 struct wpa_used_freq_data *freqs_data;
7783 int num, i;
7784
7785 os_memset(freq_array, 0, sizeof(int) * len);
7786
7787 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7788 if (!freqs_data)
7789 return -1;
7790
7791 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7792 for (i = 0; i < num; i++)
7793 freq_array[i] = freqs_data[i].freq;
7794
7795 os_free(freqs_data);
7796
7797 return num;
7798}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007799
7800
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007801struct wpa_supplicant *
7802wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7803{
7804 switch (frame) {
7805#ifdef CONFIG_P2P
7806 case VENDOR_ELEM_PROBE_REQ_P2P:
7807 case VENDOR_ELEM_PROBE_RESP_P2P:
7808 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7809 case VENDOR_ELEM_BEACON_P2P_GO:
7810 case VENDOR_ELEM_P2P_PD_REQ:
7811 case VENDOR_ELEM_P2P_PD_RESP:
7812 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7813 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7814 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7815 case VENDOR_ELEM_P2P_INV_REQ:
7816 case VENDOR_ELEM_P2P_INV_RESP:
7817 case VENDOR_ELEM_P2P_ASSOC_REQ:
7818 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007819 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007820#endif /* CONFIG_P2P */
7821 default:
7822 return wpa_s;
7823 }
7824}
7825
7826
7827void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7828{
7829 unsigned int i;
7830 char buf[30];
7831
7832 wpa_printf(MSG_DEBUG, "Update vendor elements");
7833
7834 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7835 if (wpa_s->vendor_elem[i]) {
7836 int res;
7837
7838 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7839 if (!os_snprintf_error(sizeof(buf), res)) {
7840 wpa_hexdump_buf(MSG_DEBUG, buf,
7841 wpa_s->vendor_elem[i]);
7842 }
7843 }
7844 }
7845
7846#ifdef CONFIG_P2P
7847 if (wpa_s->parent == wpa_s &&
7848 wpa_s->global->p2p &&
7849 !wpa_s->global->p2p_disabled)
7850 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7851#endif /* CONFIG_P2P */
7852}
7853
7854
7855int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7856 const u8 *elem, size_t len)
7857{
7858 u8 *ie, *end;
7859
7860 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7861 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7862
7863 for (; ie + 1 < end; ie += 2 + ie[1]) {
7864 if (ie + len > end)
7865 break;
7866 if (os_memcmp(ie, elem, len) != 0)
7867 continue;
7868
7869 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7870 wpabuf_free(wpa_s->vendor_elem[frame]);
7871 wpa_s->vendor_elem[frame] = NULL;
7872 } else {
7873 os_memmove(ie, ie + len, end - (ie + len));
7874 wpa_s->vendor_elem[frame]->used -= len;
7875 }
7876 wpas_vendor_elem_update(wpa_s);
7877 return 0;
7878 }
7879
7880 return -1;
7881}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007882
7883
7884struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07007885 u16 num_modes, enum hostapd_hw_mode mode,
7886 int is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007887{
7888 u16 i;
7889
7890 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007891 if (modes[i].mode != mode ||
7892 !modes[i].num_channels || !modes[i].channels)
7893 continue;
7894 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
7895 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007896 return &modes[i];
7897 }
7898
7899 return NULL;
7900}
7901
7902
7903static struct
7904wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7905 const u8 *bssid)
7906{
7907 struct wpa_bss_tmp_disallowed *bss;
7908
7909 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7910 struct wpa_bss_tmp_disallowed, list) {
7911 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7912 return bss;
7913 }
7914
7915 return NULL;
7916}
7917
7918
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007919static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7920{
7921 struct wpa_bss_tmp_disallowed *tmp;
7922 unsigned int num_bssid = 0;
7923 u8 *bssids;
7924 int ret;
7925
7926 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7927 if (!bssids)
7928 return -1;
7929 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7930 struct wpa_bss_tmp_disallowed, list) {
7931 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7932 ETH_ALEN);
7933 num_bssid++;
7934 }
7935 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7936 os_free(bssids);
7937 return ret;
7938}
7939
7940
7941static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7942{
7943 struct wpa_supplicant *wpa_s = eloop_ctx;
7944 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7945
7946 /* Make sure the bss is not already freed */
7947 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7948 struct wpa_bss_tmp_disallowed, list) {
7949 if (bss == tmp) {
7950 dl_list_del(&tmp->list);
7951 os_free(tmp);
7952 wpa_set_driver_tmp_disallow_list(wpa_s);
7953 break;
7954 }
7955 }
7956}
7957
7958
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007959void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08007960 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007961{
7962 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007963
7964 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7965 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007966 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08007967 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007968 }
7969
7970 bss = os_malloc(sizeof(*bss));
7971 if (!bss) {
7972 wpa_printf(MSG_DEBUG,
7973 "Failed to allocate memory for temp disallow BSS");
7974 return;
7975 }
7976
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007977 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7978 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007979 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08007980
7981finish:
7982 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007983 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7984 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007985}
7986
7987
Hai Shalom74f70d42019-02-11 14:42:39 -08007988int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
7989 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007990{
Hai Shalom74f70d42019-02-11 14:42:39 -08007991 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007992
7993 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7994 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007995 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
7996 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007997 break;
7998 }
7999 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008000 if (!disallowed)
8001 return 0;
8002
8003 if (disallowed->rssi_threshold != 0 &&
8004 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008005 return 0;
8006
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008007 return 1;
8008}
Hai Shalom81f62d82019-07-22 12:10:00 -07008009
8010
8011int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8012 unsigned int type, const u8 *addr,
8013 const u8 *mask)
8014{
8015 if ((addr && !mask) || (!addr && mask)) {
8016 wpa_printf(MSG_INFO,
8017 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8018 return -1;
8019 }
8020
8021 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8022 wpa_printf(MSG_INFO,
8023 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8024 return -1;
8025 }
8026
8027 if (type & MAC_ADDR_RAND_SCAN) {
8028 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8029 addr, mask))
8030 return -1;
8031 }
8032
8033 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8034 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8035 addr, mask))
8036 return -1;
8037
8038 if (wpa_s->sched_scanning && !wpa_s->pno)
8039 wpas_scan_restart_sched_scan(wpa_s);
8040 }
8041
8042 if (type & MAC_ADDR_RAND_PNO) {
8043 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8044 addr, mask))
8045 return -1;
8046
8047 if (wpa_s->pno) {
8048 wpas_stop_pno(wpa_s);
8049 wpas_start_pno(wpa_s);
8050 }
8051 }
8052
8053 return 0;
8054}
8055
8056
8057int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8058 unsigned int type)
8059{
8060 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8061 if (wpa_s->pno) {
8062 if (type & MAC_ADDR_RAND_PNO) {
8063 wpas_stop_pno(wpa_s);
8064 wpas_start_pno(wpa_s);
8065 }
8066 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8067 wpas_scan_restart_sched_scan(wpa_s);
8068 }
8069
8070 return 0;
8071}
Hai Shalomfdcde762020-04-02 11:19:20 -07008072
8073
8074int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8075 struct wpa_signal_info *si)
8076{
8077 int res;
8078
8079 if (!wpa_s->driver->signal_poll)
8080 return -1;
8081
8082 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8083
8084#ifdef CONFIG_TESTING_OPTIONS
8085 if (res == 0) {
8086 struct driver_signal_override *dso;
8087
8088 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8089 struct driver_signal_override, list) {
8090 if (os_memcmp(wpa_s->bssid, dso->bssid,
8091 ETH_ALEN) != 0)
8092 continue;
8093 wpa_printf(MSG_DEBUG,
8094 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8095 si->current_signal,
8096 dso->si_current_signal,
8097 si->avg_signal,
8098 dso->si_avg_signal,
8099 si->avg_beacon_signal,
8100 dso->si_avg_beacon_signal,
8101 si->current_noise,
8102 dso->si_current_noise);
8103 si->current_signal = dso->si_current_signal;
8104 si->avg_signal = dso->si_avg_signal;
8105 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8106 si->current_noise = dso->si_current_noise;
8107 break;
8108 }
8109 }
8110#endif /* CONFIG_TESTING_OPTIONS */
8111
8112 return res;
8113}
8114
8115
8116struct wpa_scan_results *
8117wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8118{
8119 struct wpa_scan_results *scan_res;
8120#ifdef CONFIG_TESTING_OPTIONS
8121 size_t idx;
8122#endif /* CONFIG_TESTING_OPTIONS */
8123
8124 if (!wpa_s->driver->get_scan_results2)
8125 return NULL;
8126
8127 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8128
8129#ifdef CONFIG_TESTING_OPTIONS
8130 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8131 struct driver_signal_override *dso;
8132 struct wpa_scan_res *res = scan_res->res[idx];
8133
8134 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8135 struct driver_signal_override, list) {
8136 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8137 continue;
8138 wpa_printf(MSG_DEBUG,
8139 "Override driver scan signal level %d->%d for "
8140 MACSTR,
8141 res->level, dso->scan_level,
8142 MAC2STR(res->bssid));
8143 res->flags |= WPA_SCAN_QUAL_INVALID;
8144 if (dso->scan_level < 0)
8145 res->flags |= WPA_SCAN_LEVEL_DBM;
8146 else
8147 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8148 res->level = dso->scan_level;
8149 break;
8150 }
8151 }
8152#endif /* CONFIG_TESTING_OPTIONS */
8153
8154 return scan_res;
8155}