blob: 6f44613401f65da4a2b9b1e26848f647f3a272c4 [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);
Hai Shalome21d4e82020-04-29 16:34:06 -0700323 eapol_sm_notify_eap_success(wpa_s->eapol, true);
324 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700325 return;
326 }
327#endif /* CONFIG_IBSS_RSN */
328
Hai Shalome21d4e82020-04-29 16:34:06 -0700329 eapol_sm_notify_eap_success(wpa_s->eapol, false);
330 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700331
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)
Hai Shalome21d4e82020-04-29 16:34:06 -0700898 bool update_fils_connect_params = false;
Hai Shalomc3565922019-10-28 11:58:20 -0700899#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 Shalome21d4e82020-04-29 16:34:06 -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 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001164 eapol_sm_notify_eap_success(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 }
1166 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1167 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001168 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001169 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1170 rsn_preauth_deinit(wpa_s->wpa);
1171
1172 old_ap_scan = wpa_s->conf->ap_scan;
1173 wpa_config_free(wpa_s->conf);
1174 wpa_s->conf = conf;
1175 if (old_ap_scan != wpa_s->conf->ap_scan)
1176 wpas_notify_ap_scan_changed(wpa_s);
1177
1178 if (reconf_ctrl)
1179 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1180
1181 wpa_supplicant_update_config(wpa_s);
1182
1183 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001184 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001185 wpa_s->reassociate = 1;
1186 wpa_supplicant_req_scan(wpa_s, 0, 0);
1187 }
1188 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1189 return 0;
1190}
1191
1192
1193static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1194{
1195 struct wpa_global *global = signal_ctx;
1196 struct wpa_supplicant *wpa_s;
1197 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1198 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1199 sig);
1200 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1201 wpa_supplicant_terminate_proc(global);
1202 }
1203 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001204
1205 if (wpa_debug_reopen_file() < 0) {
1206 /* Ignore errors since we cannot really do much to fix this */
1207 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1208 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209}
1210
1211
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001212static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1213 struct wpa_ssid *ssid,
1214 struct wpa_ie_data *ie)
1215{
1216 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1217 if (ret) {
1218 if (ret == -2) {
1219 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1220 "from association info");
1221 }
1222 return -1;
1223 }
1224
1225 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1226 "cipher suites");
1227 if (!(ie->group_cipher & ssid->group_cipher)) {
1228 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1229 "cipher 0x%x (mask 0x%x) - reject",
1230 ie->group_cipher, ssid->group_cipher);
1231 return -1;
1232 }
1233 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1234 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1235 "cipher 0x%x (mask 0x%x) - reject",
1236 ie->pairwise_cipher, ssid->pairwise_cipher);
1237 return -1;
1238 }
1239 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1240 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1241 "management 0x%x (mask 0x%x) - reject",
1242 ie->key_mgmt, ssid->key_mgmt);
1243 return -1;
1244 }
1245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001246 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001247 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001248 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1249 "that does not support management frame protection - "
1250 "reject");
1251 return -1;
1252 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001253
1254 return 0;
1255}
1256
1257
Hai Shalom021b0b52019-04-10 11:17:58 -07001258static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
1259 int freq)
1260{
1261 if (!ie->has_group)
1262 ie->group_cipher = wpa_default_rsn_cipher(freq);
1263 if (!ie->has_pairwise)
1264 ie->pairwise_cipher = wpa_default_rsn_cipher(freq);
1265 return (ie->group_cipher & ssid->group_cipher) &&
1266 (ie->pairwise_cipher & ssid->pairwise_cipher);
1267}
1268
1269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001270/**
1271 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1272 * @wpa_s: Pointer to wpa_supplicant data
1273 * @bss: Scan results for the selected BSS, or %NULL if not available
1274 * @ssid: Configuration data for the selected network
1275 * @wpa_ie: Buffer for the WPA/RSN IE
1276 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1277 * used buffer length in case the functions returns success.
1278 * Returns: 0 on success or -1 on failure
1279 *
1280 * This function is used to configure authentication and encryption parameters
1281 * based on the network configuration and scan result for the selected BSS (if
1282 * available).
1283 */
1284int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1285 struct wpa_bss *bss, struct wpa_ssid *ssid,
1286 u8 *wpa_ie, size_t *wpa_ie_len)
1287{
1288 struct wpa_ie_data ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07001289 int sel, proto, sae_pwe;
Hai Shalomc3565922019-10-28 11:58:20 -07001290 const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001291
1292 if (bss) {
1293 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1294 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Hai Shalomc3565922019-10-28 11:58:20 -07001295 bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001296 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001297 } else {
1298 bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
1299 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300
1301 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1302 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001303 matching_ciphers(ssid, &ie, bss->freq) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001304 (ie.key_mgmt & ssid->key_mgmt)) {
1305 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1306 proto = WPA_PROTO_RSN;
1307 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001308 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001309 (ie.group_cipher & ssid->group_cipher) &&
1310 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1311 (ie.key_mgmt & ssid->key_mgmt)) {
1312 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1313 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001314#ifdef CONFIG_HS20
Hai Shalom74f70d42019-02-11 14:42:39 -08001315 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
1316 wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
1317 (ie.group_cipher & ssid->group_cipher) &&
1318 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1319 (ie.key_mgmt & ssid->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001320 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001321 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001322 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1323 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1324 (ie.group_cipher & ssid->group_cipher) &&
1325 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1326 (ie.key_mgmt & ssid->key_mgmt)) {
1327 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1328 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001329#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 } else if (bss) {
1331 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001332 wpa_dbg(wpa_s, MSG_DEBUG,
1333 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1334 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1335 ssid->key_mgmt);
1336 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1337 MAC2STR(bss->bssid),
1338 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1339 bss_wpa ? " WPA" : "",
1340 bss_rsn ? " RSN" : "",
1341 bss_osen ? " OSEN" : "");
1342 if (bss_rsn) {
1343 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1344 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1345 wpa_dbg(wpa_s, MSG_DEBUG,
1346 "Could not parse RSN element");
1347 } else {
1348 wpa_dbg(wpa_s, MSG_DEBUG,
1349 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1350 ie.pairwise_cipher, ie.group_cipher,
1351 ie.key_mgmt);
1352 }
1353 }
1354 if (bss_wpa) {
1355 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1356 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1357 wpa_dbg(wpa_s, MSG_DEBUG,
1358 "Could not parse WPA element");
1359 } else {
1360 wpa_dbg(wpa_s, MSG_DEBUG,
1361 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1362 ie.pairwise_cipher, ie.group_cipher,
1363 ie.key_mgmt);
1364 }
1365 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366 return -1;
1367 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001368 if (ssid->proto & WPA_PROTO_OSEN)
1369 proto = WPA_PROTO_OSEN;
1370 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001371 proto = WPA_PROTO_RSN;
1372 else
1373 proto = WPA_PROTO_WPA;
1374 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1375 os_memset(&ie, 0, sizeof(ie));
1376 ie.group_cipher = ssid->group_cipher;
1377 ie.pairwise_cipher = ssid->pairwise_cipher;
1378 ie.key_mgmt = ssid->key_mgmt;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001379 ie.mgmt_group_cipher = 0;
1380 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1381 if (ssid->group_mgmt_cipher &
1382 WPA_CIPHER_BIP_GMAC_256)
1383 ie.mgmt_group_cipher =
1384 WPA_CIPHER_BIP_GMAC_256;
1385 else if (ssid->group_mgmt_cipher &
1386 WPA_CIPHER_BIP_CMAC_256)
1387 ie.mgmt_group_cipher =
1388 WPA_CIPHER_BIP_CMAC_256;
1389 else if (ssid->group_mgmt_cipher &
1390 WPA_CIPHER_BIP_GMAC_128)
1391 ie.mgmt_group_cipher =
1392 WPA_CIPHER_BIP_GMAC_128;
1393 else
1394 ie.mgmt_group_cipher =
1395 WPA_CIPHER_AES_128_CMAC;
1396 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001397#ifdef CONFIG_OWE
1398 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1399 !ssid->owe_only &&
1400 !bss_wpa && !bss_rsn && !bss_osen) {
1401 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1402 wpa_s->wpa_proto = 0;
1403 *wpa_ie_len = 0;
1404 return 0;
1405 }
1406#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001407 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1408 "based on configuration");
1409 } else
1410 proto = ie.proto;
1411 }
1412
1413 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1414 "pairwise %d key_mgmt %d proto %d",
1415 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416 if (ssid->ieee80211w) {
1417 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1418 ie.mgmt_group_cipher);
1419 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001421 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001422 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1423 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001424 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001425
1426 if (bss || !wpa_s->ap_ies_from_associnfo) {
1427 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1428 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1429 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
Hai Shalomc3565922019-10-28 11:58:20 -07001430 bss_rsn ? 2 + bss_rsn[1] : 0) ||
1431 wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
1432 bss_rsnx ? 2 + bss_rsnx[1] : 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433 return -1;
1434 }
1435
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001436#ifdef CONFIG_NO_WPA
1437 wpa_s->group_cipher = WPA_CIPHER_NONE;
1438 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1439#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001440 sel = ie.group_cipher & ssid->group_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001441 wpa_dbg(wpa_s, MSG_DEBUG,
1442 "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x",
1443 ie.group_cipher, ssid->group_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001444 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1445 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1447 "cipher");
1448 return -1;
1449 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001450 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1451 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001452
1453 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Hai Shalom021b0b52019-04-10 11:17:58 -07001454 wpa_dbg(wpa_s, MSG_DEBUG,
1455 "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x",
1456 ie.pairwise_cipher, ssid->pairwise_cipher, sel);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001457 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1458 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1460 "cipher");
1461 return -1;
1462 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001463 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1464 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001465#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466
1467 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001468#ifdef CONFIG_SAE
1469 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1470 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1471#endif /* CONFIG_SAE */
Hai Shalomfdcde762020-04-02 11:19:20 -07001472#ifdef CONFIG_IEEE80211R
1473 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
1474 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
1475 sel &= ~WPA_KEY_MGMT_FT;
1476#endif /* CONFIG_IEEE80211R */
1477 wpa_dbg(wpa_s, MSG_DEBUG,
1478 "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x",
1479 ie.key_mgmt, ssid->key_mgmt, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001480 if (0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001481#ifdef CONFIG_IEEE80211R
1482#ifdef CONFIG_SHA384
Hai Shalomc3565922019-10-28 11:58:20 -07001483 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
1484 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001485 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1486 wpa_dbg(wpa_s, MSG_DEBUG,
1487 "WPA: using KEY_MGMT FT/802.1X-SHA384");
Hai Shalom81f62d82019-07-22 12:10:00 -07001488 if (!ssid->ft_eap_pmksa_caching &&
1489 pmksa_cache_get_current(wpa_s->wpa)) {
1490 /* PMKSA caching with FT may have interoperability
1491 * issues, so disable that case by default for now. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001492 wpa_dbg(wpa_s, MSG_DEBUG,
1493 "WPA: Disable PMKSA caching for FT/802.1X connection");
1494 pmksa_cache_clear_current(wpa_s->wpa);
1495 }
1496#endif /* CONFIG_SHA384 */
1497#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001498#ifdef CONFIG_SUITEB192
1499 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1500 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1501 wpa_dbg(wpa_s, MSG_DEBUG,
1502 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1503#endif /* CONFIG_SUITEB192 */
1504#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001505 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1506 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1507 wpa_dbg(wpa_s, MSG_DEBUG,
1508 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001509#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001510#ifdef CONFIG_FILS
1511#ifdef CONFIG_IEEE80211R
1512 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1513 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1514 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1515 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1516 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1517 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1518#endif /* CONFIG_IEEE80211R */
1519 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1520 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1521 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1522 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1523 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1524 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1525#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001526#ifdef CONFIG_IEEE80211R
Hai Shalomc3565922019-10-28 11:58:20 -07001527 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
1528 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1530 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Hai Shalom81f62d82019-07-22 12:10:00 -07001531 if (!ssid->ft_eap_pmksa_caching &&
1532 pmksa_cache_get_current(wpa_s->wpa)) {
1533 /* PMKSA caching with FT may have interoperability
1534 * issues, so disable that case by default for now. */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001535 wpa_dbg(wpa_s, MSG_DEBUG,
1536 "WPA: Disable PMKSA caching for FT/802.1X connection");
1537 pmksa_cache_clear_current(wpa_s->wpa);
1538 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001539#endif /* CONFIG_IEEE80211R */
1540#ifdef CONFIG_DPP
1541 } else if (sel & WPA_KEY_MGMT_DPP) {
1542 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1543 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1544#endif /* CONFIG_DPP */
1545#ifdef CONFIG_SAE
1546 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1547 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1548 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1549 } else if (sel & WPA_KEY_MGMT_SAE) {
1550 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1551 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1552#endif /* CONFIG_SAE */
1553#ifdef CONFIG_IEEE80211R
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001554 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1555 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1556 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1557#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1559 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1560 wpa_dbg(wpa_s, MSG_DEBUG,
1561 "WPA: using KEY_MGMT 802.1X with SHA256");
1562 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1563 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1564 wpa_dbg(wpa_s, MSG_DEBUG,
1565 "WPA: using KEY_MGMT PSK with SHA256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001566 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1567 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1568 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1569 } else if (sel & WPA_KEY_MGMT_PSK) {
1570 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1571 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1572 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1573 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1574 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001575#ifdef CONFIG_HS20
1576 } else if (sel & WPA_KEY_MGMT_OSEN) {
1577 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1578 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1579#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001580#ifdef CONFIG_OWE
1581 } else if (sel & WPA_KEY_MGMT_OWE) {
1582 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1583 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1584#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001585 } else {
1586 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1587 "authenticated key management type");
1588 return -1;
1589 }
1590
1591 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1592 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1593 wpa_s->pairwise_cipher);
1594 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1595
Hai Shalomc3565922019-10-28 11:58:20 -07001596 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
1597 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
1598 wpa_msg(wpa_s, MSG_INFO,
1599 "RSN: Management frame protection required but the selected AP does not enable it");
1600 return -1;
1601 }
1602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001603 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001604 if (ssid->group_mgmt_cipher)
1605 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001606 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001607 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1608 sel = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001609 wpa_dbg(wpa_s, MSG_DEBUG,
1610 "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
1611 ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001612 if (sel & WPA_CIPHER_AES_128_CMAC) {
1613 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1614 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1615 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001616 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1617 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1618 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1619 "BIP-GMAC-128");
1620 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1621 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1622 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1623 "BIP-GMAC-256");
1624 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1625 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1626 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1627 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001628 } else {
1629 wpa_s->mgmt_group_cipher = 0;
1630 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1631 }
1632 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1633 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001634 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001635 wpas_get_ssid_pmf(wpa_s, ssid));
Hai Shalom74f70d42019-02-11 14:42:39 -08001636#ifdef CONFIG_OCV
1637 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
1638#endif /* CONFIG_OCV */
Hai Shalomfdcde762020-04-02 11:19:20 -07001639 sae_pwe = wpa_s->conf->sae_pwe;
1640 if (ssid->sae_password_id && sae_pwe != 3)
1641 sae_pwe = 1;
1642 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001643#ifdef CONFIG_TESTING_OPTIONS
1644 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
1645 wpa_s->ft_rsnxe_used);
1646#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -07001647
1648 /* Extended Key ID is only supported in infrastructure BSS so far */
1649 if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id &&
1650 (ssid->proto & WPA_PROTO_RSN) &&
1651 ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
1652 WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) &&
1653 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) {
1654 int use_ext_key_id = 0;
1655
1656 wpa_msg(wpa_s, MSG_DEBUG,
1657 "WPA: Enable Extended Key ID support");
1658 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID,
1659 wpa_s->conf->extended_key_id);
1660 if (bss_rsn &&
1661 wpa_s->conf->extended_key_id &&
1662 wpa_s->pairwise_cipher != WPA_CIPHER_TKIP &&
1663 (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST))
1664 use_ext_key_id = 1;
1665 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID,
1666 use_ext_key_id);
1667 } else {
1668 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0);
1669 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
1670 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671
1672 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1673 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1674 return -1;
1675 }
1676
Hai Shalomc3565922019-10-28 11:58:20 -07001677 wpa_s->rsnxe_len = sizeof(wpa_s->rsnxe);
1678 if (wpa_sm_set_assoc_rsnxe_default(wpa_s->wpa, wpa_s->rsnxe,
1679 &wpa_s->rsnxe_len)) {
1680 wpa_msg(wpa_s, MSG_WARNING, "RSN: Failed to generate RSNXE");
1681 return -1;
1682 }
1683
Hai Shalom021b0b52019-04-10 11:17:58 -07001684 if (0) {
1685#ifdef CONFIG_DPP
1686 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
1687 /* Use PMK from DPP network introduction (PMKSA entry) */
1688 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001689#ifdef CONFIG_DPP2
1690 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs);
1691#endif /* CONFIG_DPP2 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001692#endif /* CONFIG_DPP */
1693 } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001694 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001695 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001696
Roshan Pius3a1667e2018-07-03 15:17:14 -07001697 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1698 WPA_KEY_MGMT_FT_PSK |
1699 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1700
1701 if (ssid->psk_set && !sae_only) {
1702 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1703 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001704 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1705 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001706 psk_set = 1;
1707 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001708
Roshan Pius3a1667e2018-07-03 15:17:14 -07001709 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1710 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001711 psk_set = 1;
1712
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001713#ifndef CONFIG_NO_PBKDF2
1714 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001715 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001716 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001717 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1718 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001719 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1720 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001721 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001722 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001723 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001724 }
1725#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001726#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001727 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001728 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1729 ssid->ext_psk);
1730 char pw_str[64 + 1];
1731 u8 psk[PMK_LEN];
1732
1733 if (pw == NULL) {
1734 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1735 "found from external storage");
1736 return -1;
1737 }
1738
1739 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1740 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1741 "PSK length %d in external storage",
1742 (int) wpabuf_len(pw));
1743 ext_password_free(pw);
1744 return -1;
1745 }
1746
1747 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1748 pw_str[wpabuf_len(pw)] = '\0';
1749
1750#ifndef CONFIG_NO_PBKDF2
1751 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1752 {
1753 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1754 4096, psk, PMK_LEN);
1755 os_memset(pw_str, 0, sizeof(pw_str));
1756 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1757 "external passphrase)",
1758 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001759 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1760 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001761 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001762 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001763 } else
1764#endif /* CONFIG_NO_PBKDF2 */
1765 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1766 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1767 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1768 "Invalid PSK hex string");
1769 os_memset(pw_str, 0, sizeof(pw_str));
1770 ext_password_free(pw);
1771 return -1;
1772 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001773 wpa_hexdump_key(MSG_MSGDUMP,
1774 "PSK (from external PSK)",
1775 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001776 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1777 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001778 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001779 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001780 } else {
1781 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1782 "PSK available");
1783 os_memset(pw_str, 0, sizeof(pw_str));
1784 ext_password_free(pw);
1785 return -1;
1786 }
1787
1788 os_memset(pw_str, 0, sizeof(pw_str));
1789 ext_password_free(pw);
1790 }
1791#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001792
1793 if (!psk_set) {
1794 wpa_msg(wpa_s, MSG_INFO,
1795 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001796 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001797 return -1;
1798 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001799#ifdef CONFIG_OWE
1800 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1801 /* OWE Diffie-Hellman exchange in (Re)Association
1802 * Request/Response frames set the PMK, so do not override it
1803 * here. */
1804#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001805 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001806 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1807
Hai Shalomfdcde762020-04-02 11:19:20 -07001808 if (ssid->mode != WPAS_MODE_IBSS &&
1809 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
1810 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
1811 (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
1812 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
1813 wpa_msg(wpa_s, MSG_INFO,
1814 "Disable PTK0 rekey support - replaced with reconnect");
1815 wpa_s->deny_ptk0_rekey = 1;
1816 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
1817 } else {
1818 wpa_s->deny_ptk0_rekey = 0;
1819 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
1820 }
1821
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001822 return 0;
1823}
1824
1825
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001826static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1827{
1828 *pos = 0x00;
1829
1830 switch (idx) {
1831 case 0: /* Bits 0-7 */
1832 break;
1833 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001834 if (wpa_s->conf->coloc_intf_reporting) {
1835 /* Bit 13 - Collocated Interference Reporting */
1836 *pos |= 0x20;
1837 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001838 break;
1839 case 2: /* Bits 16-23 */
1840#ifdef CONFIG_WNM
1841 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
Hai Shalomc3565922019-10-28 11:58:20 -07001842 if (!wpa_s->disable_mbo_oce && !wpa_s->conf->disable_btm)
Hai Shalom81f62d82019-07-22 12:10:00 -07001843 *pos |= 0x08; /* Bit 19 - BSS Transition */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001844#endif /* CONFIG_WNM */
1845 break;
1846 case 3: /* Bits 24-31 */
1847#ifdef CONFIG_WNM
1848 *pos |= 0x02; /* Bit 25 - SSID List */
1849#endif /* CONFIG_WNM */
1850#ifdef CONFIG_INTERWORKING
1851 if (wpa_s->conf->interworking)
1852 *pos |= 0x80; /* Bit 31 - Interworking */
1853#endif /* CONFIG_INTERWORKING */
1854 break;
1855 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001856#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001857 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001858 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001859#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001860 break;
1861 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001862#ifdef CONFIG_HS20
1863 if (wpa_s->conf->hs20)
1864 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1865#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001866#ifdef CONFIG_MBO
1867 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1868#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001869 break;
1870 case 6: /* Bits 48-55 */
1871 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001872 case 7: /* Bits 56-63 */
1873 break;
1874 case 8: /* Bits 64-71 */
1875 if (wpa_s->conf->ftm_responder)
1876 *pos |= 0x40; /* Bit 70 - FTM responder */
1877 if (wpa_s->conf->ftm_initiator)
1878 *pos |= 0x80; /* Bit 71 - FTM initiator */
1879 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001880 case 9: /* Bits 72-79 */
1881#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001882 if (!wpa_s->disable_fils)
1883 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001884#endif /* CONFIG_FILS */
1885 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001886 }
1887}
1888
1889
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001890int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001891{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001892 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001893 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001894
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001895 if (len < wpa_s->extended_capa_len)
1896 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001897 if (buflen < (size_t) len + 2) {
1898 wpa_printf(MSG_INFO,
1899 "Not enough room for building extended capabilities element");
1900 return -1;
1901 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001902
1903 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001904 *pos++ = len;
1905 for (i = 0; i < len; i++, pos++) {
1906 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001907
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001908 if (i < wpa_s->extended_capa_len) {
1909 *pos &= ~wpa_s->extended_capa_mask[i];
1910 *pos |= wpa_s->extended_capa[i];
1911 }
1912 }
1913
1914 while (len > 0 && buf[1 + len] == 0) {
1915 len--;
1916 buf[1] = len;
1917 }
1918 if (len == 0)
1919 return 0;
1920
1921 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001922}
1923
1924
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001925static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1926 struct wpa_bss *test_bss)
1927{
1928 struct wpa_bss *bss;
1929
1930 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1931 if (bss == test_bss)
1932 return 1;
1933 }
1934
1935 return 0;
1936}
1937
1938
1939static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1940 struct wpa_ssid *test_ssid)
1941{
1942 struct wpa_ssid *ssid;
1943
1944 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1945 if (ssid == test_ssid)
1946 return 1;
1947 }
1948
1949 return 0;
1950}
1951
1952
1953int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1954 struct wpa_ssid *test_ssid)
1955{
1956 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1957 return 0;
1958
1959 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1960}
1961
1962
1963void wpas_connect_work_free(struct wpa_connect_work *cwork)
1964{
1965 if (cwork == NULL)
1966 return;
1967 os_free(cwork);
1968}
1969
1970
1971void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1972{
1973 struct wpa_connect_work *cwork;
1974 struct wpa_radio_work *work = wpa_s->connect_work;
1975
1976 if (!work)
1977 return;
1978
1979 wpa_s->connect_work = NULL;
1980 cwork = work->ctx;
1981 work->ctx = NULL;
1982 wpas_connect_work_free(cwork);
1983 radio_work_done(work);
1984}
1985
1986
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001987int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1988{
1989 struct os_reltime now;
1990 u8 addr[ETH_ALEN];
1991
1992 os_get_reltime(&now);
1993 if (wpa_s->last_mac_addr_style == style &&
1994 wpa_s->last_mac_addr_change.sec != 0 &&
1995 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1996 wpa_s->conf->rand_addr_lifetime)) {
1997 wpa_msg(wpa_s, MSG_DEBUG,
1998 "Previously selected random MAC address has not yet expired");
1999 return 0;
2000 }
2001
2002 switch (style) {
2003 case 1:
2004 if (random_mac_addr(addr) < 0)
2005 return -1;
2006 break;
2007 case 2:
2008 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
2009 if (random_mac_addr_keep_oui(addr) < 0)
2010 return -1;
2011 break;
2012 default:
2013 return -1;
2014 }
2015
2016 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
2017 wpa_msg(wpa_s, MSG_INFO,
2018 "Failed to set random MAC address");
2019 return -1;
2020 }
2021
2022 os_get_reltime(&wpa_s->last_mac_addr_change);
2023 wpa_s->mac_addr_changed = 1;
2024 wpa_s->last_mac_addr_style = style;
2025
2026 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2027 wpa_msg(wpa_s, MSG_INFO,
2028 "Could not update MAC address information");
2029 return -1;
2030 }
2031
2032 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
2033 MAC2STR(addr));
2034
2035 return 0;
2036}
2037
2038
2039int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
2040{
2041 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
2042 !wpa_s->conf->preassoc_mac_addr)
2043 return 0;
2044
2045 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
2046}
2047
2048
Hai Shalomc3565922019-10-28 11:58:20 -07002049static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
2050{
2051#ifdef CONFIG_SAE
2052 int *groups = conf->sae_groups;
2053 int default_groups[] = { 19, 20, 21, 0 };
2054 const char *password;
2055
2056 if (!groups || groups[0] <= 0)
2057 groups = default_groups;
2058
2059 password = ssid->sae_password;
2060 if (!password)
2061 password = ssid->passphrase;
2062
Hai Shalomfdcde762020-04-02 11:19:20 -07002063 if ((conf->sae_pwe == 0 && !ssid->sae_password_id) || !password ||
2064 conf->sae_pwe == 3) {
Hai Shalomc3565922019-10-28 11:58:20 -07002065 /* PT derivation not needed */
2066 sae_deinit_pt(ssid->pt);
2067 ssid->pt = NULL;
2068 return;
2069 }
2070
2071 if (ssid->pt)
2072 return; /* PT already derived */
2073 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
2074 (const u8 *) password, os_strlen(password),
2075 ssid->sae_password_id);
2076#endif /* CONFIG_SAE */
2077}
2078
2079
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002080static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
2081{
2082#if defined(CONFIG_SAE) && defined(CONFIG_SME)
2083 os_free(wpa_s->sme.sae_rejected_groups);
2084 wpa_s->sme.sae_rejected_groups = NULL;
2085#ifdef CONFIG_TESTING_OPTIONS
2086 if (wpa_s->extra_sae_rejected_groups) {
2087 int i, *groups = wpa_s->extra_sae_rejected_groups;
2088
2089 for (i = 0; groups[i]; i++) {
2090 wpa_printf(MSG_DEBUG,
2091 "TESTING: Indicate rejection of an extra SAE group %d",
2092 groups[i]);
2093 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
2094 groups[i]);
2095 }
2096 }
2097#endif /* CONFIG_TESTING_OPTIONS */
2098#endif /* CONFIG_SAE && CONFIG_SME */
2099}
2100
2101
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002102static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
2103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002104/**
2105 * wpa_supplicant_associate - Request association
2106 * @wpa_s: Pointer to wpa_supplicant data
2107 * @bss: Scan results for the selected BSS, or %NULL if not available
2108 * @ssid: Configuration data for the selected network
2109 *
2110 * This function is used to request %wpa_supplicant to associate with a BSS.
2111 */
2112void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
2113 struct wpa_bss *bss, struct wpa_ssid *ssid)
2114{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002115 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002116 int rand_style;
2117
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002118 wpa_s->own_disconnect_req = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002119 wpa_s->own_reconnect_req = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002120
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002121 /*
2122 * If we are starting a new connection, any previously pending EAPOL
2123 * RX cannot be valid anymore.
2124 */
2125 wpabuf_free(wpa_s->pending_eapol_rx);
2126 wpa_s->pending_eapol_rx = NULL;
2127
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002128 if (ssid->mac_addr == -1)
2129 rand_style = wpa_s->conf->mac_addr;
2130 else
2131 rand_style = ssid->mac_addr;
2132
Hai Shalomfdcde762020-04-02 11:19:20 -07002133 wpa_s->multi_ap_ie = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002134 wmm_ac_clear_saved_tspecs(wpa_s);
2135 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002136 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002137#ifdef CONFIG_TESTING_OPTIONS
2138 wpa_s->testing_resend_assoc = 0;
2139#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002140
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002141 if (wpa_s->last_ssid == ssid) {
2142 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07002143 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002144 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
2145 wmm_ac_save_tspecs(wpa_s);
2146 wpa_s->reassoc_same_bss = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002147 } else if (wpa_s->current_bss && wpa_s->current_bss != bss) {
2148 os_get_reltime(&wpa_s->roam_start);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002149 }
Hai Shalomc3565922019-10-28 11:58:20 -07002150 } else {
2151#ifdef CONFIG_SAE
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002152 wpa_s_clear_sae_rejected(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002153 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
2154#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002155 }
2156
2157 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002158 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
2159 return;
2160 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002161 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002162 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
2163 wpa_msg(wpa_s, MSG_INFO,
2164 "Could not restore permanent MAC address");
2165 return;
2166 }
2167 wpa_s->mac_addr_changed = 0;
2168 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
2169 wpa_msg(wpa_s, MSG_INFO,
2170 "Could not update MAC address information");
2171 return;
2172 }
2173 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
2174 }
2175 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002176
2177#ifdef CONFIG_IBSS_RSN
2178 ibss_rsn_deinit(wpa_s->ibss_rsn);
2179 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002180#else /* CONFIG_IBSS_RSN */
2181 if (ssid->mode == WPAS_MODE_IBSS &&
2182 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
2183 wpa_msg(wpa_s, MSG_INFO,
2184 "IBSS RSN not supported in the build");
2185 return;
2186 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002187#endif /* CONFIG_IBSS_RSN */
2188
2189 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
2190 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
2191#ifdef CONFIG_AP
2192 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
2193 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
2194 "mode");
2195 return;
2196 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002197 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
2198 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002199 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
2200 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002201 return;
2202 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002203 wpa_s->current_bss = bss;
2204#else /* CONFIG_AP */
2205 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
2206 "the build");
2207#endif /* CONFIG_AP */
2208 return;
2209 }
2210
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002211 if (ssid->mode == WPAS_MODE_MESH) {
2212#ifdef CONFIG_MESH
2213 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
2214 wpa_msg(wpa_s, MSG_INFO,
2215 "Driver does not support mesh mode");
2216 return;
2217 }
2218 if (bss)
2219 ssid->frequency = bss->freq;
2220 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
2221 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
2222 return;
2223 }
2224 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002225 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
2226 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
2227 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002228 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002229#else /* CONFIG_MESH */
2230 wpa_msg(wpa_s, MSG_ERROR,
2231 "mesh mode support not included in the build");
2232#endif /* CONFIG_MESH */
2233 return;
2234 }
2235
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002236 /*
2237 * Set WPA state machine configuration to match the selected network now
2238 * so that the information is available before wpas_start_assoc_cb()
2239 * gets called. This is needed at least for RSN pre-authentication where
2240 * candidate APs are added to a list based on scan result processing
2241 * before completion of the first association.
2242 */
2243 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
2244
2245#ifdef CONFIG_DPP
2246 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
2247 return;
2248#endif /* CONFIG_DPP */
2249
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002250#ifdef CONFIG_TDLS
2251 if (bss)
2252 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2253 bss->ie_len);
2254#endif /* CONFIG_TDLS */
2255
Hai Shalomc3565922019-10-28 11:58:20 -07002256#ifdef CONFIG_MBO
2257 wpas_mbo_check_pmf(wpa_s, bss, ssid);
2258#endif /* CONFIG_MBO */
2259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002260 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
Hai Shalom81f62d82019-07-22 12:10:00 -07002261 ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002262 sme_authenticate(wpa_s, bss, ssid);
2263 return;
2264 }
2265
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002266 if (wpa_s->connect_work) {
2267 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2268 return;
2269 }
2270
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002271 if (radio_work_pending(wpa_s, "connect")) {
2272 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2273 return;
2274 }
2275
Dmitry Shmidt29333592017-01-09 12:27:11 -08002276#ifdef CONFIG_SME
2277 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2278 /* Clear possibly set auth_alg, if any, from last attempt. */
2279 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2280 }
2281#endif /* CONFIG_SME */
2282
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002283 wpas_abort_ongoing_scan(wpa_s);
2284
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002285 cwork = os_zalloc(sizeof(*cwork));
2286 if (cwork == NULL)
2287 return;
2288
2289 cwork->bss = bss;
2290 cwork->ssid = ssid;
2291
2292 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2293 wpas_start_assoc_cb, cwork) < 0) {
2294 os_free(cwork);
2295 }
2296}
2297
2298
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002299static int bss_is_ibss(struct wpa_bss *bss)
2300{
2301 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2302 IEEE80211_CAP_IBSS;
2303}
2304
2305
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002306static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2307 const struct wpa_ssid *ssid)
2308{
2309 enum hostapd_hw_mode hw_mode;
2310 struct hostapd_hw_modes *mode = NULL;
2311 u8 channel;
2312 int i;
2313
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002314 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2315 if (hw_mode == NUM_HOSTAPD_MODES)
2316 return 0;
2317 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2318 if (wpa_s->hw.modes[i].mode == hw_mode) {
2319 mode = &wpa_s->hw.modes[i];
2320 break;
2321 }
2322 }
2323
2324 if (!mode)
2325 return 0;
2326
2327 return mode->vht_capab != 0;
2328}
2329
2330
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002331void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2332 const struct wpa_ssid *ssid,
2333 struct hostapd_freq_params *freq)
2334{
Hai Shalom81f62d82019-07-22 12:10:00 -07002335 int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002336 enum hostapd_hw_mode hw_mode;
2337 struct hostapd_hw_modes *mode = NULL;
2338 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2339 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002340 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002341 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2342 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002343 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002344 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002345 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002346 int chwidth, seg0, seg1;
2347 u32 vht_caps = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07002348 int is_24ghz;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002349
2350 freq->freq = ssid->frequency;
2351
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002352 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2353 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2354
2355 if (ssid->mode != WPAS_MODE_IBSS)
2356 break;
2357
2358 /* Don't adjust control freq in case of fixed_freq */
2359 if (ssid->fixed_freq)
2360 break;
2361
2362 if (!bss_is_ibss(bss))
2363 continue;
2364
2365 if (ssid->ssid_len == bss->ssid_len &&
2366 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2367 wpa_printf(MSG_DEBUG,
2368 "IBSS already found in scan results, adjust control freq: %d",
2369 bss->freq);
2370 freq->freq = bss->freq;
2371 obss_scan = 0;
2372 break;
2373 }
2374 }
2375
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002376 /* For IBSS check HT_IBSS flag */
2377 if (ssid->mode == WPAS_MODE_IBSS &&
2378 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2379 return;
2380
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002381 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2382 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2383 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2384 wpa_printf(MSG_DEBUG,
2385 "IBSS: WEP/TKIP detected, do not try to enable HT");
2386 return;
2387 }
2388
2389 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002390 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2391 if (wpa_s->hw.modes[i].mode == hw_mode) {
2392 mode = &wpa_s->hw.modes[i];
2393 break;
2394 }
2395 }
2396
2397 if (!mode)
2398 return;
2399
Hai Shalomc3565922019-10-28 11:58:20 -07002400 is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
2401 hw_mode == HOSTAPD_MODE_IEEE80211B;
Hai Shalom81f62d82019-07-22 12:10:00 -07002402
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002403#ifdef CONFIG_HT_OVERRIDES
2404 if (ssid->disable_ht) {
2405 freq->ht_enabled = 0;
2406 return;
2407 }
2408#endif /* CONFIG_HT_OVERRIDES */
2409
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002410 freq->ht_enabled = ht_supported(mode);
2411 if (!freq->ht_enabled)
2412 return;
2413
Hai Shalomc3565922019-10-28 11:58:20 -07002414 /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */
2415 if (is_24ghz)
2416 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomfdcde762020-04-02 11:19:20 -07002417#ifdef CONFIG_HE_OVERRIDES
2418 if (is_24ghz && ssid->disable_he)
2419 freq->he_enabled = 0;
2420#endif /* CONFIG_HE_OVERRIDES */
Hai Shalomc3565922019-10-28 11:58:20 -07002421
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002422 /* Setup higher BW only for 5 GHz */
2423 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2424 return;
2425
2426 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2427 pri_chan = &mode->channels[chan_idx];
2428 if (pri_chan->chan == channel)
2429 break;
2430 pri_chan = NULL;
2431 }
2432 if (!pri_chan)
2433 return;
2434
2435 /* Check primary channel flags */
2436 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2437 return;
2438
Hai Shalom74f70d42019-02-11 14:42:39 -08002439 freq->channel = pri_chan->chan;
2440
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002441#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002442 if (ssid->disable_ht40) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002443#ifdef CONFIG_VHT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08002444 if (ssid->disable_vht)
2445 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002446#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalom74f70d42019-02-11 14:42:39 -08002447 goto skip_ht40;
2448 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002449#endif /* CONFIG_HT_OVERRIDES */
2450
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002451 /* Check/setup HT40+/HT40- */
2452 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2453 if (ht40plus[j] == channel) {
2454 ht40 = 1;
2455 break;
2456 }
2457 }
2458
2459 /* Find secondary channel */
2460 for (i = 0; i < mode->num_channels; i++) {
2461 sec_chan = &mode->channels[i];
2462 if (sec_chan->chan == channel + ht40 * 4)
2463 break;
2464 sec_chan = NULL;
2465 }
2466 if (!sec_chan)
2467 return;
2468
2469 /* Check secondary channel flags */
2470 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2471 return;
2472
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002473 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002474 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2475 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002476 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002477 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2478 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002479 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002480 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002481
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002482 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002483 struct wpa_scan_results *scan_res;
2484
2485 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2486 if (scan_res == NULL) {
2487 /* Back to HT20 */
2488 freq->sec_channel_offset = 0;
2489 return;
2490 }
2491
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002492 res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002493 switch (res) {
2494 case 0:
2495 /* Back to HT20 */
2496 freq->sec_channel_offset = 0;
2497 break;
2498 case 1:
2499 /* Configuration allowed */
2500 break;
2501 case 2:
2502 /* Switch pri/sec channels */
2503 freq->freq = hw_get_freq(mode, sec_chan->chan);
2504 freq->sec_channel_offset = -freq->sec_channel_offset;
2505 freq->channel = sec_chan->chan;
2506 break;
2507 default:
2508 freq->sec_channel_offset = 0;
2509 break;
2510 }
2511
2512 wpa_scan_results_free(scan_res);
2513 }
2514
Hai Shalom74f70d42019-02-11 14:42:39 -08002515#ifdef CONFIG_HT_OVERRIDES
2516skip_ht40:
2517#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002518 wpa_printf(MSG_DEBUG,
2519 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2520 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002521
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002522 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002523 return;
2524
2525 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002526 if (ssid->mode == WPAS_MODE_IBSS &&
2527 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002528 return;
2529
2530 vht_freq = *freq;
2531
Paul Stewart092955c2017-02-06 09:13:09 -08002532#ifdef CONFIG_VHT_OVERRIDES
2533 if (ssid->disable_vht) {
2534 freq->vht_enabled = 0;
2535 return;
2536 }
2537#endif /* CONFIG_VHT_OVERRIDES */
2538
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002539 vht_freq.vht_enabled = vht_supported(mode);
2540 if (!vht_freq.vht_enabled)
2541 return;
2542
Hai Shalomfdcde762020-04-02 11:19:20 -07002543 /* Enable HE with VHT for 5 GHz */
2544 freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
Hai Shalomc3565922019-10-28 11:58:20 -07002545
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002546 /* setup center_freq1, bandwidth */
2547 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2548 if (freq->channel >= vht80[j] &&
2549 freq->channel < vht80[j] + 16)
2550 break;
2551 }
2552
2553 if (j == ARRAY_SIZE(vht80))
2554 return;
2555
2556 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2557 struct hostapd_channel_data *chan;
2558
2559 chan = hw_get_channel_chan(mode, i, NULL);
2560 if (!chan)
2561 return;
2562
2563 /* Back to HT configuration if channel not usable */
2564 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2565 return;
2566 }
2567
Hai Shalom81f62d82019-07-22 12:10:00 -07002568 chwidth = CHANWIDTH_80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002569 seg0 = vht80[j] + 6;
2570 seg1 = 0;
2571
Hai Shalom81f62d82019-07-22 12:10:00 -07002572 if (ssid->max_oper_chwidth == CHANWIDTH_80P80MHZ) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002573 /* setup center_freq2, bandwidth */
2574 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2575 /* Only accept 80 MHz segments separated by a gap */
2576 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2577 continue;
2578 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2579 struct hostapd_channel_data *chan;
2580
2581 chan = hw_get_channel_chan(mode, i, NULL);
2582 if (!chan)
2583 continue;
2584
2585 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2586 HOSTAPD_CHAN_NO_IR |
2587 HOSTAPD_CHAN_RADAR))
2588 continue;
2589
2590 /* Found a suitable second segment for 80+80 */
Hai Shalom81f62d82019-07-22 12:10:00 -07002591 chwidth = CHANWIDTH_80P80MHZ;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002592 vht_caps |=
2593 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2594 seg1 = vht80[k] + 6;
2595 }
2596
Hai Shalom81f62d82019-07-22 12:10:00 -07002597 if (chwidth == CHANWIDTH_80P80MHZ)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002598 break;
2599 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002600 } else if (ssid->max_oper_chwidth == CHANWIDTH_160MHZ) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002601 if (freq->freq == 5180) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002602 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002603 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2604 seg0 = 50;
2605 } else if (freq->freq == 5520) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002606 chwidth = CHANWIDTH_160MHZ;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002607 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2608 seg0 = 114;
2609 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002610 } else if (ssid->max_oper_chwidth == CHANWIDTH_USE_HT) {
2611 chwidth = CHANWIDTH_USE_HT;
Hai Shalom74f70d42019-02-11 14:42:39 -08002612 seg0 = vht80[j] + 2;
2613#ifdef CONFIG_HT_OVERRIDES
2614 if (ssid->disable_ht40)
2615 seg0 = 0;
2616#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002617 }
2618
Hai Shalomfdcde762020-04-02 11:19:20 -07002619#ifdef CONFIG_HE_OVERRIDES
2620 if (ssid->disable_he) {
2621 vht_freq.he_enabled = 0;
2622 freq->he_enabled = 0;
2623 }
2624#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002625 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
Hai Shalomc3565922019-10-28 11:58:20 -07002626 freq->channel, ssid->enable_edmg,
2627 ssid->edmg_channel, freq->ht_enabled,
Hai Shalom81f62d82019-07-22 12:10:00 -07002628 vht_freq.vht_enabled, freq->he_enabled,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002629 freq->sec_channel_offset,
Hai Shalom81f62d82019-07-22 12:10:00 -07002630 chwidth, seg0, seg1, vht_caps,
2631 &mode->he_capab[ieee80211_mode]) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002632 return;
2633
2634 *freq = vht_freq;
2635
2636 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2637 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002638}
2639
2640
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002641#ifdef CONFIG_FILS
2642static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2643 size_t ie_buf_len)
2644{
2645 struct fils_hlp_req *req;
2646 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2647 const u8 *pos;
2648 u8 *buf = ie_buf;
2649
2650 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2651 list) {
2652 rem_len = ie_buf_len - ie_len;
2653 pos = wpabuf_head(req->pkt);
2654 hdr_len = 1 + 2 * ETH_ALEN + 6;
2655 hlp_len = wpabuf_len(req->pkt);
2656
2657 if (rem_len < 2 + hdr_len + hlp_len) {
2658 wpa_printf(MSG_ERROR,
2659 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2660 (unsigned long) rem_len,
2661 (unsigned long) (2 + hdr_len + hlp_len));
2662 break;
2663 }
2664
2665 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2666 /* Element ID */
2667 *buf++ = WLAN_EID_EXTENSION;
2668 /* Length */
2669 *buf++ = len;
2670 /* Element ID Extension */
2671 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2672 /* Destination MAC address */
2673 os_memcpy(buf, req->dst, ETH_ALEN);
2674 buf += ETH_ALEN;
2675 /* Source MAC address */
2676 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2677 buf += ETH_ALEN;
2678 /* LLC/SNAP Header */
2679 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2680 buf += 6;
2681 /* HLP Packet */
2682 os_memcpy(buf, pos, len - hdr_len);
2683 buf += len - hdr_len;
2684 pos += len - hdr_len;
2685
2686 hlp_len -= len - hdr_len;
2687 ie_len += 2 + len;
2688 rem_len -= 2 + len;
2689
2690 while (hlp_len) {
2691 len = (hlp_len > 255) ? 255 : hlp_len;
2692 if (rem_len < 2 + len)
2693 break;
2694 *buf++ = WLAN_EID_FRAGMENT;
2695 *buf++ = len;
2696 os_memcpy(buf, pos, len);
2697 buf += len;
2698 pos += len;
2699
2700 hlp_len -= len;
2701 ie_len += 2 + len;
2702 rem_len -= 2 + len;
2703 }
2704 }
2705
2706 return ie_len;
2707}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002708
2709
2710int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2711{
2712 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2713 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2714 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2715 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2716}
2717
2718
2719int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2720{
2721#ifdef CONFIG_FILS_SK_PFS
2722 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2723 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2724#else /* CONFIG_FILS_SK_PFS */
2725 return 0;
2726#endif /* CONFIG_FILS_SK_PFS */
2727}
2728
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002729#endif /* CONFIG_FILS */
2730
2731
2732static u8 * wpas_populate_assoc_ies(
2733 struct wpa_supplicant *wpa_s,
2734 struct wpa_bss *bss, struct wpa_ssid *ssid,
2735 struct wpa_driver_associate_params *params,
2736 enum wpa_drv_update_connect_params_mask *mask)
2737{
2738 u8 *wpa_ie;
2739 size_t max_wpa_ie_len = 500;
2740 size_t wpa_ie_len;
2741 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002742#ifdef CONFIG_MBO
2743 const u8 *mbo_ie;
2744#endif
Hai Shalom5f92bc92019-04-18 11:54:11 -07002745#ifdef CONFIG_SAE
2746 int sae_pmksa_cached = 0;
2747#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002748#ifdef CONFIG_FILS
2749 const u8 *realm, *username, *rrk;
2750 size_t realm_len, username_len, rrk_len;
2751 u16 next_seq_num;
2752 struct fils_hlp_req *req;
2753
2754 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2755 list) {
2756 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2757 2 + 2 * wpabuf_len(req->pkt) / 255;
2758 }
2759#endif /* CONFIG_FILS */
2760
2761 wpa_ie = os_malloc(max_wpa_ie_len);
2762 if (!wpa_ie) {
2763 wpa_printf(MSG_ERROR,
2764 "Failed to allocate connect IE buffer for %lu bytes",
2765 (unsigned long) max_wpa_ie_len);
2766 return NULL;
2767 }
2768
2769 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2770 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2771 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2772 int try_opportunistic;
2773 const u8 *cache_id = NULL;
2774
2775 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2776 wpa_s->conf->okc :
2777 ssid->proactive_key_caching) &&
2778 (ssid->proto & WPA_PROTO_RSN);
2779#ifdef CONFIG_FILS
2780 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2781 cache_id = wpa_bss_get_fils_cache_id(bss);
2782#endif /* CONFIG_FILS */
2783 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2784 ssid, try_opportunistic,
Hai Shalom5f92bc92019-04-18 11:54:11 -07002785 cache_id, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002786 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Hai Shalom5f92bc92019-04-18 11:54:11 -07002787#ifdef CONFIG_SAE
2788 sae_pmksa_cached = 1;
2789#endif /* CONFIG_SAE */
2790 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002791 wpa_ie_len = max_wpa_ie_len;
2792 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2793 wpa_ie, &wpa_ie_len)) {
2794 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2795 "key management and encryption suites");
2796 os_free(wpa_ie);
2797 return NULL;
2798 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002799#ifdef CONFIG_HS20
2800 } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
2801 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
2802 /* No PMKSA caching, but otherwise similar to RSN/WPA */
2803 wpa_ie_len = max_wpa_ie_len;
2804 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2805 wpa_ie, &wpa_ie_len)) {
2806 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2807 "key management and encryption suites");
2808 os_free(wpa_ie);
2809 return NULL;
2810 }
2811#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002812 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2813 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2814 /*
2815 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2816 * use non-WPA since the scan results did not indicate that the
2817 * AP is using WPA or WPA2.
2818 */
2819 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2820 wpa_ie_len = 0;
2821 wpa_s->wpa_proto = 0;
2822 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2823 wpa_ie_len = max_wpa_ie_len;
2824 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2825 wpa_ie, &wpa_ie_len)) {
2826 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2827 "key management and encryption suites (no "
2828 "scan results)");
2829 os_free(wpa_ie);
2830 return NULL;
2831 }
2832#ifdef CONFIG_WPS
2833 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2834 struct wpabuf *wps_ie;
2835 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2836 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2837 wpa_ie_len = wpabuf_len(wps_ie);
2838 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2839 } else
2840 wpa_ie_len = 0;
2841 wpabuf_free(wps_ie);
2842 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2843 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2844 params->wps = WPS_MODE_PRIVACY;
2845 else
2846 params->wps = WPS_MODE_OPEN;
2847 wpa_s->wpa_proto = 0;
2848#endif /* CONFIG_WPS */
2849 } else {
2850 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2851 wpa_ie_len = 0;
2852 wpa_s->wpa_proto = 0;
2853 }
2854
2855#ifdef IEEE8021X_EAPOL
2856 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2857 if (ssid->leap) {
2858 if (ssid->non_leap == 0)
2859 algs = WPA_AUTH_ALG_LEAP;
2860 else
2861 algs |= WPA_AUTH_ALG_LEAP;
2862 }
2863 }
2864
2865#ifdef CONFIG_FILS
2866 /* Clear FILS association */
2867 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2868
2869 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2870 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2871 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2872 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002873 &next_seq_num, &rrk, &rrk_len) == 0 &&
2874 (!wpa_s->last_con_fail_realm ||
2875 wpa_s->last_con_fail_realm_len != realm_len ||
2876 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002877 algs = WPA_AUTH_ALG_FILS;
2878 params->fils_erp_username = username;
2879 params->fils_erp_username_len = username_len;
2880 params->fils_erp_realm = realm;
2881 params->fils_erp_realm_len = realm_len;
2882 params->fils_erp_next_seq_num = next_seq_num;
2883 params->fils_erp_rrk = rrk;
2884 params->fils_erp_rrk_len = rrk_len;
2885
2886 if (mask)
2887 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2888 }
2889#endif /* CONFIG_FILS */
2890#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002891#ifdef CONFIG_SAE
2892 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2893 algs = WPA_AUTH_ALG_SAE;
2894#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002895
2896 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2897 if (ssid->auth_alg) {
2898 algs = ssid->auth_alg;
2899 wpa_dbg(wpa_s, MSG_DEBUG,
2900 "Overriding auth_alg selection: 0x%x", algs);
2901 }
2902
Hai Shalom5f92bc92019-04-18 11:54:11 -07002903#ifdef CONFIG_SAE
2904 if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) {
2905 wpa_dbg(wpa_s, MSG_DEBUG,
2906 "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt");
2907 algs = WPA_AUTH_ALG_OPEN;
2908 }
2909#endif /* CONFIG_SAE */
2910
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002911#ifdef CONFIG_P2P
2912 if (wpa_s->global->p2p) {
2913 u8 *pos;
2914 size_t len;
2915 int res;
2916 pos = wpa_ie + wpa_ie_len;
2917 len = max_wpa_ie_len - wpa_ie_len;
2918 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2919 ssid->p2p_group);
2920 if (res >= 0)
2921 wpa_ie_len += res;
2922 }
2923
2924 wpa_s->cross_connect_disallowed = 0;
2925 if (bss) {
2926 struct wpabuf *p2p;
2927 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2928 if (p2p) {
2929 wpa_s->cross_connect_disallowed =
2930 p2p_get_cross_connect_disallowed(p2p);
2931 wpabuf_free(p2p);
2932 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2933 "connection",
2934 wpa_s->cross_connect_disallowed ?
2935 "disallows" : "allows");
2936 }
2937 }
2938
2939 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2940#endif /* CONFIG_P2P */
2941
2942 if (bss) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002943 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002944 wpa_ie + wpa_ie_len,
2945 max_wpa_ie_len -
2946 wpa_ie_len);
2947 }
2948
2949 /*
2950 * Workaround: Add Extended Capabilities element only if the AP
2951 * included this element in Beacon/Probe Response frames. Some older
2952 * APs seem to have interoperability issues if this element is
2953 * included, so while the standard may require us to include the
2954 * element in all cases, it is justifiable to skip it to avoid
2955 * interoperability issues.
2956 */
2957 if (ssid->p2p_group)
2958 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2959 else
2960 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2961
2962 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2963 u8 ext_capab[18];
2964 int ext_capab_len;
2965 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2966 sizeof(ext_capab));
2967 if (ext_capab_len > 0 &&
2968 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2969 u8 *pos = wpa_ie;
2970 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2971 pos += 2 + pos[1];
2972 os_memmove(pos + ext_capab_len, pos,
2973 wpa_ie_len - (pos - wpa_ie));
2974 wpa_ie_len += ext_capab_len;
2975 os_memcpy(pos, ext_capab, ext_capab_len);
2976 }
2977 }
2978
2979#ifdef CONFIG_HS20
2980 if (is_hs20_network(wpa_s, ssid, bss)) {
2981 struct wpabuf *hs20;
2982
Roshan Pius3a1667e2018-07-03 15:17:14 -07002983 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002984 if (hs20) {
2985 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2986 size_t len;
2987
Hai Shalom74f70d42019-02-11 14:42:39 -08002988 wpas_hs20_add_indication(hs20, pps_mo_id,
2989 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002990 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002991 len = max_wpa_ie_len - wpa_ie_len;
2992 if (wpabuf_len(hs20) <= len) {
2993 os_memcpy(wpa_ie + wpa_ie_len,
2994 wpabuf_head(hs20), wpabuf_len(hs20));
2995 wpa_ie_len += wpabuf_len(hs20);
2996 }
2997 wpabuf_free(hs20);
2998
2999 hs20_configure_frame_filters(wpa_s);
3000 }
3001 }
3002#endif /* CONFIG_HS20 */
3003
3004 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
3005 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
3006 size_t len;
3007
3008 len = max_wpa_ie_len - wpa_ie_len;
3009 if (wpabuf_len(buf) <= len) {
3010 os_memcpy(wpa_ie + wpa_ie_len,
3011 wpabuf_head(buf), wpabuf_len(buf));
3012 wpa_ie_len += wpabuf_len(buf);
3013 }
3014 }
3015
3016#ifdef CONFIG_FST
3017 if (wpa_s->fst_ies) {
3018 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
3019
3020 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
3021 os_memcpy(wpa_ie + wpa_ie_len,
3022 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
3023 wpa_ie_len += fst_ies_len;
3024 }
3025 }
3026#endif /* CONFIG_FST */
3027
3028#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07003029 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
Hai Shalomc3565922019-10-28 11:58:20 -07003030 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003031 int len;
3032
3033 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07003034 max_wpa_ie_len - wpa_ie_len,
3035 !!mbo_attr_from_mbo_ie(mbo_ie,
3036 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003037 if (len >= 0)
3038 wpa_ie_len += len;
3039 }
3040#endif /* CONFIG_MBO */
3041
3042#ifdef CONFIG_FILS
3043 if (algs == WPA_AUTH_ALG_FILS) {
3044 size_t len;
3045
3046 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
3047 max_wpa_ie_len - wpa_ie_len);
3048 wpa_ie_len += len;
3049 }
3050#endif /* CONFIG_FILS */
3051
3052#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003053#ifdef CONFIG_TESTING_OPTIONS
3054 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
3055 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
3056 } else
3057#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003058 if (algs == WPA_AUTH_ALG_OPEN &&
3059 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
3060 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003061 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003062
Roshan Pius3a1667e2018-07-03 15:17:14 -07003063 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003064 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08003065 } else if (wpa_s->assoc_status_code ==
3066 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003067 if (wpa_s->last_owe_group == 19)
3068 group = 20;
3069 else if (wpa_s->last_owe_group == 20)
3070 group = 21;
3071 else
3072 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08003073 } else {
3074 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003075 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003076
Roshan Pius3a1667e2018-07-03 15:17:14 -07003077 wpa_s->last_owe_group = group;
3078 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003079 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
3080 if (owe_ie &&
3081 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
3082 os_memcpy(wpa_ie + wpa_ie_len,
3083 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
3084 wpa_ie_len += wpabuf_len(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003085 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003086 wpabuf_free(owe_ie);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003087 }
3088#endif /* CONFIG_OWE */
3089
Hai Shalom021b0b52019-04-10 11:17:58 -07003090#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003091 if (DPP_VERSION > 1 &&
3092 wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003093 ssid->dpp_netaccesskey &&
3094 ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003095 struct rsn_pmksa_cache_entry *pmksa;
3096
3097 pmksa = pmksa_cache_get_current(wpa_s->wpa);
3098 if (!pmksa || !pmksa->dpp_pfs)
3099 goto pfs_fail;
3100
Hai Shalom021b0b52019-04-10 11:17:58 -07003101 dpp_pfs_free(wpa_s->dpp_pfs);
3102 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
3103 ssid->dpp_netaccesskey_len);
3104 if (!wpa_s->dpp_pfs) {
3105 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
3106 /* Try to continue without PFS */
3107 goto pfs_fail;
3108 }
3109 if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
3110 max_wpa_ie_len - wpa_ie_len) {
3111 os_memcpy(wpa_ie + wpa_ie_len,
3112 wpabuf_head(wpa_s->dpp_pfs->ie),
3113 wpabuf_len(wpa_s->dpp_pfs->ie));
3114 wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
3115 }
3116 }
3117pfs_fail:
3118#endif /* CONFIG_DPP2 */
3119
Roshan Pius3a1667e2018-07-03 15:17:14 -07003120#ifdef CONFIG_IEEE80211R
3121 /*
3122 * Add MDIE under these conditions: the network profile allows FT,
3123 * the AP supports FT, and the mobility domain ID matches.
3124 */
3125 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
3126 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3127
3128 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
3129 size_t len = 0;
3130 const u8 *md = mdie + 2;
3131 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
3132
3133 if (os_memcmp(md, wpa_md,
3134 MOBILITY_DOMAIN_ID_LEN) == 0) {
3135 /* Add mobility domain IE */
3136 len = wpa_ft_add_mdie(
3137 wpa_s->wpa, wpa_ie + wpa_ie_len,
3138 max_wpa_ie_len - wpa_ie_len, mdie);
3139 wpa_ie_len += len;
3140 }
3141#ifdef CONFIG_SME
3142 if (len > 0 && wpa_s->sme.ft_used &&
3143 wpa_sm_has_ptk(wpa_s->wpa)) {
3144 wpa_dbg(wpa_s, MSG_DEBUG,
3145 "SME: Trying to use FT over-the-air");
3146 algs |= WPA_AUTH_ALG_FT;
3147 }
3148#endif /* CONFIG_SME */
3149 }
3150 }
3151#endif /* CONFIG_IEEE80211R */
3152
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003153#ifdef CONFIG_TESTING_OPTIONS
3154 if (wpa_s->rsnxe_override_assoc &&
3155 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
3156 max_wpa_ie_len - wpa_ie_len) {
3157 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
3158 os_memcpy(wpa_ie + wpa_ie_len,
3159 wpabuf_head(wpa_s->rsnxe_override_assoc),
3160 wpabuf_len(wpa_s->rsnxe_override_assoc));
3161 wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
3162 } else
3163#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07003164 if (wpa_s->rsnxe_len > 0 &&
3165 wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
3166 os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
3167 wpa_ie_len += wpa_s->rsnxe_len;
3168 }
3169
Hai Shalom74f70d42019-02-11 14:42:39 -08003170 if (ssid->multi_ap_backhaul_sta) {
3171 size_t multi_ap_ie_len;
3172
3173 multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len,
3174 max_wpa_ie_len - wpa_ie_len,
3175 MULTI_AP_BACKHAUL_STA);
3176 if (multi_ap_ie_len == 0) {
3177 wpa_printf(MSG_ERROR,
3178 "Multi-AP: Failed to build Multi-AP IE");
3179 os_free(wpa_ie);
3180 return NULL;
3181 }
3182 wpa_ie_len += multi_ap_ie_len;
3183 }
3184
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003185 params->wpa_ie = wpa_ie;
3186 params->wpa_ie_len = wpa_ie_len;
3187 params->auth_alg = algs;
3188 if (mask)
3189 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
3190
3191 return wpa_ie;
3192}
3193
3194
Hai Shalomc3565922019-10-28 11:58:20 -07003195#ifdef CONFIG_OWE
3196static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s)
3197{
3198 struct wpa_driver_associate_params params;
3199 u8 *wpa_ie;
3200
3201 os_memset(&params, 0, sizeof(params));
3202 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3203 wpa_s->current_ssid, &params, NULL);
3204 if (!wpa_ie)
3205 return;
3206
3207 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3208 os_free(wpa_ie);
3209}
3210#endif /* CONFIG_OWE */
3211
3212
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003213#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
3214static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
3215{
3216 struct wpa_driver_associate_params params;
3217 enum wpa_drv_update_connect_params_mask mask = 0;
3218 u8 *wpa_ie;
3219
3220 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
3221 return; /* nothing to do */
3222
3223 os_memset(&params, 0, sizeof(params));
3224 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3225 wpa_s->current_ssid, &params, &mask);
3226 if (!wpa_ie)
3227 return;
3228
3229 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
3230 os_free(wpa_ie);
3231 return;
3232 }
3233
3234 wpa_s->auth_alg = params.auth_alg;
3235 wpa_drv_update_connect_params(wpa_s, &params, mask);
3236 os_free(wpa_ie);
3237}
3238#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
3239
3240
Hai Shalomc3565922019-10-28 11:58:20 -07003241static u8 wpa_ie_get_edmg_oper_chans(const u8 *edmg_ie)
3242{
3243 if (!edmg_ie || edmg_ie[1] < 6)
3244 return 0;
3245 return edmg_ie[EDMG_BSS_OPERATING_CHANNELS_OFFSET];
3246}
3247
3248
3249static u8 wpa_ie_get_edmg_oper_chan_width(const u8 *edmg_ie)
3250{
3251 if (!edmg_ie || edmg_ie[1] < 6)
3252 return 0;
3253 return edmg_ie[EDMG_OPERATING_CHANNEL_WIDTH_OFFSET];
3254}
3255
3256
3257/* Returns the intersection of two EDMG configurations.
3258 * Note: The current implementation is limited to CB2 only (CB1 included),
3259 * i.e., the implementation supports up to 2 contiguous channels.
3260 * For supporting non-contiguous (aggregated) channels and for supporting
3261 * CB3 and above, this function will need to be extended.
3262 */
3263static struct ieee80211_edmg_config
3264get_edmg_intersection(struct ieee80211_edmg_config a,
3265 struct ieee80211_edmg_config b,
3266 u8 primary_channel)
3267{
3268 struct ieee80211_edmg_config result;
3269 int i, contiguous = 0;
3270 int max_contiguous = 0;
3271
3272 result.channels = b.channels & a.channels;
3273 if (!result.channels) {
3274 wpa_printf(MSG_DEBUG,
3275 "EDMG not possible: cannot intersect channels 0x%x and 0x%x",
3276 a.channels, b.channels);
3277 goto fail;
3278 }
3279
3280 if (!(result.channels & BIT(primary_channel - 1))) {
3281 wpa_printf(MSG_DEBUG,
3282 "EDMG not possible: the primary channel %d is not one of the intersected channels 0x%x",
3283 primary_channel, result.channels);
3284 goto fail;
3285 }
3286
3287 /* Find max contiguous channels */
3288 for (i = 0; i < 6; i++) {
3289 if (result.channels & BIT(i))
3290 contiguous++;
3291 else
3292 contiguous = 0;
3293
3294 if (contiguous > max_contiguous)
3295 max_contiguous = contiguous;
3296 }
3297
3298 /* Assuming AP and STA supports ONLY contiguous channels,
3299 * bw configuration can have value between 4-7.
3300 */
3301 if ((b.bw_config < a.bw_config))
3302 result.bw_config = b.bw_config;
3303 else
3304 result.bw_config = a.bw_config;
3305
3306 if ((max_contiguous >= 2 && result.bw_config < EDMG_BW_CONFIG_5) ||
3307 (max_contiguous >= 1 && result.bw_config < EDMG_BW_CONFIG_4)) {
3308 wpa_printf(MSG_DEBUG,
3309 "EDMG not possible: not enough contiguous channels %d for supporting CB1 or CB2",
3310 max_contiguous);
3311 goto fail;
3312 }
3313
3314 return result;
3315
3316fail:
3317 result.channels = 0;
3318 result.bw_config = 0;
3319 return result;
3320}
3321
3322
3323static struct ieee80211_edmg_config
3324get_supported_edmg(struct wpa_supplicant *wpa_s,
3325 struct hostapd_freq_params *freq,
3326 struct ieee80211_edmg_config request_edmg)
3327{
3328 enum hostapd_hw_mode hw_mode;
3329 struct hostapd_hw_modes *mode = NULL;
3330 u8 primary_channel;
3331
3332 if (!wpa_s->hw.modes)
3333 goto fail;
3334
3335 hw_mode = ieee80211_freq_to_chan(freq->freq, &primary_channel);
3336 if (hw_mode == NUM_HOSTAPD_MODES)
3337 goto fail;
3338
Hai Shalomfdcde762020-04-02 11:19:20 -07003339 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003340 if (!mode)
3341 goto fail;
3342
3343 return get_edmg_intersection(mode->edmg, request_edmg, primary_channel);
3344
3345fail:
3346 request_edmg.channels = 0;
3347 request_edmg.bw_config = 0;
3348 return request_edmg;
3349}
3350
3351
Hai Shalom021b0b52019-04-10 11:17:58 -07003352#ifdef CONFIG_MBO
3353void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s)
3354{
3355 struct wpa_driver_associate_params params;
3356 u8 *wpa_ie;
3357
3358 /*
3359 * Update MBO connect params only in case of change of MBO attributes
3360 * when connected, if the AP support MBO.
3361 */
3362
3363 if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid ||
3364 !wpa_s->current_bss ||
3365 !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
3366 return;
3367
3368 os_memset(&params, 0, sizeof(params));
3369 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
3370 wpa_s->current_ssid, &params, NULL);
3371 if (!wpa_ie)
3372 return;
3373
3374 wpa_drv_update_connect_params(wpa_s, &params, WPA_DRV_UPDATE_ASSOC_IES);
3375 os_free(wpa_ie);
3376}
3377#endif /* CONFIG_MBO */
3378
3379
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003380static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
3381{
3382 struct wpa_connect_work *cwork = work->ctx;
3383 struct wpa_bss *bss = cwork->bss;
3384 struct wpa_ssid *ssid = cwork->ssid;
3385 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003386 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07003387 const u8 *edmg_ie_oper;
Hai Shalomfdcde762020-04-02 11:19:20 -07003388 int use_crypt, ret, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003389 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003390 struct wpa_driver_associate_params params;
Hai Shalomfdcde762020-04-02 11:19:20 -07003391#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003392 int wep_keys_set = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003393#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003394 int assoc_failed = 0;
3395 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07003396 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003397#ifdef CONFIG_HT_OVERRIDES
3398 struct ieee80211_ht_capabilities htcaps;
3399 struct ieee80211_ht_capabilities htcaps_mask;
3400#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003401#ifdef CONFIG_VHT_OVERRIDES
3402 struct ieee80211_vht_capabilities vhtcaps;
3403 struct ieee80211_vht_capabilities vhtcaps_mask;
3404#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003405
3406 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003407 if (work->started) {
3408 wpa_s->connect_work = NULL;
3409
3410 /* cancel possible auth. timeout */
3411 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
3412 NULL);
3413 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003414 wpas_connect_work_free(cwork);
3415 return;
3416 }
3417
3418 wpa_s->connect_work = work;
3419
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003420 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
3421 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003422 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
3423 wpas_connect_work_done(wpa_s);
3424 return;
3425 }
3426
Dmitry Shmidte4663042016-04-04 10:07:49 -07003427 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003428 os_memset(&params, 0, sizeof(params));
3429 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003430 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003431 if (bss &&
3432 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003433#ifdef CONFIG_IEEE80211R
3434 const u8 *ie, *md = NULL;
3435#endif /* CONFIG_IEEE80211R */
3436 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
3437 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
3438 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
3439 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
3440 os_memset(wpa_s->bssid, 0, ETH_ALEN);
3441 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3442 if (bssid_changed)
3443 wpas_notify_bssid_changed(wpa_s);
3444#ifdef CONFIG_IEEE80211R
3445 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
3446 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
3447 md = ie + 2;
3448 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
3449 if (md) {
3450 /* Prepare for the next transition */
3451 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
3452 }
3453#endif /* CONFIG_IEEE80211R */
3454#ifdef CONFIG_WPS
3455 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
3456 wpa_s->conf->ap_scan == 2 &&
3457 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
3458 /* Use ap_scan==1 style network selection to find the network
3459 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003460 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003461 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003462 wpa_s->reassociate = 1;
3463 wpa_supplicant_req_scan(wpa_s, 0, 0);
3464 return;
3465#endif /* CONFIG_WPS */
3466 } else {
3467 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
3468 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003469 if (bss)
3470 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
3471 else
3472 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003473 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003474 if (!wpa_s->pno)
3475 wpa_supplicant_cancel_sched_scan(wpa_s);
3476
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 wpa_supplicant_cancel_scan(wpa_s);
3478
3479 /* Starting new association, so clear the possibly used WPA IE from the
3480 * previous association. */
3481 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07003482 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
3483 wpa_s->rsnxe_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003484
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003485 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
3486 if (!wpa_ie) {
3487 wpas_connect_work_done(wpa_s);
3488 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003490
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
3492 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003493 cipher_pairwise = wpa_s->pairwise_cipher;
3494 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003495 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003496 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
3497 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3498 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
3499 use_crypt = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003500#ifdef CONFIG_WEP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003501 if (wpa_set_wep_keys(wpa_s, ssid)) {
3502 use_crypt = 1;
3503 wep_keys_set = 1;
3504 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003505#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003506 }
3507 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
3508 use_crypt = 0;
3509
3510#ifdef IEEE8021X_EAPOL
3511 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3512 if ((ssid->eapol_flags &
3513 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
3514 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
3515 !wep_keys_set) {
3516 use_crypt = 0;
3517 } else {
3518 /* Assume that dynamic WEP-104 keys will be used and
3519 * set cipher suites in order for drivers to expect
3520 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003521 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003522 }
3523 }
3524#endif /* IEEE8021X_EAPOL */
3525
3526 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3527 /* Set the key before (and later after) association */
3528 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3529 }
3530
3531 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
3532 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003533 params.ssid = bss->ssid;
3534 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003535 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
3536 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003537 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
3538 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003539 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07003540 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003541 ssid->bssid_set,
3542 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003543 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003544 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003545 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003546 params.bssid_hint = bss->bssid;
3547 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003548 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003549 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003550 if (ssid->bssid_hint_set)
3551 params.bssid_hint = ssid->bssid_hint;
3552
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003553 params.ssid = ssid->ssid;
3554 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003555 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003556 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003557
3558 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3559 wpa_s->conf->ap_scan == 2) {
3560 params.bssid = ssid->bssid;
3561 params.fixed_bssid = 1;
3562 }
3563
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003564 /* Initial frequency for IBSS/mesh */
3565 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003566 ssid->frequency > 0 && params.freq.freq == 0)
3567 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003568
3569 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003570 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003571 if (ssid->beacon_int)
3572 params.beacon_int = ssid->beacon_int;
3573 else
3574 params.beacon_int = wpa_s->conf->beacon_int;
3575 }
3576
Hai Shalomc3565922019-10-28 11:58:20 -07003577 if (bss && ssid->enable_edmg)
3578 edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len,
3579 WLAN_EID_EXT_EDMG_OPERATION);
3580 else
3581 edmg_ie_oper = NULL;
3582
3583 if (edmg_ie_oper) {
3584 params.freq.edmg.channels =
3585 wpa_ie_get_edmg_oper_chans(edmg_ie_oper);
3586 params.freq.edmg.bw_config =
3587 wpa_ie_get_edmg_oper_chan_width(edmg_ie_oper);
3588 wpa_printf(MSG_DEBUG,
3589 "AP supports EDMG channels 0x%x, bw_config %d",
3590 params.freq.edmg.channels,
3591 params.freq.edmg.bw_config);
3592
3593 /* User may ask for specific EDMG channel for EDMG connection
3594 * (must be supported by AP)
3595 */
3596 if (ssid->edmg_channel) {
3597 struct ieee80211_edmg_config configured_edmg;
3598 enum hostapd_hw_mode hw_mode;
3599 u8 primary_channel;
3600
3601 hw_mode = ieee80211_freq_to_chan(bss->freq,
3602 &primary_channel);
3603 if (hw_mode == NUM_HOSTAPD_MODES)
3604 goto edmg_fail;
3605
3606 hostapd_encode_edmg_chan(ssid->enable_edmg,
3607 ssid->edmg_channel,
3608 primary_channel,
3609 &configured_edmg);
3610
3611 if (ieee802_edmg_is_allowed(params.freq.edmg,
3612 configured_edmg)) {
3613 params.freq.edmg = configured_edmg;
3614 wpa_printf(MSG_DEBUG,
3615 "Use EDMG channel %d for connection",
3616 ssid->edmg_channel);
3617 } else {
3618 edmg_fail:
3619 params.freq.edmg.channels = 0;
3620 params.freq.edmg.bw_config = 0;
3621 wpa_printf(MSG_WARNING,
3622 "EDMG channel %d not supported by AP, fallback to DMG",
3623 ssid->edmg_channel);
3624 }
3625 }
3626
3627 if (params.freq.edmg.channels) {
3628 wpa_printf(MSG_DEBUG,
3629 "EDMG before: channels 0x%x, bw_config %d",
3630 params.freq.edmg.channels,
3631 params.freq.edmg.bw_config);
3632 params.freq.edmg = get_supported_edmg(wpa_s,
3633 &params.freq,
3634 params.freq.edmg);
3635 wpa_printf(MSG_DEBUG,
3636 "EDMG after: channels 0x%x, bw_config %d",
3637 params.freq.edmg.channels,
3638 params.freq.edmg.bw_config);
3639 }
3640 }
3641
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003642 params.pairwise_suite = cipher_pairwise;
3643 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003644 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003645 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003646 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003647 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003648 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003649 params.bg_scan_period = ssid->bg_scan_period;
Hai Shalomfdcde762020-04-02 11:19:20 -07003650#ifdef CONFIG_WEP
3651 {
3652 int i;
3653
3654 for (i = 0; i < NUM_WEP_KEYS; i++) {
3655 if (ssid->wep_key_len[i])
3656 params.wep_key[i] = ssid->wep_key[i];
3657 params.wep_key_len[i] = ssid->wep_key_len[i];
3658 }
3659 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003660 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003661#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003662
Hai Shalom74f70d42019-02-11 14:42:39 -08003663 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003664 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3665 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003666 params.passphrase = ssid->passphrase;
3667 if (ssid->psk_set)
3668 params.psk = ssid->psk;
3669 }
3670
Hai Shalom74f70d42019-02-11 14:42:39 -08003671 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
3672 (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3673 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
3674 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3675 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192))
Hai Shalomc3565922019-10-28 11:58:20 -07003676 params.req_handshake_offload = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003677
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003678 if (wpa_s->conf->key_mgmt_offload) {
3679 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3680 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003681 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3682 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003683 params.req_key_mgmt_offload =
3684 ssid->proactive_key_caching < 0 ?
3685 wpa_s->conf->okc : ssid->proactive_key_caching;
3686 else
3687 params.req_key_mgmt_offload = 1;
3688
3689 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3690 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3691 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3692 ssid->psk_set)
3693 params.psk = ssid->psk;
3694 }
3695
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003696 params.drop_unencrypted = use_crypt;
3697
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003698 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003699 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003700 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3701 struct wpa_ie_data ie;
3702 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3703 ie.capabilities &
3704 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3705 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3706 "MFP: require MFP");
3707 params.mgmt_frame_protection =
3708 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003709#ifdef CONFIG_OWE
3710 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3711 !ssid->owe_only) {
3712 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3713#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003714 }
3715 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003716
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003717 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003718
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003719 if (wpa_s->p2pdev->set_sta_uapsd)
3720 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003721 else
3722 params.uapsd = -1;
3723
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003724#ifdef CONFIG_HT_OVERRIDES
3725 os_memset(&htcaps, 0, sizeof(htcaps));
3726 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3727 params.htcaps = (u8 *) &htcaps;
3728 params.htcaps_mask = (u8 *) &htcaps_mask;
3729 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3730#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003731#ifdef CONFIG_VHT_OVERRIDES
3732 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3733 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3734 params.vhtcaps = &vhtcaps;
3735 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003736 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003737#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07003738#ifdef CONFIG_HE_OVERRIDES
3739 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
3740#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003741
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003742#ifdef CONFIG_P2P
3743 /*
3744 * If multi-channel concurrency is not supported, check for any
3745 * frequency conflict. In case of any frequency conflict, remove the
3746 * least prioritized connection.
3747 */
3748 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003749 int freq, num;
3750 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003751 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003752 wpa_printf(MSG_DEBUG,
3753 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003754 freq, params.freq.freq);
3755 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003756 wpa_s, params.freq.freq, ssid) < 0) {
3757 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003758 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003759 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003760 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003761 }
3762 }
3763#endif /* CONFIG_P2P */
3764
Dmitry Shmidte4663042016-04-04 10:07:49 -07003765 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3766 wpa_s->current_ssid)
3767 params.prev_bssid = prev_bssid;
3768
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003769 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003770 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003771 if (ret < 0) {
3772 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3773 "failed");
3774 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3775 /*
3776 * The driver is known to mean what is saying, so we
3777 * can stop right here; the association will not
3778 * succeed.
3779 */
3780 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003781 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003782 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3783 return;
3784 }
3785 /* try to continue anyway; new association will be tried again
3786 * after timeout */
3787 assoc_failed = 1;
3788 }
3789
3790 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3791 /* Set the key after the association just in case association
3792 * cleared the previously configured key. */
3793 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3794 /* No need to timeout authentication since there is no key
3795 * management. */
3796 wpa_supplicant_cancel_auth_timeout(wpa_s);
3797 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3798#ifdef CONFIG_IBSS_RSN
3799 } else if (ssid->mode == WPAS_MODE_IBSS &&
3800 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3801 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3802 /*
3803 * RSN IBSS authentication is per-STA and we can disable the
3804 * per-BSSID authentication.
3805 */
3806 wpa_supplicant_cancel_auth_timeout(wpa_s);
3807#endif /* CONFIG_IBSS_RSN */
3808 } else {
3809 /* Timeout for IEEE 802.11 authentication and association */
3810 int timeout = 60;
3811
3812 if (assoc_failed) {
3813 /* give IBSS a bit more time */
3814 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3815 } else if (wpa_s->conf->ap_scan == 1) {
3816 /* give IBSS a bit more time */
3817 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3818 }
3819 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3820 }
3821
Hai Shalomfdcde762020-04-02 11:19:20 -07003822#ifdef CONFIG_WEP
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003823 if (wep_keys_set &&
3824 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 /* Set static WEP keys again */
3826 wpa_set_wep_keys(wpa_s, ssid);
3827 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003828#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003829
3830 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3831 /*
3832 * Do not allow EAP session resumption between different
3833 * network configurations.
3834 */
3835 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3836 }
3837 old_ssid = wpa_s->current_ssid;
3838 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003839
3840 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003841 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003842#ifdef CONFIG_HS20
3843 hs20_configure_frame_filters(wpa_s);
3844#endif /* CONFIG_HS20 */
3845 }
3846
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003847 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3848 wpa_supplicant_initiate_eapol(wpa_s);
3849 if (old_ssid != wpa_s->current_ssid)
3850 wpas_notify_network_changed(wpa_s);
3851}
3852
3853
3854static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3855 const u8 *addr)
3856{
3857 struct wpa_ssid *old_ssid;
3858
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003859 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003860 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003861 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003862 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003863 wpa_sm_set_config(wpa_s->wpa, NULL);
3864 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3865 if (old_ssid != wpa_s->current_ssid)
3866 wpas_notify_network_changed(wpa_s);
3867 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3868}
3869
3870
3871/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003872 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3873 * @wpa_s: Pointer to wpa_supplicant data
3874 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3875 *
3876 * This function is used to request %wpa_supplicant to deauthenticate from the
3877 * current AP.
3878 */
3879void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
Hai Shalom81f62d82019-07-22 12:10:00 -07003880 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003881{
3882 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003883 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003884 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003885
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003886 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
Hai Shalom81f62d82019-07-22 12:10:00 -07003887 " pending_bssid=" MACSTR " reason=%d (%s) state=%s",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003888 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
Hai Shalom81f62d82019-07-22 12:10:00 -07003889 reason_code, reason2str(reason_code),
3890 wpa_supplicant_state_txt(wpa_s->wpa_state));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003891
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003892 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3893 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3894 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003895 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003896 else if (!is_zero_ether_addr(wpa_s->bssid))
3897 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003898 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3899 /*
3900 * When using driver-based BSS selection, we may not know the
3901 * BSSID with which we are currently trying to associate. We
3902 * need to notify the driver of this disconnection even in such
3903 * a case, so use the all zeros address here.
3904 */
3905 addr = wpa_s->bssid;
3906 zero_addr = 1;
3907 }
3908
Hai Shalom74f70d42019-02-11 14:42:39 -08003909 if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0)
3910 wpa_s->enabled_4addr_mode = 0;
3911
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003912#ifdef CONFIG_TDLS
3913 wpa_tdls_teardown_peers(wpa_s->wpa);
3914#endif /* CONFIG_TDLS */
3915
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003916#ifdef CONFIG_MESH
3917 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003918 struct mesh_conf *mconf;
3919
3920 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003921 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3922 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003923 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3924 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003925 wpa_supplicant_leave_mesh(wpa_s);
3926 }
3927#endif /* CONFIG_MESH */
3928
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003929 if (addr) {
3930 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003931 os_memset(&event, 0, sizeof(event));
Hai Shalom81f62d82019-07-22 12:10:00 -07003932 event.deauth_info.reason_code = reason_code;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003933 event.deauth_info.locally_generated = 1;
3934 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003935 if (zero_addr)
3936 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003937 }
3938
3939 wpa_supplicant_clear_connection(wpa_s, addr);
3940}
3941
Hai Shalomfdcde762020-04-02 11:19:20 -07003942
3943void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
3944{
3945 wpa_s->own_reconnect_req = 1;
3946 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
3947
3948}
3949
3950
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003951static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3952 struct wpa_ssid *ssid)
3953{
3954 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3955 return;
3956
3957 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003958 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003959 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3960 wpas_notify_network_enabled_changed(wpa_s, ssid);
3961
3962 /*
3963 * Try to reassociate since there is no current configuration and a new
3964 * network was made available.
3965 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003966 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003967 wpa_s->reassociate = 1;
3968}
3969
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003970
Roshan Pius950bec92016-07-19 09:49:24 -07003971/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003972 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003973 * @wpa_s: wpa_supplicant structure for a network interface
3974 * Returns: The new network configuration or %NULL if operation failed
3975 *
3976 * This function performs the following operations:
3977 * 1. Adds a new network.
3978 * 2. Send network addition notification.
3979 * 3. Marks the network disabled.
3980 * 4. Set network default parameters.
3981 */
3982struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3983{
3984 struct wpa_ssid *ssid;
3985
3986 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003987 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003988 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003989 wpas_notify_network_added(wpa_s, ssid);
3990 ssid->disabled = 1;
3991 wpa_config_set_network_defaults(ssid);
3992
3993 return ssid;
3994}
3995
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003996
Roshan Pius950bec92016-07-19 09:49:24 -07003997/**
3998 * wpa_supplicant_remove_network - Remove a configured network based on id
3999 * @wpa_s: wpa_supplicant structure for a network interface
4000 * @id: Unique network id to search for
4001 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
4002 * could not be removed
4003 *
4004 * This function performs the following operations:
4005 * 1. Removes the network.
4006 * 2. Send network removal notification.
4007 * 3. Update internal state machines.
4008 * 4. Stop any running sched scans.
4009 */
4010int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
4011{
4012 struct wpa_ssid *ssid;
4013 int was_disabled;
4014
4015 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004016 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07004017 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004018 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07004019
4020 if (wpa_s->last_ssid == ssid)
4021 wpa_s->last_ssid = NULL;
4022
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004023 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07004024#ifdef CONFIG_SME
4025 wpa_s->sme.prev_bssid_set = 0;
4026#endif /* CONFIG_SME */
4027 /*
4028 * Invalidate the EAP session cache if the current or
4029 * previously used network is removed.
4030 */
4031 eapol_sm_invalidate_cached_session(wpa_s->eapol);
4032 }
4033
4034 if (ssid == wpa_s->current_ssid) {
4035 wpa_sm_set_config(wpa_s->wpa, NULL);
4036 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
4037
4038 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4039 wpa_s->own_disconnect_req = 1;
4040 wpa_supplicant_deauthenticate(wpa_s,
4041 WLAN_REASON_DEAUTH_LEAVING);
4042 }
4043
4044 was_disabled = ssid->disabled;
4045
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004046 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07004047 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07004048
4049 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004050 wpa_printf(MSG_DEBUG,
4051 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07004052 wpa_supplicant_cancel_sched_scan(wpa_s);
4053 wpa_supplicant_req_scan(wpa_s, 0, 0);
4054 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004055
Roshan Pius950bec92016-07-19 09:49:24 -07004056 return 0;
4057}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004058
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004059
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004060/**
4061 * wpa_supplicant_enable_network - Mark a configured network as enabled
4062 * @wpa_s: wpa_supplicant structure for a network interface
4063 * @ssid: wpa_ssid structure for a configured network or %NULL
4064 *
4065 * Enables the specified network or all networks if no network specified.
4066 */
4067void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
4068 struct wpa_ssid *ssid)
4069{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004070 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004071 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4072 wpa_supplicant_enable_one_network(wpa_s, ssid);
4073 } else
4074 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004076 if (wpa_s->reassociate && !wpa_s->disconnected &&
4077 (!wpa_s->current_ssid ||
4078 wpa_s->wpa_state == WPA_DISCONNECTED ||
4079 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004080 if (wpa_s->sched_scanning) {
4081 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
4082 "new network to scan filters");
4083 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004084 }
4085
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004086 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
4087 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004088 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004089 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004090 }
4091}
4092
4093
4094/**
4095 * wpa_supplicant_disable_network - Mark a configured network as disabled
4096 * @wpa_s: wpa_supplicant structure for a network interface
4097 * @ssid: wpa_ssid structure for a configured network or %NULL
4098 *
4099 * Disables the specified network or all networks if no network specified.
4100 */
4101void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
4102 struct wpa_ssid *ssid)
4103{
4104 struct wpa_ssid *other_ssid;
4105 int was_disabled;
4106
4107 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004108 if (wpa_s->sched_scanning)
4109 wpa_supplicant_cancel_sched_scan(wpa_s);
4110
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004111 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4112 other_ssid = other_ssid->next) {
4113 was_disabled = other_ssid->disabled;
4114 if (was_disabled == 2)
4115 continue; /* do not change persistent P2P group
4116 * data */
4117
4118 other_ssid->disabled = 1;
4119
4120 if (was_disabled != other_ssid->disabled)
4121 wpas_notify_network_enabled_changed(
4122 wpa_s, other_ssid);
4123 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004124 if (wpa_s->current_ssid) {
4125 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4126 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004127 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004128 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004129 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004130 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004131 if (ssid == wpa_s->current_ssid) {
4132 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4133 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004134 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004135 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004136 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004137
4138 was_disabled = ssid->disabled;
4139
4140 ssid->disabled = 1;
4141
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004142 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004143 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004144 if (wpa_s->sched_scanning) {
4145 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
4146 "to remove network from filters");
4147 wpa_supplicant_cancel_sched_scan(wpa_s);
4148 wpa_supplicant_req_scan(wpa_s, 0, 0);
4149 }
4150 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004151 }
4152}
4153
4154
4155/**
4156 * wpa_supplicant_select_network - Attempt association with a network
4157 * @wpa_s: wpa_supplicant structure for a network interface
4158 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
4159 */
4160void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
4161 struct wpa_ssid *ssid)
4162{
4163
4164 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004165 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004166
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004167 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004168 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
4169 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004170 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004171 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004172 disconnected = 1;
4173 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004174
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004175 if (ssid)
4176 wpas_clear_temp_disabled(wpa_s, ssid, 1);
4177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004178 /*
4179 * Mark all other networks disabled or mark all networks enabled if no
4180 * network specified.
4181 */
4182 for (other_ssid = wpa_s->conf->ssid; other_ssid;
4183 other_ssid = other_ssid->next) {
4184 int was_disabled = other_ssid->disabled;
4185 if (was_disabled == 2)
4186 continue; /* do not change persistent P2P group data */
4187
4188 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004189 if (was_disabled && !other_ssid->disabled)
4190 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004191
4192 if (was_disabled != other_ssid->disabled)
4193 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
4194 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004195
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004196 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
4197 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004198 /* We are already associated with the selected network */
4199 wpa_printf(MSG_DEBUG, "Already associated with the "
4200 "selected network - do nothing");
4201 return;
4202 }
4203
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004204 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004205 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004206 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004207 wpa_s->connect_without_scan =
4208 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07004209
4210 /*
4211 * Don't optimize next scan freqs since a new ESS has been
4212 * selected.
4213 */
4214 os_free(wpa_s->next_scan_freqs);
4215 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004216 } else {
4217 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004218 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004219
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004220 wpa_s->disconnected = 0;
4221 wpa_s->reassociate = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004222 wpa_s_clear_sae_rejected(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004223 wpa_s->last_owe_group = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004224 if (ssid) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004225 ssid->owe_transition_bss_select_count = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07004226 wpa_s_setup_sae_pt(wpa_s->conf, ssid);
4227 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004228
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004229 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004230 wpa_supplicant_fast_associate(wpa_s) != 1) {
4231 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004232 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004233 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004234 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004235
4236 if (ssid)
4237 wpas_notify_network_selected(wpa_s, ssid);
4238}
4239
4240
4241/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004242 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
4243 * @wpa_s: wpa_supplicant structure for a network interface
4244 * @pkcs11_engine_path: PKCS #11 engine path or NULL
4245 * @pkcs11_module_path: PKCS #11 module path or NULL
4246 * Returns: 0 on success; -1 on failure
4247 *
4248 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
4249 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
4250 * module path fails the paths will be reset to the default value (NULL).
4251 */
4252int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
4253 const char *pkcs11_engine_path,
4254 const char *pkcs11_module_path)
4255{
4256 char *pkcs11_engine_path_copy = NULL;
4257 char *pkcs11_module_path_copy = NULL;
4258
4259 if (pkcs11_engine_path != NULL) {
4260 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
4261 if (pkcs11_engine_path_copy == NULL)
4262 return -1;
4263 }
4264 if (pkcs11_module_path != NULL) {
4265 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08004266 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004267 os_free(pkcs11_engine_path_copy);
4268 return -1;
4269 }
4270 }
4271
4272 os_free(wpa_s->conf->pkcs11_engine_path);
4273 os_free(wpa_s->conf->pkcs11_module_path);
4274 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
4275 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
4276
4277 wpa_sm_set_eapol(wpa_s->wpa, NULL);
4278 eapol_sm_deinit(wpa_s->eapol);
4279 wpa_s->eapol = NULL;
4280 if (wpa_supplicant_init_eapol(wpa_s)) {
4281 /* Error -> Reset paths to the default value (NULL) once. */
4282 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
4283 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
4284 NULL);
4285
4286 return -1;
4287 }
4288 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4289
4290 return 0;
4291}
4292
4293
4294/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004295 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
4296 * @wpa_s: wpa_supplicant structure for a network interface
4297 * @ap_scan: AP scan mode
4298 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
4299 *
4300 */
4301int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
4302{
4303
4304 int old_ap_scan;
4305
4306 if (ap_scan < 0 || ap_scan > 2)
4307 return -1;
4308
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004309 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4310 wpa_printf(MSG_INFO,
4311 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4312 }
4313
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004314#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004315 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
4316 wpa_s->wpa_state >= WPA_ASSOCIATING &&
4317 wpa_s->wpa_state < WPA_COMPLETED) {
4318 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
4319 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004320 return 0;
4321 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004322#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07004323
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004324 old_ap_scan = wpa_s->conf->ap_scan;
4325 wpa_s->conf->ap_scan = ap_scan;
4326
4327 if (old_ap_scan != wpa_s->conf->ap_scan)
4328 wpas_notify_ap_scan_changed(wpa_s);
4329
4330 return 0;
4331}
4332
4333
4334/**
4335 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
4336 * @wpa_s: wpa_supplicant structure for a network interface
4337 * @expire_age: Expiration age in seconds
4338 * Returns: 0 if succeed or -1 if expire_age has an invalid value
4339 *
4340 */
4341int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
4342 unsigned int bss_expire_age)
4343{
4344 if (bss_expire_age < 10) {
4345 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
4346 bss_expire_age);
4347 return -1;
4348 }
4349 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
4350 bss_expire_age);
4351 wpa_s->conf->bss_expiration_age = bss_expire_age;
4352
4353 return 0;
4354}
4355
4356
4357/**
4358 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
4359 * @wpa_s: wpa_supplicant structure for a network interface
4360 * @expire_count: number of scans after which an unseen BSS is reclaimed
4361 * Returns: 0 if succeed or -1 if expire_count has an invalid value
4362 *
4363 */
4364int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
4365 unsigned int bss_expire_count)
4366{
4367 if (bss_expire_count < 1) {
4368 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
4369 bss_expire_count);
4370 return -1;
4371 }
4372 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
4373 bss_expire_count);
4374 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
4375
4376 return 0;
4377}
4378
4379
4380/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07004381 * wpa_supplicant_set_scan_interval - Set scan interval
4382 * @wpa_s: wpa_supplicant structure for a network interface
4383 * @scan_interval: scan interval in seconds
4384 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
4385 *
4386 */
4387int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
4388 int scan_interval)
4389{
4390 if (scan_interval < 0) {
4391 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
4392 scan_interval);
4393 return -1;
4394 }
4395 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
4396 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004397 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004398
4399 return 0;
4400}
4401
4402
4403/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004404 * wpa_supplicant_set_debug_params - Set global debug params
4405 * @global: wpa_global structure
4406 * @debug_level: debug level
4407 * @debug_timestamp: determines if show timestamp in debug data
4408 * @debug_show_keys: determines if show keys in debug data
4409 * Returns: 0 if succeed or -1 if debug_level has wrong value
4410 */
4411int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
4412 int debug_timestamp, int debug_show_keys)
4413{
4414
4415 int old_level, old_timestamp, old_show_keys;
4416
4417 /* check for allowed debuglevels */
4418 if (debug_level != MSG_EXCESSIVE &&
4419 debug_level != MSG_MSGDUMP &&
4420 debug_level != MSG_DEBUG &&
4421 debug_level != MSG_INFO &&
4422 debug_level != MSG_WARNING &&
4423 debug_level != MSG_ERROR)
4424 return -1;
4425
4426 old_level = wpa_debug_level;
4427 old_timestamp = wpa_debug_timestamp;
4428 old_show_keys = wpa_debug_show_keys;
4429
4430 wpa_debug_level = debug_level;
4431 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
4432 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
4433
4434 if (wpa_debug_level != old_level)
4435 wpas_notify_debug_level_changed(global);
4436 if (wpa_debug_timestamp != old_timestamp)
4437 wpas_notify_debug_timestamp_changed(global);
4438 if (wpa_debug_show_keys != old_show_keys)
4439 wpas_notify_debug_show_keys_changed(global);
4440
4441 return 0;
4442}
4443
4444
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004445#ifdef CONFIG_OWE
4446static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
4447 const u8 *entry_ssid, size_t entry_ssid_len)
4448{
4449 const u8 *owe, *pos, *end;
4450 u8 ssid_len;
4451 struct wpa_bss *bss;
4452
4453 /* Check network profile SSID aganst the SSID in the
4454 * OWE Transition Mode element. */
4455
4456 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
4457 if (!bss)
4458 return 0;
4459
4460 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
4461 if (!owe)
4462 return 0;
4463
4464 pos = owe + 6;
4465 end = owe + 2 + owe[1];
4466
4467 if (end - pos < ETH_ALEN + 1)
4468 return 0;
4469 pos += ETH_ALEN;
4470 ssid_len = *pos++;
4471 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
4472 return 0;
4473
4474 return entry_ssid_len == ssid_len &&
4475 os_memcmp(pos, entry_ssid, ssid_len) == 0;
4476}
4477#endif /* CONFIG_OWE */
4478
4479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004480/**
4481 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
4482 * @wpa_s: Pointer to wpa_supplicant data
4483 * Returns: A pointer to the current network structure or %NULL on failure
4484 */
4485struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
4486{
4487 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004488 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004489 int res;
4490 size_t ssid_len;
4491 u8 bssid[ETH_ALEN];
4492 int wired;
4493
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004494 res = wpa_drv_get_ssid(wpa_s, ssid);
4495 if (res < 0) {
4496 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
4497 "driver");
4498 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004499 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004500 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004501
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004502 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004503 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
4504 "driver");
4505 return NULL;
4506 }
4507
4508 wired = wpa_s->conf->ap_scan == 0 &&
4509 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
4510
4511 entry = wpa_s->conf->ssid;
4512 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07004513 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004514 ((ssid_len == entry->ssid_len &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004515 (!entry->ssid ||
4516 os_memcmp(ssid, entry->ssid, ssid_len) == 0)) ||
4517 wired) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004518 (!entry->bssid_set ||
4519 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4520 return entry;
4521#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07004522 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004523 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
4524 (entry->ssid == NULL || entry->ssid_len == 0) &&
4525 (!entry->bssid_set ||
4526 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4527 return entry;
4528#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004529
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004530#ifdef CONFIG_OWE
4531 if (!wpas_network_disabled(wpa_s, entry) &&
4532 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
4533 entry->ssid_len) &&
4534 (!entry->bssid_set ||
4535 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
4536 return entry;
4537#endif /* CONFIG_OWE */
4538
Dmitry Shmidt04949592012-07-19 12:16:46 -07004539 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004540 entry->ssid_len == 0 &&
4541 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
4542 return entry;
4543
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004544 entry = entry->next;
4545 }
4546
4547 return NULL;
4548}
4549
4550
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004551static int select_driver(struct wpa_supplicant *wpa_s, int i)
4552{
4553 struct wpa_global *global = wpa_s->global;
4554
4555 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07004556 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004557 if (global->drv_priv[i] == NULL) {
4558 wpa_printf(MSG_ERROR, "Failed to initialize driver "
4559 "'%s'", wpa_drivers[i]->name);
4560 return -1;
4561 }
4562 }
4563
4564 wpa_s->driver = wpa_drivers[i];
4565 wpa_s->global_drv_priv = global->drv_priv[i];
4566
4567 return 0;
4568}
4569
4570
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004571static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
4572 const char *name)
4573{
4574 int i;
4575 size_t len;
4576 const char *pos, *driver = name;
4577
4578 if (wpa_s == NULL)
4579 return -1;
4580
4581 if (wpa_drivers[0] == NULL) {
4582 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
4583 "wpa_supplicant");
4584 return -1;
4585 }
4586
4587 if (name == NULL) {
4588 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004589 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004590 }
4591
4592 do {
4593 pos = os_strchr(driver, ',');
4594 if (pos)
4595 len = pos - driver;
4596 else
4597 len = os_strlen(driver);
4598
4599 for (i = 0; wpa_drivers[i]; i++) {
4600 if (os_strlen(wpa_drivers[i]->name) == len &&
4601 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004602 0) {
4603 /* First driver that succeeds wins */
4604 if (select_driver(wpa_s, i) == 0)
4605 return 0;
4606 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004607 }
4608
4609 driver = pos + 1;
4610 } while (pos);
4611
4612 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
4613 return -1;
4614}
4615
4616
4617/**
4618 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
4619 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
4620 * with struct wpa_driver_ops::init()
4621 * @src_addr: Source address of the EAPOL frame
4622 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
4623 * @len: Length of the EAPOL data
4624 *
4625 * This function is called for each received EAPOL frame. Most driver
4626 * interfaces rely on more generic OS mechanism for receiving frames through
4627 * l2_packet, but if such a mechanism is not available, the driver wrapper may
4628 * take care of received EAPOL frames and deliver them to the core supplicant
4629 * code by calling this function.
4630 */
4631void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
4632 const u8 *buf, size_t len)
4633{
4634 struct wpa_supplicant *wpa_s = ctx;
4635
4636 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
4637 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
4638
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004639#ifdef CONFIG_TESTING_OPTIONS
4640 if (wpa_s->ignore_auth_resp) {
4641 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
4642 return;
4643 }
4644#endif /* CONFIG_TESTING_OPTIONS */
4645
Jouni Malinena05074c2012-12-21 21:35:35 +02004646 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
4647 (wpa_s->last_eapol_matches_bssid &&
4648#ifdef CONFIG_AP
4649 !wpa_s->ap_iface &&
4650#endif /* CONFIG_AP */
4651 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004652 /*
4653 * There is possible race condition between receiving the
4654 * association event and the EAPOL frame since they are coming
4655 * through different paths from the driver. In order to avoid
4656 * issues in trying to process the EAPOL frame before receiving
4657 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004658 * the association event is received. This may also be needed in
4659 * driver-based roaming case, so also use src_addr != BSSID as a
4660 * trigger if we have previously confirmed that the
4661 * Authenticator uses BSSID as the src_addr (which is not the
4662 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004663 */
4664 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004665 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4666 wpa_supplicant_state_txt(wpa_s->wpa_state),
4667 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004668 wpabuf_free(wpa_s->pending_eapol_rx);
4669 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4670 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004671 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004672 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4673 ETH_ALEN);
4674 }
4675 return;
4676 }
4677
Jouni Malinena05074c2012-12-21 21:35:35 +02004678 wpa_s->last_eapol_matches_bssid =
4679 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4680
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004681#ifdef CONFIG_AP
4682 if (wpa_s->ap_iface) {
4683 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4684 return;
4685 }
4686#endif /* CONFIG_AP */
4687
4688 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4689 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4690 "no key management is configured");
4691 return;
4692 }
4693
4694 if (wpa_s->eapol_received == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08004695 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004696 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4697 wpa_s->wpa_state != WPA_COMPLETED) &&
4698 (wpa_s->current_ssid == NULL ||
Hai Shalom81f62d82019-07-22 12:10:00 -07004699 wpa_s->current_ssid->mode != WPAS_MODE_IBSS)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004700 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004701 int timeout = 10;
4702
4703 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4704 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4705 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4706 /* Use longer timeout for IEEE 802.1X/EAP */
4707 timeout = 70;
4708 }
4709
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004710#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004711 if (wpa_s->current_ssid && wpa_s->current_bss &&
4712 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4713 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4714 /*
4715 * Use shorter timeout if going through WPS AP iteration
4716 * for PIN config method with an AP that does not
4717 * advertise Selected Registrar.
4718 */
4719 struct wpabuf *wps_ie;
4720
4721 wps_ie = wpa_bss_get_vendor_ie_multi(
4722 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4723 if (wps_ie &&
4724 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4725 timeout = 10;
4726 wpabuf_free(wps_ie);
4727 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004728#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004729
4730 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004731 }
4732 wpa_s->eapol_received++;
4733
4734 if (wpa_s->countermeasures) {
4735 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4736 "EAPOL packet");
4737 return;
4738 }
4739
4740#ifdef CONFIG_IBSS_RSN
4741 if (wpa_s->current_ssid &&
4742 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4743 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4744 return;
4745 }
4746#endif /* CONFIG_IBSS_RSN */
4747
4748 /* Source address of the incoming EAPOL frame could be compared to the
4749 * current BSSID. However, it is possible that a centralized
4750 * Authenticator could be using another MAC address than the BSSID of
4751 * an AP, so just allow any address to be used for now. The replies are
4752 * still sent to the current BSSID (if available), though. */
4753
4754 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4755 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004756 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4757 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004758 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4759 return;
4760 wpa_drv_poll(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08004761 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004762 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4763 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4764 /*
Hai Shalome21d4e82020-04-29 16:34:06 -07004765 * Set portValid = true here since we are going to skip 4-way
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004766 * handshake processing which would normally set portValid. We
4767 * need this to allow the EAPOL state machines to be completed
4768 * without going through EAPOL-Key handshake.
4769 */
Hai Shalome21d4e82020-04-29 16:34:06 -07004770 eapol_sm_notify_portValid(wpa_s->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004771 }
4772}
4773
4774
Hai Shalomb755a2a2020-04-23 21:49:02 -07004775static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s)
4776{
4777 return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) ||
4778 !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX);
4779}
4780
4781
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004782int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004783{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004784 if ((!wpa_s->p2p_mgmt ||
4785 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4786 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004787 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004788 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4789 wpa_drv_get_mac_addr(wpa_s),
4790 ETH_P_EAPOL,
Hai Shalomb755a2a2020-04-23 21:49:02 -07004791 wpas_eapol_needs_l2_packet(wpa_s) ?
4792 wpa_supplicant_rx_eapol : NULL,
4793 wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004794 if (wpa_s->l2 == NULL)
4795 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004796
4797 if (l2_packet_set_packet_filter(wpa_s->l2,
4798 L2_PACKET_FILTER_PKTTYPE))
4799 wpa_dbg(wpa_s, MSG_DEBUG,
4800 "Failed to attach pkt_type filter");
Hai Shalomb755a2a2020-04-23 21:49:02 -07004801
4802 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4803 wpa_msg(wpa_s, MSG_ERROR,
4804 "Failed to get own L2 address");
4805 return -1;
4806 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004807 } else {
4808 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4809 if (addr)
4810 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4811 }
4812
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004813 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
Mikael Kanstrupcc779b82019-08-16 08:50:54 +02004814 wpas_wps_update_mac_addr(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004815
Hai Shalomc3565922019-10-28 11:58:20 -07004816#ifdef CONFIG_FST
4817 if (wpa_s->fst)
4818 fst_update_mac_addr(wpa_s->fst, wpa_s->own_addr);
4819#endif /* CONFIG_FST */
4820
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004821 return 0;
4822}
4823
4824
Dmitry Shmidt04949592012-07-19 12:16:46 -07004825static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4826 const u8 *buf, size_t len)
4827{
4828 struct wpa_supplicant *wpa_s = ctx;
4829 const struct l2_ethhdr *eth;
4830
4831 if (len < sizeof(*eth))
4832 return;
4833 eth = (const struct l2_ethhdr *) buf;
4834
4835 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4836 !(eth->h_dest[0] & 0x01)) {
4837 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4838 " (bridge - not for this interface - ignore)",
4839 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4840 return;
4841 }
4842
4843 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4844 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4845 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4846 len - sizeof(*eth));
4847}
4848
4849
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004850/**
4851 * wpa_supplicant_driver_init - Initialize driver interface parameters
4852 * @wpa_s: Pointer to wpa_supplicant data
4853 * Returns: 0 on success, -1 on failure
4854 *
4855 * This function is called to initialize driver interface parameters.
4856 * wpa_drv_init() must have been called before this function to initialize the
4857 * driver interface.
4858 */
4859int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4860{
4861 static int interface_count = 0;
4862
4863 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4864 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004865
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004866 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4867 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004868 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004869 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4870
Hai Shalomb755a2a2020-04-23 21:49:02 -07004871 if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004872 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4873 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004874 wpa_s->l2_br = l2_packet_init_bridge(
4875 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4876 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004877 if (wpa_s->l2_br == NULL) {
4878 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4879 "connection for the bridge interface '%s'",
4880 wpa_s->bridge_ifname);
4881 return -1;
4882 }
4883 }
4884
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004885 if (wpa_s->conf->ap_scan == 2 &&
4886 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4887 wpa_printf(MSG_INFO,
4888 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4889 }
4890
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004891 wpa_clear_keys(wpa_s, NULL);
4892
4893 /* Make sure that TKIP countermeasures are not left enabled (could
4894 * happen if wpa_supplicant is killed during countermeasures. */
4895 wpa_drv_set_countermeasures(wpa_s, 0);
4896
4897 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4898 wpa_drv_flush_pmkid(wpa_s);
4899
4900 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004901 wpa_s->prev_scan_wildcard = 0;
4902
Dmitry Shmidt04949592012-07-19 12:16:46 -07004903 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004904 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4905 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4906 interface_count = 0;
4907 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004908#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004909 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004910 wpa_supplicant_delayed_sched_scan(wpa_s,
4911 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004912 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004913 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004914 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004915#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004916 interface_count++;
4917 } else
4918 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4919
4920 return 0;
4921}
4922
4923
4924static int wpa_supplicant_daemon(const char *pid_file)
4925{
4926 wpa_printf(MSG_DEBUG, "Daemonize..");
4927 return os_daemonize(pid_file);
4928}
4929
4930
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004931static struct wpa_supplicant *
4932wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004933{
4934 struct wpa_supplicant *wpa_s;
4935
4936 wpa_s = os_zalloc(sizeof(*wpa_s));
4937 if (wpa_s == NULL)
4938 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004939 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004940 wpa_s->scan_interval = 5;
4941 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004942 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004943 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004944 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004945
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004946 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004947 dl_list_init(&wpa_s->fils_hlp_req);
Hai Shalomfdcde762020-04-02 11:19:20 -07004948#ifdef CONFIG_TESTING_OPTIONS
4949 dl_list_init(&wpa_s->drv_signal_override);
4950#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004951
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004952 return wpa_s;
4953}
4954
4955
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004956#ifdef CONFIG_HT_OVERRIDES
4957
4958static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4959 struct ieee80211_ht_capabilities *htcaps,
4960 struct ieee80211_ht_capabilities *htcaps_mask,
4961 const char *ht_mcs)
4962{
4963 /* parse ht_mcs into hex array */
4964 int i;
4965 const char *tmp = ht_mcs;
4966 char *end = NULL;
4967
4968 /* If ht_mcs is null, do not set anything */
4969 if (!ht_mcs)
4970 return 0;
4971
4972 /* This is what we are setting in the kernel */
4973 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4974
4975 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4976
4977 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004978 long v;
4979
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004980 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004981 v = strtol(tmp, &end, 16);
4982
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004983 if (errno == 0) {
4984 wpa_msg(wpa_s, MSG_DEBUG,
4985 "htcap value[%i]: %ld end: %p tmp: %p",
4986 i, v, end, tmp);
4987 if (end == tmp)
4988 break;
4989
4990 htcaps->supported_mcs_set[i] = v;
4991 tmp = end;
4992 } else {
4993 wpa_msg(wpa_s, MSG_ERROR,
4994 "Failed to parse ht-mcs: %s, error: %s\n",
4995 ht_mcs, strerror(errno));
4996 return -1;
4997 }
4998 }
4999
5000 /*
5001 * If we were able to parse any values, then set mask for the MCS set.
5002 */
5003 if (i) {
5004 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
5005 IEEE80211_HT_MCS_MASK_LEN - 1);
5006 /* skip the 3 reserved bits */
5007 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
5008 0x1f;
5009 }
5010
5011 return 0;
5012}
5013
5014
5015static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
5016 struct ieee80211_ht_capabilities *htcaps,
5017 struct ieee80211_ht_capabilities *htcaps_mask,
5018 int disabled)
5019{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005020 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005021
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005022 if (disabled == -1)
5023 return 0;
5024
Hai Shalom74f70d42019-02-11 14:42:39 -08005025 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
5026
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005027 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
5028 htcaps_mask->ht_capabilities_info |= msk;
5029 if (disabled)
5030 htcaps->ht_capabilities_info &= msk;
5031 else
5032 htcaps->ht_capabilities_info |= msk;
5033
5034 return 0;
5035}
5036
5037
5038static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
5039 struct ieee80211_ht_capabilities *htcaps,
5040 struct ieee80211_ht_capabilities *htcaps_mask,
5041 int factor)
5042{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005043 if (factor == -1)
5044 return 0;
5045
Hai Shalom74f70d42019-02-11 14:42:39 -08005046 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
5047
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005048 if (factor < 0 || factor > 3) {
5049 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
5050 "Must be 0-3 or -1", factor);
5051 return -EINVAL;
5052 }
5053
5054 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
5055 htcaps->a_mpdu_params &= ~0x3;
5056 htcaps->a_mpdu_params |= factor & 0x3;
5057
5058 return 0;
5059}
5060
5061
5062static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
5063 struct ieee80211_ht_capabilities *htcaps,
5064 struct ieee80211_ht_capabilities *htcaps_mask,
5065 int density)
5066{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005067 if (density == -1)
5068 return 0;
5069
Hai Shalom74f70d42019-02-11 14:42:39 -08005070 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
5071
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005072 if (density < 0 || density > 7) {
5073 wpa_msg(wpa_s, MSG_ERROR,
5074 "ampdu_density: %d out of range. Must be 0-7 or -1.",
5075 density);
5076 return -EINVAL;
5077 }
5078
5079 htcaps_mask->a_mpdu_params |= 0x1C;
5080 htcaps->a_mpdu_params &= ~(0x1C);
5081 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
5082
5083 return 0;
5084}
5085
5086
5087static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
5088 struct ieee80211_ht_capabilities *htcaps,
5089 struct ieee80211_ht_capabilities *htcaps_mask,
5090 int disabled)
5091{
Hai Shalom74f70d42019-02-11 14:42:39 -08005092 if (disabled)
5093 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005094
Paul Stewart092955c2017-02-06 09:13:09 -08005095 set_disable_ht40(htcaps, disabled);
5096 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005097
5098 return 0;
5099}
5100
5101
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005102static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
5103 struct ieee80211_ht_capabilities *htcaps,
5104 struct ieee80211_ht_capabilities *htcaps_mask,
5105 int disabled)
5106{
5107 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005108 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
5109 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005110
Hai Shalom74f70d42019-02-11 14:42:39 -08005111 if (disabled)
5112 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005113
5114 if (disabled)
5115 htcaps->ht_capabilities_info &= ~msk;
5116 else
5117 htcaps->ht_capabilities_info |= msk;
5118
5119 htcaps_mask->ht_capabilities_info |= msk;
5120
5121 return 0;
5122}
5123
5124
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005125static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
5126 struct ieee80211_ht_capabilities *htcaps,
5127 struct ieee80211_ht_capabilities *htcaps_mask,
5128 int disabled)
5129{
5130 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005131 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005132
Hai Shalom74f70d42019-02-11 14:42:39 -08005133 if (disabled)
5134 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005135
5136 if (disabled)
5137 htcaps->ht_capabilities_info &= ~msk;
5138 else
5139 htcaps->ht_capabilities_info |= msk;
5140
5141 htcaps_mask->ht_capabilities_info |= msk;
5142
5143 return 0;
5144}
5145
5146
Hai Shalom74f70d42019-02-11 14:42:39 -08005147static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s,
5148 struct ieee80211_ht_capabilities *htcaps,
5149 struct ieee80211_ht_capabilities *htcaps_mask,
5150 int tx_stbc)
5151{
5152 le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC);
5153
5154 if (tx_stbc == -1)
5155 return 0;
5156
5157 wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc);
5158
5159 if (tx_stbc < 0 || tx_stbc > 1) {
5160 wpa_msg(wpa_s, MSG_ERROR,
5161 "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc);
5162 return -EINVAL;
5163 }
5164
5165 htcaps_mask->ht_capabilities_info |= msk;
5166 htcaps->ht_capabilities_info &= ~msk;
5167 htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk;
5168
5169 return 0;
5170}
5171
5172
5173static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s,
5174 struct ieee80211_ht_capabilities *htcaps,
5175 struct ieee80211_ht_capabilities *htcaps_mask,
5176 int rx_stbc)
5177{
5178 le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK);
5179
5180 if (rx_stbc == -1)
5181 return 0;
5182
5183 wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc);
5184
5185 if (rx_stbc < 0 || rx_stbc > 3) {
5186 wpa_msg(wpa_s, MSG_ERROR,
5187 "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc);
5188 return -EINVAL;
5189 }
5190
5191 htcaps_mask->ht_capabilities_info |= msk;
5192 htcaps->ht_capabilities_info &= ~msk;
5193 htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk;
5194
5195 return 0;
5196}
5197
5198
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005199void wpa_supplicant_apply_ht_overrides(
5200 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5201 struct wpa_driver_associate_params *params)
5202{
5203 struct ieee80211_ht_capabilities *htcaps;
5204 struct ieee80211_ht_capabilities *htcaps_mask;
5205
5206 if (!ssid)
5207 return;
5208
5209 params->disable_ht = ssid->disable_ht;
5210 if (!params->htcaps || !params->htcaps_mask)
5211 return;
5212
5213 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
5214 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
5215 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
5216 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
5217 ssid->disable_max_amsdu);
5218 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
5219 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
5220 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005221 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005222 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Hai Shalom74f70d42019-02-11 14:42:39 -08005223 wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc);
5224 wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005225
5226 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005227 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005228 htcaps->ht_capabilities_info |= bit;
5229 htcaps_mask->ht_capabilities_info |= bit;
5230 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005231}
5232
5233#endif /* CONFIG_HT_OVERRIDES */
5234
5235
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005236#ifdef CONFIG_VHT_OVERRIDES
5237void wpa_supplicant_apply_vht_overrides(
5238 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5239 struct wpa_driver_associate_params *params)
5240{
5241 struct ieee80211_vht_capabilities *vhtcaps;
5242 struct ieee80211_vht_capabilities *vhtcaps_mask;
5243
5244 if (!ssid)
5245 return;
5246
5247 params->disable_vht = ssid->disable_vht;
5248
5249 vhtcaps = (void *) params->vhtcaps;
5250 vhtcaps_mask = (void *) params->vhtcaps_mask;
5251
5252 if (!vhtcaps || !vhtcaps_mask)
5253 return;
5254
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005255 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
5256 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005257
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005258#ifdef CONFIG_HT_OVERRIDES
Hai Shalom74f70d42019-02-11 14:42:39 -08005259 if (ssid->disable_sgi) {
5260 vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 |
5261 VHT_CAP_SHORT_GI_160);
5262 vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 |
5263 VHT_CAP_SHORT_GI_160);
5264 wpa_msg(wpa_s, MSG_DEBUG,
5265 "disable-sgi override specified, vht-caps: 0x%x",
5266 vhtcaps->vht_capabilities_info);
5267 }
5268
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005269 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005270 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
5271 int max_ampdu;
5272
5273 max_ampdu = (ssid->vht_capa &
5274 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
5275 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005276
5277 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
5278 wpa_set_ampdu_factor(wpa_s,
5279 (void *) params->htcaps,
5280 (void *) params->htcaps_mask,
5281 max_ampdu);
5282 }
5283#endif /* CONFIG_HT_OVERRIDES */
5284
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005285#define OVERRIDE_MCS(i) \
5286 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
5287 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005288 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005289 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005290 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
5291 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005292 } \
5293 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
5294 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005295 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005296 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005297 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
5298 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005299 }
5300
5301 OVERRIDE_MCS(1);
5302 OVERRIDE_MCS(2);
5303 OVERRIDE_MCS(3);
5304 OVERRIDE_MCS(4);
5305 OVERRIDE_MCS(5);
5306 OVERRIDE_MCS(6);
5307 OVERRIDE_MCS(7);
5308 OVERRIDE_MCS(8);
5309}
5310#endif /* CONFIG_VHT_OVERRIDES */
5311
5312
Hai Shalomfdcde762020-04-02 11:19:20 -07005313#ifdef CONFIG_HE_OVERRIDES
5314void wpa_supplicant_apply_he_overrides(
5315 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
5316 struct wpa_driver_associate_params *params)
5317{
5318 if (!ssid)
5319 return;
5320
5321 params->disable_he = ssid->disable_he;
5322}
5323#endif /* CONFIG_HE_OVERRIDES */
5324
5325
Dmitry Shmidt04949592012-07-19 12:16:46 -07005326static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
5327{
5328#ifdef PCSC_FUNCS
5329 size_t len;
5330
5331 if (!wpa_s->conf->pcsc_reader)
5332 return 0;
5333
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005334 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005335 if (!wpa_s->scard)
5336 return 1;
5337
5338 if (wpa_s->conf->pcsc_pin &&
5339 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
5340 scard_deinit(wpa_s->scard);
5341 wpa_s->scard = NULL;
5342 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
5343 return -1;
5344 }
5345
5346 len = sizeof(wpa_s->imsi) - 1;
5347 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
5348 scard_deinit(wpa_s->scard);
5349 wpa_s->scard = NULL;
5350 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
5351 return -1;
5352 }
5353 wpa_s->imsi[len] = '\0';
5354
5355 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
5356
5357 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
5358 wpa_s->imsi, wpa_s->mnc_len);
5359
5360 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
5361 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5362#endif /* PCSC_FUNCS */
5363
5364 return 0;
5365}
5366
5367
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005368int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
5369{
5370 char *val, *pos;
5371
5372 ext_password_deinit(wpa_s->ext_pw);
5373 wpa_s->ext_pw = NULL;
5374 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
5375
5376 if (!wpa_s->conf->ext_password_backend)
5377 return 0;
5378
5379 val = os_strdup(wpa_s->conf->ext_password_backend);
5380 if (val == NULL)
5381 return -1;
5382 pos = os_strchr(val, ':');
5383 if (pos)
5384 *pos++ = '\0';
5385
5386 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
5387
5388 wpa_s->ext_pw = ext_password_init(val, pos);
5389 os_free(val);
5390 if (wpa_s->ext_pw == NULL) {
5391 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
5392 return -1;
5393 }
5394 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
5395
5396 return 0;
5397}
5398
5399
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005400#ifdef CONFIG_FST
5401
5402static const u8 * wpas_fst_get_bssid_cb(void *ctx)
5403{
5404 struct wpa_supplicant *wpa_s = ctx;
5405
5406 return (is_zero_ether_addr(wpa_s->bssid) ||
5407 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
5408}
5409
5410
5411static void wpas_fst_get_channel_info_cb(void *ctx,
5412 enum hostapd_hw_mode *hw_mode,
5413 u8 *channel)
5414{
5415 struct wpa_supplicant *wpa_s = ctx;
5416
5417 if (wpa_s->current_bss) {
5418 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
5419 channel);
5420 } else if (wpa_s->hw.num_modes) {
5421 *hw_mode = wpa_s->hw.modes[0].mode;
5422 } else {
5423 WPA_ASSERT(0);
5424 *hw_mode = 0;
5425 }
5426}
5427
5428
5429static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
5430{
5431 struct wpa_supplicant *wpa_s = ctx;
5432
5433 *modes = wpa_s->hw.modes;
5434 return wpa_s->hw.num_modes;
5435}
5436
5437
5438static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
5439{
5440 struct wpa_supplicant *wpa_s = ctx;
5441
5442 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
5443 wpa_s->fst_ies = fst_ies;
5444}
5445
5446
5447static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
5448{
5449 struct wpa_supplicant *wpa_s = ctx;
5450
Paul Stewart092955c2017-02-06 09:13:09 -08005451 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
5452 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
5453 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
5454 return -1;
5455 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005456 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08005457 wpa_s->own_addr, wpa_s->bssid,
5458 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005459 0);
5460}
5461
5462
5463static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
5464{
5465 struct wpa_supplicant *wpa_s = ctx;
5466
5467 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5468 return wpa_s->received_mb_ies;
5469}
5470
5471
5472static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
5473 const u8 *buf, size_t size)
5474{
5475 struct wpa_supplicant *wpa_s = ctx;
5476 struct mb_ies_info info;
5477
5478 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
5479
5480 if (!mb_ies_info_by_ies(&info, buf, size)) {
5481 wpabuf_free(wpa_s->received_mb_ies);
5482 wpa_s->received_mb_ies = mb_ies_by_info(&info);
5483 }
5484}
5485
5486
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005487static const u8 * wpas_fst_get_peer_first(void *ctx,
5488 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005489 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005490{
5491 struct wpa_supplicant *wpa_s = ctx;
5492
5493 *get_ctx = NULL;
5494 if (!is_zero_ether_addr(wpa_s->bssid))
5495 return (wpa_s->received_mb_ies || !mb_only) ?
5496 wpa_s->bssid : NULL;
5497 return NULL;
5498}
5499
5500
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07005501static const u8 * wpas_fst_get_peer_next(void *ctx,
5502 struct fst_get_peer_ctx **get_ctx,
Hai Shalome21d4e82020-04-29 16:34:06 -07005503 bool mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005504{
5505 return NULL;
5506}
5507
5508void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
5509 struct fst_wpa_obj *iface_obj)
5510{
5511 iface_obj->ctx = wpa_s;
5512 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
5513 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
5514 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
5515 iface_obj->set_ies = wpas_fst_set_ies_cb;
5516 iface_obj->send_action = wpas_fst_send_action_cb;
5517 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
5518 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
5519 iface_obj->get_peer_first = wpas_fst_get_peer_first;
5520 iface_obj->get_peer_next = wpas_fst_get_peer_next;
5521}
5522#endif /* CONFIG_FST */
5523
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005524static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005525 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005526{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005527 struct wowlan_triggers *triggers;
5528 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005529
5530 if (!wpa_s->conf->wowlan_triggers)
5531 return 0;
5532
Dmitry Shmidt0207e232014-09-03 14:58:37 -07005533 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
5534 if (triggers) {
5535 ret = wpa_drv_wowlan(wpa_s, triggers);
5536 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005537 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005538 return ret;
5539}
5540
5541
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005542enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005543{
5544 if (freq < 3000)
5545 return BAND_2_4_GHZ;
5546 if (freq > 50000)
5547 return BAND_60_GHZ;
5548 return BAND_5_GHZ;
5549}
5550
5551
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005552unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005553{
5554 int i;
5555 unsigned int band = 0;
5556
5557 if (freqs) {
5558 /* freqs are specified for the radio work */
5559 for (i = 0; freqs[i]; i++)
5560 band |= wpas_freq_to_band(freqs[i]);
5561 } else {
5562 /*
5563 * freqs are not specified, implies all
5564 * the supported freqs by HW
5565 */
5566 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5567 if (wpa_s->hw.modes[i].num_channels != 0) {
5568 if (wpa_s->hw.modes[i].mode ==
5569 HOSTAPD_MODE_IEEE80211B ||
5570 wpa_s->hw.modes[i].mode ==
5571 HOSTAPD_MODE_IEEE80211G)
5572 band |= BAND_2_4_GHZ;
5573 else if (wpa_s->hw.modes[i].mode ==
5574 HOSTAPD_MODE_IEEE80211A)
5575 band |= BAND_5_GHZ;
5576 else if (wpa_s->hw.modes[i].mode ==
5577 HOSTAPD_MODE_IEEE80211AD)
5578 band |= BAND_60_GHZ;
5579 else if (wpa_s->hw.modes[i].mode ==
5580 HOSTAPD_MODE_IEEE80211ANY)
5581 band = BAND_2_4_GHZ | BAND_5_GHZ |
5582 BAND_60_GHZ;
5583 }
5584 }
5585 }
5586
5587 return band;
5588}
5589
5590
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005591static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
5592 const char *rn)
5593{
5594 struct wpa_supplicant *iface = wpa_s->global->ifaces;
5595 struct wpa_radio *radio;
5596
5597 while (rn && iface) {
5598 radio = iface->radio;
5599 if (radio && os_strcmp(rn, radio->name) == 0) {
5600 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
5601 wpa_s->ifname, rn);
5602 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5603 return radio;
5604 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08005605
5606 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005607 }
5608
5609 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
5610 wpa_s->ifname, rn ? rn : "N/A");
5611 radio = os_zalloc(sizeof(*radio));
5612 if (radio == NULL)
5613 return NULL;
5614
5615 if (rn)
5616 os_strlcpy(radio->name, rn, sizeof(radio->name));
5617 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005618 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005619 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
5620
5621 return radio;
5622}
5623
5624
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005625static void radio_work_free(struct wpa_radio_work *work)
5626{
5627 if (work->wpa_s->scan_work == work) {
5628 /* This should not really happen. */
5629 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
5630 work->type, work, work->started);
5631 work->wpa_s->scan_work = NULL;
5632 }
5633
5634#ifdef CONFIG_P2P
5635 if (work->wpa_s->p2p_scan_work == work) {
5636 /* This should not really happen. */
5637 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
5638 work->type, work, work->started);
5639 work->wpa_s->p2p_scan_work = NULL;
5640 }
5641#endif /* CONFIG_P2P */
5642
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005643 if (work->started) {
5644 work->wpa_s->radio->num_active_works--;
5645 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005646 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005647 work->type, work,
5648 work->wpa_s->radio->num_active_works);
5649 }
5650
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005651 dl_list_del(&work->list);
5652 os_free(work);
5653}
5654
5655
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005656static int radio_work_is_connect(struct wpa_radio_work *work)
5657{
5658 return os_strcmp(work->type, "sme-connect") == 0 ||
5659 os_strcmp(work->type, "connect") == 0;
5660}
5661
5662
5663static int radio_work_is_scan(struct wpa_radio_work *work)
5664{
5665 return os_strcmp(work->type, "scan") == 0 ||
5666 os_strcmp(work->type, "p2p-scan") == 0;
5667}
5668
5669
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005670static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
5671{
5672 struct wpa_radio_work *active_work = NULL;
5673 struct wpa_radio_work *tmp;
5674
5675 /* Get the active work to know the type and band. */
5676 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5677 if (tmp->started) {
5678 active_work = tmp;
5679 break;
5680 }
5681 }
5682
5683 if (!active_work) {
5684 /* No active work, start one */
5685 radio->num_active_works = 0;
5686 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
5687 list) {
5688 if (os_strcmp(tmp->type, "scan") == 0 &&
5689 radio->external_scan_running &&
5690 (((struct wpa_driver_scan_params *)
5691 tmp->ctx)->only_new_results ||
5692 tmp->wpa_s->clear_driver_scan_cache))
5693 continue;
5694 return tmp;
5695 }
5696 return NULL;
5697 }
5698
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005699 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005700 /*
5701 * If the active work is either connect or sme-connect,
5702 * do not parallelize them with other radio works.
5703 */
5704 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5705 "Do not parallelize radio work with %s",
5706 active_work->type);
5707 return NULL;
5708 }
5709
5710 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
5711 if (tmp->started)
5712 continue;
5713
5714 /*
5715 * If connect or sme-connect are enqueued, parallelize only
5716 * those operations ahead of them in the queue.
5717 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005718 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005719 break;
5720
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005721 /* Serialize parallel scan and p2p_scan operations on the same
5722 * interface since the driver_nl80211 mechanism for tracking
5723 * scan cookies does not yet have support for this. */
5724 if (active_work->wpa_s == tmp->wpa_s &&
5725 radio_work_is_scan(active_work) &&
5726 radio_work_is_scan(tmp)) {
5727 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5728 "Do not start work '%s' when another work '%s' is already scheduled",
5729 tmp->type, active_work->type);
5730 continue;
5731 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005732 /*
5733 * Check that the radio works are distinct and
5734 * on different bands.
5735 */
5736 if (os_strcmp(active_work->type, tmp->type) != 0 &&
5737 (active_work->bands != tmp->bands)) {
5738 /*
5739 * If a scan has to be scheduled through nl80211 scan
5740 * interface and if an external scan is already running,
5741 * do not schedule the scan since it is likely to get
5742 * rejected by kernel.
5743 */
5744 if (os_strcmp(tmp->type, "scan") == 0 &&
5745 radio->external_scan_running &&
5746 (((struct wpa_driver_scan_params *)
5747 tmp->ctx)->only_new_results ||
5748 tmp->wpa_s->clear_driver_scan_cache))
5749 continue;
5750
5751 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5752 "active_work:%s new_work:%s",
5753 active_work->type, tmp->type);
5754 return tmp;
5755 }
5756 }
5757
5758 /* Did not find a radio work to schedule in parallel. */
5759 return NULL;
5760}
5761
5762
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005763static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5764{
5765 struct wpa_radio *radio = eloop_ctx;
5766 struct wpa_radio_work *work;
5767 struct os_reltime now, diff;
5768 struct wpa_supplicant *wpa_s;
5769
5770 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005771 if (work == NULL) {
5772 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005773 return;
5774 }
5775
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005776 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5777 radio_list);
5778
5779 if (!(wpa_s &&
5780 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5781 if (work->started)
5782 return; /* already started and still in progress */
5783
5784 if (wpa_s && wpa_s->radio->external_scan_running) {
5785 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5786 return;
5787 }
5788 } else {
5789 work = NULL;
5790 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5791 /* get the work to schedule next */
5792 work = radio_work_get_next_work(radio);
5793 }
5794 if (!work)
5795 return;
5796 }
5797
5798 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005799 os_get_reltime(&now);
5800 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005801 wpa_dbg(wpa_s, MSG_DEBUG,
5802 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005803 work->type, work, diff.sec, diff.usec);
5804 work->started = 1;
5805 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005806 radio->num_active_works++;
5807
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005808 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005809
5810 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5811 radio->num_active_works < MAX_ACTIVE_WORKS)
5812 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005813}
5814
5815
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005816/*
5817 * This function removes both started and pending radio works running on
5818 * the provided interface's radio.
5819 * Prior to the removal of the radio work, its callback (cb) is called with
5820 * deinit set to be 1. Each work's callback is responsible for clearing its
5821 * internal data and restoring to a correct state.
5822 * @wpa_s: wpa_supplicant data
5823 * @type: type of works to be removed
5824 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5825 * this interface's works.
5826 */
5827void radio_remove_works(struct wpa_supplicant *wpa_s,
5828 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005829{
5830 struct wpa_radio_work *work, *tmp;
5831 struct wpa_radio *radio = wpa_s->radio;
5832
5833 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5834 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005835 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005836 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005837
5838 /* skip other ifaces' works */
5839 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005840 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005841
5842 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5843 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005844 work->cb(work, 1);
5845 radio_work_free(work);
5846 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005847
5848 /* in case we removed the started work */
5849 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005850}
5851
5852
Roshan Pius3a1667e2018-07-03 15:17:14 -07005853void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5854{
5855 struct wpa_radio_work *work;
5856 struct wpa_radio *radio = wpa_s->radio;
5857
5858 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5859 if (work->ctx != ctx)
5860 continue;
5861 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5862 work->type, work, work->started ? " (started)" : "");
5863 radio_work_free(work);
5864 break;
5865 }
5866}
5867
5868
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005869static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5870{
5871 struct wpa_radio *radio = wpa_s->radio;
5872
5873 if (!radio)
5874 return;
5875
5876 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5877 wpa_s->ifname, radio->name);
5878 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005879 radio_remove_works(wpa_s, NULL, 0);
5880 wpa_s->radio = NULL;
5881 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005882 return; /* Interfaces remain for this radio */
5883
5884 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005885 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005886 os_free(radio);
5887}
5888
5889
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005890void radio_work_check_next(struct wpa_supplicant *wpa_s)
5891{
5892 struct wpa_radio *radio = wpa_s->radio;
5893
5894 if (dl_list_empty(&radio->work))
5895 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005896 if (wpa_s->ext_work_in_progress) {
5897 wpa_printf(MSG_DEBUG,
5898 "External radio work in progress - delay start of pending item");
5899 return;
5900 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005901 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5902 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5903}
5904
5905
5906/**
5907 * radio_add_work - Add a radio work item
5908 * @wpa_s: Pointer to wpa_supplicant data
5909 * @freq: Frequency of the offchannel operation in MHz or 0
5910 * @type: Unique identifier for each type of work
5911 * @next: Force as the next work to be executed
5912 * @cb: Callback function for indicating when radio is available
5913 * @ctx: Context pointer for the work (work->ctx in cb())
5914 * Returns: 0 on success, -1 on failure
5915 *
5916 * This function is used to request time for an operation that requires
5917 * exclusive radio control. Once the radio is available, the registered callback
5918 * function will be called. radio_work_done() must be called once the exclusive
5919 * radio operation has been completed, so that the radio is freed for other
5920 * operations. The special case of deinit=1 is used to free the context data
5921 * during interface removal. That does not allow the callback function to start
5922 * the radio operation, i.e., it must free any resources allocated for the radio
5923 * work and return.
5924 *
5925 * The @freq parameter can be used to indicate a single channel on which the
5926 * offchannel operation will occur. This may allow multiple radio work
5927 * operations to be performed in parallel if they apply for the same channel.
5928 * Setting this to 0 indicates that the work item may use multiple channels or
5929 * requires exclusive control of the radio.
5930 */
5931int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5932 const char *type, int next,
5933 void (*cb)(struct wpa_radio_work *work, int deinit),
5934 void *ctx)
5935{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005936 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005937 struct wpa_radio_work *work;
5938 int was_empty;
5939
5940 work = os_zalloc(sizeof(*work));
5941 if (work == NULL)
5942 return -1;
5943 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5944 os_get_reltime(&work->time);
5945 work->freq = freq;
5946 work->type = type;
5947 work->wpa_s = wpa_s;
5948 work->cb = cb;
5949 work->ctx = ctx;
5950
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005951 if (freq)
5952 work->bands = wpas_freq_to_band(freq);
5953 else if (os_strcmp(type, "scan") == 0 ||
5954 os_strcmp(type, "p2p-scan") == 0)
5955 work->bands = wpas_get_bands(wpa_s,
5956 ((struct wpa_driver_scan_params *)
5957 ctx)->freqs);
5958 else
5959 work->bands = wpas_get_bands(wpa_s, NULL);
5960
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005961 was_empty = dl_list_empty(&wpa_s->radio->work);
5962 if (next)
5963 dl_list_add(&wpa_s->radio->work, &work->list);
5964 else
5965 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5966 if (was_empty) {
5967 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5968 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005969 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5970 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5971 wpa_dbg(wpa_s, MSG_DEBUG,
5972 "Try to schedule a radio work (num_active_works=%u)",
5973 radio->num_active_works);
5974 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005975 }
5976
5977 return 0;
5978}
5979
5980
5981/**
5982 * radio_work_done - Indicate that a radio work item has been completed
5983 * @work: Completed work
5984 *
5985 * This function is called once the callback function registered with
5986 * radio_add_work() has completed its work.
5987 */
5988void radio_work_done(struct wpa_radio_work *work)
5989{
5990 struct wpa_supplicant *wpa_s = work->wpa_s;
5991 struct os_reltime now, diff;
5992 unsigned int started = work->started;
5993
5994 os_get_reltime(&now);
5995 os_reltime_sub(&now, &work->time, &diff);
5996 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5997 work->type, work, started ? "done" : "canceled",
5998 diff.sec, diff.usec);
5999 radio_work_free(work);
6000 if (started)
6001 radio_work_check_next(wpa_s);
6002}
6003
6004
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006005struct wpa_radio_work *
6006radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006007{
6008 struct wpa_radio_work *work;
6009 struct wpa_radio *radio = wpa_s->radio;
6010
6011 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
6012 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006013 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006014 }
6015
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08006016 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006017}
6018
6019
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006020static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006021 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006022{
6023 const char *ifname, *driver, *rn;
6024
6025 driver = iface->driver;
6026next_driver:
6027 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
6028 return -1;
6029
6030 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
6031 if (wpa_s->drv_priv == NULL) {
6032 const char *pos;
6033 pos = driver ? os_strchr(driver, ',') : NULL;
6034 if (pos) {
6035 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
6036 "driver interface - try next driver wrapper");
6037 driver = pos + 1;
6038 goto next_driver;
6039 }
6040 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
6041 "interface");
6042 return -1;
6043 }
6044 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
6045 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
6046 "driver_param '%s'", wpa_s->conf->driver_param);
6047 return -1;
6048 }
6049
6050 ifname = wpa_drv_get_ifname(wpa_s);
6051 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
6052 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
6053 "interface name with '%s'", ifname);
6054 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
6055 }
6056
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07006057 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006058 if (rn && rn[0] == '\0')
6059 rn = NULL;
6060
6061 wpa_s->radio = radio_add_interface(wpa_s, rn);
6062 if (wpa_s->radio == NULL)
6063 return -1;
6064
6065 return 0;
6066}
6067
6068
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006069#ifdef CONFIG_GAS_SERVER
6070
6071static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
6072 unsigned int freq, const u8 *dst,
6073 const u8 *src, const u8 *bssid,
6074 const u8 *data, size_t data_len,
6075 enum offchannel_send_action_result result)
6076{
6077 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
6078 " result=%s",
6079 freq, MAC2STR(dst),
6080 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
6081 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
6082 "FAILED"));
6083 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
6084 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
6085}
6086
6087
6088static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
6089 struct wpabuf *buf, unsigned int wait_time)
6090{
6091 struct wpa_supplicant *wpa_s = ctx;
6092 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6093
6094 if (wait_time > wpa_s->max_remain_on_chan)
6095 wait_time = wpa_s->max_remain_on_chan;
6096
6097 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
6098 wpabuf_head(buf), wpabuf_len(buf),
6099 wait_time, wpas_gas_server_tx_status, 0);
6100}
6101
6102#endif /* CONFIG_GAS_SERVER */
6103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006104static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006105 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006106{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006107 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006108 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006109 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006110
6111 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
6112 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
6113 iface->confname ? iface->confname : "N/A",
6114 iface->driver ? iface->driver : "default",
6115 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
6116 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
6117
6118 if (iface->confname) {
6119#ifdef CONFIG_BACKEND_FILE
6120 wpa_s->confname = os_rel2abs_path(iface->confname);
6121 if (wpa_s->confname == NULL) {
6122 wpa_printf(MSG_ERROR, "Failed to get absolute path "
6123 "for configuration file '%s'.",
6124 iface->confname);
6125 return -1;
6126 }
6127 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
6128 iface->confname, wpa_s->confname);
6129#else /* CONFIG_BACKEND_FILE */
6130 wpa_s->confname = os_strdup(iface->confname);
6131#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006132 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006133 if (wpa_s->conf == NULL) {
6134 wpa_printf(MSG_ERROR, "Failed to read or parse "
6135 "configuration '%s'.", wpa_s->confname);
6136 return -1;
6137 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07006138 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006139 if (wpa_s->confanother &&
6140 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
6141 wpa_printf(MSG_ERROR,
6142 "Failed to read or parse configuration '%s'.",
6143 wpa_s->confanother);
6144 return -1;
6145 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006146
6147 /*
6148 * Override ctrl_interface and driver_param if set on command
6149 * line.
6150 */
6151 if (iface->ctrl_interface) {
6152 os_free(wpa_s->conf->ctrl_interface);
6153 wpa_s->conf->ctrl_interface =
6154 os_strdup(iface->ctrl_interface);
6155 }
6156
6157 if (iface->driver_param) {
6158 os_free(wpa_s->conf->driver_param);
6159 wpa_s->conf->driver_param =
6160 os_strdup(iface->driver_param);
6161 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006162
6163 if (iface->p2p_mgmt && !iface->ctrl_interface) {
6164 os_free(wpa_s->conf->ctrl_interface);
6165 wpa_s->conf->ctrl_interface = NULL;
6166 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006167 } else
6168 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
6169 iface->driver_param);
6170
6171 if (wpa_s->conf == NULL) {
6172 wpa_printf(MSG_ERROR, "\nNo configuration found.");
6173 return -1;
6174 }
6175
6176 if (iface->ifname == NULL) {
6177 wpa_printf(MSG_ERROR, "\nInterface name is required.");
6178 return -1;
6179 }
6180 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
6181 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
6182 iface->ifname);
6183 return -1;
6184 }
6185 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
6186
6187 if (iface->bridge_ifname) {
6188 if (os_strlen(iface->bridge_ifname) >=
6189 sizeof(wpa_s->bridge_ifname)) {
6190 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
6191 "name '%s'.", iface->bridge_ifname);
6192 return -1;
6193 }
6194 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
6195 sizeof(wpa_s->bridge_ifname));
6196 }
6197
6198 /* RSNA Supplicant Key Management - INITIALIZE */
Hai Shalome21d4e82020-04-29 16:34:06 -07006199 eapol_sm_notify_portEnabled(wpa_s->eapol, false);
6200 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006201
6202 /* Initialize driver interface and register driver event handler before
6203 * L2 receive handler so that association events are processed before
6204 * EAPOL-Key packets if both become available for the same select()
6205 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006206 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006207 return -1;
6208
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006209 if (wpa_supplicant_init_wpa(wpa_s) < 0)
6210 return -1;
6211
6212 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
6213 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
6214 NULL);
6215 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
6216
6217 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
6218 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
6219 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
6220 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6221 "dot11RSNAConfigPMKLifetime");
6222 return -1;
6223 }
6224
6225 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
6226 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
6227 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
6228 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6229 "dot11RSNAConfigPMKReauthThreshold");
6230 return -1;
6231 }
6232
6233 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
6234 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
6235 wpa_s->conf->dot11RSNAConfigSATimeout)) {
6236 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
6237 "dot11RSNAConfigSATimeout");
6238 return -1;
6239 }
6240
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006241 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
6242 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006243 &wpa_s->hw.flags,
6244 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006245 if (wpa_s->hw.modes) {
6246 u16 i;
6247
6248 for (i = 0; i < wpa_s->hw.num_modes; i++) {
6249 if (wpa_s->hw.modes[i].vht_capab) {
6250 wpa_s->hw_capab = CAPAB_VHT;
6251 break;
6252 }
6253
6254 if (wpa_s->hw.modes[i].ht_capab &
6255 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
6256 wpa_s->hw_capab = CAPAB_HT40;
6257 else if (wpa_s->hw.modes[i].ht_capab &&
6258 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
6259 wpa_s->hw_capab = CAPAB_HT;
6260 }
6261 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006262
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006263 capa_res = wpa_drv_get_capa(wpa_s, &capa);
6264 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006265 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006266 wpa_s->drv_flags = capa.flags;
Hai Shalomb755a2a2020-04-23 21:49:02 -07006267 wpa_s->drv_flags2 = capa.flags2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006268 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006269 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006270 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006271 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006272 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006273 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
6274 wpa_s->max_sched_scan_plan_interval =
6275 capa.max_sched_scan_plan_interval;
6276 wpa_s->max_sched_scan_plan_iterations =
6277 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006278 wpa_s->sched_scan_supported = capa.sched_scan_supported;
6279 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006280 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
6281 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07006282 wpa_s->extended_capa = capa.extended_capa;
6283 wpa_s->extended_capa_mask = capa.extended_capa_mask;
6284 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006285 wpa_s->num_multichan_concurrent =
6286 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006287 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
6288
6289 if (capa.mac_addr_rand_scan_supported)
6290 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
6291 if (wpa_s->sched_scan_supported &&
6292 capa.mac_addr_rand_sched_scan_supported)
6293 wpa_s->mac_addr_rand_supported |=
6294 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Hai Shalom74f70d42019-02-11 14:42:39 -08006295
6296 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
6297 if (wpa_s->extended_capa &&
6298 wpa_s->extended_capa_len >= 3 &&
6299 wpa_s->extended_capa[2] & 0x40)
6300 wpa_s->multi_bss_support = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006301 }
6302 if (wpa_s->max_remain_on_chan == 0)
6303 wpa_s->max_remain_on_chan = 1000;
6304
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006305 /*
6306 * Only take p2p_mgmt parameters when P2P Device is supported.
6307 * Doing it here as it determines whether l2_packet_init() will be done
6308 * during wpa_supplicant_driver_init().
6309 */
6310 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
6311 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006312
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006313 if (wpa_s->num_multichan_concurrent == 0)
6314 wpa_s->num_multichan_concurrent = 1;
6315
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006316 if (wpa_supplicant_driver_init(wpa_s) < 0)
6317 return -1;
6318
6319#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07006320 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006321 return -1;
6322#endif /* CONFIG_TDLS */
6323
6324 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
6325 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
6326 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
6327 return -1;
6328 }
6329
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006330#ifdef CONFIG_FST
6331 if (wpa_s->conf->fst_group_id) {
6332 struct fst_iface_cfg cfg;
6333 struct fst_wpa_obj iface_obj;
6334
6335 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
6336 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
6337 sizeof(cfg.group_id));
6338 cfg.priority = wpa_s->conf->fst_priority;
6339 cfg.llt = wpa_s->conf->fst_llt;
6340
6341 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
6342 &iface_obj, &cfg);
6343 if (!wpa_s->fst) {
6344 wpa_msg(wpa_s, MSG_ERROR,
6345 "FST: Cannot attach iface %s to group %s",
6346 wpa_s->ifname, cfg.group_id);
6347 return -1;
6348 }
6349 }
6350#endif /* CONFIG_FST */
6351
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006352 if (wpas_wps_init(wpa_s))
6353 return -1;
6354
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006355#ifdef CONFIG_GAS_SERVER
6356 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
6357 if (!wpa_s->gas_server) {
6358 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
6359 return -1;
6360 }
6361#endif /* CONFIG_GAS_SERVER */
6362
6363#ifdef CONFIG_DPP
6364 if (wpas_dpp_init(wpa_s) < 0)
6365 return -1;
6366#endif /* CONFIG_DPP */
6367
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006368 if (wpa_supplicant_init_eapol(wpa_s) < 0)
6369 return -1;
6370 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
6371
6372 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
6373 if (wpa_s->ctrl_iface == NULL) {
6374 wpa_printf(MSG_ERROR,
6375 "Failed to initialize control interface '%s'.\n"
6376 "You may have another wpa_supplicant process "
6377 "already running or the file was\n"
6378 "left by an unclean termination of wpa_supplicant "
6379 "in which case you will need\n"
6380 "to manually remove this file before starting "
6381 "wpa_supplicant again.\n",
6382 wpa_s->conf->ctrl_interface);
6383 return -1;
6384 }
6385
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006386 wpa_s->gas = gas_query_init(wpa_s);
6387 if (wpa_s->gas == NULL) {
6388 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
6389 return -1;
6390 }
6391
Roshan Pius3a1667e2018-07-03 15:17:14 -07006392 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
6393 wpa_s->p2p_mgmt) &&
6394 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006395 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
6396 return -1;
6397 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006398
6399 if (wpa_bss_init(wpa_s) < 0)
6400 return -1;
6401
Paul Stewart092955c2017-02-06 09:13:09 -08006402#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6403#ifdef CONFIG_MESH
6404 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
6405#endif /* CONFIG_MESH */
6406#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6407
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006408 /*
6409 * Set Wake-on-WLAN triggers, if configured.
6410 * Note: We don't restore/remove the triggers on shutdown (it doesn't
6411 * have effect anyway when the interface is down).
6412 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006413 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07006414 return -1;
6415
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006416#ifdef CONFIG_EAP_PROXY
6417{
6418 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006419 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
6420 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006421 if (wpa_s->mnc_len > 0) {
6422 wpa_s->imsi[len] = '\0';
6423 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
6424 wpa_s->imsi, wpa_s->mnc_len);
6425 } else {
6426 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
6427 }
6428}
6429#endif /* CONFIG_EAP_PROXY */
6430
Dmitry Shmidt04949592012-07-19 12:16:46 -07006431 if (pcsc_reader_init(wpa_s) < 0)
6432 return -1;
6433
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006434 if (wpas_init_ext_pw(wpa_s) < 0)
6435 return -1;
6436
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006437 wpas_rrm_reset(wpa_s);
6438
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006439 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6440
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006441#ifdef CONFIG_HS20
6442 hs20_init(wpa_s);
6443#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006444#ifdef CONFIG_MBO
Hai Shalomc3565922019-10-28 11:58:20 -07006445 if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006446 if ((wpa_s->conf->oce & OCE_STA) &&
6447 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
6448 wpa_s->enable_oce = OCE_STA;
6449 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
6450 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
6451 /* TODO: Need to add STA-CFON support */
6452 wpa_printf(MSG_ERROR,
6453 "OCE STA-CFON feature is not yet supported");
6454 }
6455 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006456 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
6457#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08006458
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006459 wpa_supplicant_set_default_scan_ies(wpa_s);
6460
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006461 return 0;
6462}
6463
6464
6465static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006466 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006467{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006468 struct wpa_global *global = wpa_s->global;
6469 struct wpa_supplicant *iface, *prev;
6470
6471 if (wpa_s == wpa_s->parent)
6472 wpas_p2p_group_remove(wpa_s, "*");
6473
6474 iface = global->ifaces;
6475 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006476 if (iface->p2pdev == wpa_s)
6477 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006478 if (iface == wpa_s || iface->parent != wpa_s) {
6479 iface = iface->next;
6480 continue;
6481 }
6482 wpa_printf(MSG_DEBUG,
6483 "Remove remaining child interface %s from parent %s",
6484 iface->ifname, wpa_s->ifname);
6485 prev = iface;
6486 iface = iface->next;
6487 wpa_supplicant_remove_iface(global, prev, terminate);
6488 }
6489
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006490 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006491 if (wpa_s->drv_priv) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006492 /* Don't deauthenticate if WoWLAN is enabled */
6493 if (!wpa_drv_get_wowlan(wpa_s)) {
6494 wpa_supplicant_deauthenticate(
6495 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006496
Hai Shalomfdcde762020-04-02 11:19:20 -07006497 wpa_drv_set_countermeasures(wpa_s, 0);
6498 wpa_clear_keys(wpa_s, NULL);
6499 } else {
6500 wpa_msg(wpa_s, MSG_INFO,
6501 "Do not deauthenticate as part of interface deinit since WoWLAN is enabled");
6502 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006503 }
6504
6505 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006506 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006507
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006508 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006509 radio_remove_interface(wpa_s);
6510
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006511#ifdef CONFIG_FST
6512 if (wpa_s->fst) {
6513 fst_detach(wpa_s->fst);
6514 wpa_s->fst = NULL;
6515 }
6516 if (wpa_s->received_mb_ies) {
6517 wpabuf_free(wpa_s->received_mb_ies);
6518 wpa_s->received_mb_ies = NULL;
6519 }
6520#endif /* CONFIG_FST */
6521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006522 if (wpa_s->drv_priv)
6523 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006524
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006525 if (notify)
6526 wpas_notify_iface_removed(wpa_s);
6527
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006528 if (terminate)
6529 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006530
6531 if (wpa_s->ctrl_iface) {
6532 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6533 wpa_s->ctrl_iface = NULL;
6534 }
6535
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006536#ifdef CONFIG_MESH
6537 if (wpa_s->ifmsh) {
6538 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
6539 wpa_s->ifmsh = NULL;
6540 }
6541#endif /* CONFIG_MESH */
6542
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006543 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07006544 wpa_config_free(wpa_s->conf);
6545 wpa_s->conf = NULL;
6546 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006547
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006548 os_free(wpa_s->ssids_from_scan_req);
Hai Shalomc3565922019-10-28 11:58:20 -07006549 os_free(wpa_s->last_scan_freqs);
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07006550
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006551 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006552}
6553
6554
Dmitry Shmidte4663042016-04-04 10:07:49 -07006555#ifdef CONFIG_MATCH_IFACE
6556
6557/**
6558 * wpa_supplicant_match_iface - Match an interface description to a name
6559 * @global: Pointer to global data from wpa_supplicant_init()
6560 * @ifname: Name of the interface to match
6561 * Returns: Pointer to the created interface description or %NULL on failure
6562 */
6563struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
6564 const char *ifname)
6565{
6566 int i;
6567 struct wpa_interface *iface, *miface;
6568
6569 for (i = 0; i < global->params.match_iface_count; i++) {
6570 miface = &global->params.match_ifaces[i];
6571 if (!miface->ifname ||
6572 fnmatch(miface->ifname, ifname, 0) == 0) {
6573 iface = os_zalloc(sizeof(*iface));
6574 if (!iface)
6575 return NULL;
6576 *iface = *miface;
6577 iface->ifname = ifname;
6578 return iface;
6579 }
6580 }
6581
6582 return NULL;
6583}
6584
6585
6586/**
6587 * wpa_supplicant_match_existing - Match existing interfaces
6588 * @global: Pointer to global data from wpa_supplicant_init()
6589 * Returns: 0 on success, -1 on failure
6590 */
6591static int wpa_supplicant_match_existing(struct wpa_global *global)
6592{
6593 struct if_nameindex *ifi, *ifp;
6594 struct wpa_supplicant *wpa_s;
6595 struct wpa_interface *iface;
6596
6597 ifp = if_nameindex();
6598 if (!ifp) {
6599 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
6600 return -1;
6601 }
6602
6603 for (ifi = ifp; ifi->if_name; ifi++) {
6604 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
6605 if (wpa_s)
6606 continue;
6607 iface = wpa_supplicant_match_iface(global, ifi->if_name);
6608 if (iface) {
6609 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
6610 os_free(iface);
6611 if (wpa_s)
6612 wpa_s->matched = 1;
6613 }
6614 }
6615
6616 if_freenameindex(ifp);
6617 return 0;
6618}
6619
6620#endif /* CONFIG_MATCH_IFACE */
6621
6622
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006623/**
6624 * wpa_supplicant_add_iface - Add a new network interface
6625 * @global: Pointer to global data from wpa_supplicant_init()
6626 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006627 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006628 * Returns: Pointer to the created interface or %NULL on failure
6629 *
6630 * This function is used to add new network interfaces for %wpa_supplicant.
6631 * This can be called before wpa_supplicant_run() to add interfaces before the
6632 * main event loop has been started. In addition, new interfaces can be added
6633 * dynamically while %wpa_supplicant is already running. This could happen,
6634 * e.g., when a hotplug network adapter is inserted.
6635 */
6636struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006637 struct wpa_interface *iface,
6638 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006639{
6640 struct wpa_supplicant *wpa_s;
6641 struct wpa_interface t_iface;
6642 struct wpa_ssid *ssid;
6643
6644 if (global == NULL || iface == NULL)
6645 return NULL;
6646
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006647 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006648 if (wpa_s == NULL)
6649 return NULL;
6650
6651 wpa_s->global = global;
6652
6653 t_iface = *iface;
6654 if (global->params.override_driver) {
6655 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
6656 "('%s' -> '%s')",
6657 iface->driver, global->params.override_driver);
6658 t_iface.driver = global->params.override_driver;
6659 }
6660 if (global->params.override_ctrl_interface) {
6661 wpa_printf(MSG_DEBUG, "Override interface parameter: "
6662 "ctrl_interface ('%s' -> '%s')",
6663 iface->ctrl_interface,
6664 global->params.override_ctrl_interface);
6665 t_iface.ctrl_interface =
6666 global->params.override_ctrl_interface;
6667 }
6668 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
6669 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
6670 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006671 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006672 return NULL;
6673 }
6674
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006675 /* Notify the control interfaces about new iface */
6676 if (wpas_notify_iface_added(wpa_s)) {
6677 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
6678 return NULL;
6679 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006680
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08006681 /* Notify the control interfaces about new networks for non p2p mgmt
6682 * ifaces. */
6683 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006684 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
6685 wpas_notify_network_added(wpa_s, ssid);
6686 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006687
6688 wpa_s->next = global->ifaces;
6689 global->ifaces = wpa_s;
6690
6691 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006692 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006693
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006694#ifdef CONFIG_P2P
6695 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006696 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006697 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07006698 wpas_p2p_add_p2pdev_interface(
6699 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006700 wpa_printf(MSG_INFO,
6701 "P2P: Failed to enable P2P Device interface");
6702 /* Try to continue without. P2P will be disabled. */
6703 }
6704#endif /* CONFIG_P2P */
6705
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006706 return wpa_s;
6707}
6708
6709
6710/**
6711 * wpa_supplicant_remove_iface - Remove a network interface
6712 * @global: Pointer to global data from wpa_supplicant_init()
6713 * @wpa_s: Pointer to the network interface to be removed
6714 * Returns: 0 if interface was removed, -1 if interface was not found
6715 *
6716 * This function can be used to dynamically remove network interfaces from
6717 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
6718 * addition, this function is used to remove all remaining interfaces when
6719 * %wpa_supplicant is terminated.
6720 */
6721int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006722 struct wpa_supplicant *wpa_s,
6723 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006724{
6725 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006726#ifdef CONFIG_MESH
6727 unsigned int mesh_if_created = wpa_s->mesh_if_created;
6728 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006729 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006730#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006731
6732 /* Remove interface from the global list of interfaces */
6733 prev = global->ifaces;
6734 if (prev == wpa_s) {
6735 global->ifaces = wpa_s->next;
6736 } else {
6737 while (prev && prev->next != wpa_s)
6738 prev = prev->next;
6739 if (prev == NULL)
6740 return -1;
6741 prev->next = wpa_s->next;
6742 }
6743
6744 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
6745
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006746#ifdef CONFIG_MESH
6747 if (mesh_if_created) {
6748 ifname = os_strdup(wpa_s->ifname);
6749 if (ifname == NULL) {
6750 wpa_dbg(wpa_s, MSG_ERROR,
6751 "mesh: Failed to malloc ifname");
6752 return -1;
6753 }
6754 }
6755#endif /* CONFIG_MESH */
6756
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006757 if (global->p2p_group_formation == wpa_s)
6758 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07006759 if (global->p2p_invite_group == wpa_s)
6760 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006761 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006762
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006763#ifdef CONFIG_MESH
6764 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006765 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006766 os_free(ifname);
6767 }
6768#endif /* CONFIG_MESH */
6769
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006770 return 0;
6771}
6772
6773
6774/**
6775 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6776 * @wpa_s: Pointer to the network interface
6777 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6778 */
6779const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6780{
6781 const char *eapol_method;
6782
6783 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6784 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6785 return "NO-EAP";
6786 }
6787
6788 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6789 if (eapol_method == NULL)
6790 return "UNKNOWN-EAP";
6791
6792 return eapol_method;
6793}
6794
6795
6796/**
6797 * wpa_supplicant_get_iface - Get a new network interface
6798 * @global: Pointer to global data from wpa_supplicant_init()
6799 * @ifname: Interface name
6800 * Returns: Pointer to the interface or %NULL if not found
6801 */
6802struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6803 const char *ifname)
6804{
6805 struct wpa_supplicant *wpa_s;
6806
6807 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6808 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6809 return wpa_s;
6810 }
6811 return NULL;
6812}
6813
6814
6815#ifndef CONFIG_NO_WPA_MSG
6816static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6817{
6818 struct wpa_supplicant *wpa_s = ctx;
6819 if (wpa_s == NULL)
6820 return NULL;
6821 return wpa_s->ifname;
6822}
6823#endif /* CONFIG_NO_WPA_MSG */
6824
6825
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006826#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6827#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6828#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6829
6830/* Periodic cleanup tasks */
6831static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6832{
6833 struct wpa_global *global = eloop_ctx;
6834 struct wpa_supplicant *wpa_s;
6835
6836 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6837 wpas_periodic, global, NULL);
6838
6839#ifdef CONFIG_P2P
6840 if (global->p2p)
6841 p2p_expire_peers(global->p2p);
6842#endif /* CONFIG_P2P */
6843
6844 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6845 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6846#ifdef CONFIG_AP
6847 ap_periodic(wpa_s);
6848#endif /* CONFIG_AP */
6849 }
6850}
6851
6852
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006853/**
6854 * wpa_supplicant_init - Initialize %wpa_supplicant
6855 * @params: Parameters for %wpa_supplicant
6856 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6857 *
6858 * This function is used to initialize %wpa_supplicant. After successful
6859 * initialization, the returned data pointer can be used to add and remove
6860 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6861 */
6862struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6863{
6864 struct wpa_global *global;
6865 int ret, i;
6866
6867 if (params == NULL)
6868 return NULL;
6869
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006870#ifdef CONFIG_DRIVER_NDIS
6871 {
6872 void driver_ndis_init_ops(void);
6873 driver_ndis_init_ops();
6874 }
6875#endif /* CONFIG_DRIVER_NDIS */
6876
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006877#ifndef CONFIG_NO_WPA_MSG
6878 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6879#endif /* CONFIG_NO_WPA_MSG */
6880
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006881 if (params->wpa_debug_file_path)
6882 wpa_debug_open_file(params->wpa_debug_file_path);
Hai Shalomfdcde762020-04-02 11:19:20 -07006883 if (!params->wpa_debug_file_path && !params->wpa_debug_syslog)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006884 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006885 if (params->wpa_debug_syslog)
6886 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006887 if (params->wpa_debug_tracing) {
6888 ret = wpa_debug_open_linux_tracing();
6889 if (ret) {
6890 wpa_printf(MSG_ERROR,
6891 "Failed to enable trace logging");
6892 return NULL;
6893 }
6894 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006895
6896 ret = eap_register_methods();
6897 if (ret) {
6898 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6899 if (ret == -2)
6900 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6901 "the same EAP type.");
6902 return NULL;
6903 }
6904
6905 global = os_zalloc(sizeof(*global));
6906 if (global == NULL)
6907 return NULL;
6908 dl_list_init(&global->p2p_srv_bonjour);
6909 dl_list_init(&global->p2p_srv_upnp);
6910 global->params.daemonize = params->daemonize;
6911 global->params.wait_for_monitor = params->wait_for_monitor;
6912 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6913 if (params->pid_file)
6914 global->params.pid_file = os_strdup(params->pid_file);
6915 if (params->ctrl_interface)
6916 global->params.ctrl_interface =
6917 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006918 if (params->ctrl_interface_group)
6919 global->params.ctrl_interface_group =
6920 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006921 if (params->override_driver)
6922 global->params.override_driver =
6923 os_strdup(params->override_driver);
6924 if (params->override_ctrl_interface)
6925 global->params.override_ctrl_interface =
6926 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006927#ifdef CONFIG_MATCH_IFACE
6928 global->params.match_iface_count = params->match_iface_count;
6929 if (params->match_iface_count) {
6930 global->params.match_ifaces =
6931 os_calloc(params->match_iface_count,
6932 sizeof(struct wpa_interface));
6933 os_memcpy(global->params.match_ifaces,
6934 params->match_ifaces,
6935 params->match_iface_count *
6936 sizeof(struct wpa_interface));
6937 }
6938#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006939#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006940 if (params->conf_p2p_dev)
6941 global->params.conf_p2p_dev =
6942 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006943#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006944 wpa_debug_level = global->params.wpa_debug_level =
6945 params->wpa_debug_level;
6946 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6947 params->wpa_debug_show_keys;
6948 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6949 params->wpa_debug_timestamp;
6950
Hai Shalomfdcde762020-04-02 11:19:20 -07006951 wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006952
6953 if (eloop_init()) {
6954 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6955 wpa_supplicant_deinit(global);
6956 return NULL;
6957 }
6958
Jouni Malinen75ecf522011-06-27 15:19:46 -07006959 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006960
6961 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6962 if (global->ctrl_iface == NULL) {
6963 wpa_supplicant_deinit(global);
6964 return NULL;
6965 }
6966
6967 if (wpas_notify_supplicant_initialized(global)) {
6968 wpa_supplicant_deinit(global);
6969 return NULL;
6970 }
6971
6972 for (i = 0; wpa_drivers[i]; i++)
6973 global->drv_count++;
6974 if (global->drv_count == 0) {
6975 wpa_printf(MSG_ERROR, "No drivers enabled");
6976 wpa_supplicant_deinit(global);
6977 return NULL;
6978 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006979 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006980 if (global->drv_priv == NULL) {
6981 wpa_supplicant_deinit(global);
6982 return NULL;
6983 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006984
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006985#ifdef CONFIG_WIFI_DISPLAY
6986 if (wifi_display_init(global) < 0) {
6987 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6988 wpa_supplicant_deinit(global);
6989 return NULL;
6990 }
6991#endif /* CONFIG_WIFI_DISPLAY */
6992
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006993 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6994 wpas_periodic, global, NULL);
6995
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006996 return global;
6997}
6998
6999
7000/**
7001 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
7002 * @global: Pointer to global data from wpa_supplicant_init()
7003 * Returns: 0 after successful event loop run, -1 on failure
7004 *
7005 * This function starts the main event loop and continues running as long as
7006 * there are any remaining events. In most cases, this function is running as
7007 * long as the %wpa_supplicant process in still in use.
7008 */
7009int wpa_supplicant_run(struct wpa_global *global)
7010{
7011 struct wpa_supplicant *wpa_s;
7012
7013 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08007014 (wpa_supplicant_daemon(global->params.pid_file) ||
7015 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007016 return -1;
7017
Dmitry Shmidte4663042016-04-04 10:07:49 -07007018#ifdef CONFIG_MATCH_IFACE
7019 if (wpa_supplicant_match_existing(global))
7020 return -1;
7021#endif
7022
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007023 if (global->params.wait_for_monitor) {
7024 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08007025 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007026 wpa_supplicant_ctrl_iface_wait(
7027 wpa_s->ctrl_iface);
7028 }
7029
7030 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
7031 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
7032
7033 eloop_run();
7034
7035 return 0;
7036}
7037
7038
7039/**
7040 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
7041 * @global: Pointer to global data from wpa_supplicant_init()
7042 *
7043 * This function is called to deinitialize %wpa_supplicant and to free all
7044 * allocated resources. Remaining network interfaces will also be removed.
7045 */
7046void wpa_supplicant_deinit(struct wpa_global *global)
7047{
7048 int i;
7049
7050 if (global == NULL)
7051 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007052
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007053 eloop_cancel_timeout(wpas_periodic, global, NULL);
7054
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007055#ifdef CONFIG_WIFI_DISPLAY
7056 wifi_display_deinit(global);
7057#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007058
7059 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07007060 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007061
7062 if (global->ctrl_iface)
7063 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
7064
7065 wpas_notify_supplicant_deinitialized(global);
7066
7067 eap_peer_unregister_methods();
7068#ifdef CONFIG_AP
7069 eap_server_unregister_methods();
7070#endif /* CONFIG_AP */
7071
7072 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
7073 if (!global->drv_priv[i])
7074 continue;
7075 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
7076 }
7077 os_free(global->drv_priv);
7078
7079 random_deinit();
7080
7081 eloop_destroy();
7082
7083 if (global->params.pid_file) {
7084 os_daemonize_terminate(global->params.pid_file);
7085 os_free(global->params.pid_file);
7086 }
7087 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07007088 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007089 os_free(global->params.override_driver);
7090 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07007091#ifdef CONFIG_MATCH_IFACE
7092 os_free(global->params.match_ifaces);
7093#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007094#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07007095 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007096#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007097
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07007098 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007099 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007100 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007101
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007102 os_free(global);
7103 wpa_debug_close_syslog();
7104 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07007105 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007106}
7107
7108
7109void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
7110{
7111 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
7112 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
7113 char country[3];
7114 country[0] = wpa_s->conf->country[0];
7115 country[1] = wpa_s->conf->country[1];
7116 country[2] = '\0';
7117 if (wpa_drv_set_country(wpa_s, country) < 0) {
7118 wpa_printf(MSG_ERROR, "Failed to set country code "
7119 "'%s'", country);
7120 }
7121 }
7122
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007123 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
7124 wpas_init_ext_pw(wpa_s);
7125
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007126 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
7127 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
7128
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007129 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
7130 struct wpa_driver_capa capa;
7131 int res = wpa_drv_get_capa(wpa_s, &capa);
7132
7133 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
7134 wpa_printf(MSG_ERROR,
7135 "Failed to update wowlan_triggers to '%s'",
7136 wpa_s->conf->wowlan_triggers);
7137 }
7138
Hai Shalom81f62d82019-07-22 12:10:00 -07007139 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM)
7140 wpa_supplicant_set_default_scan_ies(wpa_s);
7141
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007142#ifdef CONFIG_WPS
7143 wpas_wps_update_config(wpa_s);
7144#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007145 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007146 wpa_s->conf->changed_parameters = 0;
7147}
7148
7149
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007150void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007151{
7152 int i;
7153
7154 for (i = 0; i < *num_freqs; i++) {
7155 if (freqs[i] == freq)
7156 return;
7157 }
7158
7159 freqs[*num_freqs] = freq;
7160 (*num_freqs)++;
7161}
7162
7163
7164static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
7165{
7166 struct wpa_bss *bss, *cbss;
7167 const int max_freqs = 10;
7168 int *freqs;
7169 int num_freqs = 0;
7170
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007171 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007172 if (freqs == NULL)
7173 return NULL;
7174
7175 cbss = wpa_s->current_bss;
7176
7177 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
7178 if (bss == cbss)
7179 continue;
7180 if (bss->ssid_len == cbss->ssid_len &&
7181 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
7182 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
7183 add_freq(freqs, &num_freqs, bss->freq);
7184 if (num_freqs == max_freqs)
7185 break;
7186 }
7187 }
7188
7189 if (num_freqs == 0) {
7190 os_free(freqs);
7191 freqs = NULL;
7192 }
7193
7194 return freqs;
7195}
7196
7197
7198void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7199{
7200 int timeout;
7201 int count;
7202 int *freqs = NULL;
7203
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007204 wpas_connect_work_done(wpa_s);
7205
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007206 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007207 * Remove possible authentication timeout since the connection failed.
7208 */
7209 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
7210
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007211 /*
7212 * There is no point in blacklisting the AP if this event is
7213 * generated based on local request to disconnect.
7214 */
Hai Shalomfdcde762020-04-02 11:19:20 -07007215 if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007216 wpa_s->own_disconnect_req = 0;
7217 wpa_dbg(wpa_s, MSG_DEBUG,
7218 "Ignore connection failure due to local request to disconnect");
7219 return;
7220 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007221 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007222 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7223 "indication since interface has been put into "
7224 "disconnected state");
7225 return;
7226 }
Roshan Piusb1ae0fe2019-02-15 08:05:38 -08007227 if (wpa_s->auto_reconnect_disabled) {
7228 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
7229 "indication since auto connect is disabled");
7230 return;
7231 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007232
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007233 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007234 * Add the failed BSSID into the blacklist and speed up next scan
7235 * attempt if there could be other APs that could accept association.
7236 * The current blacklist count indicates how many times we have tried
7237 * connecting to this AP and multiple attempts mean that other APs are
7238 * either not available or has already been tried, so that we can start
7239 * increasing the delay here to avoid constant scanning.
7240 */
7241 count = wpa_blacklist_add(wpa_s, bssid);
7242 if (count == 1 && wpa_s->current_bss) {
7243 /*
7244 * This BSS was not in the blacklist before. If there is
7245 * another BSS available for the same ESS, we should try that
7246 * next. Otherwise, we may as well try this one once more
7247 * before allowing other, likely worse, ESSes to be considered.
7248 */
7249 freqs = get_bss_freqs_in_ess(wpa_s);
7250 if (freqs) {
7251 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
7252 "has been seen; try it next");
7253 wpa_blacklist_add(wpa_s, bssid);
7254 /*
7255 * On the next scan, go through only the known channels
7256 * used in this ESS based on previous scans to speed up
7257 * common load balancing use case.
7258 */
7259 os_free(wpa_s->next_scan_freqs);
7260 wpa_s->next_scan_freqs = freqs;
7261 }
7262 }
7263
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007264 /*
7265 * Add previous failure count in case the temporary blacklist was
7266 * cleared due to no other BSSes being available.
7267 */
7268 count += wpa_s->extra_blacklist_count;
7269
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007270 if (count > 3 && wpa_s->current_ssid) {
7271 wpa_printf(MSG_DEBUG, "Continuous association failures - "
7272 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007273 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07007274 }
7275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007276 switch (count) {
7277 case 1:
7278 timeout = 100;
7279 break;
7280 case 2:
7281 timeout = 500;
7282 break;
7283 case 3:
7284 timeout = 1000;
7285 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007286 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007287 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007288 break;
7289 default:
7290 timeout = 10000;
7291 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007292 }
7293
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007294 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
7295 "ms", count, timeout);
7296
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007297 /*
7298 * TODO: if more than one possible AP is available in scan results,
7299 * could try the other ones before requesting a new scan.
7300 */
Hai Shalom021b0b52019-04-10 11:17:58 -07007301
7302 /* speed up the connection attempt with normal scan */
7303 wpa_s->normal_scans = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007304 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
7305 1000 * (timeout % 1000));
7306}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007307
7308
Hai Shalomce48b4a2018-09-05 11:41:35 -07007309#ifdef CONFIG_FILS
7310void fils_connection_failure(struct wpa_supplicant *wpa_s)
7311{
7312 struct wpa_ssid *ssid = wpa_s->current_ssid;
7313 const u8 *realm, *username, *rrk;
7314 size_t realm_len, username_len, rrk_len;
7315 u16 next_seq_num;
7316
7317 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
7318 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
7319 &username, &username_len,
7320 &realm, &realm_len, &next_seq_num,
7321 &rrk, &rrk_len) != 0 ||
7322 !realm)
7323 return;
7324
7325 wpa_hexdump_ascii(MSG_DEBUG,
7326 "FILS: Store last connection failure realm",
7327 realm, realm_len);
7328 os_free(wpa_s->last_con_fail_realm);
7329 wpa_s->last_con_fail_realm = os_malloc(realm_len);
7330 if (wpa_s->last_con_fail_realm) {
7331 wpa_s->last_con_fail_realm_len = realm_len;
7332 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
7333 }
7334}
7335#endif /* CONFIG_FILS */
7336
7337
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007338int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
7339{
7340 return wpa_s->conf->ap_scan == 2 ||
7341 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
7342}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007343
Dmitry Shmidt04949592012-07-19 12:16:46 -07007344
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007345#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007346int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7347 struct wpa_ssid *ssid,
7348 const char *field,
7349 const char *value)
7350{
7351#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007352 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007353
7354 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
7355 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
7356 (const u8 *) value, os_strlen(value));
7357
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007358 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07007359 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007360#else /* IEEE8021X_EAPOL */
7361 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7362 return -1;
7363#endif /* IEEE8021X_EAPOL */
7364}
7365
7366int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
7367 struct wpa_ssid *ssid,
7368 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07007369 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007370{
7371#ifdef IEEE8021X_EAPOL
7372 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08007373 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007374
7375 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007376 case WPA_CTRL_REQ_EAP_IDENTITY:
7377 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08007378 os_free(eap->imsi_identity);
7379 if (value == NULL)
7380 return -1;
7381 identity = os_strchr(value, ':');
7382 if (identity == NULL) {
7383 /* plain identity */
7384 eap->identity = (u8 *)os_strdup(value);
7385 eap->identity_len = os_strlen(value);
7386 } else {
7387 /* have both plain identity and encrypted identity */
7388 imsi_identity = value;
7389 *identity++ = '\0';
7390 /* plain identity */
7391 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
7392 eap->imsi_identity_len = strlen(imsi_identity);
7393 /* encrypted identity */
7394 eap->identity = (u8 *)dup_binstr(identity,
7395 value_len - strlen(imsi_identity) - 1);
7396 eap->identity_len = value_len - strlen(imsi_identity) - 1;
7397 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007398 eap->pending_req_identity = 0;
7399 if (ssid == wpa_s->current_ssid)
7400 wpa_s->reassociate = 1;
7401 break;
7402 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007403 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007404 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007405 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007406 eap->pending_req_password = 0;
7407 if (ssid == wpa_s->current_ssid)
7408 wpa_s->reassociate = 1;
7409 break;
7410 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007411 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007412 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007413 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007414 eap->pending_req_new_password = 0;
7415 if (ssid == wpa_s->current_ssid)
7416 wpa_s->reassociate = 1;
7417 break;
7418 case WPA_CTRL_REQ_EAP_PIN:
Hai Shalomc3565922019-10-28 11:58:20 -07007419 str_clear_free(eap->cert.pin);
7420 eap->cert.pin = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007421 eap->pending_req_pin = 0;
7422 if (ssid == wpa_s->current_ssid)
7423 wpa_s->reassociate = 1;
7424 break;
7425 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007426 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007427 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07007428 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007429 os_free(eap->pending_req_otp);
7430 eap->pending_req_otp = NULL;
7431 eap->pending_req_otp_len = 0;
7432 break;
7433 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Hai Shalomc3565922019-10-28 11:58:20 -07007434 str_clear_free(eap->cert.private_key_passwd);
7435 eap->cert.private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007436 eap->pending_req_passphrase = 0;
7437 if (ssid == wpa_s->current_ssid)
7438 wpa_s->reassociate = 1;
7439 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007440 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07007441 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07007442 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007443 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007444 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007445 case WPA_CTRL_REQ_PSK_PASSPHRASE:
7446 if (wpa_config_set(ssid, "psk", value, 0) < 0)
7447 return -1;
7448 ssid->mem_only_psk = 1;
7449 if (ssid->passphrase)
7450 wpa_config_update_psk(ssid);
7451 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
7452 wpa_supplicant_req_scan(wpa_s, 0, 0);
7453 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007454 case WPA_CTRL_REQ_EXT_CERT_CHECK:
7455 if (eap->pending_ext_cert_check != PENDING_CHECK)
7456 return -1;
7457 if (os_strcmp(value, "good") == 0)
7458 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
7459 else if (os_strcmp(value, "bad") == 0)
7460 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
7461 else
7462 return -1;
7463 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007464 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07007465 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007466 return -1;
7467 }
7468
7469 return 0;
7470#else /* IEEE8021X_EAPOL */
7471 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
7472 return -1;
7473#endif /* IEEE8021X_EAPOL */
7474}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07007475#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007476
7477
7478int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7479{
Hai Shalomfdcde762020-04-02 11:19:20 -07007480#ifdef CONFIG_WEP
Dmitry Shmidt04949592012-07-19 12:16:46 -07007481 int i;
7482 unsigned int drv_enc;
Hai Shalomfdcde762020-04-02 11:19:20 -07007483#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007484
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007485 if (wpa_s->p2p_mgmt)
7486 return 1; /* no normal network profiles on p2p_mgmt interface */
7487
Dmitry Shmidt04949592012-07-19 12:16:46 -07007488 if (ssid == NULL)
7489 return 1;
7490
7491 if (ssid->disabled)
7492 return 1;
7493
Hai Shalomfdcde762020-04-02 11:19:20 -07007494#ifdef CONFIG_WEP
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08007495 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007496 drv_enc = wpa_s->drv_enc;
7497 else
7498 drv_enc = (unsigned int) -1;
7499
7500 for (i = 0; i < NUM_WEP_KEYS; i++) {
7501 size_t len = ssid->wep_key_len[i];
7502 if (len == 0)
7503 continue;
7504 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
7505 continue;
7506 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
7507 continue;
7508 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
7509 continue;
7510 return 1; /* invalid WEP key */
7511 }
Hai Shalomfdcde762020-04-02 11:19:20 -07007512#endif /* CONFIG_WEP */
Dmitry Shmidt04949592012-07-19 12:16:46 -07007513
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007514 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007515 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007516 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007517 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007518 return 1;
7519
Dmitry Shmidt04949592012-07-19 12:16:46 -07007520 return 0;
7521}
7522
7523
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007524int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
7525{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007526 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
7527 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
7528 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
7529 /*
7530 * Driver does not support BIP -- ignore pmf=1 default
7531 * since the connection with PMF would fail and the
7532 * configuration does not require PMF to be enabled.
7533 */
7534 return NO_MGMT_FRAME_PROTECTION;
7535 }
7536
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007537 if (ssid &&
7538 (ssid->key_mgmt &
7539 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
7540 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
7541 /*
7542 * Do not use the default PMF value for non-RSN networks
7543 * since PMF is available only with RSN and pmf=2
7544 * configuration would otherwise prevent connections to
7545 * all open networks.
7546 */
7547 return NO_MGMT_FRAME_PROTECTION;
7548 }
7549
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007550 return wpa_s->conf->pmf;
7551 }
7552
7553 return ssid->ieee80211w;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007554}
7555
7556
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007557int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007558{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007559 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007560 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07007561 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007562 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07007563 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007564}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007565
7566
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007567void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007568{
7569 struct wpa_ssid *ssid = wpa_s->current_ssid;
7570 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007571 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007572
7573 if (ssid == NULL) {
7574 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
7575 "SSID block");
7576 return;
7577 }
7578
7579 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
7580 return;
7581
7582 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07007583
7584#ifdef CONFIG_P2P
7585 if (ssid->p2p_group &&
7586 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
7587 /*
7588 * Skip the wait time since there is a short timeout on the
7589 * connection to a P2P group.
7590 */
7591 return;
7592 }
7593#endif /* CONFIG_P2P */
7594
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007595 if (ssid->auth_failures > 50)
7596 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007597 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007598 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007599 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007600 dur = 90;
7601 else if (ssid->auth_failures > 3)
7602 dur = 60;
7603 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007604 dur = 30;
7605 else if (ssid->auth_failures > 1)
7606 dur = 20;
7607 else
7608 dur = 10;
7609
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08007610 if (ssid->auth_failures > 1 &&
7611 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
7612 dur += os_random() % (ssid->auth_failures * 10);
7613
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007614 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007615 if (now.sec + dur <= ssid->disabled_until.sec)
7616 return;
7617
7618 ssid->disabled_until.sec = now.sec + dur;
7619
7620 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007621 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007622 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007623 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007624}
7625
7626
7627void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
7628 struct wpa_ssid *ssid, int clear_failures)
7629{
7630 if (ssid == NULL)
7631 return;
7632
7633 if (ssid->disabled_until.sec) {
7634 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
7635 "id=%d ssid=\"%s\"",
7636 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
7637 }
7638 ssid->disabled_until.sec = 0;
7639 ssid->disabled_until.usec = 0;
7640 if (clear_failures)
7641 ssid->auth_failures = 0;
7642}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007643
7644
7645int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
7646{
7647 size_t i;
7648
7649 if (wpa_s->disallow_aps_bssid == NULL)
7650 return 0;
7651
7652 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
7653 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
7654 bssid, ETH_ALEN) == 0)
7655 return 1;
7656 }
7657
7658 return 0;
7659}
7660
7661
7662int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
7663 size_t ssid_len)
7664{
7665 size_t i;
7666
7667 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
7668 return 0;
7669
7670 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
7671 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
7672 if (ssid_len == s->ssid_len &&
7673 os_memcmp(ssid, s->ssid, ssid_len) == 0)
7674 return 1;
7675 }
7676
7677 return 0;
7678}
7679
7680
7681/**
7682 * wpas_request_connection - Request a new connection
7683 * @wpa_s: Pointer to the network interface
7684 *
7685 * This function is used to request a new connection to be found. It will mark
7686 * the interface to allow reassociation and request a new scan to find a
7687 * suitable network to connect to.
7688 */
7689void wpas_request_connection(struct wpa_supplicant *wpa_s)
7690{
7691 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007692 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007693 wpa_supplicant_reinit_autoscan(wpa_s);
7694 wpa_s->extra_blacklist_count = 0;
7695 wpa_s->disconnected = 0;
7696 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007697 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007698
7699 if (wpa_supplicant_fast_associate(wpa_s) != 1)
7700 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007701 else
7702 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007703}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007704
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007705
Roshan Pius02242d72016-08-09 15:31:48 -07007706/**
7707 * wpas_request_disconnection - Request disconnection
7708 * @wpa_s: Pointer to the network interface
7709 *
7710 * This function is used to request disconnection from the currently connected
7711 * network. This will stop any ongoing scans and initiate deauthentication.
7712 */
7713void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
7714{
7715#ifdef CONFIG_SME
7716 wpa_s->sme.prev_bssid_set = 0;
7717#endif /* CONFIG_SME */
7718 wpa_s->reassociate = 0;
7719 wpa_s->disconnected = 1;
7720 wpa_supplicant_cancel_sched_scan(wpa_s);
7721 wpa_supplicant_cancel_scan(wpa_s);
7722 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
7723 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07007724 radio_remove_works(wpa_s, "connect", 0);
7725 radio_remove_works(wpa_s, "sme-connect", 0);
Roshan Pius02242d72016-08-09 15:31:48 -07007726}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007727
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07007728
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007729void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
7730 struct wpa_used_freq_data *freqs_data,
7731 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007732{
7733 unsigned int i;
7734
7735 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
7736 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007737 for (i = 0; i < len; i++) {
7738 struct wpa_used_freq_data *cur = &freqs_data[i];
7739 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
7740 i, cur->freq, cur->flags);
7741 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007742}
7743
7744
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007745/*
7746 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007747 * are using the same radio as the current interface, and in addition, get
7748 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007749 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007750int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
7751 struct wpa_used_freq_data *freqs_data,
7752 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007753{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007754 struct wpa_supplicant *ifs;
7755 u8 bssid[ETH_ALEN];
7756 int freq;
7757 unsigned int idx = 0, i;
7758
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007759 wpa_dbg(wpa_s, MSG_DEBUG,
7760 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007761 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007762
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08007763 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7764 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007765 if (idx == len)
7766 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007767
7768 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
7769 continue;
7770
7771 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007772 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7773 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007774 freq = ifs->current_ssid->frequency;
7775 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7776 freq = ifs->assoc_freq;
7777 else
7778 continue;
7779
7780 /* Hold only distinct freqs */
7781 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007782 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007783 break;
7784
7785 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007786 freqs_data[idx++].freq = freq;
7787
7788 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007789 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007790 WPA_FREQ_USED_BY_P2P_CLIENT :
7791 WPA_FREQ_USED_BY_INFRA_STATION;
7792 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007793 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007794
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007795 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007796 return idx;
7797}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007798
7799
7800/*
7801 * Find the operating frequencies of any of the virtual interfaces that
7802 * are using the same radio as the current interface.
7803 */
7804int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7805 int *freq_array, unsigned int len)
7806{
7807 struct wpa_used_freq_data *freqs_data;
7808 int num, i;
7809
7810 os_memset(freq_array, 0, sizeof(int) * len);
7811
7812 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7813 if (!freqs_data)
7814 return -1;
7815
7816 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7817 for (i = 0; i < num; i++)
7818 freq_array[i] = freqs_data[i].freq;
7819
7820 os_free(freqs_data);
7821
7822 return num;
7823}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007824
7825
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007826struct wpa_supplicant *
7827wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7828{
7829 switch (frame) {
7830#ifdef CONFIG_P2P
7831 case VENDOR_ELEM_PROBE_REQ_P2P:
7832 case VENDOR_ELEM_PROBE_RESP_P2P:
7833 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7834 case VENDOR_ELEM_BEACON_P2P_GO:
7835 case VENDOR_ELEM_P2P_PD_REQ:
7836 case VENDOR_ELEM_P2P_PD_RESP:
7837 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7838 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7839 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7840 case VENDOR_ELEM_P2P_INV_REQ:
7841 case VENDOR_ELEM_P2P_INV_RESP:
7842 case VENDOR_ELEM_P2P_ASSOC_REQ:
7843 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007844 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007845#endif /* CONFIG_P2P */
7846 default:
7847 return wpa_s;
7848 }
7849}
7850
7851
7852void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7853{
7854 unsigned int i;
7855 char buf[30];
7856
7857 wpa_printf(MSG_DEBUG, "Update vendor elements");
7858
7859 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7860 if (wpa_s->vendor_elem[i]) {
7861 int res;
7862
7863 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7864 if (!os_snprintf_error(sizeof(buf), res)) {
7865 wpa_hexdump_buf(MSG_DEBUG, buf,
7866 wpa_s->vendor_elem[i]);
7867 }
7868 }
7869 }
7870
7871#ifdef CONFIG_P2P
7872 if (wpa_s->parent == wpa_s &&
7873 wpa_s->global->p2p &&
7874 !wpa_s->global->p2p_disabled)
7875 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7876#endif /* CONFIG_P2P */
7877}
7878
7879
7880int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7881 const u8 *elem, size_t len)
7882{
7883 u8 *ie, *end;
7884
7885 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7886 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7887
7888 for (; ie + 1 < end; ie += 2 + ie[1]) {
7889 if (ie + len > end)
7890 break;
7891 if (os_memcmp(ie, elem, len) != 0)
7892 continue;
7893
7894 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7895 wpabuf_free(wpa_s->vendor_elem[frame]);
7896 wpa_s->vendor_elem[frame] = NULL;
7897 } else {
7898 os_memmove(ie, ie + len, end - (ie + len));
7899 wpa_s->vendor_elem[frame]->used -= len;
7900 }
7901 wpas_vendor_elem_update(wpa_s);
7902 return 0;
7903 }
7904
7905 return -1;
7906}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007907
7908
7909struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07007910 u16 num_modes, enum hostapd_hw_mode mode,
7911 int is_6ghz)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007912{
7913 u16 i;
7914
7915 for (i = 0; i < num_modes; i++) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007916 if (modes[i].mode != mode ||
7917 !modes[i].num_channels || !modes[i].channels)
7918 continue;
7919 if ((!is_6ghz && !is_6ghz_freq(modes[i].channels[0].freq)) ||
7920 (is_6ghz && is_6ghz_freq(modes[i].channels[0].freq)))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007921 return &modes[i];
7922 }
7923
7924 return NULL;
7925}
7926
7927
7928static struct
7929wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7930 const u8 *bssid)
7931{
7932 struct wpa_bss_tmp_disallowed *bss;
7933
7934 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7935 struct wpa_bss_tmp_disallowed, list) {
7936 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7937 return bss;
7938 }
7939
7940 return NULL;
7941}
7942
7943
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007944static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7945{
7946 struct wpa_bss_tmp_disallowed *tmp;
7947 unsigned int num_bssid = 0;
7948 u8 *bssids;
7949 int ret;
7950
7951 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7952 if (!bssids)
7953 return -1;
7954 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7955 struct wpa_bss_tmp_disallowed, list) {
7956 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7957 ETH_ALEN);
7958 num_bssid++;
7959 }
7960 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7961 os_free(bssids);
7962 return ret;
7963}
7964
7965
7966static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7967{
7968 struct wpa_supplicant *wpa_s = eloop_ctx;
7969 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7970
7971 /* Make sure the bss is not already freed */
7972 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7973 struct wpa_bss_tmp_disallowed, list) {
7974 if (bss == tmp) {
7975 dl_list_del(&tmp->list);
7976 os_free(tmp);
7977 wpa_set_driver_tmp_disallow_list(wpa_s);
7978 break;
7979 }
7980 }
7981}
7982
7983
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007984void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08007985 unsigned int sec, int rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007986{
7987 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007988
7989 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7990 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007991 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Hai Shalom74f70d42019-02-11 14:42:39 -08007992 goto finish;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007993 }
7994
7995 bss = os_malloc(sizeof(*bss));
7996 if (!bss) {
7997 wpa_printf(MSG_DEBUG,
7998 "Failed to allocate memory for temp disallow BSS");
7999 return;
8000 }
8001
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008002 os_memcpy(bss->bssid, bssid, ETH_ALEN);
8003 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008004 wpa_set_driver_tmp_disallow_list(wpa_s);
Hai Shalom74f70d42019-02-11 14:42:39 -08008005
8006finish:
8007 bss->rssi_threshold = rssi_threshold;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008008 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
8009 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008010}
8011
8012
Hai Shalom74f70d42019-02-11 14:42:39 -08008013int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s,
8014 struct wpa_bss *bss)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008015{
Hai Shalom74f70d42019-02-11 14:42:39 -08008016 struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008017
8018 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
8019 struct wpa_bss_tmp_disallowed, list) {
Hai Shalom74f70d42019-02-11 14:42:39 -08008020 if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) {
8021 disallowed = tmp;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008022 break;
8023 }
8024 }
Hai Shalom74f70d42019-02-11 14:42:39 -08008025 if (!disallowed)
8026 return 0;
8027
8028 if (disallowed->rssi_threshold != 0 &&
8029 bss->level > disallowed->rssi_threshold)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008030 return 0;
8031
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08008032 return 1;
8033}
Hai Shalom81f62d82019-07-22 12:10:00 -07008034
8035
8036int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8037 unsigned int type, const u8 *addr,
8038 const u8 *mask)
8039{
8040 if ((addr && !mask) || (!addr && mask)) {
8041 wpa_printf(MSG_INFO,
8042 "MAC_ADDR_RAND_SCAN invalid addr/mask combination");
8043 return -1;
8044 }
8045
8046 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) {
8047 wpa_printf(MSG_INFO,
8048 "MAC_ADDR_RAND_SCAN cannot allow multicast address");
8049 return -1;
8050 }
8051
8052 if (type & MAC_ADDR_RAND_SCAN) {
8053 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN,
8054 addr, mask))
8055 return -1;
8056 }
8057
8058 if (type & MAC_ADDR_RAND_SCHED_SCAN) {
8059 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
8060 addr, mask))
8061 return -1;
8062
8063 if (wpa_s->sched_scanning && !wpa_s->pno)
8064 wpas_scan_restart_sched_scan(wpa_s);
8065 }
8066
8067 if (type & MAC_ADDR_RAND_PNO) {
8068 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO,
8069 addr, mask))
8070 return -1;
8071
8072 if (wpa_s->pno) {
8073 wpas_stop_pno(wpa_s);
8074 wpas_start_pno(wpa_s);
8075 }
8076 }
8077
8078 return 0;
8079}
8080
8081
8082int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
8083 unsigned int type)
8084{
8085 wpas_mac_addr_rand_scan_clear(wpa_s, type);
8086 if (wpa_s->pno) {
8087 if (type & MAC_ADDR_RAND_PNO) {
8088 wpas_stop_pno(wpa_s);
8089 wpas_start_pno(wpa_s);
8090 }
8091 } else if (wpa_s->sched_scanning && (type & MAC_ADDR_RAND_SCHED_SCAN)) {
8092 wpas_scan_restart_sched_scan(wpa_s);
8093 }
8094
8095 return 0;
8096}
Hai Shalomfdcde762020-04-02 11:19:20 -07008097
8098
8099int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
8100 struct wpa_signal_info *si)
8101{
8102 int res;
8103
8104 if (!wpa_s->driver->signal_poll)
8105 return -1;
8106
8107 res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
8108
8109#ifdef CONFIG_TESTING_OPTIONS
8110 if (res == 0) {
8111 struct driver_signal_override *dso;
8112
8113 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8114 struct driver_signal_override, list) {
8115 if (os_memcmp(wpa_s->bssid, dso->bssid,
8116 ETH_ALEN) != 0)
8117 continue;
8118 wpa_printf(MSG_DEBUG,
8119 "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
8120 si->current_signal,
8121 dso->si_current_signal,
8122 si->avg_signal,
8123 dso->si_avg_signal,
8124 si->avg_beacon_signal,
8125 dso->si_avg_beacon_signal,
8126 si->current_noise,
8127 dso->si_current_noise);
8128 si->current_signal = dso->si_current_signal;
8129 si->avg_signal = dso->si_avg_signal;
8130 si->avg_beacon_signal = dso->si_avg_beacon_signal;
8131 si->current_noise = dso->si_current_noise;
8132 break;
8133 }
8134 }
8135#endif /* CONFIG_TESTING_OPTIONS */
8136
8137 return res;
8138}
8139
8140
8141struct wpa_scan_results *
8142wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
8143{
8144 struct wpa_scan_results *scan_res;
8145#ifdef CONFIG_TESTING_OPTIONS
8146 size_t idx;
8147#endif /* CONFIG_TESTING_OPTIONS */
8148
8149 if (!wpa_s->driver->get_scan_results2)
8150 return NULL;
8151
8152 scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
8153
8154#ifdef CONFIG_TESTING_OPTIONS
8155 for (idx = 0; scan_res && idx < scan_res->num; idx++) {
8156 struct driver_signal_override *dso;
8157 struct wpa_scan_res *res = scan_res->res[idx];
8158
8159 dl_list_for_each(dso, &wpa_s->drv_signal_override,
8160 struct driver_signal_override, list) {
8161 if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
8162 continue;
8163 wpa_printf(MSG_DEBUG,
8164 "Override driver scan signal level %d->%d for "
8165 MACSTR,
8166 res->level, dso->scan_level,
8167 MAC2STR(res->bssid));
8168 res->flags |= WPA_SCAN_QUAL_INVALID;
8169 if (dso->scan_level < 0)
8170 res->flags |= WPA_SCAN_LEVEL_DBM;
8171 else
8172 res->flags &= ~WPA_SCAN_LEVEL_DBM;
8173 res->level = dso->scan_level;
8174 break;
8175 }
8176 }
8177#endif /* CONFIG_TESTING_OPTIONS */
8178
8179 return scan_res;
8180}