blob: 4432ec31e60d488a64efb5a65cda0087376564b4 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Roshan Pius3a1667e2018-07-03 15:17:14 -07003 * Copyright (c) 2003-2018, 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"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070039#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080040#include "common/hw_features_common.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070041#include "common/gas_server.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080043#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070044#include "blacklist.h"
45#include "wpas_glue.h"
46#include "wps_supplicant.h"
47#include "ibss_rsn.h"
48#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080049#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070050#include "ap.h"
51#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070052#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053#include "notify.h"
54#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070055#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070056#include "bss.h"
57#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080058#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070059#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070060#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070061#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080062#include "mesh.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070063#include "dpp_supplicant.h"
64#ifdef CONFIG_MESH
65#include "ap/ap_config.h"
66#include "ap/hostapd.h"
67#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070068
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070069const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidt29333592017-01-09 12:27:11 -080071"Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070073const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080074"This software may be distributed under the terms of the BSD license.\n"
75"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076#ifdef EAP_TLS_OPENSSL
77"\nThis product includes software developed by the OpenSSL Project\n"
78"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
79#endif /* EAP_TLS_OPENSSL */
80;
81
82#ifndef CONFIG_NO_STDOUT_DEBUG
83/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070084const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080085"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070086const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080087"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088"\n"
89"Redistribution and use in source and binary forms, with or without\n"
90"modification, are permitted provided that the following conditions are\n"
91"met:\n"
92"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070093const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070094"1. Redistributions of source code must retain the above copyright\n"
95" notice, this list of conditions and the following disclaimer.\n"
96"\n"
97"2. Redistributions in binary form must reproduce the above copyright\n"
98" notice, this list of conditions and the following disclaimer in the\n"
99" documentation and/or other materials provided with the distribution.\n"
100"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700101const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
103" names of its contributors may be used to endorse or promote products\n"
104" derived from this software without specific prior written permission.\n"
105"\n"
106"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
107"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
108"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
109"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700110const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700111"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
112"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
113"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
114"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
115"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
116"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
117"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
118"\n";
119#endif /* CONFIG_NO_STDOUT_DEBUG */
120
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700121
122static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
123#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
124static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
125#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
126
127
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700128/* Configure default/group WEP keys for static WEP */
129int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
130{
131 int i, set = 0;
132
133 for (i = 0; i < NUM_WEP_KEYS; i++) {
134 if (ssid->wep_key_len[i] == 0)
135 continue;
136
137 set = 1;
138 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
139 i, i == ssid->wep_tx_keyidx, NULL, 0,
140 ssid->wep_key[i], ssid->wep_key_len[i]);
141 }
142
143 return set;
144}
145
146
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700147int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
148 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700149{
150 u8 key[32];
151 size_t keylen;
152 enum wpa_alg alg;
153 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800154 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700155
156 /* IBSS/WPA-None uses only one key (Group) for both receiving and
157 * sending unicast and multicast packets. */
158
159 if (ssid->mode != WPAS_MODE_IBSS) {
160 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
161 "IBSS/ad-hoc) for WPA-None", ssid->mode);
162 return -1;
163 }
164
165 if (!ssid->psk_set) {
166 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
167 "WPA-None");
168 return -1;
169 }
170
171 switch (wpa_s->group_cipher) {
172 case WPA_CIPHER_CCMP:
173 os_memcpy(key, ssid->psk, 16);
174 keylen = 16;
175 alg = WPA_ALG_CCMP;
176 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700177 case WPA_CIPHER_GCMP:
178 os_memcpy(key, ssid->psk, 16);
179 keylen = 16;
180 alg = WPA_ALG_GCMP;
181 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700182 case WPA_CIPHER_TKIP:
183 /* WPA-None uses the same Michael MIC key for both TX and RX */
184 os_memcpy(key, ssid->psk, 16 + 8);
185 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
186 keylen = 32;
187 alg = WPA_ALG_TKIP;
188 break;
189 default:
190 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
191 "WPA-None", wpa_s->group_cipher);
192 return -1;
193 }
194
195 /* TODO: should actually remember the previously used seq#, both for TX
196 * and RX from each STA.. */
197
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800198 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
199 os_memset(key, 0, sizeof(key));
200 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700201}
202
203
204static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
205{
206 struct wpa_supplicant *wpa_s = eloop_ctx;
207 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700208 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
209 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
210 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700211 bssid = wpa_s->pending_bssid;
212 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
213 MAC2STR(bssid));
214 wpa_blacklist_add(wpa_s, bssid);
215 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800216 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700217 wpa_s->reassociate = 1;
Roshan Pius38e96762017-01-23 14:52:00 -0800218 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700219
220 /*
221 * If we timed out, the AP or the local radio may be busy.
222 * So, wait a second until scanning again.
223 */
224 wpa_supplicant_req_scan(wpa_s, 1, 0);
225}
226
227
228/**
229 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
230 * @wpa_s: Pointer to wpa_supplicant data
231 * @sec: Number of seconds after which to time out authentication
232 * @usec: Number of microseconds after which to time out authentication
233 *
234 * This function is used to schedule a timeout for the current authentication
235 * attempt.
236 */
237void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
238 int sec, int usec)
239{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700240 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700241 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
242 return;
243
244 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
245 "%d usec", sec, usec);
246 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700247 wpa_s->last_auth_timeout_sec = sec;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700248 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
249}
250
251
Roshan Pius3a1667e2018-07-03 15:17:14 -0700252/*
253 * wpas_auth_timeout_restart - Restart and change timeout for authentication
254 * @wpa_s: Pointer to wpa_supplicant data
255 * @sec_diff: difference in seconds applied to original timeout value
256 */
257void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff)
258{
259 int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
260
261 if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
262 wpa_dbg(wpa_s, MSG_DEBUG,
263 "Authentication timeout restart: %d sec", new_sec);
264 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
265 eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
266 wpa_s, NULL);
267 }
268}
269
270
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700271/**
272 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
273 * @wpa_s: Pointer to wpa_supplicant data
274 *
275 * This function is used to cancel authentication timeout scheduled with
276 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
277 * been completed.
278 */
279void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
280{
281 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
282 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
283 wpa_blacklist_del(wpa_s, wpa_s->bssid);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700284 os_free(wpa_s->last_con_fail_realm);
285 wpa_s->last_con_fail_realm = NULL;
286 wpa_s->last_con_fail_realm_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700287}
288
289
290/**
291 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
292 * @wpa_s: Pointer to wpa_supplicant data
293 *
294 * This function is used to configure EAPOL state machine based on the selected
295 * authentication mode.
296 */
297void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
298{
299#ifdef IEEE8021X_EAPOL
300 struct eapol_config eapol_conf;
301 struct wpa_ssid *ssid = wpa_s->current_ssid;
302
303#ifdef CONFIG_IBSS_RSN
304 if (ssid->mode == WPAS_MODE_IBSS &&
305 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
306 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
307 /*
308 * RSN IBSS authentication is per-STA and we can disable the
309 * per-BSSID EAPOL authentication.
310 */
311 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
312 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
313 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
314 return;
315 }
316#endif /* CONFIG_IBSS_RSN */
317
318 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
319 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
320
321 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
322 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
323 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
324 else
325 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
326
327 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
328 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
329 eapol_conf.accept_802_1x_keys = 1;
330 eapol_conf.required_keys = 0;
331 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
332 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
333 }
334 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
335 eapol_conf.required_keys |=
336 EAPOL_REQUIRE_KEY_BROADCAST;
337 }
338
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700339 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700340 eapol_conf.required_keys = 0;
341 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700342 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700343 eapol_conf.workaround = ssid->eap_workaround;
344 eapol_conf.eap_disabled =
345 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
346 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
347 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700348 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800349
350#ifdef CONFIG_WPS
351 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
352 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
353 if (wpa_s->current_bss) {
354 struct wpabuf *ie;
355 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
356 WPS_IE_VENDOR_TYPE);
357 if (ie) {
358 if (wps_is_20(ie))
359 eapol_conf.wps |=
360 EAPOL_PEER_IS_WPS20_AP;
361 wpabuf_free(ie);
362 }
363 }
364 }
365#endif /* CONFIG_WPS */
366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700367 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700368
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800369#ifdef CONFIG_MACSEC
370 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
371 ieee802_1x_create_preshared_mka(wpa_s, ssid);
372 else
373 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
374#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800375#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700376}
377
378
379/**
380 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
381 * @wpa_s: Pointer to wpa_supplicant data
382 * @ssid: Configuration data for the network
383 *
384 * This function is used to configure WPA state machine and related parameters
385 * to a mode where WPA is not enabled. This is called as part of the
386 * authentication configuration when the selected network does not use WPA.
387 */
388void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
389 struct wpa_ssid *ssid)
390{
391 int i;
392
393 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
394 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
395 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
396 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
397 else
398 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
399 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
400 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
401 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
402 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
403 wpa_s->group_cipher = WPA_CIPHER_NONE;
404 wpa_s->mgmt_group_cipher = 0;
405
406 for (i = 0; i < NUM_WEP_KEYS; i++) {
407 if (ssid->wep_key_len[i] > 5) {
408 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
409 wpa_s->group_cipher = WPA_CIPHER_WEP104;
410 break;
411 } else if (ssid->wep_key_len[i] > 0) {
412 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
413 wpa_s->group_cipher = WPA_CIPHER_WEP40;
414 break;
415 }
416 }
417
418 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
419 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
420 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
421 wpa_s->pairwise_cipher);
422 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
423#ifdef CONFIG_IEEE80211W
424 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
425 wpa_s->mgmt_group_cipher);
426#endif /* CONFIG_IEEE80211W */
427
428 pmksa_cache_clear_current(wpa_s->wpa);
429}
430
431
Dmitry Shmidt04949592012-07-19 12:16:46 -0700432void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800433{
434 int i;
435 if (wpa_s->hw.modes == NULL)
436 return;
437
438 for (i = 0; i < wpa_s->hw.num_modes; i++) {
439 os_free(wpa_s->hw.modes[i].channels);
440 os_free(wpa_s->hw.modes[i].rates);
441 }
442
443 os_free(wpa_s->hw.modes);
444 wpa_s->hw.modes = NULL;
445}
446
447
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800448static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
449{
450 struct wpa_bss_tmp_disallowed *bss, *prev;
451
452 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
453 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700454 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800455 dl_list_del(&bss->list);
456 os_free(bss);
457 }
458}
459
460
Paul Stewart092955c2017-02-06 09:13:09 -0800461void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
462{
463 struct fils_hlp_req *req;
464
465 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
466 list)) != NULL) {
467 dl_list_del(&req->list);
468 wpabuf_free(req->pkt);
469 os_free(req);
470 }
471}
472
473
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700474static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
475{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700476 int i;
477
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700479 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700480 scard_deinit(wpa_s->scard);
481 wpa_s->scard = NULL;
482 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
483 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
484 l2_packet_deinit(wpa_s->l2);
485 wpa_s->l2 = NULL;
486 if (wpa_s->l2_br) {
487 l2_packet_deinit(wpa_s->l2_br);
488 wpa_s->l2_br = NULL;
489 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800490#ifdef CONFIG_TESTING_OPTIONS
491 l2_packet_deinit(wpa_s->l2_test);
492 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800493 os_free(wpa_s->get_pref_freq_list_override);
494 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700495 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
496 wpa_s->last_assoc_req_wpa_ie = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800497#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700498
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700499 if (wpa_s->conf != NULL) {
500 struct wpa_ssid *ssid;
501 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
502 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700503 }
504
505 os_free(wpa_s->confname);
506 wpa_s->confname = NULL;
507
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700508 os_free(wpa_s->confanother);
509 wpa_s->confanother = NULL;
510
Hai Shalomce48b4a2018-09-05 11:41:35 -0700511 os_free(wpa_s->last_con_fail_realm);
512 wpa_s->last_con_fail_realm = NULL;
513 wpa_s->last_con_fail_realm_len = 0;
514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515 wpa_sm_set_eapol(wpa_s->wpa, NULL);
516 eapol_sm_deinit(wpa_s->eapol);
517 wpa_s->eapol = NULL;
518
519 rsn_preauth_deinit(wpa_s->wpa);
520
521#ifdef CONFIG_TDLS
522 wpa_tdls_deinit(wpa_s->wpa);
523#endif /* CONFIG_TDLS */
524
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800525 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700526 pmksa_candidate_free(wpa_s->wpa);
527 wpa_sm_deinit(wpa_s->wpa);
528 wpa_s->wpa = NULL;
529 wpa_blacklist_clear(wpa_s);
530
531 wpa_bss_deinit(wpa_s);
532
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700533 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700534 wpa_supplicant_cancel_scan(wpa_s);
535 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800536 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
537#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
538 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
539 wpa_s, NULL);
540#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700541
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700542 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
543
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700544 wpas_wps_deinit(wpa_s);
545
546 wpabuf_free(wpa_s->pending_eapol_rx);
547 wpa_s->pending_eapol_rx = NULL;
548
549#ifdef CONFIG_IBSS_RSN
550 ibss_rsn_deinit(wpa_s->ibss_rsn);
551 wpa_s->ibss_rsn = NULL;
552#endif /* CONFIG_IBSS_RSN */
553
554 sme_deinit(wpa_s);
555
556#ifdef CONFIG_AP
557 wpa_supplicant_ap_deinit(wpa_s);
558#endif /* CONFIG_AP */
559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700560 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800562#ifdef CONFIG_OFFCHANNEL
563 offchannel_deinit(wpa_s);
564#endif /* CONFIG_OFFCHANNEL */
565
566 wpa_supplicant_cancel_sched_scan(wpa_s);
567
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700568 os_free(wpa_s->next_scan_freqs);
569 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800570
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800571 os_free(wpa_s->manual_scan_freqs);
572 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700573 os_free(wpa_s->select_network_scan_freqs);
574 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800575
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700576 os_free(wpa_s->manual_sched_scan_freqs);
577 wpa_s->manual_sched_scan_freqs = NULL;
578
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800579 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
580
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700581 /*
582 * Need to remove any pending gas-query radio work before the
583 * gas_query_deinit() call because gas_query::work has not yet been set
584 * for works that have not been started. gas_query_free() will be unable
585 * to cancel such pending radio works and once the pending gas-query
586 * radio work eventually gets removed, the deinit notification call to
587 * gas_query_start_cb() would result in dereferencing freed memory.
588 */
589 if (wpa_s->radio)
590 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800591 gas_query_deinit(wpa_s->gas);
592 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700593 gas_server_deinit(wpa_s->gas_server);
594 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800595
596 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700597
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700598 ieee802_1x_dealloc_kay_sm(wpa_s);
599
Dmitry Shmidt04949592012-07-19 12:16:46 -0700600 os_free(wpa_s->bssid_filter);
601 wpa_s->bssid_filter = NULL;
602
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800603 os_free(wpa_s->disallow_aps_bssid);
604 wpa_s->disallow_aps_bssid = NULL;
605 os_free(wpa_s->disallow_aps_ssid);
606 wpa_s->disallow_aps_ssid = NULL;
607
Dmitry Shmidt04949592012-07-19 12:16:46 -0700608 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700609#ifdef CONFIG_WNM
610 wnm_deallocate_memory(wpa_s);
611#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700612
613 ext_password_deinit(wpa_s->ext_pw);
614 wpa_s->ext_pw = NULL;
615
616 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800617 wpa_s->last_gas_resp = NULL;
618 wpabuf_free(wpa_s->prev_gas_resp);
619 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700620
621 os_free(wpa_s->last_scan_res);
622 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800623
624#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700625 if (wpa_s->drv_priv)
626 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700627 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800628#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700629
630 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
631 wpabuf_free(wpa_s->vendor_elem[i]);
632 wpa_s->vendor_elem[i] = NULL;
633 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800634
635 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800636
637 wpa_s->sched_scan_plans_num = 0;
638 os_free(wpa_s->sched_scan_plans);
639 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800640
641#ifdef CONFIG_MBO
642 wpa_s->non_pref_chan_num = 0;
643 os_free(wpa_s->non_pref_chan);
644 wpa_s->non_pref_chan = NULL;
645#endif /* CONFIG_MBO */
646
647 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700648
649 wpabuf_free(wpa_s->lci);
650 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800651 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800652
653#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
654#ifdef CONFIG_MESH
655 {
656 struct external_pmksa_cache *entry;
657
658 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
659 struct external_pmksa_cache,
660 list)) != NULL) {
661 dl_list_del(&entry->list);
662 os_free(entry->pmksa_cache);
663 os_free(entry);
664 }
665 }
666#endif /* CONFIG_MESH */
667#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
668
669 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800670
671 wpabuf_free(wpa_s->ric_ies);
672 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700673
674#ifdef CONFIG_DPP
675 wpas_dpp_deinit(wpa_s);
676#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677}
678
679
680/**
681 * wpa_clear_keys - Clear keys configured for the driver
682 * @wpa_s: Pointer to wpa_supplicant data
683 * @addr: Previously used BSSID or %NULL if not available
684 *
685 * This function clears the encryption keys that has been previously configured
686 * for the driver.
687 */
688void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
689{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800690 int i, max;
691
692#ifdef CONFIG_IEEE80211W
693 max = 6;
694#else /* CONFIG_IEEE80211W */
695 max = 4;
696#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697
698 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800699 for (i = 0; i < max; i++) {
700 if (wpa_s->keys_cleared & BIT(i))
701 continue;
702 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
703 NULL, 0);
704 }
705 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
706 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
708 0);
709 /* MLME-SETPROTECTION.request(None) */
710 wpa_drv_mlme_setprotection(
711 wpa_s, addr,
712 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
713 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
714 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800715 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716}
717
718
719/**
720 * wpa_supplicant_state_txt - Get the connection state name as a text string
721 * @state: State (wpa_state; WPA_*)
722 * Returns: The state name as a printable text string
723 */
724const char * wpa_supplicant_state_txt(enum wpa_states state)
725{
726 switch (state) {
727 case WPA_DISCONNECTED:
728 return "DISCONNECTED";
729 case WPA_INACTIVE:
730 return "INACTIVE";
731 case WPA_INTERFACE_DISABLED:
732 return "INTERFACE_DISABLED";
733 case WPA_SCANNING:
734 return "SCANNING";
735 case WPA_AUTHENTICATING:
736 return "AUTHENTICATING";
737 case WPA_ASSOCIATING:
738 return "ASSOCIATING";
739 case WPA_ASSOCIATED:
740 return "ASSOCIATED";
741 case WPA_4WAY_HANDSHAKE:
742 return "4WAY_HANDSHAKE";
743 case WPA_GROUP_HANDSHAKE:
744 return "GROUP_HANDSHAKE";
745 case WPA_COMPLETED:
746 return "COMPLETED";
747 default:
748 return "UNKNOWN";
749 }
750}
751
752
753#ifdef CONFIG_BGSCAN
754
755static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
756{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800757 const char *name;
758
759 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
760 name = wpa_s->current_ssid->bgscan;
761 else
762 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800763 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800764 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800765 if (wpas_driver_bss_selection(wpa_s))
766 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700767 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
768 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800769#ifdef CONFIG_P2P
770 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
771 return;
772#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773
774 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800775 if (wpa_s->current_ssid) {
776 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700777 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
778 "bgscan");
779 /*
780 * Live without bgscan; it is only used as a roaming
781 * optimization, so the initial connection is not
782 * affected.
783 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700784 } else {
785 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700787 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
788 0);
789 if (scan_res) {
790 bgscan_notify_scan(wpa_s, scan_res);
791 wpa_scan_results_free(scan_res);
792 }
793 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700794 } else
795 wpa_s->bgscan_ssid = NULL;
796}
797
798
799static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
800{
801 if (wpa_s->bgscan_ssid != NULL) {
802 bgscan_deinit(wpa_s);
803 wpa_s->bgscan_ssid = NULL;
804 }
805}
806
807#endif /* CONFIG_BGSCAN */
808
809
Dmitry Shmidt04949592012-07-19 12:16:46 -0700810static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
811{
812 if (autoscan_init(wpa_s, 0))
813 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
814}
815
816
817static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
818{
819 autoscan_deinit(wpa_s);
820}
821
822
823void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
824{
825 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
826 wpa_s->wpa_state == WPA_SCANNING) {
827 autoscan_deinit(wpa_s);
828 wpa_supplicant_start_autoscan(wpa_s);
829 }
830}
831
832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700833/**
834 * wpa_supplicant_set_state - Set current connection state
835 * @wpa_s: Pointer to wpa_supplicant data
836 * @state: The new connection state
837 *
838 * This function is called whenever the connection state changes, e.g.,
839 * association is completed for WPA/WPA2 4-Way Handshake is started.
840 */
841void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
842 enum wpa_states state)
843{
844 enum wpa_states old_state = wpa_s->wpa_state;
845
846 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
847 wpa_supplicant_state_txt(wpa_s->wpa_state),
848 wpa_supplicant_state_txt(state));
849
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800850 if (state == WPA_INTERFACE_DISABLED) {
851 /* Assure normal scan when interface is restored */
852 wpa_s->normal_scans = 0;
853 }
854
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700855 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800856 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700857 /* Reinitialize normal_scan counter */
858 wpa_s->normal_scans = 0;
859 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800860
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700861#ifdef CONFIG_P2P
862 /*
863 * P2PS client has to reply to Probe Request frames received on the
864 * group operating channel. Enable Probe Request frame reporting for
865 * P2P connected client in case p2p_cli_probe configuration property is
866 * set to 1.
867 */
868 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
869 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
870 wpa_s->current_ssid->p2p_group) {
871 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
872 wpa_dbg(wpa_s, MSG_DEBUG,
873 "P2P: Enable CLI Probe Request RX reporting");
874 wpa_s->p2p_cli_probe =
875 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
876 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
877 wpa_dbg(wpa_s, MSG_DEBUG,
878 "P2P: Disable CLI Probe Request RX reporting");
879 wpa_s->p2p_cli_probe = 0;
880 wpa_drv_probe_req_report(wpa_s, 0);
881 }
882 }
883#endif /* CONFIG_P2P */
884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885 if (state != WPA_SCANNING)
886 wpa_supplicant_notify_scanning(wpa_s, 0);
887
888 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700889 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700890 int fils_hlp_sent = 0;
891
892#ifdef CONFIG_SME
893 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
894 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
895 fils_hlp_sent = 1;
896#endif /* CONFIG_SME */
897 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
898 wpa_auth_alg_fils(wpa_s->auth_alg))
899 fils_hlp_sent = 1;
900
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700901#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700903 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800904 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700905 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700906 ssid && ssid->id_str ? ssid->id_str : "",
907 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700908#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700909 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700910 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800911 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700912 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700913 wpa_drv_set_operstate(wpa_s, 1);
914#ifndef IEEE8021X_EAPOL
915 wpa_drv_set_supp_port(wpa_s, 1);
916#endif /* IEEE8021X_EAPOL */
917 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700918 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700919 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700920
921 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700922
923#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
924 if (!fils_hlp_sent && ssid && ssid->eap.erp)
925 wpas_update_fils_connect_params(wpa_s);
926#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700927 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
928 state == WPA_ASSOCIATED) {
929 wpa_s->new_connection = 1;
930 wpa_drv_set_operstate(wpa_s, 0);
931#ifndef IEEE8021X_EAPOL
932 wpa_drv_set_supp_port(wpa_s, 0);
933#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700934 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935 }
936 wpa_s->wpa_state = state;
937
938#ifdef CONFIG_BGSCAN
939 if (state == WPA_COMPLETED)
940 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800941 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700942 wpa_supplicant_stop_bgscan(wpa_s);
943#endif /* CONFIG_BGSCAN */
944
Dmitry Shmidt04949592012-07-19 12:16:46 -0700945 if (state == WPA_AUTHENTICATING)
946 wpa_supplicant_stop_autoscan(wpa_s);
947
948 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
949 wpa_supplicant_start_autoscan(wpa_s);
950
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800951 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
952 wmm_ac_notify_disassoc(wpa_s);
953
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700954 if (wpa_s->wpa_state != old_state) {
955 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
956
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700957 /*
958 * Notify the P2P Device interface about a state change in one
959 * of the interfaces.
960 */
961 wpas_p2p_indicate_state_change(wpa_s);
962
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700963 if (wpa_s->wpa_state == WPA_COMPLETED ||
964 old_state == WPA_COMPLETED)
965 wpas_notify_auth_changed(wpa_s);
966 }
967}
968
969
970void wpa_supplicant_terminate_proc(struct wpa_global *global)
971{
972 int pending = 0;
973#ifdef CONFIG_WPS
974 struct wpa_supplicant *wpa_s = global->ifaces;
975 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800976 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700977 if (wpas_wps_terminate_pending(wpa_s) == 1)
978 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700979#ifdef CONFIG_P2P
980 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
981 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
982 wpas_p2p_disconnect(wpa_s);
983#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800984 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700985 }
986#endif /* CONFIG_WPS */
987 if (pending)
988 return;
989 eloop_terminate();
990}
991
992
993static void wpa_supplicant_terminate(int sig, void *signal_ctx)
994{
995 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996 wpa_supplicant_terminate_proc(global);
997}
998
999
1000void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
1001{
1002 enum wpa_states old_state = wpa_s->wpa_state;
1003
1004 wpa_s->pairwise_cipher = 0;
1005 wpa_s->group_cipher = 0;
1006 wpa_s->mgmt_group_cipher = 0;
1007 wpa_s->key_mgmt = 0;
1008 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001009 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010
1011 if (wpa_s->wpa_state != old_state)
1012 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1013}
1014
1015
1016/**
1017 * wpa_supplicant_reload_configuration - Reload configuration data
1018 * @wpa_s: Pointer to wpa_supplicant data
1019 * Returns: 0 on success or -1 if configuration parsing failed
1020 *
1021 * This function can be used to request that the configuration data is reloaded
1022 * (e.g., after configuration file change). This function is reloading
1023 * configuration only for one interface, so this may need to be called multiple
1024 * times if %wpa_supplicant is controlling multiple interfaces and all
1025 * interfaces need reconfiguration.
1026 */
1027int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1028{
1029 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 int reconf_ctrl;
1031 int old_ap_scan;
1032
1033 if (wpa_s->confname == NULL)
1034 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001035 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001036 if (conf == NULL) {
1037 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1038 "file '%s' - exiting", wpa_s->confname);
1039 return -1;
1040 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001041 if (wpa_s->confanother &&
1042 !wpa_config_read(wpa_s->confanother, conf)) {
1043 wpa_msg(wpa_s, MSG_ERROR,
1044 "Failed to parse the configuration file '%s' - exiting",
1045 wpa_s->confanother);
1046 return -1;
1047 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001048
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001049 conf->changed_parameters = (unsigned int) -1;
1050
1051 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1052 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1053 os_strcmp(conf->ctrl_interface,
1054 wpa_s->conf->ctrl_interface) != 0);
1055
1056 if (reconf_ctrl && wpa_s->ctrl_iface) {
1057 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1058 wpa_s->ctrl_iface = NULL;
1059 }
1060
1061 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001062 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001063 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1064 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001065 wpa_supplicant_deauthenticate(wpa_s,
1066 WLAN_REASON_DEAUTH_LEAVING);
1067 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001068
1069 /*
1070 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001071 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001072 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001073 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1074 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1075 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001076 /*
1077 * Clear forced success to clear EAP state for next
1078 * authentication.
1079 */
1080 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1081 }
1082 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1083 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001084 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1086 rsn_preauth_deinit(wpa_s->wpa);
1087
1088 old_ap_scan = wpa_s->conf->ap_scan;
1089 wpa_config_free(wpa_s->conf);
1090 wpa_s->conf = conf;
1091 if (old_ap_scan != wpa_s->conf->ap_scan)
1092 wpas_notify_ap_scan_changed(wpa_s);
1093
1094 if (reconf_ctrl)
1095 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1096
1097 wpa_supplicant_update_config(wpa_s);
1098
1099 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001100 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001101 wpa_s->reassociate = 1;
1102 wpa_supplicant_req_scan(wpa_s, 0, 0);
1103 }
1104 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1105 return 0;
1106}
1107
1108
1109static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1110{
1111 struct wpa_global *global = signal_ctx;
1112 struct wpa_supplicant *wpa_s;
1113 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1114 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1115 sig);
1116 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1117 wpa_supplicant_terminate_proc(global);
1118 }
1119 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001120
1121 if (wpa_debug_reopen_file() < 0) {
1122 /* Ignore errors since we cannot really do much to fix this */
1123 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1124 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125}
1126
1127
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1129 struct wpa_ssid *ssid,
1130 struct wpa_ie_data *ie)
1131{
1132 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1133 if (ret) {
1134 if (ret == -2) {
1135 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1136 "from association info");
1137 }
1138 return -1;
1139 }
1140
1141 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1142 "cipher suites");
1143 if (!(ie->group_cipher & ssid->group_cipher)) {
1144 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1145 "cipher 0x%x (mask 0x%x) - reject",
1146 ie->group_cipher, ssid->group_cipher);
1147 return -1;
1148 }
1149 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1150 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1151 "cipher 0x%x (mask 0x%x) - reject",
1152 ie->pairwise_cipher, ssid->pairwise_cipher);
1153 return -1;
1154 }
1155 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1156 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1157 "management 0x%x (mask 0x%x) - reject",
1158 ie->key_mgmt, ssid->key_mgmt);
1159 return -1;
1160 }
1161
1162#ifdef CONFIG_IEEE80211W
1163 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001164 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1166 "that does not support management frame protection - "
1167 "reject");
1168 return -1;
1169 }
1170#endif /* CONFIG_IEEE80211W */
1171
1172 return 0;
1173}
1174
1175
1176/**
1177 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1178 * @wpa_s: Pointer to wpa_supplicant data
1179 * @bss: Scan results for the selected BSS, or %NULL if not available
1180 * @ssid: Configuration data for the selected network
1181 * @wpa_ie: Buffer for the WPA/RSN IE
1182 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1183 * used buffer length in case the functions returns success.
1184 * Returns: 0 on success or -1 on failure
1185 *
1186 * This function is used to configure authentication and encryption parameters
1187 * based on the network configuration and scan result for the selected BSS (if
1188 * available).
1189 */
1190int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1191 struct wpa_bss *bss, struct wpa_ssid *ssid,
1192 u8 *wpa_ie, size_t *wpa_ie_len)
1193{
1194 struct wpa_ie_data ie;
1195 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001196 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197
1198 if (bss) {
1199 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1200 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001201 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001202 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001203 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001204
1205 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1206 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1207 (ie.group_cipher & ssid->group_cipher) &&
1208 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1209 (ie.key_mgmt & ssid->key_mgmt)) {
1210 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1211 proto = WPA_PROTO_RSN;
1212 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001213 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001214 (ie.group_cipher & ssid->group_cipher) &&
1215 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1216 (ie.key_mgmt & ssid->key_mgmt)) {
1217 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1218 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001219#ifdef CONFIG_HS20
1220 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1221 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1222 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001223 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001224 ie.group_cipher = WPA_CIPHER_CCMP;
1225 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1226 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1227 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001228 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1229 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1230 (ie.group_cipher & ssid->group_cipher) &&
1231 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1232 (ie.key_mgmt & ssid->key_mgmt)) {
1233 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1234 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001235#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236 } else if (bss) {
1237 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001238 wpa_dbg(wpa_s, MSG_DEBUG,
1239 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1240 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1241 ssid->key_mgmt);
1242 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1243 MAC2STR(bss->bssid),
1244 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1245 bss_wpa ? " WPA" : "",
1246 bss_rsn ? " RSN" : "",
1247 bss_osen ? " OSEN" : "");
1248 if (bss_rsn) {
1249 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1250 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1251 wpa_dbg(wpa_s, MSG_DEBUG,
1252 "Could not parse RSN element");
1253 } else {
1254 wpa_dbg(wpa_s, MSG_DEBUG,
1255 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1256 ie.pairwise_cipher, ie.group_cipher,
1257 ie.key_mgmt);
1258 }
1259 }
1260 if (bss_wpa) {
1261 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1262 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1263 wpa_dbg(wpa_s, MSG_DEBUG,
1264 "Could not parse WPA element");
1265 } else {
1266 wpa_dbg(wpa_s, MSG_DEBUG,
1267 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1268 ie.pairwise_cipher, ie.group_cipher,
1269 ie.key_mgmt);
1270 }
1271 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001272 return -1;
1273 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001274 if (ssid->proto & WPA_PROTO_OSEN)
1275 proto = WPA_PROTO_OSEN;
1276 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001277 proto = WPA_PROTO_RSN;
1278 else
1279 proto = WPA_PROTO_WPA;
1280 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1281 os_memset(&ie, 0, sizeof(ie));
1282 ie.group_cipher = ssid->group_cipher;
1283 ie.pairwise_cipher = ssid->pairwise_cipher;
1284 ie.key_mgmt = ssid->key_mgmt;
1285#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001286 ie.mgmt_group_cipher = 0;
1287 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1288 if (ssid->group_mgmt_cipher &
1289 WPA_CIPHER_BIP_GMAC_256)
1290 ie.mgmt_group_cipher =
1291 WPA_CIPHER_BIP_GMAC_256;
1292 else if (ssid->group_mgmt_cipher &
1293 WPA_CIPHER_BIP_CMAC_256)
1294 ie.mgmt_group_cipher =
1295 WPA_CIPHER_BIP_CMAC_256;
1296 else if (ssid->group_mgmt_cipher &
1297 WPA_CIPHER_BIP_GMAC_128)
1298 ie.mgmt_group_cipher =
1299 WPA_CIPHER_BIP_GMAC_128;
1300 else
1301 ie.mgmt_group_cipher =
1302 WPA_CIPHER_AES_128_CMAC;
1303 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001304#endif /* CONFIG_IEEE80211W */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001305#ifdef CONFIG_OWE
1306 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1307 !ssid->owe_only &&
1308 !bss_wpa && !bss_rsn && !bss_osen) {
1309 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1310 wpa_s->wpa_proto = 0;
1311 *wpa_ie_len = 0;
1312 return 0;
1313 }
1314#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1316 "based on configuration");
1317 } else
1318 proto = ie.proto;
1319 }
1320
1321 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1322 "pairwise %d key_mgmt %d proto %d",
1323 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1324#ifdef CONFIG_IEEE80211W
1325 if (ssid->ieee80211w) {
1326 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1327 ie.mgmt_group_cipher);
1328 }
1329#endif /* CONFIG_IEEE80211W */
1330
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001331 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001332 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1333 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001334 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001335
1336 if (bss || !wpa_s->ap_ies_from_associnfo) {
1337 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1338 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1339 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1340 bss_rsn ? 2 + bss_rsn[1] : 0))
1341 return -1;
1342 }
1343
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001344#ifdef CONFIG_NO_WPA
1345 wpa_s->group_cipher = WPA_CIPHER_NONE;
1346 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1347#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001348 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001349 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1350 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001351 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1352 "cipher");
1353 return -1;
1354 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001355 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1356 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001357
1358 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001359 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1360 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001361 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1362 "cipher");
1363 return -1;
1364 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001365 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1366 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001367#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001368
1369 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001370#ifdef CONFIG_SAE
1371 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1372 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1373#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001374 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001375#ifdef CONFIG_SUITEB192
1376 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1377 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1378 wpa_dbg(wpa_s, MSG_DEBUG,
1379 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1380#endif /* CONFIG_SUITEB192 */
1381#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001382 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1383 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1384 wpa_dbg(wpa_s, MSG_DEBUG,
1385 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001386#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001387#ifdef CONFIG_FILS
1388#ifdef CONFIG_IEEE80211R
1389 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1390 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1391 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1392 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1393 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1394 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1395#endif /* CONFIG_IEEE80211R */
1396 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1397 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1398 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1399 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1400 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1401 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1402#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001403#ifdef CONFIG_IEEE80211R
Roshan Pius3a1667e2018-07-03 15:17:14 -07001404#ifdef CONFIG_SHA384
1405 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
1406 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1407 wpa_dbg(wpa_s, MSG_DEBUG,
1408 "WPA: using KEY_MGMT FT/802.1X-SHA384");
1409 if (pmksa_cache_get_current(wpa_s->wpa)) {
1410 /* PMKSA caching with FT is not fully functional, so
1411 * disable the case for now. */
1412 wpa_dbg(wpa_s, MSG_DEBUG,
1413 "WPA: Disable PMKSA caching for FT/802.1X connection");
1414 pmksa_cache_clear_current(wpa_s->wpa);
1415 }
1416#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001417 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1418 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1419 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001420 if (pmksa_cache_get_current(wpa_s->wpa)) {
1421 /* PMKSA caching with FT is not fully functional, so
1422 * disable the case for now. */
1423 wpa_dbg(wpa_s, MSG_DEBUG,
1424 "WPA: Disable PMKSA caching for FT/802.1X connection");
1425 pmksa_cache_clear_current(wpa_s->wpa);
1426 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001427 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1428 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1429 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1430#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001431#ifdef CONFIG_SAE
1432 } else if (sel & WPA_KEY_MGMT_SAE) {
1433 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1434 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1435 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1436 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1437 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1438#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001439#ifdef CONFIG_IEEE80211W
1440 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1441 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1442 wpa_dbg(wpa_s, MSG_DEBUG,
1443 "WPA: using KEY_MGMT 802.1X with SHA256");
1444 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1445 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1446 wpa_dbg(wpa_s, MSG_DEBUG,
1447 "WPA: using KEY_MGMT PSK with SHA256");
1448#endif /* CONFIG_IEEE80211W */
1449 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1450 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1451 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1452 } else if (sel & WPA_KEY_MGMT_PSK) {
1453 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1454 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1455 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1456 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1457 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001458#ifdef CONFIG_HS20
1459 } else if (sel & WPA_KEY_MGMT_OSEN) {
1460 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1461 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1462#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001463#ifdef CONFIG_OWE
1464 } else if (sel & WPA_KEY_MGMT_OWE) {
1465 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1466 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1467#endif /* CONFIG_OWE */
1468#ifdef CONFIG_DPP
1469 } else if (sel & WPA_KEY_MGMT_DPP) {
1470 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1471 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1472#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001473 } else {
1474 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1475 "authenticated key management type");
1476 return -1;
1477 }
1478
1479 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1480 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1481 wpa_s->pairwise_cipher);
1482 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1483
1484#ifdef CONFIG_IEEE80211W
1485 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001486 if (ssid->group_mgmt_cipher)
1487 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001488 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001489 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1490 sel = 0;
1491 if (sel & WPA_CIPHER_AES_128_CMAC) {
1492 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1493 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1494 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001495 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1496 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1497 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1498 "BIP-GMAC-128");
1499 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1500 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1501 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1502 "BIP-GMAC-256");
1503 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1504 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1505 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1506 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001507 } else {
1508 wpa_s->mgmt_group_cipher = 0;
1509 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1510 }
1511 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1512 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001513 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001514 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001515#endif /* CONFIG_IEEE80211W */
1516
1517 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1518 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1519 return -1;
1520 }
1521
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001522 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001523 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001524 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001525
Roshan Pius3a1667e2018-07-03 15:17:14 -07001526 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1527 WPA_KEY_MGMT_FT_PSK |
1528 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1529
1530 if (ssid->psk_set && !sae_only) {
1531 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1532 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001533 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1534 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001535 psk_set = 1;
1536 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001537
Roshan Pius3a1667e2018-07-03 15:17:14 -07001538 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1539 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001540 psk_set = 1;
1541
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001542#ifndef CONFIG_NO_PBKDF2
1543 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001544 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001545 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001546 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1547 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001548 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1549 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001550 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001551 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001552 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001553 }
1554#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001555#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001556 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001557 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1558 ssid->ext_psk);
1559 char pw_str[64 + 1];
1560 u8 psk[PMK_LEN];
1561
1562 if (pw == NULL) {
1563 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1564 "found from external storage");
1565 return -1;
1566 }
1567
1568 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1569 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1570 "PSK length %d in external storage",
1571 (int) wpabuf_len(pw));
1572 ext_password_free(pw);
1573 return -1;
1574 }
1575
1576 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1577 pw_str[wpabuf_len(pw)] = '\0';
1578
1579#ifndef CONFIG_NO_PBKDF2
1580 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1581 {
1582 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1583 4096, psk, PMK_LEN);
1584 os_memset(pw_str, 0, sizeof(pw_str));
1585 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1586 "external passphrase)",
1587 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001588 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1589 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001590 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001591 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001592 } else
1593#endif /* CONFIG_NO_PBKDF2 */
1594 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1595 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1596 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1597 "Invalid PSK hex string");
1598 os_memset(pw_str, 0, sizeof(pw_str));
1599 ext_password_free(pw);
1600 return -1;
1601 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001602 wpa_hexdump_key(MSG_MSGDUMP,
1603 "PSK (from external PSK)",
1604 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001605 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1606 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001607 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001608 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001609 } else {
1610 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1611 "PSK available");
1612 os_memset(pw_str, 0, sizeof(pw_str));
1613 ext_password_free(pw);
1614 return -1;
1615 }
1616
1617 os_memset(pw_str, 0, sizeof(pw_str));
1618 ext_password_free(pw);
1619 }
1620#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001621
1622 if (!psk_set) {
1623 wpa_msg(wpa_s, MSG_INFO,
1624 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001625 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001626 return -1;
1627 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001628#ifdef CONFIG_OWE
1629 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1630 /* OWE Diffie-Hellman exchange in (Re)Association
1631 * Request/Response frames set the PMK, so do not override it
1632 * here. */
1633#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001634 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001635 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1636
1637 return 0;
1638}
1639
1640
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001641static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1642{
1643 *pos = 0x00;
1644
1645 switch (idx) {
1646 case 0: /* Bits 0-7 */
1647 break;
1648 case 1: /* Bits 8-15 */
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001649 if (wpa_s->conf->coloc_intf_reporting) {
1650 /* Bit 13 - Collocated Interference Reporting */
1651 *pos |= 0x20;
1652 }
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001653 break;
1654 case 2: /* Bits 16-23 */
1655#ifdef CONFIG_WNM
1656 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1657 *pos |= 0x08; /* Bit 19 - BSS Transition */
1658#endif /* CONFIG_WNM */
1659 break;
1660 case 3: /* Bits 24-31 */
1661#ifdef CONFIG_WNM
1662 *pos |= 0x02; /* Bit 25 - SSID List */
1663#endif /* CONFIG_WNM */
1664#ifdef CONFIG_INTERWORKING
1665 if (wpa_s->conf->interworking)
1666 *pos |= 0x80; /* Bit 31 - Interworking */
1667#endif /* CONFIG_INTERWORKING */
1668 break;
1669 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001670#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001671 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001672 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001673#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001674 break;
1675 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001676#ifdef CONFIG_HS20
1677 if (wpa_s->conf->hs20)
1678 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1679#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001680#ifdef CONFIG_MBO
1681 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1682#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001683 break;
1684 case 6: /* Bits 48-55 */
1685 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001686 case 7: /* Bits 56-63 */
1687 break;
1688 case 8: /* Bits 64-71 */
1689 if (wpa_s->conf->ftm_responder)
1690 *pos |= 0x40; /* Bit 70 - FTM responder */
1691 if (wpa_s->conf->ftm_initiator)
1692 *pos |= 0x80; /* Bit 71 - FTM initiator */
1693 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001694 case 9: /* Bits 72-79 */
1695#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001696 if (!wpa_s->disable_fils)
1697 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001698#endif /* CONFIG_FILS */
1699 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001700 }
1701}
1702
1703
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001704int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001705{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001706 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001707 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001708
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001709 if (len < wpa_s->extended_capa_len)
1710 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001711 if (buflen < (size_t) len + 2) {
1712 wpa_printf(MSG_INFO,
1713 "Not enough room for building extended capabilities element");
1714 return -1;
1715 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001716
1717 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001718 *pos++ = len;
1719 for (i = 0; i < len; i++, pos++) {
1720 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001721
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001722 if (i < wpa_s->extended_capa_len) {
1723 *pos &= ~wpa_s->extended_capa_mask[i];
1724 *pos |= wpa_s->extended_capa[i];
1725 }
1726 }
1727
1728 while (len > 0 && buf[1 + len] == 0) {
1729 len--;
1730 buf[1] = len;
1731 }
1732 if (len == 0)
1733 return 0;
1734
1735 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001736}
1737
1738
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001739static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1740 struct wpa_bss *test_bss)
1741{
1742 struct wpa_bss *bss;
1743
1744 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1745 if (bss == test_bss)
1746 return 1;
1747 }
1748
1749 return 0;
1750}
1751
1752
1753static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1754 struct wpa_ssid *test_ssid)
1755{
1756 struct wpa_ssid *ssid;
1757
1758 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1759 if (ssid == test_ssid)
1760 return 1;
1761 }
1762
1763 return 0;
1764}
1765
1766
1767int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1768 struct wpa_ssid *test_ssid)
1769{
1770 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1771 return 0;
1772
1773 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1774}
1775
1776
1777void wpas_connect_work_free(struct wpa_connect_work *cwork)
1778{
1779 if (cwork == NULL)
1780 return;
1781 os_free(cwork);
1782}
1783
1784
1785void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1786{
1787 struct wpa_connect_work *cwork;
1788 struct wpa_radio_work *work = wpa_s->connect_work;
1789
1790 if (!work)
1791 return;
1792
1793 wpa_s->connect_work = NULL;
1794 cwork = work->ctx;
1795 work->ctx = NULL;
1796 wpas_connect_work_free(cwork);
1797 radio_work_done(work);
1798}
1799
1800
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001801int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1802{
1803 struct os_reltime now;
1804 u8 addr[ETH_ALEN];
1805
1806 os_get_reltime(&now);
1807 if (wpa_s->last_mac_addr_style == style &&
1808 wpa_s->last_mac_addr_change.sec != 0 &&
1809 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1810 wpa_s->conf->rand_addr_lifetime)) {
1811 wpa_msg(wpa_s, MSG_DEBUG,
1812 "Previously selected random MAC address has not yet expired");
1813 return 0;
1814 }
1815
1816 switch (style) {
1817 case 1:
1818 if (random_mac_addr(addr) < 0)
1819 return -1;
1820 break;
1821 case 2:
1822 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1823 if (random_mac_addr_keep_oui(addr) < 0)
1824 return -1;
1825 break;
1826 default:
1827 return -1;
1828 }
1829
1830 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1831 wpa_msg(wpa_s, MSG_INFO,
1832 "Failed to set random MAC address");
1833 return -1;
1834 }
1835
1836 os_get_reltime(&wpa_s->last_mac_addr_change);
1837 wpa_s->mac_addr_changed = 1;
1838 wpa_s->last_mac_addr_style = style;
1839
1840 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1841 wpa_msg(wpa_s, MSG_INFO,
1842 "Could not update MAC address information");
1843 return -1;
1844 }
1845
1846 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1847 MAC2STR(addr));
1848
1849 return 0;
1850}
1851
1852
1853int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1854{
1855 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1856 !wpa_s->conf->preassoc_mac_addr)
1857 return 0;
1858
1859 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1860}
1861
1862
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001863static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1864
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001865/**
1866 * wpa_supplicant_associate - Request association
1867 * @wpa_s: Pointer to wpa_supplicant data
1868 * @bss: Scan results for the selected BSS, or %NULL if not available
1869 * @ssid: Configuration data for the selected network
1870 *
1871 * This function is used to request %wpa_supplicant to associate with a BSS.
1872 */
1873void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1874 struct wpa_bss *bss, struct wpa_ssid *ssid)
1875{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001876 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001877 int rand_style;
1878
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001879 wpa_s->own_disconnect_req = 0;
1880
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001881 /*
1882 * If we are starting a new connection, any previously pending EAPOL
1883 * RX cannot be valid anymore.
1884 */
1885 wpabuf_free(wpa_s->pending_eapol_rx);
1886 wpa_s->pending_eapol_rx = NULL;
1887
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001888 if (ssid->mac_addr == -1)
1889 rand_style = wpa_s->conf->mac_addr;
1890 else
1891 rand_style = ssid->mac_addr;
1892
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001893 wmm_ac_clear_saved_tspecs(wpa_s);
1894 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001895 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001896#ifdef CONFIG_TESTING_OPTIONS
1897 wpa_s->testing_resend_assoc = 0;
1898#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001899
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001900 if (wpa_s->last_ssid == ssid) {
1901 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001902 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001903 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1904 wmm_ac_save_tspecs(wpa_s);
1905 wpa_s->reassoc_same_bss = 1;
1906 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001907 }
1908
1909 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001910 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1911 return;
1912 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001913 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001914 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1915 wpa_msg(wpa_s, MSG_INFO,
1916 "Could not restore permanent MAC address");
1917 return;
1918 }
1919 wpa_s->mac_addr_changed = 0;
1920 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1921 wpa_msg(wpa_s, MSG_INFO,
1922 "Could not update MAC address information");
1923 return;
1924 }
1925 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1926 }
1927 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001928
1929#ifdef CONFIG_IBSS_RSN
1930 ibss_rsn_deinit(wpa_s->ibss_rsn);
1931 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001932#else /* CONFIG_IBSS_RSN */
1933 if (ssid->mode == WPAS_MODE_IBSS &&
1934 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1935 wpa_msg(wpa_s, MSG_INFO,
1936 "IBSS RSN not supported in the build");
1937 return;
1938 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939#endif /* CONFIG_IBSS_RSN */
1940
1941 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1942 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1943#ifdef CONFIG_AP
1944 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1945 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1946 "mode");
1947 return;
1948 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001949 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1950 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001951 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1952 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001953 return;
1954 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001955 wpa_s->current_bss = bss;
1956#else /* CONFIG_AP */
1957 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1958 "the build");
1959#endif /* CONFIG_AP */
1960 return;
1961 }
1962
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001963 if (ssid->mode == WPAS_MODE_MESH) {
1964#ifdef CONFIG_MESH
1965 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1966 wpa_msg(wpa_s, MSG_INFO,
1967 "Driver does not support mesh mode");
1968 return;
1969 }
1970 if (bss)
1971 ssid->frequency = bss->freq;
1972 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1973 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1974 return;
1975 }
1976 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001977 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1978 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1979 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001980 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001981#else /* CONFIG_MESH */
1982 wpa_msg(wpa_s, MSG_ERROR,
1983 "mesh mode support not included in the build");
1984#endif /* CONFIG_MESH */
1985 return;
1986 }
1987
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001988 /*
1989 * Set WPA state machine configuration to match the selected network now
1990 * so that the information is available before wpas_start_assoc_cb()
1991 * gets called. This is needed at least for RSN pre-authentication where
1992 * candidate APs are added to a list based on scan result processing
1993 * before completion of the first association.
1994 */
1995 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
1996
1997#ifdef CONFIG_DPP
1998 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
1999 return;
2000#endif /* CONFIG_DPP */
2001
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002002#ifdef CONFIG_TDLS
2003 if (bss)
2004 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2005 bss->ie_len);
2006#endif /* CONFIG_TDLS */
2007
2008 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2009 ssid->mode == IEEE80211_MODE_INFRA) {
2010 sme_authenticate(wpa_s, bss, ssid);
2011 return;
2012 }
2013
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002014 if (wpa_s->connect_work) {
2015 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2016 return;
2017 }
2018
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002019 if (radio_work_pending(wpa_s, "connect")) {
2020 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2021 return;
2022 }
2023
Dmitry Shmidt29333592017-01-09 12:27:11 -08002024#ifdef CONFIG_SME
2025 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2026 /* Clear possibly set auth_alg, if any, from last attempt. */
2027 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2028 }
2029#endif /* CONFIG_SME */
2030
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002031 wpas_abort_ongoing_scan(wpa_s);
2032
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002033 cwork = os_zalloc(sizeof(*cwork));
2034 if (cwork == NULL)
2035 return;
2036
2037 cwork->bss = bss;
2038 cwork->ssid = ssid;
2039
2040 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2041 wpas_start_assoc_cb, cwork) < 0) {
2042 os_free(cwork);
2043 }
2044}
2045
2046
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002047static int bss_is_ibss(struct wpa_bss *bss)
2048{
2049 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2050 IEEE80211_CAP_IBSS;
2051}
2052
2053
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002054static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2055 const struct wpa_ssid *ssid)
2056{
2057 enum hostapd_hw_mode hw_mode;
2058 struct hostapd_hw_modes *mode = NULL;
2059 u8 channel;
2060 int i;
2061
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002062 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2063 if (hw_mode == NUM_HOSTAPD_MODES)
2064 return 0;
2065 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2066 if (wpa_s->hw.modes[i].mode == hw_mode) {
2067 mode = &wpa_s->hw.modes[i];
2068 break;
2069 }
2070 }
2071
2072 if (!mode)
2073 return 0;
2074
2075 return mode->vht_capab != 0;
2076}
2077
2078
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002079void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2080 const struct wpa_ssid *ssid,
2081 struct hostapd_freq_params *freq)
2082{
2083 enum hostapd_hw_mode hw_mode;
2084 struct hostapd_hw_modes *mode = NULL;
2085 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2086 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002087 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002088 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2089 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002090 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002091 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002092 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002093 int chwidth, seg0, seg1;
2094 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002095
2096 freq->freq = ssid->frequency;
2097
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002098 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2099 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2100
2101 if (ssid->mode != WPAS_MODE_IBSS)
2102 break;
2103
2104 /* Don't adjust control freq in case of fixed_freq */
2105 if (ssid->fixed_freq)
2106 break;
2107
2108 if (!bss_is_ibss(bss))
2109 continue;
2110
2111 if (ssid->ssid_len == bss->ssid_len &&
2112 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2113 wpa_printf(MSG_DEBUG,
2114 "IBSS already found in scan results, adjust control freq: %d",
2115 bss->freq);
2116 freq->freq = bss->freq;
2117 obss_scan = 0;
2118 break;
2119 }
2120 }
2121
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002122 /* For IBSS check HT_IBSS flag */
2123 if (ssid->mode == WPAS_MODE_IBSS &&
2124 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2125 return;
2126
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002127 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2128 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2129 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2130 wpa_printf(MSG_DEBUG,
2131 "IBSS: WEP/TKIP detected, do not try to enable HT");
2132 return;
2133 }
2134
2135 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002136 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2137 if (wpa_s->hw.modes[i].mode == hw_mode) {
2138 mode = &wpa_s->hw.modes[i];
2139 break;
2140 }
2141 }
2142
2143 if (!mode)
2144 return;
2145
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002146#ifdef CONFIG_HT_OVERRIDES
2147 if (ssid->disable_ht) {
2148 freq->ht_enabled = 0;
2149 return;
2150 }
2151#endif /* CONFIG_HT_OVERRIDES */
2152
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002153 freq->ht_enabled = ht_supported(mode);
2154 if (!freq->ht_enabled)
2155 return;
2156
2157 /* Setup higher BW only for 5 GHz */
2158 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2159 return;
2160
2161 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2162 pri_chan = &mode->channels[chan_idx];
2163 if (pri_chan->chan == channel)
2164 break;
2165 pri_chan = NULL;
2166 }
2167 if (!pri_chan)
2168 return;
2169
2170 /* Check primary channel flags */
2171 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2172 return;
2173
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002174#ifdef CONFIG_HT_OVERRIDES
2175 if (ssid->disable_ht40)
2176 return;
2177#endif /* CONFIG_HT_OVERRIDES */
2178
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002179 /* Check/setup HT40+/HT40- */
2180 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2181 if (ht40plus[j] == channel) {
2182 ht40 = 1;
2183 break;
2184 }
2185 }
2186
2187 /* Find secondary channel */
2188 for (i = 0; i < mode->num_channels; i++) {
2189 sec_chan = &mode->channels[i];
2190 if (sec_chan->chan == channel + ht40 * 4)
2191 break;
2192 sec_chan = NULL;
2193 }
2194 if (!sec_chan)
2195 return;
2196
2197 /* Check secondary channel flags */
2198 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2199 return;
2200
2201 freq->channel = pri_chan->chan;
2202
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002203 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002204 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2205 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002206 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002207 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2208 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002209 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002210 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002211
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002212 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002213 struct wpa_scan_results *scan_res;
2214
2215 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2216 if (scan_res == NULL) {
2217 /* Back to HT20 */
2218 freq->sec_channel_offset = 0;
2219 return;
2220 }
2221
2222 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2223 sec_chan->chan);
2224 switch (res) {
2225 case 0:
2226 /* Back to HT20 */
2227 freq->sec_channel_offset = 0;
2228 break;
2229 case 1:
2230 /* Configuration allowed */
2231 break;
2232 case 2:
2233 /* Switch pri/sec channels */
2234 freq->freq = hw_get_freq(mode, sec_chan->chan);
2235 freq->sec_channel_offset = -freq->sec_channel_offset;
2236 freq->channel = sec_chan->chan;
2237 break;
2238 default:
2239 freq->sec_channel_offset = 0;
2240 break;
2241 }
2242
2243 wpa_scan_results_free(scan_res);
2244 }
2245
2246 wpa_printf(MSG_DEBUG,
2247 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2248 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002249
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002250 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002251 return;
2252
2253 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002254 if (ssid->mode == WPAS_MODE_IBSS &&
2255 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002256 return;
2257
2258 vht_freq = *freq;
2259
Paul Stewart092955c2017-02-06 09:13:09 -08002260#ifdef CONFIG_VHT_OVERRIDES
2261 if (ssid->disable_vht) {
2262 freq->vht_enabled = 0;
2263 return;
2264 }
2265#endif /* CONFIG_VHT_OVERRIDES */
2266
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002267 vht_freq.vht_enabled = vht_supported(mode);
2268 if (!vht_freq.vht_enabled)
2269 return;
2270
2271 /* setup center_freq1, bandwidth */
2272 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2273 if (freq->channel >= vht80[j] &&
2274 freq->channel < vht80[j] + 16)
2275 break;
2276 }
2277
2278 if (j == ARRAY_SIZE(vht80))
2279 return;
2280
2281 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2282 struct hostapd_channel_data *chan;
2283
2284 chan = hw_get_channel_chan(mode, i, NULL);
2285 if (!chan)
2286 return;
2287
2288 /* Back to HT configuration if channel not usable */
2289 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2290 return;
2291 }
2292
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002293 chwidth = VHT_CHANWIDTH_80MHZ;
2294 seg0 = vht80[j] + 6;
2295 seg1 = 0;
2296
2297 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2298 /* setup center_freq2, bandwidth */
2299 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2300 /* Only accept 80 MHz segments separated by a gap */
2301 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2302 continue;
2303 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2304 struct hostapd_channel_data *chan;
2305
2306 chan = hw_get_channel_chan(mode, i, NULL);
2307 if (!chan)
2308 continue;
2309
2310 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2311 HOSTAPD_CHAN_NO_IR |
2312 HOSTAPD_CHAN_RADAR))
2313 continue;
2314
2315 /* Found a suitable second segment for 80+80 */
2316 chwidth = VHT_CHANWIDTH_80P80MHZ;
2317 vht_caps |=
2318 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2319 seg1 = vht80[k] + 6;
2320 }
2321
2322 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2323 break;
2324 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002325 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2326 if (freq->freq == 5180) {
2327 chwidth = VHT_CHANWIDTH_160MHZ;
2328 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2329 seg0 = 50;
2330 } else if (freq->freq == 5520) {
2331 chwidth = VHT_CHANWIDTH_160MHZ;
2332 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2333 seg0 = 114;
2334 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002335 }
2336
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002337 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2338 freq->channel, freq->ht_enabled,
2339 vht_freq.vht_enabled,
2340 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002341 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002342 return;
2343
2344 *freq = vht_freq;
2345
2346 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2347 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002348}
2349
2350
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002351#ifdef CONFIG_FILS
2352static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2353 size_t ie_buf_len)
2354{
2355 struct fils_hlp_req *req;
2356 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2357 const u8 *pos;
2358 u8 *buf = ie_buf;
2359
2360 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2361 list) {
2362 rem_len = ie_buf_len - ie_len;
2363 pos = wpabuf_head(req->pkt);
2364 hdr_len = 1 + 2 * ETH_ALEN + 6;
2365 hlp_len = wpabuf_len(req->pkt);
2366
2367 if (rem_len < 2 + hdr_len + hlp_len) {
2368 wpa_printf(MSG_ERROR,
2369 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2370 (unsigned long) rem_len,
2371 (unsigned long) (2 + hdr_len + hlp_len));
2372 break;
2373 }
2374
2375 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2376 /* Element ID */
2377 *buf++ = WLAN_EID_EXTENSION;
2378 /* Length */
2379 *buf++ = len;
2380 /* Element ID Extension */
2381 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2382 /* Destination MAC address */
2383 os_memcpy(buf, req->dst, ETH_ALEN);
2384 buf += ETH_ALEN;
2385 /* Source MAC address */
2386 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2387 buf += ETH_ALEN;
2388 /* LLC/SNAP Header */
2389 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2390 buf += 6;
2391 /* HLP Packet */
2392 os_memcpy(buf, pos, len - hdr_len);
2393 buf += len - hdr_len;
2394 pos += len - hdr_len;
2395
2396 hlp_len -= len - hdr_len;
2397 ie_len += 2 + len;
2398 rem_len -= 2 + len;
2399
2400 while (hlp_len) {
2401 len = (hlp_len > 255) ? 255 : hlp_len;
2402 if (rem_len < 2 + len)
2403 break;
2404 *buf++ = WLAN_EID_FRAGMENT;
2405 *buf++ = len;
2406 os_memcpy(buf, pos, len);
2407 buf += len;
2408 pos += len;
2409
2410 hlp_len -= len;
2411 ie_len += 2 + len;
2412 rem_len -= 2 + len;
2413 }
2414 }
2415
2416 return ie_len;
2417}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002418
2419
2420int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2421{
2422 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2423 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2424 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2425 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2426}
2427
2428
2429int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2430{
2431#ifdef CONFIG_FILS_SK_PFS
2432 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2433 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2434#else /* CONFIG_FILS_SK_PFS */
2435 return 0;
2436#endif /* CONFIG_FILS_SK_PFS */
2437}
2438
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002439#endif /* CONFIG_FILS */
2440
2441
2442static u8 * wpas_populate_assoc_ies(
2443 struct wpa_supplicant *wpa_s,
2444 struct wpa_bss *bss, struct wpa_ssid *ssid,
2445 struct wpa_driver_associate_params *params,
2446 enum wpa_drv_update_connect_params_mask *mask)
2447{
2448 u8 *wpa_ie;
2449 size_t max_wpa_ie_len = 500;
2450 size_t wpa_ie_len;
2451 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002452#ifdef CONFIG_MBO
2453 const u8 *mbo_ie;
2454#endif
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002455#ifdef CONFIG_FILS
2456 const u8 *realm, *username, *rrk;
2457 size_t realm_len, username_len, rrk_len;
2458 u16 next_seq_num;
2459 struct fils_hlp_req *req;
2460
2461 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2462 list) {
2463 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2464 2 + 2 * wpabuf_len(req->pkt) / 255;
2465 }
2466#endif /* CONFIG_FILS */
2467
2468 wpa_ie = os_malloc(max_wpa_ie_len);
2469 if (!wpa_ie) {
2470 wpa_printf(MSG_ERROR,
2471 "Failed to allocate connect IE buffer for %lu bytes",
2472 (unsigned long) max_wpa_ie_len);
2473 return NULL;
2474 }
2475
2476 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2477 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2478 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2479 int try_opportunistic;
2480 const u8 *cache_id = NULL;
2481
2482 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2483 wpa_s->conf->okc :
2484 ssid->proactive_key_caching) &&
2485 (ssid->proto & WPA_PROTO_RSN);
2486#ifdef CONFIG_FILS
2487 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2488 cache_id = wpa_bss_get_fils_cache_id(bss);
2489#endif /* CONFIG_FILS */
2490 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2491 ssid, try_opportunistic,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002492 cache_id, 0) == 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002493 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
2494 wpa_ie_len = max_wpa_ie_len;
2495 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2496 wpa_ie, &wpa_ie_len)) {
2497 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2498 "key management and encryption suites");
2499 os_free(wpa_ie);
2500 return NULL;
2501 }
2502 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2503 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2504 /*
2505 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2506 * use non-WPA since the scan results did not indicate that the
2507 * AP is using WPA or WPA2.
2508 */
2509 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2510 wpa_ie_len = 0;
2511 wpa_s->wpa_proto = 0;
2512 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2513 wpa_ie_len = max_wpa_ie_len;
2514 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2515 wpa_ie, &wpa_ie_len)) {
2516 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2517 "key management and encryption suites (no "
2518 "scan results)");
2519 os_free(wpa_ie);
2520 return NULL;
2521 }
2522#ifdef CONFIG_WPS
2523 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2524 struct wpabuf *wps_ie;
2525 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2526 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2527 wpa_ie_len = wpabuf_len(wps_ie);
2528 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2529 } else
2530 wpa_ie_len = 0;
2531 wpabuf_free(wps_ie);
2532 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2533 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2534 params->wps = WPS_MODE_PRIVACY;
2535 else
2536 params->wps = WPS_MODE_OPEN;
2537 wpa_s->wpa_proto = 0;
2538#endif /* CONFIG_WPS */
2539 } else {
2540 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2541 wpa_ie_len = 0;
2542 wpa_s->wpa_proto = 0;
2543 }
2544
2545#ifdef IEEE8021X_EAPOL
2546 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2547 if (ssid->leap) {
2548 if (ssid->non_leap == 0)
2549 algs = WPA_AUTH_ALG_LEAP;
2550 else
2551 algs |= WPA_AUTH_ALG_LEAP;
2552 }
2553 }
2554
2555#ifdef CONFIG_FILS
2556 /* Clear FILS association */
2557 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2558
2559 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2560 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2561 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2562 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002563 &next_seq_num, &rrk, &rrk_len) == 0 &&
2564 (!wpa_s->last_con_fail_realm ||
2565 wpa_s->last_con_fail_realm_len != realm_len ||
2566 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002567 algs = WPA_AUTH_ALG_FILS;
2568 params->fils_erp_username = username;
2569 params->fils_erp_username_len = username_len;
2570 params->fils_erp_realm = realm;
2571 params->fils_erp_realm_len = realm_len;
2572 params->fils_erp_next_seq_num = next_seq_num;
2573 params->fils_erp_rrk = rrk;
2574 params->fils_erp_rrk_len = rrk_len;
2575
2576 if (mask)
2577 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2578 }
2579#endif /* CONFIG_FILS */
2580#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002581#ifdef CONFIG_SAE
2582 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2583 algs = WPA_AUTH_ALG_SAE;
2584#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002585
2586 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2587 if (ssid->auth_alg) {
2588 algs = ssid->auth_alg;
2589 wpa_dbg(wpa_s, MSG_DEBUG,
2590 "Overriding auth_alg selection: 0x%x", algs);
2591 }
2592
2593#ifdef CONFIG_P2P
2594 if (wpa_s->global->p2p) {
2595 u8 *pos;
2596 size_t len;
2597 int res;
2598 pos = wpa_ie + wpa_ie_len;
2599 len = max_wpa_ie_len - wpa_ie_len;
2600 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2601 ssid->p2p_group);
2602 if (res >= 0)
2603 wpa_ie_len += res;
2604 }
2605
2606 wpa_s->cross_connect_disallowed = 0;
2607 if (bss) {
2608 struct wpabuf *p2p;
2609 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2610 if (p2p) {
2611 wpa_s->cross_connect_disallowed =
2612 p2p_get_cross_connect_disallowed(p2p);
2613 wpabuf_free(p2p);
2614 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2615 "connection",
2616 wpa_s->cross_connect_disallowed ?
2617 "disallows" : "allows");
2618 }
2619 }
2620
2621 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2622#endif /* CONFIG_P2P */
2623
2624 if (bss) {
2625 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
2626 wpa_ie + wpa_ie_len,
2627 max_wpa_ie_len -
2628 wpa_ie_len);
2629 }
2630
2631 /*
2632 * Workaround: Add Extended Capabilities element only if the AP
2633 * included this element in Beacon/Probe Response frames. Some older
2634 * APs seem to have interoperability issues if this element is
2635 * included, so while the standard may require us to include the
2636 * element in all cases, it is justifiable to skip it to avoid
2637 * interoperability issues.
2638 */
2639 if (ssid->p2p_group)
2640 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2641 else
2642 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2643
2644 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2645 u8 ext_capab[18];
2646 int ext_capab_len;
2647 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2648 sizeof(ext_capab));
2649 if (ext_capab_len > 0 &&
2650 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2651 u8 *pos = wpa_ie;
2652 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2653 pos += 2 + pos[1];
2654 os_memmove(pos + ext_capab_len, pos,
2655 wpa_ie_len - (pos - wpa_ie));
2656 wpa_ie_len += ext_capab_len;
2657 os_memcpy(pos, ext_capab, ext_capab_len);
2658 }
2659 }
2660
2661#ifdef CONFIG_HS20
2662 if (is_hs20_network(wpa_s, ssid, bss)) {
2663 struct wpabuf *hs20;
2664
Roshan Pius3a1667e2018-07-03 15:17:14 -07002665 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002666 if (hs20) {
2667 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2668 size_t len;
2669
2670 wpas_hs20_add_indication(hs20, pps_mo_id);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002671 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002672 len = max_wpa_ie_len - wpa_ie_len;
2673 if (wpabuf_len(hs20) <= len) {
2674 os_memcpy(wpa_ie + wpa_ie_len,
2675 wpabuf_head(hs20), wpabuf_len(hs20));
2676 wpa_ie_len += wpabuf_len(hs20);
2677 }
2678 wpabuf_free(hs20);
2679
2680 hs20_configure_frame_filters(wpa_s);
2681 }
2682 }
2683#endif /* CONFIG_HS20 */
2684
2685 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2686 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2687 size_t len;
2688
2689 len = max_wpa_ie_len - wpa_ie_len;
2690 if (wpabuf_len(buf) <= len) {
2691 os_memcpy(wpa_ie + wpa_ie_len,
2692 wpabuf_head(buf), wpabuf_len(buf));
2693 wpa_ie_len += wpabuf_len(buf);
2694 }
2695 }
2696
2697#ifdef CONFIG_FST
2698 if (wpa_s->fst_ies) {
2699 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2700
2701 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
2702 os_memcpy(wpa_ie + wpa_ie_len,
2703 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2704 wpa_ie_len += fst_ies_len;
2705 }
2706 }
2707#endif /* CONFIG_FST */
2708
2709#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07002710 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
2711 if (mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002712 int len;
2713
2714 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002715 max_wpa_ie_len - wpa_ie_len,
2716 !!mbo_attr_from_mbo_ie(mbo_ie,
2717 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002718 if (len >= 0)
2719 wpa_ie_len += len;
2720 }
2721#endif /* CONFIG_MBO */
2722
2723#ifdef CONFIG_FILS
2724 if (algs == WPA_AUTH_ALG_FILS) {
2725 size_t len;
2726
2727 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
2728 max_wpa_ie_len - wpa_ie_len);
2729 wpa_ie_len += len;
2730 }
2731#endif /* CONFIG_FILS */
2732
2733#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002734#ifdef CONFIG_TESTING_OPTIONS
2735 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
2736 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2737 } else
2738#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002739 if (algs == WPA_AUTH_ALG_OPEN &&
2740 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
2741 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002742 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002743
Roshan Pius3a1667e2018-07-03 15:17:14 -07002744 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002745 group = ssid->owe_group;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002746 } else {
2747 if (wpa_s->last_owe_group == 19)
2748 group = 20;
2749 else if (wpa_s->last_owe_group == 20)
2750 group = 21;
2751 else
2752 group = OWE_DH_GROUP;
2753 }
2754 wpa_s->last_owe_group = group;
2755 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002756 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2757 if (owe_ie &&
2758 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
2759 os_memcpy(wpa_ie + wpa_ie_len,
2760 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2761 wpa_ie_len += wpabuf_len(owe_ie);
2762 wpabuf_free(owe_ie);
2763 }
2764 }
2765#endif /* CONFIG_OWE */
2766
Roshan Pius3a1667e2018-07-03 15:17:14 -07002767#ifdef CONFIG_IEEE80211R
2768 /*
2769 * Add MDIE under these conditions: the network profile allows FT,
2770 * the AP supports FT, and the mobility domain ID matches.
2771 */
2772 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
2773 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2774
2775 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
2776 size_t len = 0;
2777 const u8 *md = mdie + 2;
2778 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
2779
2780 if (os_memcmp(md, wpa_md,
2781 MOBILITY_DOMAIN_ID_LEN) == 0) {
2782 /* Add mobility domain IE */
2783 len = wpa_ft_add_mdie(
2784 wpa_s->wpa, wpa_ie + wpa_ie_len,
2785 max_wpa_ie_len - wpa_ie_len, mdie);
2786 wpa_ie_len += len;
2787 }
2788#ifdef CONFIG_SME
2789 if (len > 0 && wpa_s->sme.ft_used &&
2790 wpa_sm_has_ptk(wpa_s->wpa)) {
2791 wpa_dbg(wpa_s, MSG_DEBUG,
2792 "SME: Trying to use FT over-the-air");
2793 algs |= WPA_AUTH_ALG_FT;
2794 }
2795#endif /* CONFIG_SME */
2796 }
2797 }
2798#endif /* CONFIG_IEEE80211R */
2799
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002800 params->wpa_ie = wpa_ie;
2801 params->wpa_ie_len = wpa_ie_len;
2802 params->auth_alg = algs;
2803 if (mask)
2804 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
2805
2806 return wpa_ie;
2807}
2808
2809
2810#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
2811static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
2812{
2813 struct wpa_driver_associate_params params;
2814 enum wpa_drv_update_connect_params_mask mask = 0;
2815 u8 *wpa_ie;
2816
2817 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
2818 return; /* nothing to do */
2819
2820 os_memset(&params, 0, sizeof(params));
2821 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
2822 wpa_s->current_ssid, &params, &mask);
2823 if (!wpa_ie)
2824 return;
2825
2826 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
2827 os_free(wpa_ie);
2828 return;
2829 }
2830
2831 wpa_s->auth_alg = params.auth_alg;
2832 wpa_drv_update_connect_params(wpa_s, &params, mask);
2833 os_free(wpa_ie);
2834}
2835#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
2836
2837
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002838static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2839{
2840 struct wpa_connect_work *cwork = work->ctx;
2841 struct wpa_bss *bss = cwork->bss;
2842 struct wpa_ssid *ssid = cwork->ssid;
2843 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002844 u8 *wpa_ie;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002845 int use_crypt, ret, i, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002846 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002847 struct wpa_driver_associate_params params;
2848 int wep_keys_set = 0;
2849 int assoc_failed = 0;
2850 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002851 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002852#ifdef CONFIG_HT_OVERRIDES
2853 struct ieee80211_ht_capabilities htcaps;
2854 struct ieee80211_ht_capabilities htcaps_mask;
2855#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002856#ifdef CONFIG_VHT_OVERRIDES
2857 struct ieee80211_vht_capabilities vhtcaps;
2858 struct ieee80211_vht_capabilities vhtcaps_mask;
2859#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002860
2861 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002862 if (work->started) {
2863 wpa_s->connect_work = NULL;
2864
2865 /* cancel possible auth. timeout */
2866 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2867 NULL);
2868 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002869 wpas_connect_work_free(cwork);
2870 return;
2871 }
2872
2873 wpa_s->connect_work = work;
2874
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002875 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2876 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002877 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2878 wpas_connect_work_done(wpa_s);
2879 return;
2880 }
2881
Dmitry Shmidte4663042016-04-04 10:07:49 -07002882 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002883 os_memset(&params, 0, sizeof(params));
2884 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002885 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002886 if (bss &&
2887 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002888#ifdef CONFIG_IEEE80211R
2889 const u8 *ie, *md = NULL;
2890#endif /* CONFIG_IEEE80211R */
2891 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2892 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2893 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2894 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2895 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2896 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2897 if (bssid_changed)
2898 wpas_notify_bssid_changed(wpa_s);
2899#ifdef CONFIG_IEEE80211R
2900 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2901 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2902 md = ie + 2;
2903 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2904 if (md) {
2905 /* Prepare for the next transition */
2906 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2907 }
2908#endif /* CONFIG_IEEE80211R */
2909#ifdef CONFIG_WPS
2910 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2911 wpa_s->conf->ap_scan == 2 &&
2912 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2913 /* Use ap_scan==1 style network selection to find the network
2914 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002915 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002916 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002917 wpa_s->reassociate = 1;
2918 wpa_supplicant_req_scan(wpa_s, 0, 0);
2919 return;
2920#endif /* CONFIG_WPS */
2921 } else {
2922 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2923 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002924 if (bss)
2925 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2926 else
2927 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002929 if (!wpa_s->pno)
2930 wpa_supplicant_cancel_sched_scan(wpa_s);
2931
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002932 wpa_supplicant_cancel_scan(wpa_s);
2933
2934 /* Starting new association, so clear the possibly used WPA IE from the
2935 * previous association. */
2936 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2937
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002938 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
2939 if (!wpa_ie) {
2940 wpas_connect_work_done(wpa_s);
2941 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002942 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002943
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002944 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2945 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002946 cipher_pairwise = wpa_s->pairwise_cipher;
2947 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002948 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2950 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2951 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2952 use_crypt = 0;
2953 if (wpa_set_wep_keys(wpa_s, ssid)) {
2954 use_crypt = 1;
2955 wep_keys_set = 1;
2956 }
2957 }
2958 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2959 use_crypt = 0;
2960
2961#ifdef IEEE8021X_EAPOL
2962 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2963 if ((ssid->eapol_flags &
2964 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2965 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2966 !wep_keys_set) {
2967 use_crypt = 0;
2968 } else {
2969 /* Assume that dynamic WEP-104 keys will be used and
2970 * set cipher suites in order for drivers to expect
2971 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002972 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002973 }
2974 }
2975#endif /* IEEE8021X_EAPOL */
2976
2977 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2978 /* Set the key before (and later after) association */
2979 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2980 }
2981
2982 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2983 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002984 params.ssid = bss->ssid;
2985 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002986 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2987 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002988 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2989 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002990 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002991 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002992 ssid->bssid_set,
2993 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002994 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002995 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002996 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002997 params.bssid_hint = bss->bssid;
2998 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002999 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003000 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003001 if (ssid->bssid_hint_set)
3002 params.bssid_hint = ssid->bssid_hint;
3003
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003004 params.ssid = ssid->ssid;
3005 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003006 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003008
3009 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3010 wpa_s->conf->ap_scan == 2) {
3011 params.bssid = ssid->bssid;
3012 params.fixed_bssid = 1;
3013 }
3014
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003015 /* Initial frequency for IBSS/mesh */
3016 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003017 ssid->frequency > 0 && params.freq.freq == 0)
3018 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003019
3020 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003021 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003022 if (ssid->beacon_int)
3023 params.beacon_int = ssid->beacon_int;
3024 else
3025 params.beacon_int = wpa_s->conf->beacon_int;
3026 }
3027
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003028 params.pairwise_suite = cipher_pairwise;
3029 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003030 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003031 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003032 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003033 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003034 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003035 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003036 for (i = 0; i < NUM_WEP_KEYS; i++) {
3037 if (ssid->wep_key_len[i])
3038 params.wep_key[i] = ssid->wep_key[i];
3039 params.wep_key_len[i] = ssid->wep_key_len[i];
3040 }
3041 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
3042
3043 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003044 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3045 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003046 params.passphrase = ssid->passphrase;
3047 if (ssid->psk_set)
3048 params.psk = ssid->psk;
3049 }
3050
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003051 if (wpa_s->conf->key_mgmt_offload) {
3052 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3053 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003054 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3055 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003056 params.req_key_mgmt_offload =
3057 ssid->proactive_key_caching < 0 ?
3058 wpa_s->conf->okc : ssid->proactive_key_caching;
3059 else
3060 params.req_key_mgmt_offload = 1;
3061
3062 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3063 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3064 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3065 ssid->psk_set)
3066 params.psk = ssid->psk;
3067 }
3068
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003069 params.drop_unencrypted = use_crypt;
3070
3071#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003072 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003073 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003074 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3075 struct wpa_ie_data ie;
3076 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3077 ie.capabilities &
3078 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3079 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3080 "MFP: require MFP");
3081 params.mgmt_frame_protection =
3082 MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003083#ifdef CONFIG_OWE
3084 } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
3085 !ssid->owe_only) {
3086 params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
3087#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003088 }
3089 }
3090#endif /* CONFIG_IEEE80211W */
3091
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003092 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003093
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003094 if (wpa_s->p2pdev->set_sta_uapsd)
3095 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003096 else
3097 params.uapsd = -1;
3098
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003099#ifdef CONFIG_HT_OVERRIDES
3100 os_memset(&htcaps, 0, sizeof(htcaps));
3101 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3102 params.htcaps = (u8 *) &htcaps;
3103 params.htcaps_mask = (u8 *) &htcaps_mask;
3104 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3105#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003106#ifdef CONFIG_VHT_OVERRIDES
3107 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3108 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3109 params.vhtcaps = &vhtcaps;
3110 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003111 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003112#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003113
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003114#ifdef CONFIG_P2P
3115 /*
3116 * If multi-channel concurrency is not supported, check for any
3117 * frequency conflict. In case of any frequency conflict, remove the
3118 * least prioritized connection.
3119 */
3120 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003121 int freq, num;
3122 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003123 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003124 wpa_printf(MSG_DEBUG,
3125 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003126 freq, params.freq.freq);
3127 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003128 wpa_s, params.freq.freq, ssid) < 0) {
3129 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003130 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003131 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003132 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003133 }
3134 }
3135#endif /* CONFIG_P2P */
3136
Dmitry Shmidte4663042016-04-04 10:07:49 -07003137 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3138 wpa_s->current_ssid)
3139 params.prev_bssid = prev_bssid;
3140
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003141 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003142 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003143 if (ret < 0) {
3144 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3145 "failed");
3146 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3147 /*
3148 * The driver is known to mean what is saying, so we
3149 * can stop right here; the association will not
3150 * succeed.
3151 */
3152 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003153 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003154 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3155 return;
3156 }
3157 /* try to continue anyway; new association will be tried again
3158 * after timeout */
3159 assoc_failed = 1;
3160 }
3161
3162 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3163 /* Set the key after the association just in case association
3164 * cleared the previously configured key. */
3165 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3166 /* No need to timeout authentication since there is no key
3167 * management. */
3168 wpa_supplicant_cancel_auth_timeout(wpa_s);
3169 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3170#ifdef CONFIG_IBSS_RSN
3171 } else if (ssid->mode == WPAS_MODE_IBSS &&
3172 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3173 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3174 /*
3175 * RSN IBSS authentication is per-STA and we can disable the
3176 * per-BSSID authentication.
3177 */
3178 wpa_supplicant_cancel_auth_timeout(wpa_s);
3179#endif /* CONFIG_IBSS_RSN */
3180 } else {
3181 /* Timeout for IEEE 802.11 authentication and association */
3182 int timeout = 60;
3183
3184 if (assoc_failed) {
3185 /* give IBSS a bit more time */
3186 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3187 } else if (wpa_s->conf->ap_scan == 1) {
3188 /* give IBSS a bit more time */
3189 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3190 }
3191 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3192 }
3193
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003194 if (wep_keys_set &&
3195 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003196 /* Set static WEP keys again */
3197 wpa_set_wep_keys(wpa_s, ssid);
3198 }
3199
3200 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3201 /*
3202 * Do not allow EAP session resumption between different
3203 * network configurations.
3204 */
3205 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3206 }
3207 old_ssid = wpa_s->current_ssid;
3208 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003209
3210 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003211 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003212#ifdef CONFIG_HS20
3213 hs20_configure_frame_filters(wpa_s);
3214#endif /* CONFIG_HS20 */
3215 }
3216
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003217 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3218 wpa_supplicant_initiate_eapol(wpa_s);
3219 if (old_ssid != wpa_s->current_ssid)
3220 wpas_notify_network_changed(wpa_s);
3221}
3222
3223
3224static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3225 const u8 *addr)
3226{
3227 struct wpa_ssid *old_ssid;
3228
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003229 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003230 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003231 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003232 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003233 wpa_sm_set_config(wpa_s->wpa, NULL);
3234 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3235 if (old_ssid != wpa_s->current_ssid)
3236 wpas_notify_network_changed(wpa_s);
3237 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3238}
3239
3240
3241/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003242 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3243 * @wpa_s: Pointer to wpa_supplicant data
3244 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3245 *
3246 * This function is used to request %wpa_supplicant to deauthenticate from the
3247 * current AP.
3248 */
3249void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
3250 int reason_code)
3251{
3252 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003253 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003254 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003255
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003256 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
3257 " pending_bssid=" MACSTR " reason=%d state=%s",
3258 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
3259 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
3260
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003261 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3262 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3263 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003264 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003265 else if (!is_zero_ether_addr(wpa_s->bssid))
3266 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003267 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3268 /*
3269 * When using driver-based BSS selection, we may not know the
3270 * BSSID with which we are currently trying to associate. We
3271 * need to notify the driver of this disconnection even in such
3272 * a case, so use the all zeros address here.
3273 */
3274 addr = wpa_s->bssid;
3275 zero_addr = 1;
3276 }
3277
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003278#ifdef CONFIG_TDLS
3279 wpa_tdls_teardown_peers(wpa_s->wpa);
3280#endif /* CONFIG_TDLS */
3281
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003282#ifdef CONFIG_MESH
3283 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003284 struct mesh_conf *mconf;
3285
3286 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003287 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3288 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003289 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3290 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003291 wpa_supplicant_leave_mesh(wpa_s);
3292 }
3293#endif /* CONFIG_MESH */
3294
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003295 if (addr) {
3296 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003297 os_memset(&event, 0, sizeof(event));
3298 event.deauth_info.reason_code = (u16) reason_code;
3299 event.deauth_info.locally_generated = 1;
3300 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003301 if (zero_addr)
3302 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003303 }
3304
3305 wpa_supplicant_clear_connection(wpa_s, addr);
3306}
3307
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003308static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3309 struct wpa_ssid *ssid)
3310{
3311 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3312 return;
3313
3314 ssid->disabled = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003315 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003316 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3317 wpas_notify_network_enabled_changed(wpa_s, ssid);
3318
3319 /*
3320 * Try to reassociate since there is no current configuration and a new
3321 * network was made available.
3322 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003323 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003324 wpa_s->reassociate = 1;
3325}
3326
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003327
Roshan Pius950bec92016-07-19 09:49:24 -07003328/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003329 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003330 * @wpa_s: wpa_supplicant structure for a network interface
3331 * Returns: The new network configuration or %NULL if operation failed
3332 *
3333 * This function performs the following operations:
3334 * 1. Adds a new network.
3335 * 2. Send network addition notification.
3336 * 3. Marks the network disabled.
3337 * 4. Set network default parameters.
3338 */
3339struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3340{
3341 struct wpa_ssid *ssid;
3342
3343 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003344 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003345 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003346 wpas_notify_network_added(wpa_s, ssid);
3347 ssid->disabled = 1;
3348 wpa_config_set_network_defaults(ssid);
3349
3350 return ssid;
3351}
3352
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003353
Roshan Pius950bec92016-07-19 09:49:24 -07003354/**
3355 * wpa_supplicant_remove_network - Remove a configured network based on id
3356 * @wpa_s: wpa_supplicant structure for a network interface
3357 * @id: Unique network id to search for
3358 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3359 * could not be removed
3360 *
3361 * This function performs the following operations:
3362 * 1. Removes the network.
3363 * 2. Send network removal notification.
3364 * 3. Update internal state machines.
3365 * 4. Stop any running sched scans.
3366 */
3367int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
3368{
3369 struct wpa_ssid *ssid;
3370 int was_disabled;
3371
3372 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003373 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003374 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003375 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07003376
3377 if (wpa_s->last_ssid == ssid)
3378 wpa_s->last_ssid = NULL;
3379
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003380 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07003381#ifdef CONFIG_SME
3382 wpa_s->sme.prev_bssid_set = 0;
3383#endif /* CONFIG_SME */
3384 /*
3385 * Invalidate the EAP session cache if the current or
3386 * previously used network is removed.
3387 */
3388 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3389 }
3390
3391 if (ssid == wpa_s->current_ssid) {
3392 wpa_sm_set_config(wpa_s->wpa, NULL);
3393 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3394
3395 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3396 wpa_s->own_disconnect_req = 1;
3397 wpa_supplicant_deauthenticate(wpa_s,
3398 WLAN_REASON_DEAUTH_LEAVING);
3399 }
3400
3401 was_disabled = ssid->disabled;
3402
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003403 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07003404 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07003405
3406 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003407 wpa_printf(MSG_DEBUG,
3408 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07003409 wpa_supplicant_cancel_sched_scan(wpa_s);
3410 wpa_supplicant_req_scan(wpa_s, 0, 0);
3411 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003412
Roshan Pius950bec92016-07-19 09:49:24 -07003413 return 0;
3414}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003415
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003416
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003417/**
3418 * wpa_supplicant_enable_network - Mark a configured network as enabled
3419 * @wpa_s: wpa_supplicant structure for a network interface
3420 * @ssid: wpa_ssid structure for a configured network or %NULL
3421 *
3422 * Enables the specified network or all networks if no network specified.
3423 */
3424void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
3425 struct wpa_ssid *ssid)
3426{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003427 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003428 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3429 wpa_supplicant_enable_one_network(wpa_s, ssid);
3430 } else
3431 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003432
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003433 if (wpa_s->reassociate && !wpa_s->disconnected &&
3434 (!wpa_s->current_ssid ||
3435 wpa_s->wpa_state == WPA_DISCONNECTED ||
3436 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003437 if (wpa_s->sched_scanning) {
3438 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
3439 "new network to scan filters");
3440 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003441 }
3442
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003443 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3444 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003445 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003446 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003447 }
3448}
3449
3450
3451/**
3452 * wpa_supplicant_disable_network - Mark a configured network as disabled
3453 * @wpa_s: wpa_supplicant structure for a network interface
3454 * @ssid: wpa_ssid structure for a configured network or %NULL
3455 *
3456 * Disables the specified network or all networks if no network specified.
3457 */
3458void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
3459 struct wpa_ssid *ssid)
3460{
3461 struct wpa_ssid *other_ssid;
3462 int was_disabled;
3463
3464 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003465 if (wpa_s->sched_scanning)
3466 wpa_supplicant_cancel_sched_scan(wpa_s);
3467
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3469 other_ssid = other_ssid->next) {
3470 was_disabled = other_ssid->disabled;
3471 if (was_disabled == 2)
3472 continue; /* do not change persistent P2P group
3473 * data */
3474
3475 other_ssid->disabled = 1;
3476
3477 if (was_disabled != other_ssid->disabled)
3478 wpas_notify_network_enabled_changed(
3479 wpa_s, other_ssid);
3480 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003481 if (wpa_s->current_ssid) {
3482 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3483 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003484 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003485 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003486 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003487 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003488 if (ssid == wpa_s->current_ssid) {
3489 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3490 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003491 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003492 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003493 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003494
3495 was_disabled = ssid->disabled;
3496
3497 ssid->disabled = 1;
3498
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003499 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003500 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003501 if (wpa_s->sched_scanning) {
3502 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3503 "to remove network from filters");
3504 wpa_supplicant_cancel_sched_scan(wpa_s);
3505 wpa_supplicant_req_scan(wpa_s, 0, 0);
3506 }
3507 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003508 }
3509}
3510
3511
3512/**
3513 * wpa_supplicant_select_network - Attempt association with a network
3514 * @wpa_s: wpa_supplicant structure for a network interface
3515 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3516 */
3517void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3518 struct wpa_ssid *ssid)
3519{
3520
3521 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003522 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003523
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003524 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003525 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3526 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003527 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003528 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003529 disconnected = 1;
3530 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003531
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003532 if (ssid)
3533 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3534
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003535 /*
3536 * Mark all other networks disabled or mark all networks enabled if no
3537 * network specified.
3538 */
3539 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3540 other_ssid = other_ssid->next) {
3541 int was_disabled = other_ssid->disabled;
3542 if (was_disabled == 2)
3543 continue; /* do not change persistent P2P group data */
3544
3545 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003546 if (was_disabled && !other_ssid->disabled)
3547 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003548
3549 if (was_disabled != other_ssid->disabled)
3550 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3551 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003552
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003553 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3554 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003555 /* We are already associated with the selected network */
3556 wpa_printf(MSG_DEBUG, "Already associated with the "
3557 "selected network - do nothing");
3558 return;
3559 }
3560
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003561 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003562 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003563 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003564 wpa_s->connect_without_scan =
3565 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003566
3567 /*
3568 * Don't optimize next scan freqs since a new ESS has been
3569 * selected.
3570 */
3571 os_free(wpa_s->next_scan_freqs);
3572 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003573 } else {
3574 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003575 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003576
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003577 wpa_s->disconnected = 0;
3578 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003579 wpa_s->last_owe_group = 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003580 if (ssid)
3581 ssid->owe_transition_bss_select_count = 0;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003582
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003583 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003584 wpa_supplicant_fast_associate(wpa_s) != 1) {
3585 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003586 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003587 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003588 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003589
3590 if (ssid)
3591 wpas_notify_network_selected(wpa_s, ssid);
3592}
3593
3594
3595/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003596 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3597 * @wpa_s: wpa_supplicant structure for a network interface
3598 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3599 * @pkcs11_module_path: PKCS #11 module path or NULL
3600 * Returns: 0 on success; -1 on failure
3601 *
3602 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3603 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3604 * module path fails the paths will be reset to the default value (NULL).
3605 */
3606int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3607 const char *pkcs11_engine_path,
3608 const char *pkcs11_module_path)
3609{
3610 char *pkcs11_engine_path_copy = NULL;
3611 char *pkcs11_module_path_copy = NULL;
3612
3613 if (pkcs11_engine_path != NULL) {
3614 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3615 if (pkcs11_engine_path_copy == NULL)
3616 return -1;
3617 }
3618 if (pkcs11_module_path != NULL) {
3619 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003620 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003621 os_free(pkcs11_engine_path_copy);
3622 return -1;
3623 }
3624 }
3625
3626 os_free(wpa_s->conf->pkcs11_engine_path);
3627 os_free(wpa_s->conf->pkcs11_module_path);
3628 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3629 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3630
3631 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3632 eapol_sm_deinit(wpa_s->eapol);
3633 wpa_s->eapol = NULL;
3634 if (wpa_supplicant_init_eapol(wpa_s)) {
3635 /* Error -> Reset paths to the default value (NULL) once. */
3636 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3637 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3638 NULL);
3639
3640 return -1;
3641 }
3642 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3643
3644 return 0;
3645}
3646
3647
3648/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003649 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3650 * @wpa_s: wpa_supplicant structure for a network interface
3651 * @ap_scan: AP scan mode
3652 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3653 *
3654 */
3655int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3656{
3657
3658 int old_ap_scan;
3659
3660 if (ap_scan < 0 || ap_scan > 2)
3661 return -1;
3662
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003663 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3664 wpa_printf(MSG_INFO,
3665 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3666 }
3667
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003668#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003669 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3670 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3671 wpa_s->wpa_state < WPA_COMPLETED) {
3672 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3673 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003674 return 0;
3675 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003676#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003677
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003678 old_ap_scan = wpa_s->conf->ap_scan;
3679 wpa_s->conf->ap_scan = ap_scan;
3680
3681 if (old_ap_scan != wpa_s->conf->ap_scan)
3682 wpas_notify_ap_scan_changed(wpa_s);
3683
3684 return 0;
3685}
3686
3687
3688/**
3689 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3690 * @wpa_s: wpa_supplicant structure for a network interface
3691 * @expire_age: Expiration age in seconds
3692 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3693 *
3694 */
3695int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3696 unsigned int bss_expire_age)
3697{
3698 if (bss_expire_age < 10) {
3699 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3700 bss_expire_age);
3701 return -1;
3702 }
3703 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3704 bss_expire_age);
3705 wpa_s->conf->bss_expiration_age = bss_expire_age;
3706
3707 return 0;
3708}
3709
3710
3711/**
3712 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3713 * @wpa_s: wpa_supplicant structure for a network interface
3714 * @expire_count: number of scans after which an unseen BSS is reclaimed
3715 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3716 *
3717 */
3718int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3719 unsigned int bss_expire_count)
3720{
3721 if (bss_expire_count < 1) {
3722 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3723 bss_expire_count);
3724 return -1;
3725 }
3726 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3727 bss_expire_count);
3728 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3729
3730 return 0;
3731}
3732
3733
3734/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003735 * wpa_supplicant_set_scan_interval - Set scan interval
3736 * @wpa_s: wpa_supplicant structure for a network interface
3737 * @scan_interval: scan interval in seconds
3738 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3739 *
3740 */
3741int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3742 int scan_interval)
3743{
3744 if (scan_interval < 0) {
3745 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3746 scan_interval);
3747 return -1;
3748 }
3749 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3750 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003751 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003752
3753 return 0;
3754}
3755
3756
3757/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003758 * wpa_supplicant_set_debug_params - Set global debug params
3759 * @global: wpa_global structure
3760 * @debug_level: debug level
3761 * @debug_timestamp: determines if show timestamp in debug data
3762 * @debug_show_keys: determines if show keys in debug data
3763 * Returns: 0 if succeed or -1 if debug_level has wrong value
3764 */
3765int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3766 int debug_timestamp, int debug_show_keys)
3767{
3768
3769 int old_level, old_timestamp, old_show_keys;
3770
3771 /* check for allowed debuglevels */
3772 if (debug_level != MSG_EXCESSIVE &&
3773 debug_level != MSG_MSGDUMP &&
3774 debug_level != MSG_DEBUG &&
3775 debug_level != MSG_INFO &&
3776 debug_level != MSG_WARNING &&
3777 debug_level != MSG_ERROR)
3778 return -1;
3779
3780 old_level = wpa_debug_level;
3781 old_timestamp = wpa_debug_timestamp;
3782 old_show_keys = wpa_debug_show_keys;
3783
3784 wpa_debug_level = debug_level;
3785 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3786 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3787
3788 if (wpa_debug_level != old_level)
3789 wpas_notify_debug_level_changed(global);
3790 if (wpa_debug_timestamp != old_timestamp)
3791 wpas_notify_debug_timestamp_changed(global);
3792 if (wpa_debug_show_keys != old_show_keys)
3793 wpas_notify_debug_show_keys_changed(global);
3794
3795 return 0;
3796}
3797
3798
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003799#ifdef CONFIG_OWE
3800static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
3801 const u8 *entry_ssid, size_t entry_ssid_len)
3802{
3803 const u8 *owe, *pos, *end;
3804 u8 ssid_len;
3805 struct wpa_bss *bss;
3806
3807 /* Check network profile SSID aganst the SSID in the
3808 * OWE Transition Mode element. */
3809
3810 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
3811 if (!bss)
3812 return 0;
3813
3814 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3815 if (!owe)
3816 return 0;
3817
3818 pos = owe + 6;
3819 end = owe + 2 + owe[1];
3820
3821 if (end - pos < ETH_ALEN + 1)
3822 return 0;
3823 pos += ETH_ALEN;
3824 ssid_len = *pos++;
3825 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
3826 return 0;
3827
3828 return entry_ssid_len == ssid_len &&
3829 os_memcmp(pos, entry_ssid, ssid_len) == 0;
3830}
3831#endif /* CONFIG_OWE */
3832
3833
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003834/**
3835 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3836 * @wpa_s: Pointer to wpa_supplicant data
3837 * Returns: A pointer to the current network structure or %NULL on failure
3838 */
3839struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3840{
3841 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003842 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003843 int res;
3844 size_t ssid_len;
3845 u8 bssid[ETH_ALEN];
3846 int wired;
3847
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003848 res = wpa_drv_get_ssid(wpa_s, ssid);
3849 if (res < 0) {
3850 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3851 "driver");
3852 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003853 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003854 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003855
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003856 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003857 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3858 "driver");
3859 return NULL;
3860 }
3861
3862 wired = wpa_s->conf->ap_scan == 0 &&
3863 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3864
3865 entry = wpa_s->conf->ssid;
3866 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003867 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003868 ((ssid_len == entry->ssid_len &&
3869 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3870 (!entry->bssid_set ||
3871 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3872 return entry;
3873#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003874 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003875 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3876 (entry->ssid == NULL || entry->ssid_len == 0) &&
3877 (!entry->bssid_set ||
3878 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3879 return entry;
3880#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003881
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003882#ifdef CONFIG_OWE
3883 if (!wpas_network_disabled(wpa_s, entry) &&
3884 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
3885 entry->ssid_len) &&
3886 (!entry->bssid_set ||
3887 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3888 return entry;
3889#endif /* CONFIG_OWE */
3890
Dmitry Shmidt04949592012-07-19 12:16:46 -07003891 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003892 entry->ssid_len == 0 &&
3893 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3894 return entry;
3895
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003896 entry = entry->next;
3897 }
3898
3899 return NULL;
3900}
3901
3902
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003903static int select_driver(struct wpa_supplicant *wpa_s, int i)
3904{
3905 struct wpa_global *global = wpa_s->global;
3906
3907 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003908 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003909 if (global->drv_priv[i] == NULL) {
3910 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3911 "'%s'", wpa_drivers[i]->name);
3912 return -1;
3913 }
3914 }
3915
3916 wpa_s->driver = wpa_drivers[i];
3917 wpa_s->global_drv_priv = global->drv_priv[i];
3918
3919 return 0;
3920}
3921
3922
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3924 const char *name)
3925{
3926 int i;
3927 size_t len;
3928 const char *pos, *driver = name;
3929
3930 if (wpa_s == NULL)
3931 return -1;
3932
3933 if (wpa_drivers[0] == NULL) {
3934 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3935 "wpa_supplicant");
3936 return -1;
3937 }
3938
3939 if (name == NULL) {
3940 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003941 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003942 }
3943
3944 do {
3945 pos = os_strchr(driver, ',');
3946 if (pos)
3947 len = pos - driver;
3948 else
3949 len = os_strlen(driver);
3950
3951 for (i = 0; wpa_drivers[i]; i++) {
3952 if (os_strlen(wpa_drivers[i]->name) == len &&
3953 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003954 0) {
3955 /* First driver that succeeds wins */
3956 if (select_driver(wpa_s, i) == 0)
3957 return 0;
3958 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003959 }
3960
3961 driver = pos + 1;
3962 } while (pos);
3963
3964 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3965 return -1;
3966}
3967
3968
3969/**
3970 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3971 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3972 * with struct wpa_driver_ops::init()
3973 * @src_addr: Source address of the EAPOL frame
3974 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3975 * @len: Length of the EAPOL data
3976 *
3977 * This function is called for each received EAPOL frame. Most driver
3978 * interfaces rely on more generic OS mechanism for receiving frames through
3979 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3980 * take care of received EAPOL frames and deliver them to the core supplicant
3981 * code by calling this function.
3982 */
3983void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3984 const u8 *buf, size_t len)
3985{
3986 struct wpa_supplicant *wpa_s = ctx;
3987
3988 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3989 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3990
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003991#ifdef CONFIG_TESTING_OPTIONS
3992 if (wpa_s->ignore_auth_resp) {
3993 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3994 return;
3995 }
3996#endif /* CONFIG_TESTING_OPTIONS */
3997
Jouni Malinena05074c2012-12-21 21:35:35 +02003998 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3999 (wpa_s->last_eapol_matches_bssid &&
4000#ifdef CONFIG_AP
4001 !wpa_s->ap_iface &&
4002#endif /* CONFIG_AP */
4003 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004004 /*
4005 * There is possible race condition between receiving the
4006 * association event and the EAPOL frame since they are coming
4007 * through different paths from the driver. In order to avoid
4008 * issues in trying to process the EAPOL frame before receiving
4009 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02004010 * the association event is received. This may also be needed in
4011 * driver-based roaming case, so also use src_addr != BSSID as a
4012 * trigger if we have previously confirmed that the
4013 * Authenticator uses BSSID as the src_addr (which is not the
4014 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004015 */
4016 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004017 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4018 wpa_supplicant_state_txt(wpa_s->wpa_state),
4019 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004020 wpabuf_free(wpa_s->pending_eapol_rx);
4021 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4022 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004023 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004024 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4025 ETH_ALEN);
4026 }
4027 return;
4028 }
4029
Jouni Malinena05074c2012-12-21 21:35:35 +02004030 wpa_s->last_eapol_matches_bssid =
4031 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4032
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004033#ifdef CONFIG_AP
4034 if (wpa_s->ap_iface) {
4035 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4036 return;
4037 }
4038#endif /* CONFIG_AP */
4039
4040 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4041 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4042 "no key management is configured");
4043 return;
4044 }
4045
4046 if (wpa_s->eapol_received == 0 &&
4047 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
4048 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4049 wpa_s->wpa_state != WPA_COMPLETED) &&
4050 (wpa_s->current_ssid == NULL ||
4051 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
4052 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004053 int timeout = 10;
4054
4055 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4056 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4057 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4058 /* Use longer timeout for IEEE 802.1X/EAP */
4059 timeout = 70;
4060 }
4061
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004062#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004063 if (wpa_s->current_ssid && wpa_s->current_bss &&
4064 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4065 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4066 /*
4067 * Use shorter timeout if going through WPS AP iteration
4068 * for PIN config method with an AP that does not
4069 * advertise Selected Registrar.
4070 */
4071 struct wpabuf *wps_ie;
4072
4073 wps_ie = wpa_bss_get_vendor_ie_multi(
4074 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4075 if (wps_ie &&
4076 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4077 timeout = 10;
4078 wpabuf_free(wps_ie);
4079 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004080#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004081
4082 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004083 }
4084 wpa_s->eapol_received++;
4085
4086 if (wpa_s->countermeasures) {
4087 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4088 "EAPOL packet");
4089 return;
4090 }
4091
4092#ifdef CONFIG_IBSS_RSN
4093 if (wpa_s->current_ssid &&
4094 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4095 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4096 return;
4097 }
4098#endif /* CONFIG_IBSS_RSN */
4099
4100 /* Source address of the incoming EAPOL frame could be compared to the
4101 * current BSSID. However, it is possible that a centralized
4102 * Authenticator could be using another MAC address than the BSSID of
4103 * an AP, so just allow any address to be used for now. The replies are
4104 * still sent to the current BSSID (if available), though. */
4105
4106 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4107 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004108 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4109 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004110 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4111 return;
4112 wpa_drv_poll(wpa_s);
4113 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
4114 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4115 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4116 /*
4117 * Set portValid = TRUE here since we are going to skip 4-way
4118 * handshake processing which would normally set portValid. We
4119 * need this to allow the EAPOL state machines to be completed
4120 * without going through EAPOL-Key handshake.
4121 */
4122 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
4123 }
4124}
4125
4126
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004127int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004128{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004129 if ((!wpa_s->p2p_mgmt ||
4130 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4131 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004132 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004133 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4134 wpa_drv_get_mac_addr(wpa_s),
4135 ETH_P_EAPOL,
4136 wpa_supplicant_rx_eapol, wpa_s, 0);
4137 if (wpa_s->l2 == NULL)
4138 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004139
4140 if (l2_packet_set_packet_filter(wpa_s->l2,
4141 L2_PACKET_FILTER_PKTTYPE))
4142 wpa_dbg(wpa_s, MSG_DEBUG,
4143 "Failed to attach pkt_type filter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004144 } else {
4145 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4146 if (addr)
4147 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4148 }
4149
4150 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4151 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
4152 return -1;
4153 }
4154
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004155 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4156
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004157 return 0;
4158}
4159
4160
Dmitry Shmidt04949592012-07-19 12:16:46 -07004161static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4162 const u8 *buf, size_t len)
4163{
4164 struct wpa_supplicant *wpa_s = ctx;
4165 const struct l2_ethhdr *eth;
4166
4167 if (len < sizeof(*eth))
4168 return;
4169 eth = (const struct l2_ethhdr *) buf;
4170
4171 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4172 !(eth->h_dest[0] & 0x01)) {
4173 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4174 " (bridge - not for this interface - ignore)",
4175 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4176 return;
4177 }
4178
4179 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4180 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4181 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4182 len - sizeof(*eth));
4183}
4184
4185
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004186/**
4187 * wpa_supplicant_driver_init - Initialize driver interface parameters
4188 * @wpa_s: Pointer to wpa_supplicant data
4189 * Returns: 0 on success, -1 on failure
4190 *
4191 * This function is called to initialize driver interface parameters.
4192 * wpa_drv_init() must have been called before this function to initialize the
4193 * driver interface.
4194 */
4195int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4196{
4197 static int interface_count = 0;
4198
4199 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4200 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004201
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004202 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4203 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004204 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004205 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4206
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004207 if (wpa_s->bridge_ifname[0]) {
4208 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4209 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004210 wpa_s->l2_br = l2_packet_init_bridge(
4211 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4212 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004213 if (wpa_s->l2_br == NULL) {
4214 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4215 "connection for the bridge interface '%s'",
4216 wpa_s->bridge_ifname);
4217 return -1;
4218 }
4219 }
4220
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004221 if (wpa_s->conf->ap_scan == 2 &&
4222 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4223 wpa_printf(MSG_INFO,
4224 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4225 }
4226
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004227 wpa_clear_keys(wpa_s, NULL);
4228
4229 /* Make sure that TKIP countermeasures are not left enabled (could
4230 * happen if wpa_supplicant is killed during countermeasures. */
4231 wpa_drv_set_countermeasures(wpa_s, 0);
4232
4233 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4234 wpa_drv_flush_pmkid(wpa_s);
4235
4236 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004237 wpa_s->prev_scan_wildcard = 0;
4238
Dmitry Shmidt04949592012-07-19 12:16:46 -07004239 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004240 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4241 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4242 interface_count = 0;
4243 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004244#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004245 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004246 wpa_supplicant_delayed_sched_scan(wpa_s,
4247 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004248 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004249 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004250 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004251#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004252 interface_count++;
4253 } else
4254 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4255
4256 return 0;
4257}
4258
4259
4260static int wpa_supplicant_daemon(const char *pid_file)
4261{
4262 wpa_printf(MSG_DEBUG, "Daemonize..");
4263 return os_daemonize(pid_file);
4264}
4265
4266
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004267static struct wpa_supplicant *
4268wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004269{
4270 struct wpa_supplicant *wpa_s;
4271
4272 wpa_s = os_zalloc(sizeof(*wpa_s));
4273 if (wpa_s == NULL)
4274 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004275 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004276 wpa_s->scan_interval = 5;
4277 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004278 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004279 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004280 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004281
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004282 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004283 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 return wpa_s;
4286}
4287
4288
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004289#ifdef CONFIG_HT_OVERRIDES
4290
4291static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4292 struct ieee80211_ht_capabilities *htcaps,
4293 struct ieee80211_ht_capabilities *htcaps_mask,
4294 const char *ht_mcs)
4295{
4296 /* parse ht_mcs into hex array */
4297 int i;
4298 const char *tmp = ht_mcs;
4299 char *end = NULL;
4300
4301 /* If ht_mcs is null, do not set anything */
4302 if (!ht_mcs)
4303 return 0;
4304
4305 /* This is what we are setting in the kernel */
4306 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4307
4308 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4309
4310 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004311 long v;
4312
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004313 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004314 v = strtol(tmp, &end, 16);
4315
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004316 if (errno == 0) {
4317 wpa_msg(wpa_s, MSG_DEBUG,
4318 "htcap value[%i]: %ld end: %p tmp: %p",
4319 i, v, end, tmp);
4320 if (end == tmp)
4321 break;
4322
4323 htcaps->supported_mcs_set[i] = v;
4324 tmp = end;
4325 } else {
4326 wpa_msg(wpa_s, MSG_ERROR,
4327 "Failed to parse ht-mcs: %s, error: %s\n",
4328 ht_mcs, strerror(errno));
4329 return -1;
4330 }
4331 }
4332
4333 /*
4334 * If we were able to parse any values, then set mask for the MCS set.
4335 */
4336 if (i) {
4337 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4338 IEEE80211_HT_MCS_MASK_LEN - 1);
4339 /* skip the 3 reserved bits */
4340 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4341 0x1f;
4342 }
4343
4344 return 0;
4345}
4346
4347
4348static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4349 struct ieee80211_ht_capabilities *htcaps,
4350 struct ieee80211_ht_capabilities *htcaps_mask,
4351 int disabled)
4352{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004353 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004354
4355 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
4356
4357 if (disabled == -1)
4358 return 0;
4359
4360 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
4361 htcaps_mask->ht_capabilities_info |= msk;
4362 if (disabled)
4363 htcaps->ht_capabilities_info &= msk;
4364 else
4365 htcaps->ht_capabilities_info |= msk;
4366
4367 return 0;
4368}
4369
4370
4371static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
4372 struct ieee80211_ht_capabilities *htcaps,
4373 struct ieee80211_ht_capabilities *htcaps_mask,
4374 int factor)
4375{
4376 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
4377
4378 if (factor == -1)
4379 return 0;
4380
4381 if (factor < 0 || factor > 3) {
4382 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
4383 "Must be 0-3 or -1", factor);
4384 return -EINVAL;
4385 }
4386
4387 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
4388 htcaps->a_mpdu_params &= ~0x3;
4389 htcaps->a_mpdu_params |= factor & 0x3;
4390
4391 return 0;
4392}
4393
4394
4395static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
4396 struct ieee80211_ht_capabilities *htcaps,
4397 struct ieee80211_ht_capabilities *htcaps_mask,
4398 int density)
4399{
4400 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
4401
4402 if (density == -1)
4403 return 0;
4404
4405 if (density < 0 || density > 7) {
4406 wpa_msg(wpa_s, MSG_ERROR,
4407 "ampdu_density: %d out of range. Must be 0-7 or -1.",
4408 density);
4409 return -EINVAL;
4410 }
4411
4412 htcaps_mask->a_mpdu_params |= 0x1C;
4413 htcaps->a_mpdu_params &= ~(0x1C);
4414 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
4415
4416 return 0;
4417}
4418
4419
4420static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
4421 struct ieee80211_ht_capabilities *htcaps,
4422 struct ieee80211_ht_capabilities *htcaps_mask,
4423 int disabled)
4424{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004425 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
4426
Paul Stewart092955c2017-02-06 09:13:09 -08004427 set_disable_ht40(htcaps, disabled);
4428 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004429
4430 return 0;
4431}
4432
4433
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004434static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
4435 struct ieee80211_ht_capabilities *htcaps,
4436 struct ieee80211_ht_capabilities *htcaps_mask,
4437 int disabled)
4438{
4439 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004440 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
4441 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004442
4443 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
4444
4445 if (disabled)
4446 htcaps->ht_capabilities_info &= ~msk;
4447 else
4448 htcaps->ht_capabilities_info |= msk;
4449
4450 htcaps_mask->ht_capabilities_info |= msk;
4451
4452 return 0;
4453}
4454
4455
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004456static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
4457 struct ieee80211_ht_capabilities *htcaps,
4458 struct ieee80211_ht_capabilities *htcaps_mask,
4459 int disabled)
4460{
4461 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004462 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004463
4464 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
4465
4466 if (disabled)
4467 htcaps->ht_capabilities_info &= ~msk;
4468 else
4469 htcaps->ht_capabilities_info |= msk;
4470
4471 htcaps_mask->ht_capabilities_info |= msk;
4472
4473 return 0;
4474}
4475
4476
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004477void wpa_supplicant_apply_ht_overrides(
4478 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4479 struct wpa_driver_associate_params *params)
4480{
4481 struct ieee80211_ht_capabilities *htcaps;
4482 struct ieee80211_ht_capabilities *htcaps_mask;
4483
4484 if (!ssid)
4485 return;
4486
4487 params->disable_ht = ssid->disable_ht;
4488 if (!params->htcaps || !params->htcaps_mask)
4489 return;
4490
4491 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
4492 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
4493 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
4494 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
4495 ssid->disable_max_amsdu);
4496 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
4497 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
4498 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004499 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004500 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004501
4502 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004503 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004504 htcaps->ht_capabilities_info |= bit;
4505 htcaps_mask->ht_capabilities_info |= bit;
4506 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004507}
4508
4509#endif /* CONFIG_HT_OVERRIDES */
4510
4511
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004512#ifdef CONFIG_VHT_OVERRIDES
4513void wpa_supplicant_apply_vht_overrides(
4514 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4515 struct wpa_driver_associate_params *params)
4516{
4517 struct ieee80211_vht_capabilities *vhtcaps;
4518 struct ieee80211_vht_capabilities *vhtcaps_mask;
4519
4520 if (!ssid)
4521 return;
4522
4523 params->disable_vht = ssid->disable_vht;
4524
4525 vhtcaps = (void *) params->vhtcaps;
4526 vhtcaps_mask = (void *) params->vhtcaps_mask;
4527
4528 if (!vhtcaps || !vhtcaps_mask)
4529 return;
4530
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004531 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
4532 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004533
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004534#ifdef CONFIG_HT_OVERRIDES
4535 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004536 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
4537 int max_ampdu;
4538
4539 max_ampdu = (ssid->vht_capa &
4540 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4541 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004542
4543 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4544 wpa_set_ampdu_factor(wpa_s,
4545 (void *) params->htcaps,
4546 (void *) params->htcaps_mask,
4547 max_ampdu);
4548 }
4549#endif /* CONFIG_HT_OVERRIDES */
4550
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004551#define OVERRIDE_MCS(i) \
4552 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4553 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004554 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004555 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004556 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4557 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004558 } \
4559 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4560 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004561 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004562 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004563 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4564 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004565 }
4566
4567 OVERRIDE_MCS(1);
4568 OVERRIDE_MCS(2);
4569 OVERRIDE_MCS(3);
4570 OVERRIDE_MCS(4);
4571 OVERRIDE_MCS(5);
4572 OVERRIDE_MCS(6);
4573 OVERRIDE_MCS(7);
4574 OVERRIDE_MCS(8);
4575}
4576#endif /* CONFIG_VHT_OVERRIDES */
4577
4578
Dmitry Shmidt04949592012-07-19 12:16:46 -07004579static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4580{
4581#ifdef PCSC_FUNCS
4582 size_t len;
4583
4584 if (!wpa_s->conf->pcsc_reader)
4585 return 0;
4586
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004587 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004588 if (!wpa_s->scard)
4589 return 1;
4590
4591 if (wpa_s->conf->pcsc_pin &&
4592 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4593 scard_deinit(wpa_s->scard);
4594 wpa_s->scard = NULL;
4595 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4596 return -1;
4597 }
4598
4599 len = sizeof(wpa_s->imsi) - 1;
4600 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4601 scard_deinit(wpa_s->scard);
4602 wpa_s->scard = NULL;
4603 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4604 return -1;
4605 }
4606 wpa_s->imsi[len] = '\0';
4607
4608 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4609
4610 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4611 wpa_s->imsi, wpa_s->mnc_len);
4612
4613 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4614 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4615#endif /* PCSC_FUNCS */
4616
4617 return 0;
4618}
4619
4620
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004621int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4622{
4623 char *val, *pos;
4624
4625 ext_password_deinit(wpa_s->ext_pw);
4626 wpa_s->ext_pw = NULL;
4627 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4628
4629 if (!wpa_s->conf->ext_password_backend)
4630 return 0;
4631
4632 val = os_strdup(wpa_s->conf->ext_password_backend);
4633 if (val == NULL)
4634 return -1;
4635 pos = os_strchr(val, ':');
4636 if (pos)
4637 *pos++ = '\0';
4638
4639 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4640
4641 wpa_s->ext_pw = ext_password_init(val, pos);
4642 os_free(val);
4643 if (wpa_s->ext_pw == NULL) {
4644 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4645 return -1;
4646 }
4647 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4648
4649 return 0;
4650}
4651
4652
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004653#ifdef CONFIG_FST
4654
4655static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4656{
4657 struct wpa_supplicant *wpa_s = ctx;
4658
4659 return (is_zero_ether_addr(wpa_s->bssid) ||
4660 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4661}
4662
4663
4664static void wpas_fst_get_channel_info_cb(void *ctx,
4665 enum hostapd_hw_mode *hw_mode,
4666 u8 *channel)
4667{
4668 struct wpa_supplicant *wpa_s = ctx;
4669
4670 if (wpa_s->current_bss) {
4671 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4672 channel);
4673 } else if (wpa_s->hw.num_modes) {
4674 *hw_mode = wpa_s->hw.modes[0].mode;
4675 } else {
4676 WPA_ASSERT(0);
4677 *hw_mode = 0;
4678 }
4679}
4680
4681
4682static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4683{
4684 struct wpa_supplicant *wpa_s = ctx;
4685
4686 *modes = wpa_s->hw.modes;
4687 return wpa_s->hw.num_modes;
4688}
4689
4690
4691static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4692{
4693 struct wpa_supplicant *wpa_s = ctx;
4694
4695 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4696 wpa_s->fst_ies = fst_ies;
4697}
4698
4699
4700static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4701{
4702 struct wpa_supplicant *wpa_s = ctx;
4703
Paul Stewart092955c2017-02-06 09:13:09 -08004704 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
4705 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
4706 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
4707 return -1;
4708 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004709 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08004710 wpa_s->own_addr, wpa_s->bssid,
4711 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004712 0);
4713}
4714
4715
4716static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4717{
4718 struct wpa_supplicant *wpa_s = ctx;
4719
4720 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4721 return wpa_s->received_mb_ies;
4722}
4723
4724
4725static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4726 const u8 *buf, size_t size)
4727{
4728 struct wpa_supplicant *wpa_s = ctx;
4729 struct mb_ies_info info;
4730
4731 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4732
4733 if (!mb_ies_info_by_ies(&info, buf, size)) {
4734 wpabuf_free(wpa_s->received_mb_ies);
4735 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4736 }
4737}
4738
4739
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004740static const u8 * wpas_fst_get_peer_first(void *ctx,
4741 struct fst_get_peer_ctx **get_ctx,
4742 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004743{
4744 struct wpa_supplicant *wpa_s = ctx;
4745
4746 *get_ctx = NULL;
4747 if (!is_zero_ether_addr(wpa_s->bssid))
4748 return (wpa_s->received_mb_ies || !mb_only) ?
4749 wpa_s->bssid : NULL;
4750 return NULL;
4751}
4752
4753
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004754static const u8 * wpas_fst_get_peer_next(void *ctx,
4755 struct fst_get_peer_ctx **get_ctx,
4756 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004757{
4758 return NULL;
4759}
4760
4761void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4762 struct fst_wpa_obj *iface_obj)
4763{
4764 iface_obj->ctx = wpa_s;
4765 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4766 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4767 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4768 iface_obj->set_ies = wpas_fst_set_ies_cb;
4769 iface_obj->send_action = wpas_fst_send_action_cb;
4770 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4771 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4772 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4773 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4774}
4775#endif /* CONFIG_FST */
4776
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004777static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004778 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004779{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004780 struct wowlan_triggers *triggers;
4781 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004782
4783 if (!wpa_s->conf->wowlan_triggers)
4784 return 0;
4785
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004786 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4787 if (triggers) {
4788 ret = wpa_drv_wowlan(wpa_s, triggers);
4789 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004790 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004791 return ret;
4792}
4793
4794
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004795enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004796{
4797 if (freq < 3000)
4798 return BAND_2_4_GHZ;
4799 if (freq > 50000)
4800 return BAND_60_GHZ;
4801 return BAND_5_GHZ;
4802}
4803
4804
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004805unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004806{
4807 int i;
4808 unsigned int band = 0;
4809
4810 if (freqs) {
4811 /* freqs are specified for the radio work */
4812 for (i = 0; freqs[i]; i++)
4813 band |= wpas_freq_to_band(freqs[i]);
4814 } else {
4815 /*
4816 * freqs are not specified, implies all
4817 * the supported freqs by HW
4818 */
4819 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4820 if (wpa_s->hw.modes[i].num_channels != 0) {
4821 if (wpa_s->hw.modes[i].mode ==
4822 HOSTAPD_MODE_IEEE80211B ||
4823 wpa_s->hw.modes[i].mode ==
4824 HOSTAPD_MODE_IEEE80211G)
4825 band |= BAND_2_4_GHZ;
4826 else if (wpa_s->hw.modes[i].mode ==
4827 HOSTAPD_MODE_IEEE80211A)
4828 band |= BAND_5_GHZ;
4829 else if (wpa_s->hw.modes[i].mode ==
4830 HOSTAPD_MODE_IEEE80211AD)
4831 band |= BAND_60_GHZ;
4832 else if (wpa_s->hw.modes[i].mode ==
4833 HOSTAPD_MODE_IEEE80211ANY)
4834 band = BAND_2_4_GHZ | BAND_5_GHZ |
4835 BAND_60_GHZ;
4836 }
4837 }
4838 }
4839
4840 return band;
4841}
4842
4843
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004844static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4845 const char *rn)
4846{
4847 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4848 struct wpa_radio *radio;
4849
4850 while (rn && iface) {
4851 radio = iface->radio;
4852 if (radio && os_strcmp(rn, radio->name) == 0) {
4853 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4854 wpa_s->ifname, rn);
4855 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4856 return radio;
4857 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004858
4859 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004860 }
4861
4862 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4863 wpa_s->ifname, rn ? rn : "N/A");
4864 radio = os_zalloc(sizeof(*radio));
4865 if (radio == NULL)
4866 return NULL;
4867
4868 if (rn)
4869 os_strlcpy(radio->name, rn, sizeof(radio->name));
4870 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004871 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004872 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4873
4874 return radio;
4875}
4876
4877
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004878static void radio_work_free(struct wpa_radio_work *work)
4879{
4880 if (work->wpa_s->scan_work == work) {
4881 /* This should not really happen. */
4882 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4883 work->type, work, work->started);
4884 work->wpa_s->scan_work = NULL;
4885 }
4886
4887#ifdef CONFIG_P2P
4888 if (work->wpa_s->p2p_scan_work == work) {
4889 /* This should not really happen. */
4890 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4891 work->type, work, work->started);
4892 work->wpa_s->p2p_scan_work = NULL;
4893 }
4894#endif /* CONFIG_P2P */
4895
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004896 if (work->started) {
4897 work->wpa_s->radio->num_active_works--;
4898 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004899 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004900 work->type, work,
4901 work->wpa_s->radio->num_active_works);
4902 }
4903
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004904 dl_list_del(&work->list);
4905 os_free(work);
4906}
4907
4908
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004909static int radio_work_is_connect(struct wpa_radio_work *work)
4910{
4911 return os_strcmp(work->type, "sme-connect") == 0 ||
4912 os_strcmp(work->type, "connect") == 0;
4913}
4914
4915
4916static int radio_work_is_scan(struct wpa_radio_work *work)
4917{
4918 return os_strcmp(work->type, "scan") == 0 ||
4919 os_strcmp(work->type, "p2p-scan") == 0;
4920}
4921
4922
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004923static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4924{
4925 struct wpa_radio_work *active_work = NULL;
4926 struct wpa_radio_work *tmp;
4927
4928 /* Get the active work to know the type and band. */
4929 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4930 if (tmp->started) {
4931 active_work = tmp;
4932 break;
4933 }
4934 }
4935
4936 if (!active_work) {
4937 /* No active work, start one */
4938 radio->num_active_works = 0;
4939 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4940 list) {
4941 if (os_strcmp(tmp->type, "scan") == 0 &&
4942 radio->external_scan_running &&
4943 (((struct wpa_driver_scan_params *)
4944 tmp->ctx)->only_new_results ||
4945 tmp->wpa_s->clear_driver_scan_cache))
4946 continue;
4947 return tmp;
4948 }
4949 return NULL;
4950 }
4951
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004952 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004953 /*
4954 * If the active work is either connect or sme-connect,
4955 * do not parallelize them with other radio works.
4956 */
4957 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4958 "Do not parallelize radio work with %s",
4959 active_work->type);
4960 return NULL;
4961 }
4962
4963 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4964 if (tmp->started)
4965 continue;
4966
4967 /*
4968 * If connect or sme-connect are enqueued, parallelize only
4969 * those operations ahead of them in the queue.
4970 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004971 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004972 break;
4973
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004974 /* Serialize parallel scan and p2p_scan operations on the same
4975 * interface since the driver_nl80211 mechanism for tracking
4976 * scan cookies does not yet have support for this. */
4977 if (active_work->wpa_s == tmp->wpa_s &&
4978 radio_work_is_scan(active_work) &&
4979 radio_work_is_scan(tmp)) {
4980 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4981 "Do not start work '%s' when another work '%s' is already scheduled",
4982 tmp->type, active_work->type);
4983 continue;
4984 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004985 /*
4986 * Check that the radio works are distinct and
4987 * on different bands.
4988 */
4989 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4990 (active_work->bands != tmp->bands)) {
4991 /*
4992 * If a scan has to be scheduled through nl80211 scan
4993 * interface and if an external scan is already running,
4994 * do not schedule the scan since it is likely to get
4995 * rejected by kernel.
4996 */
4997 if (os_strcmp(tmp->type, "scan") == 0 &&
4998 radio->external_scan_running &&
4999 (((struct wpa_driver_scan_params *)
5000 tmp->ctx)->only_new_results ||
5001 tmp->wpa_s->clear_driver_scan_cache))
5002 continue;
5003
5004 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
5005 "active_work:%s new_work:%s",
5006 active_work->type, tmp->type);
5007 return tmp;
5008 }
5009 }
5010
5011 /* Did not find a radio work to schedule in parallel. */
5012 return NULL;
5013}
5014
5015
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005016static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5017{
5018 struct wpa_radio *radio = eloop_ctx;
5019 struct wpa_radio_work *work;
5020 struct os_reltime now, diff;
5021 struct wpa_supplicant *wpa_s;
5022
5023 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005024 if (work == NULL) {
5025 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005026 return;
5027 }
5028
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005029 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5030 radio_list);
5031
5032 if (!(wpa_s &&
5033 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5034 if (work->started)
5035 return; /* already started and still in progress */
5036
5037 if (wpa_s && wpa_s->radio->external_scan_running) {
5038 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5039 return;
5040 }
5041 } else {
5042 work = NULL;
5043 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5044 /* get the work to schedule next */
5045 work = radio_work_get_next_work(radio);
5046 }
5047 if (!work)
5048 return;
5049 }
5050
5051 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005052 os_get_reltime(&now);
5053 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005054 wpa_dbg(wpa_s, MSG_DEBUG,
5055 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005056 work->type, work, diff.sec, diff.usec);
5057 work->started = 1;
5058 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005059 radio->num_active_works++;
5060
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005061 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005062
5063 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5064 radio->num_active_works < MAX_ACTIVE_WORKS)
5065 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005066}
5067
5068
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005069/*
5070 * This function removes both started and pending radio works running on
5071 * the provided interface's radio.
5072 * Prior to the removal of the radio work, its callback (cb) is called with
5073 * deinit set to be 1. Each work's callback is responsible for clearing its
5074 * internal data and restoring to a correct state.
5075 * @wpa_s: wpa_supplicant data
5076 * @type: type of works to be removed
5077 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5078 * this interface's works.
5079 */
5080void radio_remove_works(struct wpa_supplicant *wpa_s,
5081 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005082{
5083 struct wpa_radio_work *work, *tmp;
5084 struct wpa_radio *radio = wpa_s->radio;
5085
5086 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5087 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005088 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005089 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005090
5091 /* skip other ifaces' works */
5092 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005093 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005094
5095 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5096 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005097 work->cb(work, 1);
5098 radio_work_free(work);
5099 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005100
5101 /* in case we removed the started work */
5102 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005103}
5104
5105
Roshan Pius3a1667e2018-07-03 15:17:14 -07005106void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5107{
5108 struct wpa_radio_work *work;
5109 struct wpa_radio *radio = wpa_s->radio;
5110
5111 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5112 if (work->ctx != ctx)
5113 continue;
5114 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5115 work->type, work, work->started ? " (started)" : "");
5116 radio_work_free(work);
5117 break;
5118 }
5119}
5120
5121
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005122static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5123{
5124 struct wpa_radio *radio = wpa_s->radio;
5125
5126 if (!radio)
5127 return;
5128
5129 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5130 wpa_s->ifname, radio->name);
5131 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005132 radio_remove_works(wpa_s, NULL, 0);
5133 wpa_s->radio = NULL;
5134 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005135 return; /* Interfaces remain for this radio */
5136
5137 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005138 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005139 os_free(radio);
5140}
5141
5142
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005143void radio_work_check_next(struct wpa_supplicant *wpa_s)
5144{
5145 struct wpa_radio *radio = wpa_s->radio;
5146
5147 if (dl_list_empty(&radio->work))
5148 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005149 if (wpa_s->ext_work_in_progress) {
5150 wpa_printf(MSG_DEBUG,
5151 "External radio work in progress - delay start of pending item");
5152 return;
5153 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005154 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5155 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5156}
5157
5158
5159/**
5160 * radio_add_work - Add a radio work item
5161 * @wpa_s: Pointer to wpa_supplicant data
5162 * @freq: Frequency of the offchannel operation in MHz or 0
5163 * @type: Unique identifier for each type of work
5164 * @next: Force as the next work to be executed
5165 * @cb: Callback function for indicating when radio is available
5166 * @ctx: Context pointer for the work (work->ctx in cb())
5167 * Returns: 0 on success, -1 on failure
5168 *
5169 * This function is used to request time for an operation that requires
5170 * exclusive radio control. Once the radio is available, the registered callback
5171 * function will be called. radio_work_done() must be called once the exclusive
5172 * radio operation has been completed, so that the radio is freed for other
5173 * operations. The special case of deinit=1 is used to free the context data
5174 * during interface removal. That does not allow the callback function to start
5175 * the radio operation, i.e., it must free any resources allocated for the radio
5176 * work and return.
5177 *
5178 * The @freq parameter can be used to indicate a single channel on which the
5179 * offchannel operation will occur. This may allow multiple radio work
5180 * operations to be performed in parallel if they apply for the same channel.
5181 * Setting this to 0 indicates that the work item may use multiple channels or
5182 * requires exclusive control of the radio.
5183 */
5184int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5185 const char *type, int next,
5186 void (*cb)(struct wpa_radio_work *work, int deinit),
5187 void *ctx)
5188{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005189 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005190 struct wpa_radio_work *work;
5191 int was_empty;
5192
5193 work = os_zalloc(sizeof(*work));
5194 if (work == NULL)
5195 return -1;
5196 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5197 os_get_reltime(&work->time);
5198 work->freq = freq;
5199 work->type = type;
5200 work->wpa_s = wpa_s;
5201 work->cb = cb;
5202 work->ctx = ctx;
5203
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005204 if (freq)
5205 work->bands = wpas_freq_to_band(freq);
5206 else if (os_strcmp(type, "scan") == 0 ||
5207 os_strcmp(type, "p2p-scan") == 0)
5208 work->bands = wpas_get_bands(wpa_s,
5209 ((struct wpa_driver_scan_params *)
5210 ctx)->freqs);
5211 else
5212 work->bands = wpas_get_bands(wpa_s, NULL);
5213
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005214 was_empty = dl_list_empty(&wpa_s->radio->work);
5215 if (next)
5216 dl_list_add(&wpa_s->radio->work, &work->list);
5217 else
5218 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5219 if (was_empty) {
5220 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5221 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005222 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5223 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5224 wpa_dbg(wpa_s, MSG_DEBUG,
5225 "Try to schedule a radio work (num_active_works=%u)",
5226 radio->num_active_works);
5227 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005228 }
5229
5230 return 0;
5231}
5232
5233
5234/**
5235 * radio_work_done - Indicate that a radio work item has been completed
5236 * @work: Completed work
5237 *
5238 * This function is called once the callback function registered with
5239 * radio_add_work() has completed its work.
5240 */
5241void radio_work_done(struct wpa_radio_work *work)
5242{
5243 struct wpa_supplicant *wpa_s = work->wpa_s;
5244 struct os_reltime now, diff;
5245 unsigned int started = work->started;
5246
5247 os_get_reltime(&now);
5248 os_reltime_sub(&now, &work->time, &diff);
5249 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5250 work->type, work, started ? "done" : "canceled",
5251 diff.sec, diff.usec);
5252 radio_work_free(work);
5253 if (started)
5254 radio_work_check_next(wpa_s);
5255}
5256
5257
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005258struct wpa_radio_work *
5259radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005260{
5261 struct wpa_radio_work *work;
5262 struct wpa_radio *radio = wpa_s->radio;
5263
5264 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5265 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005266 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005267 }
5268
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005269 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005270}
5271
5272
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005273static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005274 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005275{
5276 const char *ifname, *driver, *rn;
5277
5278 driver = iface->driver;
5279next_driver:
5280 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
5281 return -1;
5282
5283 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
5284 if (wpa_s->drv_priv == NULL) {
5285 const char *pos;
5286 pos = driver ? os_strchr(driver, ',') : NULL;
5287 if (pos) {
5288 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
5289 "driver interface - try next driver wrapper");
5290 driver = pos + 1;
5291 goto next_driver;
5292 }
5293 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
5294 "interface");
5295 return -1;
5296 }
5297 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
5298 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
5299 "driver_param '%s'", wpa_s->conf->driver_param);
5300 return -1;
5301 }
5302
5303 ifname = wpa_drv_get_ifname(wpa_s);
5304 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
5305 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
5306 "interface name with '%s'", ifname);
5307 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
5308 }
5309
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005310 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005311 if (rn && rn[0] == '\0')
5312 rn = NULL;
5313
5314 wpa_s->radio = radio_add_interface(wpa_s, rn);
5315 if (wpa_s->radio == NULL)
5316 return -1;
5317
5318 return 0;
5319}
5320
5321
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005322#ifdef CONFIG_GAS_SERVER
5323
5324static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
5325 unsigned int freq, const u8 *dst,
5326 const u8 *src, const u8 *bssid,
5327 const u8 *data, size_t data_len,
5328 enum offchannel_send_action_result result)
5329{
5330 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
5331 " result=%s",
5332 freq, MAC2STR(dst),
5333 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
5334 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
5335 "FAILED"));
5336 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
5337 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
5338}
5339
5340
5341static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
5342 struct wpabuf *buf, unsigned int wait_time)
5343{
5344 struct wpa_supplicant *wpa_s = ctx;
5345 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
5346
5347 if (wait_time > wpa_s->max_remain_on_chan)
5348 wait_time = wpa_s->max_remain_on_chan;
5349
5350 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
5351 wpabuf_head(buf), wpabuf_len(buf),
5352 wait_time, wpas_gas_server_tx_status, 0);
5353}
5354
5355#endif /* CONFIG_GAS_SERVER */
5356
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005357static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005358 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005359{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005360 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005361 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005362 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005363
5364 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
5365 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
5366 iface->confname ? iface->confname : "N/A",
5367 iface->driver ? iface->driver : "default",
5368 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
5369 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
5370
5371 if (iface->confname) {
5372#ifdef CONFIG_BACKEND_FILE
5373 wpa_s->confname = os_rel2abs_path(iface->confname);
5374 if (wpa_s->confname == NULL) {
5375 wpa_printf(MSG_ERROR, "Failed to get absolute path "
5376 "for configuration file '%s'.",
5377 iface->confname);
5378 return -1;
5379 }
5380 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
5381 iface->confname, wpa_s->confname);
5382#else /* CONFIG_BACKEND_FILE */
5383 wpa_s->confname = os_strdup(iface->confname);
5384#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005385 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005386 if (wpa_s->conf == NULL) {
5387 wpa_printf(MSG_ERROR, "Failed to read or parse "
5388 "configuration '%s'.", wpa_s->confname);
5389 return -1;
5390 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005391 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005392 if (wpa_s->confanother &&
5393 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
5394 wpa_printf(MSG_ERROR,
5395 "Failed to read or parse configuration '%s'.",
5396 wpa_s->confanother);
5397 return -1;
5398 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005399
5400 /*
5401 * Override ctrl_interface and driver_param if set on command
5402 * line.
5403 */
5404 if (iface->ctrl_interface) {
5405 os_free(wpa_s->conf->ctrl_interface);
5406 wpa_s->conf->ctrl_interface =
5407 os_strdup(iface->ctrl_interface);
5408 }
5409
5410 if (iface->driver_param) {
5411 os_free(wpa_s->conf->driver_param);
5412 wpa_s->conf->driver_param =
5413 os_strdup(iface->driver_param);
5414 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005415
5416 if (iface->p2p_mgmt && !iface->ctrl_interface) {
5417 os_free(wpa_s->conf->ctrl_interface);
5418 wpa_s->conf->ctrl_interface = NULL;
5419 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005420 } else
5421 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
5422 iface->driver_param);
5423
5424 if (wpa_s->conf == NULL) {
5425 wpa_printf(MSG_ERROR, "\nNo configuration found.");
5426 return -1;
5427 }
5428
5429 if (iface->ifname == NULL) {
5430 wpa_printf(MSG_ERROR, "\nInterface name is required.");
5431 return -1;
5432 }
5433 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
5434 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
5435 iface->ifname);
5436 return -1;
5437 }
5438 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
5439
5440 if (iface->bridge_ifname) {
5441 if (os_strlen(iface->bridge_ifname) >=
5442 sizeof(wpa_s->bridge_ifname)) {
5443 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
5444 "name '%s'.", iface->bridge_ifname);
5445 return -1;
5446 }
5447 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
5448 sizeof(wpa_s->bridge_ifname));
5449 }
5450
5451 /* RSNA Supplicant Key Management - INITIALIZE */
5452 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
5453 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
5454
5455 /* Initialize driver interface and register driver event handler before
5456 * L2 receive handler so that association events are processed before
5457 * EAPOL-Key packets if both become available for the same select()
5458 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005459 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005460 return -1;
5461
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005462 if (wpa_supplicant_init_wpa(wpa_s) < 0)
5463 return -1;
5464
5465 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
5466 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
5467 NULL);
5468 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
5469
5470 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
5471 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
5472 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
5473 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5474 "dot11RSNAConfigPMKLifetime");
5475 return -1;
5476 }
5477
5478 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
5479 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
5480 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
5481 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5482 "dot11RSNAConfigPMKReauthThreshold");
5483 return -1;
5484 }
5485
5486 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
5487 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
5488 wpa_s->conf->dot11RSNAConfigSATimeout)) {
5489 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5490 "dot11RSNAConfigSATimeout");
5491 return -1;
5492 }
5493
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005494 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
5495 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005496 &wpa_s->hw.flags,
5497 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005498 if (wpa_s->hw.modes) {
5499 u16 i;
5500
5501 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5502 if (wpa_s->hw.modes[i].vht_capab) {
5503 wpa_s->hw_capab = CAPAB_VHT;
5504 break;
5505 }
5506
5507 if (wpa_s->hw.modes[i].ht_capab &
5508 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
5509 wpa_s->hw_capab = CAPAB_HT40;
5510 else if (wpa_s->hw.modes[i].ht_capab &&
5511 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
5512 wpa_s->hw_capab = CAPAB_HT;
5513 }
5514 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005515
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005516 capa_res = wpa_drv_get_capa(wpa_s, &capa);
5517 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005518 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005519 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005520 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005521 wpa_s->drv_smps_modes = capa.smps_modes;
5522 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005523 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005524 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005525 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005526 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
5527 wpa_s->max_sched_scan_plan_interval =
5528 capa.max_sched_scan_plan_interval;
5529 wpa_s->max_sched_scan_plan_iterations =
5530 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005531 wpa_s->sched_scan_supported = capa.sched_scan_supported;
5532 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005533 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
5534 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005535 wpa_s->extended_capa = capa.extended_capa;
5536 wpa_s->extended_capa_mask = capa.extended_capa_mask;
5537 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005538 wpa_s->num_multichan_concurrent =
5539 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005540 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
5541
5542 if (capa.mac_addr_rand_scan_supported)
5543 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
5544 if (wpa_s->sched_scan_supported &&
5545 capa.mac_addr_rand_sched_scan_supported)
5546 wpa_s->mac_addr_rand_supported |=
5547 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005548 }
5549 if (wpa_s->max_remain_on_chan == 0)
5550 wpa_s->max_remain_on_chan = 1000;
5551
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005552 /*
5553 * Only take p2p_mgmt parameters when P2P Device is supported.
5554 * Doing it here as it determines whether l2_packet_init() will be done
5555 * during wpa_supplicant_driver_init().
5556 */
5557 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
5558 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005559
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005560 if (wpa_s->num_multichan_concurrent == 0)
5561 wpa_s->num_multichan_concurrent = 1;
5562
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005563 if (wpa_supplicant_driver_init(wpa_s) < 0)
5564 return -1;
5565
5566#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07005567 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005568 return -1;
5569#endif /* CONFIG_TDLS */
5570
5571 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
5572 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
5573 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
5574 return -1;
5575 }
5576
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005577#ifdef CONFIG_FST
5578 if (wpa_s->conf->fst_group_id) {
5579 struct fst_iface_cfg cfg;
5580 struct fst_wpa_obj iface_obj;
5581
5582 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
5583 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
5584 sizeof(cfg.group_id));
5585 cfg.priority = wpa_s->conf->fst_priority;
5586 cfg.llt = wpa_s->conf->fst_llt;
5587
5588 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
5589 &iface_obj, &cfg);
5590 if (!wpa_s->fst) {
5591 wpa_msg(wpa_s, MSG_ERROR,
5592 "FST: Cannot attach iface %s to group %s",
5593 wpa_s->ifname, cfg.group_id);
5594 return -1;
5595 }
5596 }
5597#endif /* CONFIG_FST */
5598
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005599 if (wpas_wps_init(wpa_s))
5600 return -1;
5601
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005602#ifdef CONFIG_GAS_SERVER
5603 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
5604 if (!wpa_s->gas_server) {
5605 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
5606 return -1;
5607 }
5608#endif /* CONFIG_GAS_SERVER */
5609
5610#ifdef CONFIG_DPP
5611 if (wpas_dpp_init(wpa_s) < 0)
5612 return -1;
5613#endif /* CONFIG_DPP */
5614
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005615 if (wpa_supplicant_init_eapol(wpa_s) < 0)
5616 return -1;
5617 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5618
5619 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
5620 if (wpa_s->ctrl_iface == NULL) {
5621 wpa_printf(MSG_ERROR,
5622 "Failed to initialize control interface '%s'.\n"
5623 "You may have another wpa_supplicant process "
5624 "already running or the file was\n"
5625 "left by an unclean termination of wpa_supplicant "
5626 "in which case you will need\n"
5627 "to manually remove this file before starting "
5628 "wpa_supplicant again.\n",
5629 wpa_s->conf->ctrl_interface);
5630 return -1;
5631 }
5632
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005633 wpa_s->gas = gas_query_init(wpa_s);
5634 if (wpa_s->gas == NULL) {
5635 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5636 return -1;
5637 }
5638
Roshan Pius3a1667e2018-07-03 15:17:14 -07005639 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
5640 wpa_s->p2p_mgmt) &&
5641 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005642 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5643 return -1;
5644 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005645
5646 if (wpa_bss_init(wpa_s) < 0)
5647 return -1;
5648
Paul Stewart092955c2017-02-06 09:13:09 -08005649#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5650#ifdef CONFIG_MESH
5651 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
5652#endif /* CONFIG_MESH */
5653#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5654
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005655 /*
5656 * Set Wake-on-WLAN triggers, if configured.
5657 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5658 * have effect anyway when the interface is down).
5659 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005660 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005661 return -1;
5662
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005663#ifdef CONFIG_EAP_PROXY
5664{
5665 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005666 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
5667 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005668 if (wpa_s->mnc_len > 0) {
5669 wpa_s->imsi[len] = '\0';
5670 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5671 wpa_s->imsi, wpa_s->mnc_len);
5672 } else {
5673 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5674 }
5675}
5676#endif /* CONFIG_EAP_PROXY */
5677
Dmitry Shmidt04949592012-07-19 12:16:46 -07005678 if (pcsc_reader_init(wpa_s) < 0)
5679 return -1;
5680
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005681 if (wpas_init_ext_pw(wpa_s) < 0)
5682 return -1;
5683
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005684 wpas_rrm_reset(wpa_s);
5685
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005686 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5687
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005688#ifdef CONFIG_HS20
5689 hs20_init(wpa_s);
5690#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005691#ifdef CONFIG_MBO
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005692 if (wpa_s->conf->oce) {
5693 if ((wpa_s->conf->oce & OCE_STA) &&
5694 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
5695 wpa_s->enable_oce = OCE_STA;
5696 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
5697 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
5698 /* TODO: Need to add STA-CFON support */
5699 wpa_printf(MSG_ERROR,
5700 "OCE STA-CFON feature is not yet supported");
5701 }
5702 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005703 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5704#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005705
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005706 wpa_supplicant_set_default_scan_ies(wpa_s);
5707
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005708 return 0;
5709}
5710
5711
5712static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005713 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005714{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005715 struct wpa_global *global = wpa_s->global;
5716 struct wpa_supplicant *iface, *prev;
5717
5718 if (wpa_s == wpa_s->parent)
5719 wpas_p2p_group_remove(wpa_s, "*");
5720
5721 iface = global->ifaces;
5722 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005723 if (iface->p2pdev == wpa_s)
5724 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005725 if (iface == wpa_s || iface->parent != wpa_s) {
5726 iface = iface->next;
5727 continue;
5728 }
5729 wpa_printf(MSG_DEBUG,
5730 "Remove remaining child interface %s from parent %s",
5731 iface->ifname, wpa_s->ifname);
5732 prev = iface;
5733 iface = iface->next;
5734 wpa_supplicant_remove_iface(global, prev, terminate);
5735 }
5736
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005737 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005738 if (wpa_s->drv_priv) {
5739 wpa_supplicant_deauthenticate(wpa_s,
5740 WLAN_REASON_DEAUTH_LEAVING);
5741
5742 wpa_drv_set_countermeasures(wpa_s, 0);
5743 wpa_clear_keys(wpa_s, NULL);
5744 }
5745
5746 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005747 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005748
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005749 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005750 radio_remove_interface(wpa_s);
5751
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005752#ifdef CONFIG_FST
5753 if (wpa_s->fst) {
5754 fst_detach(wpa_s->fst);
5755 wpa_s->fst = NULL;
5756 }
5757 if (wpa_s->received_mb_ies) {
5758 wpabuf_free(wpa_s->received_mb_ies);
5759 wpa_s->received_mb_ies = NULL;
5760 }
5761#endif /* CONFIG_FST */
5762
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005763 if (wpa_s->drv_priv)
5764 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005765
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005766 if (notify)
5767 wpas_notify_iface_removed(wpa_s);
5768
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005769 if (terminate)
5770 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005771
5772 if (wpa_s->ctrl_iface) {
5773 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5774 wpa_s->ctrl_iface = NULL;
5775 }
5776
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005777#ifdef CONFIG_MESH
5778 if (wpa_s->ifmsh) {
5779 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5780 wpa_s->ifmsh = NULL;
5781 }
5782#endif /* CONFIG_MESH */
5783
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005784 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005785 wpa_config_free(wpa_s->conf);
5786 wpa_s->conf = NULL;
5787 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005788
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005789 os_free(wpa_s->ssids_from_scan_req);
5790
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005791 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005792}
5793
5794
Dmitry Shmidte4663042016-04-04 10:07:49 -07005795#ifdef CONFIG_MATCH_IFACE
5796
5797/**
5798 * wpa_supplicant_match_iface - Match an interface description to a name
5799 * @global: Pointer to global data from wpa_supplicant_init()
5800 * @ifname: Name of the interface to match
5801 * Returns: Pointer to the created interface description or %NULL on failure
5802 */
5803struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5804 const char *ifname)
5805{
5806 int i;
5807 struct wpa_interface *iface, *miface;
5808
5809 for (i = 0; i < global->params.match_iface_count; i++) {
5810 miface = &global->params.match_ifaces[i];
5811 if (!miface->ifname ||
5812 fnmatch(miface->ifname, ifname, 0) == 0) {
5813 iface = os_zalloc(sizeof(*iface));
5814 if (!iface)
5815 return NULL;
5816 *iface = *miface;
5817 iface->ifname = ifname;
5818 return iface;
5819 }
5820 }
5821
5822 return NULL;
5823}
5824
5825
5826/**
5827 * wpa_supplicant_match_existing - Match existing interfaces
5828 * @global: Pointer to global data from wpa_supplicant_init()
5829 * Returns: 0 on success, -1 on failure
5830 */
5831static int wpa_supplicant_match_existing(struct wpa_global *global)
5832{
5833 struct if_nameindex *ifi, *ifp;
5834 struct wpa_supplicant *wpa_s;
5835 struct wpa_interface *iface;
5836
5837 ifp = if_nameindex();
5838 if (!ifp) {
5839 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5840 return -1;
5841 }
5842
5843 for (ifi = ifp; ifi->if_name; ifi++) {
5844 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5845 if (wpa_s)
5846 continue;
5847 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5848 if (iface) {
5849 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5850 os_free(iface);
5851 if (wpa_s)
5852 wpa_s->matched = 1;
5853 }
5854 }
5855
5856 if_freenameindex(ifp);
5857 return 0;
5858}
5859
5860#endif /* CONFIG_MATCH_IFACE */
5861
5862
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005863/**
5864 * wpa_supplicant_add_iface - Add a new network interface
5865 * @global: Pointer to global data from wpa_supplicant_init()
5866 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005867 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005868 * Returns: Pointer to the created interface or %NULL on failure
5869 *
5870 * This function is used to add new network interfaces for %wpa_supplicant.
5871 * This can be called before wpa_supplicant_run() to add interfaces before the
5872 * main event loop has been started. In addition, new interfaces can be added
5873 * dynamically while %wpa_supplicant is already running. This could happen,
5874 * e.g., when a hotplug network adapter is inserted.
5875 */
5876struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005877 struct wpa_interface *iface,
5878 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005879{
5880 struct wpa_supplicant *wpa_s;
5881 struct wpa_interface t_iface;
5882 struct wpa_ssid *ssid;
5883
5884 if (global == NULL || iface == NULL)
5885 return NULL;
5886
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005887 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005888 if (wpa_s == NULL)
5889 return NULL;
5890
5891 wpa_s->global = global;
5892
5893 t_iface = *iface;
5894 if (global->params.override_driver) {
5895 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5896 "('%s' -> '%s')",
5897 iface->driver, global->params.override_driver);
5898 t_iface.driver = global->params.override_driver;
5899 }
5900 if (global->params.override_ctrl_interface) {
5901 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5902 "ctrl_interface ('%s' -> '%s')",
5903 iface->ctrl_interface,
5904 global->params.override_ctrl_interface);
5905 t_iface.ctrl_interface =
5906 global->params.override_ctrl_interface;
5907 }
5908 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5909 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5910 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005911 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005912 return NULL;
5913 }
5914
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005915 /* Notify the control interfaces about new iface */
5916 if (wpas_notify_iface_added(wpa_s)) {
5917 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5918 return NULL;
5919 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005920
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005921 /* Notify the control interfaces about new networks for non p2p mgmt
5922 * ifaces. */
5923 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005924 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5925 wpas_notify_network_added(wpa_s, ssid);
5926 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005927
5928 wpa_s->next = global->ifaces;
5929 global->ifaces = wpa_s;
5930
5931 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005932 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005933
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005934#ifdef CONFIG_P2P
5935 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005936 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005937 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005938 wpas_p2p_add_p2pdev_interface(
5939 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005940 wpa_printf(MSG_INFO,
5941 "P2P: Failed to enable P2P Device interface");
5942 /* Try to continue without. P2P will be disabled. */
5943 }
5944#endif /* CONFIG_P2P */
5945
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005946 return wpa_s;
5947}
5948
5949
5950/**
5951 * wpa_supplicant_remove_iface - Remove a network interface
5952 * @global: Pointer to global data from wpa_supplicant_init()
5953 * @wpa_s: Pointer to the network interface to be removed
5954 * Returns: 0 if interface was removed, -1 if interface was not found
5955 *
5956 * This function can be used to dynamically remove network interfaces from
5957 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5958 * addition, this function is used to remove all remaining interfaces when
5959 * %wpa_supplicant is terminated.
5960 */
5961int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005962 struct wpa_supplicant *wpa_s,
5963 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005964{
5965 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005966#ifdef CONFIG_MESH
5967 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5968 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005969 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005970#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005971
5972 /* Remove interface from the global list of interfaces */
5973 prev = global->ifaces;
5974 if (prev == wpa_s) {
5975 global->ifaces = wpa_s->next;
5976 } else {
5977 while (prev && prev->next != wpa_s)
5978 prev = prev->next;
5979 if (prev == NULL)
5980 return -1;
5981 prev->next = wpa_s->next;
5982 }
5983
5984 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5985
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005986#ifdef CONFIG_MESH
5987 if (mesh_if_created) {
5988 ifname = os_strdup(wpa_s->ifname);
5989 if (ifname == NULL) {
5990 wpa_dbg(wpa_s, MSG_ERROR,
5991 "mesh: Failed to malloc ifname");
5992 return -1;
5993 }
5994 }
5995#endif /* CONFIG_MESH */
5996
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005997 if (global->p2p_group_formation == wpa_s)
5998 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005999 if (global->p2p_invite_group == wpa_s)
6000 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006001 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006002
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006003#ifdef CONFIG_MESH
6004 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006005 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006006 os_free(ifname);
6007 }
6008#endif /* CONFIG_MESH */
6009
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006010 return 0;
6011}
6012
6013
6014/**
6015 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6016 * @wpa_s: Pointer to the network interface
6017 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6018 */
6019const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6020{
6021 const char *eapol_method;
6022
6023 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6024 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6025 return "NO-EAP";
6026 }
6027
6028 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6029 if (eapol_method == NULL)
6030 return "UNKNOWN-EAP";
6031
6032 return eapol_method;
6033}
6034
6035
6036/**
6037 * wpa_supplicant_get_iface - Get a new network interface
6038 * @global: Pointer to global data from wpa_supplicant_init()
6039 * @ifname: Interface name
6040 * Returns: Pointer to the interface or %NULL if not found
6041 */
6042struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6043 const char *ifname)
6044{
6045 struct wpa_supplicant *wpa_s;
6046
6047 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6048 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6049 return wpa_s;
6050 }
6051 return NULL;
6052}
6053
6054
6055#ifndef CONFIG_NO_WPA_MSG
6056static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6057{
6058 struct wpa_supplicant *wpa_s = ctx;
6059 if (wpa_s == NULL)
6060 return NULL;
6061 return wpa_s->ifname;
6062}
6063#endif /* CONFIG_NO_WPA_MSG */
6064
6065
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006066#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6067#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6068#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6069
6070/* Periodic cleanup tasks */
6071static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6072{
6073 struct wpa_global *global = eloop_ctx;
6074 struct wpa_supplicant *wpa_s;
6075
6076 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6077 wpas_periodic, global, NULL);
6078
6079#ifdef CONFIG_P2P
6080 if (global->p2p)
6081 p2p_expire_peers(global->p2p);
6082#endif /* CONFIG_P2P */
6083
6084 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6085 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6086#ifdef CONFIG_AP
6087 ap_periodic(wpa_s);
6088#endif /* CONFIG_AP */
6089 }
6090}
6091
6092
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006093/**
6094 * wpa_supplicant_init - Initialize %wpa_supplicant
6095 * @params: Parameters for %wpa_supplicant
6096 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6097 *
6098 * This function is used to initialize %wpa_supplicant. After successful
6099 * initialization, the returned data pointer can be used to add and remove
6100 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6101 */
6102struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6103{
6104 struct wpa_global *global;
6105 int ret, i;
6106
6107 if (params == NULL)
6108 return NULL;
6109
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006110#ifdef CONFIG_DRIVER_NDIS
6111 {
6112 void driver_ndis_init_ops(void);
6113 driver_ndis_init_ops();
6114 }
6115#endif /* CONFIG_DRIVER_NDIS */
6116
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006117#ifndef CONFIG_NO_WPA_MSG
6118 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6119#endif /* CONFIG_NO_WPA_MSG */
6120
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006121 if (params->wpa_debug_file_path)
6122 wpa_debug_open_file(params->wpa_debug_file_path);
6123 else
6124 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006125 if (params->wpa_debug_syslog)
6126 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006127 if (params->wpa_debug_tracing) {
6128 ret = wpa_debug_open_linux_tracing();
6129 if (ret) {
6130 wpa_printf(MSG_ERROR,
6131 "Failed to enable trace logging");
6132 return NULL;
6133 }
6134 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006135
6136 ret = eap_register_methods();
6137 if (ret) {
6138 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6139 if (ret == -2)
6140 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6141 "the same EAP type.");
6142 return NULL;
6143 }
6144
6145 global = os_zalloc(sizeof(*global));
6146 if (global == NULL)
6147 return NULL;
6148 dl_list_init(&global->p2p_srv_bonjour);
6149 dl_list_init(&global->p2p_srv_upnp);
6150 global->params.daemonize = params->daemonize;
6151 global->params.wait_for_monitor = params->wait_for_monitor;
6152 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6153 if (params->pid_file)
6154 global->params.pid_file = os_strdup(params->pid_file);
6155 if (params->ctrl_interface)
6156 global->params.ctrl_interface =
6157 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006158 if (params->ctrl_interface_group)
6159 global->params.ctrl_interface_group =
6160 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006161 if (params->override_driver)
6162 global->params.override_driver =
6163 os_strdup(params->override_driver);
6164 if (params->override_ctrl_interface)
6165 global->params.override_ctrl_interface =
6166 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006167#ifdef CONFIG_MATCH_IFACE
6168 global->params.match_iface_count = params->match_iface_count;
6169 if (params->match_iface_count) {
6170 global->params.match_ifaces =
6171 os_calloc(params->match_iface_count,
6172 sizeof(struct wpa_interface));
6173 os_memcpy(global->params.match_ifaces,
6174 params->match_ifaces,
6175 params->match_iface_count *
6176 sizeof(struct wpa_interface));
6177 }
6178#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006179#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006180 if (params->conf_p2p_dev)
6181 global->params.conf_p2p_dev =
6182 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006183#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006184 wpa_debug_level = global->params.wpa_debug_level =
6185 params->wpa_debug_level;
6186 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6187 params->wpa_debug_show_keys;
6188 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6189 params->wpa_debug_timestamp;
6190
6191 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
6192
6193 if (eloop_init()) {
6194 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6195 wpa_supplicant_deinit(global);
6196 return NULL;
6197 }
6198
Jouni Malinen75ecf522011-06-27 15:19:46 -07006199 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006200
6201 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6202 if (global->ctrl_iface == NULL) {
6203 wpa_supplicant_deinit(global);
6204 return NULL;
6205 }
6206
6207 if (wpas_notify_supplicant_initialized(global)) {
6208 wpa_supplicant_deinit(global);
6209 return NULL;
6210 }
6211
6212 for (i = 0; wpa_drivers[i]; i++)
6213 global->drv_count++;
6214 if (global->drv_count == 0) {
6215 wpa_printf(MSG_ERROR, "No drivers enabled");
6216 wpa_supplicant_deinit(global);
6217 return NULL;
6218 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006219 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006220 if (global->drv_priv == NULL) {
6221 wpa_supplicant_deinit(global);
6222 return NULL;
6223 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006224
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006225#ifdef CONFIG_WIFI_DISPLAY
6226 if (wifi_display_init(global) < 0) {
6227 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6228 wpa_supplicant_deinit(global);
6229 return NULL;
6230 }
6231#endif /* CONFIG_WIFI_DISPLAY */
6232
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006233 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6234 wpas_periodic, global, NULL);
6235
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006236 return global;
6237}
6238
6239
6240/**
6241 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6242 * @global: Pointer to global data from wpa_supplicant_init()
6243 * Returns: 0 after successful event loop run, -1 on failure
6244 *
6245 * This function starts the main event loop and continues running as long as
6246 * there are any remaining events. In most cases, this function is running as
6247 * long as the %wpa_supplicant process in still in use.
6248 */
6249int wpa_supplicant_run(struct wpa_global *global)
6250{
6251 struct wpa_supplicant *wpa_s;
6252
6253 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006254 (wpa_supplicant_daemon(global->params.pid_file) ||
6255 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006256 return -1;
6257
Dmitry Shmidte4663042016-04-04 10:07:49 -07006258#ifdef CONFIG_MATCH_IFACE
6259 if (wpa_supplicant_match_existing(global))
6260 return -1;
6261#endif
6262
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006263 if (global->params.wait_for_monitor) {
6264 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08006265 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006266 wpa_supplicant_ctrl_iface_wait(
6267 wpa_s->ctrl_iface);
6268 }
6269
6270 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
6271 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
6272
6273 eloop_run();
6274
6275 return 0;
6276}
6277
6278
6279/**
6280 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
6281 * @global: Pointer to global data from wpa_supplicant_init()
6282 *
6283 * This function is called to deinitialize %wpa_supplicant and to free all
6284 * allocated resources. Remaining network interfaces will also be removed.
6285 */
6286void wpa_supplicant_deinit(struct wpa_global *global)
6287{
6288 int i;
6289
6290 if (global == NULL)
6291 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006292
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006293 eloop_cancel_timeout(wpas_periodic, global, NULL);
6294
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006295#ifdef CONFIG_WIFI_DISPLAY
6296 wifi_display_deinit(global);
6297#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006298
6299 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006300 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006301
6302 if (global->ctrl_iface)
6303 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
6304
6305 wpas_notify_supplicant_deinitialized(global);
6306
6307 eap_peer_unregister_methods();
6308#ifdef CONFIG_AP
6309 eap_server_unregister_methods();
6310#endif /* CONFIG_AP */
6311
6312 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
6313 if (!global->drv_priv[i])
6314 continue;
6315 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
6316 }
6317 os_free(global->drv_priv);
6318
6319 random_deinit();
6320
6321 eloop_destroy();
6322
6323 if (global->params.pid_file) {
6324 os_daemonize_terminate(global->params.pid_file);
6325 os_free(global->params.pid_file);
6326 }
6327 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006328 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006329 os_free(global->params.override_driver);
6330 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006331#ifdef CONFIG_MATCH_IFACE
6332 os_free(global->params.match_ifaces);
6333#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006334#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006335 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006336#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006337
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07006338 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006339 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006340 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006342 os_free(global);
6343 wpa_debug_close_syslog();
6344 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006345 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006346}
6347
6348
6349void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
6350{
6351 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
6352 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
6353 char country[3];
6354 country[0] = wpa_s->conf->country[0];
6355 country[1] = wpa_s->conf->country[1];
6356 country[2] = '\0';
6357 if (wpa_drv_set_country(wpa_s, country) < 0) {
6358 wpa_printf(MSG_ERROR, "Failed to set country code "
6359 "'%s'", country);
6360 }
6361 }
6362
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006363 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
6364 wpas_init_ext_pw(wpa_s);
6365
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006366 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
6367 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6368
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006369 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
6370 struct wpa_driver_capa capa;
6371 int res = wpa_drv_get_capa(wpa_s, &capa);
6372
6373 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
6374 wpa_printf(MSG_ERROR,
6375 "Failed to update wowlan_triggers to '%s'",
6376 wpa_s->conf->wowlan_triggers);
6377 }
6378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006379#ifdef CONFIG_WPS
6380 wpas_wps_update_config(wpa_s);
6381#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006382 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006383 wpa_s->conf->changed_parameters = 0;
6384}
6385
6386
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006387void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006388{
6389 int i;
6390
6391 for (i = 0; i < *num_freqs; i++) {
6392 if (freqs[i] == freq)
6393 return;
6394 }
6395
6396 freqs[*num_freqs] = freq;
6397 (*num_freqs)++;
6398}
6399
6400
6401static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
6402{
6403 struct wpa_bss *bss, *cbss;
6404 const int max_freqs = 10;
6405 int *freqs;
6406 int num_freqs = 0;
6407
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006408 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006409 if (freqs == NULL)
6410 return NULL;
6411
6412 cbss = wpa_s->current_bss;
6413
6414 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
6415 if (bss == cbss)
6416 continue;
6417 if (bss->ssid_len == cbss->ssid_len &&
6418 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
6419 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
6420 add_freq(freqs, &num_freqs, bss->freq);
6421 if (num_freqs == max_freqs)
6422 break;
6423 }
6424 }
6425
6426 if (num_freqs == 0) {
6427 os_free(freqs);
6428 freqs = NULL;
6429 }
6430
6431 return freqs;
6432}
6433
6434
6435void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6436{
6437 int timeout;
6438 int count;
6439 int *freqs = NULL;
6440
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006441 wpas_connect_work_done(wpa_s);
6442
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006443 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006444 * Remove possible authentication timeout since the connection failed.
6445 */
6446 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
6447
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006448 /*
6449 * There is no point in blacklisting the AP if this event is
6450 * generated based on local request to disconnect.
6451 */
6452 if (wpa_s->own_disconnect_req) {
6453 wpa_s->own_disconnect_req = 0;
6454 wpa_dbg(wpa_s, MSG_DEBUG,
6455 "Ignore connection failure due to local request to disconnect");
6456 return;
6457 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006458 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006459 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6460 "indication since interface has been put into "
6461 "disconnected state");
6462 return;
6463 }
6464
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006465 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006466 * Add the failed BSSID into the blacklist and speed up next scan
6467 * attempt if there could be other APs that could accept association.
6468 * The current blacklist count indicates how many times we have tried
6469 * connecting to this AP and multiple attempts mean that other APs are
6470 * either not available or has already been tried, so that we can start
6471 * increasing the delay here to avoid constant scanning.
6472 */
6473 count = wpa_blacklist_add(wpa_s, bssid);
6474 if (count == 1 && wpa_s->current_bss) {
6475 /*
6476 * This BSS was not in the blacklist before. If there is
6477 * another BSS available for the same ESS, we should try that
6478 * next. Otherwise, we may as well try this one once more
6479 * before allowing other, likely worse, ESSes to be considered.
6480 */
6481 freqs = get_bss_freqs_in_ess(wpa_s);
6482 if (freqs) {
6483 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
6484 "has been seen; try it next");
6485 wpa_blacklist_add(wpa_s, bssid);
6486 /*
6487 * On the next scan, go through only the known channels
6488 * used in this ESS based on previous scans to speed up
6489 * common load balancing use case.
6490 */
6491 os_free(wpa_s->next_scan_freqs);
6492 wpa_s->next_scan_freqs = freqs;
6493 }
6494 }
6495
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006496 /*
6497 * Add previous failure count in case the temporary blacklist was
6498 * cleared due to no other BSSes being available.
6499 */
6500 count += wpa_s->extra_blacklist_count;
6501
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006502 if (count > 3 && wpa_s->current_ssid) {
6503 wpa_printf(MSG_DEBUG, "Continuous association failures - "
6504 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006505 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006506 }
6507
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006508 switch (count) {
6509 case 1:
6510 timeout = 100;
6511 break;
6512 case 2:
6513 timeout = 500;
6514 break;
6515 case 3:
6516 timeout = 1000;
6517 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006518 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006519 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006520 break;
6521 default:
6522 timeout = 10000;
6523 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006524 }
6525
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006526 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
6527 "ms", count, timeout);
6528
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006529 /*
6530 * TODO: if more than one possible AP is available in scan results,
6531 * could try the other ones before requesting a new scan.
6532 */
6533 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
6534 1000 * (timeout % 1000));
6535}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006536
6537
Hai Shalomce48b4a2018-09-05 11:41:35 -07006538#ifdef CONFIG_FILS
6539void fils_connection_failure(struct wpa_supplicant *wpa_s)
6540{
6541 struct wpa_ssid *ssid = wpa_s->current_ssid;
6542 const u8 *realm, *username, *rrk;
6543 size_t realm_len, username_len, rrk_len;
6544 u16 next_seq_num;
6545
6546 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
6547 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
6548 &username, &username_len,
6549 &realm, &realm_len, &next_seq_num,
6550 &rrk, &rrk_len) != 0 ||
6551 !realm)
6552 return;
6553
6554 wpa_hexdump_ascii(MSG_DEBUG,
6555 "FILS: Store last connection failure realm",
6556 realm, realm_len);
6557 os_free(wpa_s->last_con_fail_realm);
6558 wpa_s->last_con_fail_realm = os_malloc(realm_len);
6559 if (wpa_s->last_con_fail_realm) {
6560 wpa_s->last_con_fail_realm_len = realm_len;
6561 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
6562 }
6563}
6564#endif /* CONFIG_FILS */
6565
6566
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006567int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
6568{
6569 return wpa_s->conf->ap_scan == 2 ||
6570 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
6571}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006572
Dmitry Shmidt04949592012-07-19 12:16:46 -07006573
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006574#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006575int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6576 struct wpa_ssid *ssid,
6577 const char *field,
6578 const char *value)
6579{
6580#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006581 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006582
6583 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
6584 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
6585 (const u8 *) value, os_strlen(value));
6586
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006587 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07006588 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006589#else /* IEEE8021X_EAPOL */
6590 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6591 return -1;
6592#endif /* IEEE8021X_EAPOL */
6593}
6594
6595int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6596 struct wpa_ssid *ssid,
6597 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07006598 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006599{
6600#ifdef IEEE8021X_EAPOL
6601 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08006602 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006603
6604 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07006605 case WPA_CTRL_REQ_EAP_IDENTITY:
6606 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08006607 os_free(eap->imsi_identity);
6608 if (value == NULL)
6609 return -1;
6610 identity = os_strchr(value, ':');
6611 if (identity == NULL) {
6612 /* plain identity */
6613 eap->identity = (u8 *)os_strdup(value);
6614 eap->identity_len = os_strlen(value);
6615 } else {
6616 /* have both plain identity and encrypted identity */
6617 imsi_identity = value;
6618 *identity++ = '\0';
6619 /* plain identity */
6620 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
6621 eap->imsi_identity_len = strlen(imsi_identity);
6622 /* encrypted identity */
6623 eap->identity = (u8 *)dup_binstr(identity,
6624 value_len - strlen(imsi_identity) - 1);
6625 eap->identity_len = value_len - strlen(imsi_identity) - 1;
6626 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006627 eap->pending_req_identity = 0;
6628 if (ssid == wpa_s->current_ssid)
6629 wpa_s->reassociate = 1;
6630 break;
6631 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006632 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006633 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006634 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006635 eap->pending_req_password = 0;
6636 if (ssid == wpa_s->current_ssid)
6637 wpa_s->reassociate = 1;
6638 break;
6639 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006640 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006641 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006642 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006643 eap->pending_req_new_password = 0;
6644 if (ssid == wpa_s->current_ssid)
6645 wpa_s->reassociate = 1;
6646 break;
6647 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006648 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006649 eap->pin = os_strdup(value);
6650 eap->pending_req_pin = 0;
6651 if (ssid == wpa_s->current_ssid)
6652 wpa_s->reassociate = 1;
6653 break;
6654 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006655 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006656 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006657 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006658 os_free(eap->pending_req_otp);
6659 eap->pending_req_otp = NULL;
6660 eap->pending_req_otp_len = 0;
6661 break;
6662 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006663 str_clear_free(eap->private_key_passwd);
6664 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006665 eap->pending_req_passphrase = 0;
6666 if (ssid == wpa_s->current_ssid)
6667 wpa_s->reassociate = 1;
6668 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006669 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006670 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07006671 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006672 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006673 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006674 case WPA_CTRL_REQ_PSK_PASSPHRASE:
6675 if (wpa_config_set(ssid, "psk", value, 0) < 0)
6676 return -1;
6677 ssid->mem_only_psk = 1;
6678 if (ssid->passphrase)
6679 wpa_config_update_psk(ssid);
6680 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
6681 wpa_supplicant_req_scan(wpa_s, 0, 0);
6682 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006683 case WPA_CTRL_REQ_EXT_CERT_CHECK:
6684 if (eap->pending_ext_cert_check != PENDING_CHECK)
6685 return -1;
6686 if (os_strcmp(value, "good") == 0)
6687 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
6688 else if (os_strcmp(value, "bad") == 0)
6689 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
6690 else
6691 return -1;
6692 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006693 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006694 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006695 return -1;
6696 }
6697
6698 return 0;
6699#else /* IEEE8021X_EAPOL */
6700 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6701 return -1;
6702#endif /* IEEE8021X_EAPOL */
6703}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006704#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006705
6706
6707int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6708{
6709 int i;
6710 unsigned int drv_enc;
6711
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006712 if (wpa_s->p2p_mgmt)
6713 return 1; /* no normal network profiles on p2p_mgmt interface */
6714
Dmitry Shmidt04949592012-07-19 12:16:46 -07006715 if (ssid == NULL)
6716 return 1;
6717
6718 if (ssid->disabled)
6719 return 1;
6720
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006721 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006722 drv_enc = wpa_s->drv_enc;
6723 else
6724 drv_enc = (unsigned int) -1;
6725
6726 for (i = 0; i < NUM_WEP_KEYS; i++) {
6727 size_t len = ssid->wep_key_len[i];
6728 if (len == 0)
6729 continue;
6730 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
6731 continue;
6732 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
6733 continue;
6734 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
6735 continue;
6736 return 1; /* invalid WEP key */
6737 }
6738
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006739 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006740 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006741 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006742 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006743 return 1;
6744
Dmitry Shmidt04949592012-07-19 12:16:46 -07006745 return 0;
6746}
6747
6748
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006749int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6750{
6751#ifdef CONFIG_IEEE80211W
6752 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6753 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6754 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6755 /*
6756 * Driver does not support BIP -- ignore pmf=1 default
6757 * since the connection with PMF would fail and the
6758 * configuration does not require PMF to be enabled.
6759 */
6760 return NO_MGMT_FRAME_PROTECTION;
6761 }
6762
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006763 if (ssid &&
6764 (ssid->key_mgmt &
6765 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6766 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6767 /*
6768 * Do not use the default PMF value for non-RSN networks
6769 * since PMF is available only with RSN and pmf=2
6770 * configuration would otherwise prevent connections to
6771 * all open networks.
6772 */
6773 return NO_MGMT_FRAME_PROTECTION;
6774 }
6775
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006776 return wpa_s->conf->pmf;
6777 }
6778
6779 return ssid->ieee80211w;
6780#else /* CONFIG_IEEE80211W */
6781 return NO_MGMT_FRAME_PROTECTION;
6782#endif /* CONFIG_IEEE80211W */
6783}
6784
6785
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006786int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006787{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006788 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006789 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006790 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006791 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006792 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006793}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006794
6795
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006796void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006797{
6798 struct wpa_ssid *ssid = wpa_s->current_ssid;
6799 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006800 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006801
6802 if (ssid == NULL) {
6803 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6804 "SSID block");
6805 return;
6806 }
6807
6808 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6809 return;
6810
6811 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006812
6813#ifdef CONFIG_P2P
6814 if (ssid->p2p_group &&
6815 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6816 /*
6817 * Skip the wait time since there is a short timeout on the
6818 * connection to a P2P group.
6819 */
6820 return;
6821 }
6822#endif /* CONFIG_P2P */
6823
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006824 if (ssid->auth_failures > 50)
6825 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006826 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006827 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006828 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006829 dur = 90;
6830 else if (ssid->auth_failures > 3)
6831 dur = 60;
6832 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006833 dur = 30;
6834 else if (ssid->auth_failures > 1)
6835 dur = 20;
6836 else
6837 dur = 10;
6838
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006839 if (ssid->auth_failures > 1 &&
6840 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6841 dur += os_random() % (ssid->auth_failures * 10);
6842
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006843 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006844 if (now.sec + dur <= ssid->disabled_until.sec)
6845 return;
6846
6847 ssid->disabled_until.sec = now.sec + dur;
6848
6849 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006850 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006851 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006852 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006853}
6854
6855
6856void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6857 struct wpa_ssid *ssid, int clear_failures)
6858{
6859 if (ssid == NULL)
6860 return;
6861
6862 if (ssid->disabled_until.sec) {
6863 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6864 "id=%d ssid=\"%s\"",
6865 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6866 }
6867 ssid->disabled_until.sec = 0;
6868 ssid->disabled_until.usec = 0;
6869 if (clear_failures)
6870 ssid->auth_failures = 0;
6871}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006872
6873
6874int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6875{
6876 size_t i;
6877
6878 if (wpa_s->disallow_aps_bssid == NULL)
6879 return 0;
6880
6881 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6882 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6883 bssid, ETH_ALEN) == 0)
6884 return 1;
6885 }
6886
6887 return 0;
6888}
6889
6890
6891int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6892 size_t ssid_len)
6893{
6894 size_t i;
6895
6896 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6897 return 0;
6898
6899 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6900 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6901 if (ssid_len == s->ssid_len &&
6902 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6903 return 1;
6904 }
6905
6906 return 0;
6907}
6908
6909
6910/**
6911 * wpas_request_connection - Request a new connection
6912 * @wpa_s: Pointer to the network interface
6913 *
6914 * This function is used to request a new connection to be found. It will mark
6915 * the interface to allow reassociation and request a new scan to find a
6916 * suitable network to connect to.
6917 */
6918void wpas_request_connection(struct wpa_supplicant *wpa_s)
6919{
6920 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006921 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006922 wpa_supplicant_reinit_autoscan(wpa_s);
6923 wpa_s->extra_blacklist_count = 0;
6924 wpa_s->disconnected = 0;
6925 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006926 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006927
6928 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6929 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006930 else
6931 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006932}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006933
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006934
Roshan Pius02242d72016-08-09 15:31:48 -07006935/**
6936 * wpas_request_disconnection - Request disconnection
6937 * @wpa_s: Pointer to the network interface
6938 *
6939 * This function is used to request disconnection from the currently connected
6940 * network. This will stop any ongoing scans and initiate deauthentication.
6941 */
6942void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6943{
6944#ifdef CONFIG_SME
6945 wpa_s->sme.prev_bssid_set = 0;
6946#endif /* CONFIG_SME */
6947 wpa_s->reassociate = 0;
6948 wpa_s->disconnected = 1;
6949 wpa_supplicant_cancel_sched_scan(wpa_s);
6950 wpa_supplicant_cancel_scan(wpa_s);
6951 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6952 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6953}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006954
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006955
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006956void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6957 struct wpa_used_freq_data *freqs_data,
6958 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006959{
6960 unsigned int i;
6961
6962 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6963 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006964 for (i = 0; i < len; i++) {
6965 struct wpa_used_freq_data *cur = &freqs_data[i];
6966 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6967 i, cur->freq, cur->flags);
6968 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006969}
6970
6971
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006972/*
6973 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006974 * are using the same radio as the current interface, and in addition, get
6975 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006976 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006977int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6978 struct wpa_used_freq_data *freqs_data,
6979 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006980{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006981 struct wpa_supplicant *ifs;
6982 u8 bssid[ETH_ALEN];
6983 int freq;
6984 unsigned int idx = 0, i;
6985
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006986 wpa_dbg(wpa_s, MSG_DEBUG,
6987 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006988 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006989
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006990 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6991 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006992 if (idx == len)
6993 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006994
6995 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6996 continue;
6997
6998 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006999 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
7000 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007001 freq = ifs->current_ssid->frequency;
7002 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
7003 freq = ifs->assoc_freq;
7004 else
7005 continue;
7006
7007 /* Hold only distinct freqs */
7008 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007009 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007010 break;
7011
7012 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007013 freqs_data[idx++].freq = freq;
7014
7015 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007016 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007017 WPA_FREQ_USED_BY_P2P_CLIENT :
7018 WPA_FREQ_USED_BY_INFRA_STATION;
7019 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007020 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007021
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007022 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007023 return idx;
7024}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007025
7026
7027/*
7028 * Find the operating frequencies of any of the virtual interfaces that
7029 * are using the same radio as the current interface.
7030 */
7031int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7032 int *freq_array, unsigned int len)
7033{
7034 struct wpa_used_freq_data *freqs_data;
7035 int num, i;
7036
7037 os_memset(freq_array, 0, sizeof(int) * len);
7038
7039 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7040 if (!freqs_data)
7041 return -1;
7042
7043 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7044 for (i = 0; i < num; i++)
7045 freq_array[i] = freqs_data[i].freq;
7046
7047 os_free(freqs_data);
7048
7049 return num;
7050}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007051
7052
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007053struct wpa_supplicant *
7054wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7055{
7056 switch (frame) {
7057#ifdef CONFIG_P2P
7058 case VENDOR_ELEM_PROBE_REQ_P2P:
7059 case VENDOR_ELEM_PROBE_RESP_P2P:
7060 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7061 case VENDOR_ELEM_BEACON_P2P_GO:
7062 case VENDOR_ELEM_P2P_PD_REQ:
7063 case VENDOR_ELEM_P2P_PD_RESP:
7064 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7065 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7066 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7067 case VENDOR_ELEM_P2P_INV_REQ:
7068 case VENDOR_ELEM_P2P_INV_RESP:
7069 case VENDOR_ELEM_P2P_ASSOC_REQ:
7070 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007071 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007072#endif /* CONFIG_P2P */
7073 default:
7074 return wpa_s;
7075 }
7076}
7077
7078
7079void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7080{
7081 unsigned int i;
7082 char buf[30];
7083
7084 wpa_printf(MSG_DEBUG, "Update vendor elements");
7085
7086 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7087 if (wpa_s->vendor_elem[i]) {
7088 int res;
7089
7090 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7091 if (!os_snprintf_error(sizeof(buf), res)) {
7092 wpa_hexdump_buf(MSG_DEBUG, buf,
7093 wpa_s->vendor_elem[i]);
7094 }
7095 }
7096 }
7097
7098#ifdef CONFIG_P2P
7099 if (wpa_s->parent == wpa_s &&
7100 wpa_s->global->p2p &&
7101 !wpa_s->global->p2p_disabled)
7102 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7103#endif /* CONFIG_P2P */
7104}
7105
7106
7107int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7108 const u8 *elem, size_t len)
7109{
7110 u8 *ie, *end;
7111
7112 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7113 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7114
7115 for (; ie + 1 < end; ie += 2 + ie[1]) {
7116 if (ie + len > end)
7117 break;
7118 if (os_memcmp(ie, elem, len) != 0)
7119 continue;
7120
7121 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7122 wpabuf_free(wpa_s->vendor_elem[frame]);
7123 wpa_s->vendor_elem[frame] = NULL;
7124 } else {
7125 os_memmove(ie, ie + len, end - (ie + len));
7126 wpa_s->vendor_elem[frame]->used -= len;
7127 }
7128 wpas_vendor_elem_update(wpa_s);
7129 return 0;
7130 }
7131
7132 return -1;
7133}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007134
7135
7136struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
7137 u16 num_modes, enum hostapd_hw_mode mode)
7138{
7139 u16 i;
7140
7141 for (i = 0; i < num_modes; i++) {
7142 if (modes[i].mode == mode)
7143 return &modes[i];
7144 }
7145
7146 return NULL;
7147}
7148
7149
7150static struct
7151wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7152 const u8 *bssid)
7153{
7154 struct wpa_bss_tmp_disallowed *bss;
7155
7156 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7157 struct wpa_bss_tmp_disallowed, list) {
7158 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7159 return bss;
7160 }
7161
7162 return NULL;
7163}
7164
7165
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007166static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7167{
7168 struct wpa_bss_tmp_disallowed *tmp;
7169 unsigned int num_bssid = 0;
7170 u8 *bssids;
7171 int ret;
7172
7173 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7174 if (!bssids)
7175 return -1;
7176 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7177 struct wpa_bss_tmp_disallowed, list) {
7178 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7179 ETH_ALEN);
7180 num_bssid++;
7181 }
7182 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7183 os_free(bssids);
7184 return ret;
7185}
7186
7187
7188static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7189{
7190 struct wpa_supplicant *wpa_s = eloop_ctx;
7191 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7192
7193 /* Make sure the bss is not already freed */
7194 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7195 struct wpa_bss_tmp_disallowed, list) {
7196 if (bss == tmp) {
7197 dl_list_del(&tmp->list);
7198 os_free(tmp);
7199 wpa_set_driver_tmp_disallow_list(wpa_s);
7200 break;
7201 }
7202 }
7203}
7204
7205
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007206void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
7207 unsigned int sec)
7208{
7209 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007210
7211 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7212 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007213 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
7214 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7215 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007216 return;
7217 }
7218
7219 bss = os_malloc(sizeof(*bss));
7220 if (!bss) {
7221 wpa_printf(MSG_DEBUG,
7222 "Failed to allocate memory for temp disallow BSS");
7223 return;
7224 }
7225
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007226 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7227 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007228 wpa_set_driver_tmp_disallow_list(wpa_s);
7229 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7230 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007231}
7232
7233
7234int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7235{
7236 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007237
7238 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7239 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007240 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
7241 bss = tmp;
7242 break;
7243 }
7244 }
7245 if (!bss)
7246 return 0;
7247
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007248 return 1;
7249}