blob: fc13a57b135ae4c55616b56ce0dbf9e60cc6b6a7 [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 */
1649 break;
1650 case 2: /* Bits 16-23 */
1651#ifdef CONFIG_WNM
1652 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1653 *pos |= 0x08; /* Bit 19 - BSS Transition */
1654#endif /* CONFIG_WNM */
1655 break;
1656 case 3: /* Bits 24-31 */
1657#ifdef CONFIG_WNM
1658 *pos |= 0x02; /* Bit 25 - SSID List */
1659#endif /* CONFIG_WNM */
1660#ifdef CONFIG_INTERWORKING
1661 if (wpa_s->conf->interworking)
1662 *pos |= 0x80; /* Bit 31 - Interworking */
1663#endif /* CONFIG_INTERWORKING */
1664 break;
1665 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001666#ifdef CONFIG_INTERWORKING
Hai Shalomce48b4a2018-09-05 11:41:35 -07001667 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001668 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001669#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001670 break;
1671 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001672#ifdef CONFIG_HS20
1673 if (wpa_s->conf->hs20)
1674 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1675#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001676#ifdef CONFIG_MBO
1677 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1678#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001679 break;
1680 case 6: /* Bits 48-55 */
1681 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001682 case 7: /* Bits 56-63 */
1683 break;
1684 case 8: /* Bits 64-71 */
1685 if (wpa_s->conf->ftm_responder)
1686 *pos |= 0x40; /* Bit 70 - FTM responder */
1687 if (wpa_s->conf->ftm_initiator)
1688 *pos |= 0x80; /* Bit 71 - FTM initiator */
1689 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001690 case 9: /* Bits 72-79 */
1691#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001692 if (!wpa_s->disable_fils)
1693 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001694#endif /* CONFIG_FILS */
1695 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001696 }
1697}
1698
1699
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001700int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001701{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001702 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001703 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001704
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001705 if (len < wpa_s->extended_capa_len)
1706 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001707 if (buflen < (size_t) len + 2) {
1708 wpa_printf(MSG_INFO,
1709 "Not enough room for building extended capabilities element");
1710 return -1;
1711 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001712
1713 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001714 *pos++ = len;
1715 for (i = 0; i < len; i++, pos++) {
1716 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001717
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001718 if (i < wpa_s->extended_capa_len) {
1719 *pos &= ~wpa_s->extended_capa_mask[i];
1720 *pos |= wpa_s->extended_capa[i];
1721 }
1722 }
1723
1724 while (len > 0 && buf[1 + len] == 0) {
1725 len--;
1726 buf[1] = len;
1727 }
1728 if (len == 0)
1729 return 0;
1730
1731 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001732}
1733
1734
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001735static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1736 struct wpa_bss *test_bss)
1737{
1738 struct wpa_bss *bss;
1739
1740 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1741 if (bss == test_bss)
1742 return 1;
1743 }
1744
1745 return 0;
1746}
1747
1748
1749static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1750 struct wpa_ssid *test_ssid)
1751{
1752 struct wpa_ssid *ssid;
1753
1754 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1755 if (ssid == test_ssid)
1756 return 1;
1757 }
1758
1759 return 0;
1760}
1761
1762
1763int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1764 struct wpa_ssid *test_ssid)
1765{
1766 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1767 return 0;
1768
1769 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1770}
1771
1772
1773void wpas_connect_work_free(struct wpa_connect_work *cwork)
1774{
1775 if (cwork == NULL)
1776 return;
1777 os_free(cwork);
1778}
1779
1780
1781void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1782{
1783 struct wpa_connect_work *cwork;
1784 struct wpa_radio_work *work = wpa_s->connect_work;
1785
1786 if (!work)
1787 return;
1788
1789 wpa_s->connect_work = NULL;
1790 cwork = work->ctx;
1791 work->ctx = NULL;
1792 wpas_connect_work_free(cwork);
1793 radio_work_done(work);
1794}
1795
1796
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001797int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1798{
1799 struct os_reltime now;
1800 u8 addr[ETH_ALEN];
1801
1802 os_get_reltime(&now);
1803 if (wpa_s->last_mac_addr_style == style &&
1804 wpa_s->last_mac_addr_change.sec != 0 &&
1805 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1806 wpa_s->conf->rand_addr_lifetime)) {
1807 wpa_msg(wpa_s, MSG_DEBUG,
1808 "Previously selected random MAC address has not yet expired");
1809 return 0;
1810 }
1811
1812 switch (style) {
1813 case 1:
1814 if (random_mac_addr(addr) < 0)
1815 return -1;
1816 break;
1817 case 2:
1818 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1819 if (random_mac_addr_keep_oui(addr) < 0)
1820 return -1;
1821 break;
1822 default:
1823 return -1;
1824 }
1825
1826 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1827 wpa_msg(wpa_s, MSG_INFO,
1828 "Failed to set random MAC address");
1829 return -1;
1830 }
1831
1832 os_get_reltime(&wpa_s->last_mac_addr_change);
1833 wpa_s->mac_addr_changed = 1;
1834 wpa_s->last_mac_addr_style = style;
1835
1836 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1837 wpa_msg(wpa_s, MSG_INFO,
1838 "Could not update MAC address information");
1839 return -1;
1840 }
1841
1842 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1843 MAC2STR(addr));
1844
1845 return 0;
1846}
1847
1848
1849int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1850{
1851 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1852 !wpa_s->conf->preassoc_mac_addr)
1853 return 0;
1854
1855 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1856}
1857
1858
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001859static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1860
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001861/**
1862 * wpa_supplicant_associate - Request association
1863 * @wpa_s: Pointer to wpa_supplicant data
1864 * @bss: Scan results for the selected BSS, or %NULL if not available
1865 * @ssid: Configuration data for the selected network
1866 *
1867 * This function is used to request %wpa_supplicant to associate with a BSS.
1868 */
1869void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1870 struct wpa_bss *bss, struct wpa_ssid *ssid)
1871{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001872 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001873 int rand_style;
1874
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001875 wpa_s->own_disconnect_req = 0;
1876
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001877 /*
1878 * If we are starting a new connection, any previously pending EAPOL
1879 * RX cannot be valid anymore.
1880 */
1881 wpabuf_free(wpa_s->pending_eapol_rx);
1882 wpa_s->pending_eapol_rx = NULL;
1883
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001884 if (ssid->mac_addr == -1)
1885 rand_style = wpa_s->conf->mac_addr;
1886 else
1887 rand_style = ssid->mac_addr;
1888
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001889 wmm_ac_clear_saved_tspecs(wpa_s);
1890 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001891 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001892#ifdef CONFIG_TESTING_OPTIONS
1893 wpa_s->testing_resend_assoc = 0;
1894#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001895
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001896 if (wpa_s->last_ssid == ssid) {
1897 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001898 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001899 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1900 wmm_ac_save_tspecs(wpa_s);
1901 wpa_s->reassoc_same_bss = 1;
1902 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001903 }
1904
1905 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001906 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1907 return;
1908 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001909 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001910 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1911 wpa_msg(wpa_s, MSG_INFO,
1912 "Could not restore permanent MAC address");
1913 return;
1914 }
1915 wpa_s->mac_addr_changed = 0;
1916 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1917 wpa_msg(wpa_s, MSG_INFO,
1918 "Could not update MAC address information");
1919 return;
1920 }
1921 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1922 }
1923 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001924
1925#ifdef CONFIG_IBSS_RSN
1926 ibss_rsn_deinit(wpa_s->ibss_rsn);
1927 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001928#else /* CONFIG_IBSS_RSN */
1929 if (ssid->mode == WPAS_MODE_IBSS &&
1930 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1931 wpa_msg(wpa_s, MSG_INFO,
1932 "IBSS RSN not supported in the build");
1933 return;
1934 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001935#endif /* CONFIG_IBSS_RSN */
1936
1937 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1938 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1939#ifdef CONFIG_AP
1940 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1941 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1942 "mode");
1943 return;
1944 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001945 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1946 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001947 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1948 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001949 return;
1950 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001951 wpa_s->current_bss = bss;
1952#else /* CONFIG_AP */
1953 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1954 "the build");
1955#endif /* CONFIG_AP */
1956 return;
1957 }
1958
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001959 if (ssid->mode == WPAS_MODE_MESH) {
1960#ifdef CONFIG_MESH
1961 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1962 wpa_msg(wpa_s, MSG_INFO,
1963 "Driver does not support mesh mode");
1964 return;
1965 }
1966 if (bss)
1967 ssid->frequency = bss->freq;
1968 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1969 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1970 return;
1971 }
1972 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001973 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1974 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1975 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001976 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001977#else /* CONFIG_MESH */
1978 wpa_msg(wpa_s, MSG_ERROR,
1979 "mesh mode support not included in the build");
1980#endif /* CONFIG_MESH */
1981 return;
1982 }
1983
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001984 /*
1985 * Set WPA state machine configuration to match the selected network now
1986 * so that the information is available before wpas_start_assoc_cb()
1987 * gets called. This is needed at least for RSN pre-authentication where
1988 * candidate APs are added to a list based on scan result processing
1989 * before completion of the first association.
1990 */
1991 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
1992
1993#ifdef CONFIG_DPP
1994 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
1995 return;
1996#endif /* CONFIG_DPP */
1997
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998#ifdef CONFIG_TDLS
1999 if (bss)
2000 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
2001 bss->ie_len);
2002#endif /* CONFIG_TDLS */
2003
2004 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2005 ssid->mode == IEEE80211_MODE_INFRA) {
2006 sme_authenticate(wpa_s, bss, ssid);
2007 return;
2008 }
2009
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002010 if (wpa_s->connect_work) {
2011 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2012 return;
2013 }
2014
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002015 if (radio_work_pending(wpa_s, "connect")) {
2016 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2017 return;
2018 }
2019
Dmitry Shmidt29333592017-01-09 12:27:11 -08002020#ifdef CONFIG_SME
2021 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2022 /* Clear possibly set auth_alg, if any, from last attempt. */
2023 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2024 }
2025#endif /* CONFIG_SME */
2026
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002027 wpas_abort_ongoing_scan(wpa_s);
2028
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002029 cwork = os_zalloc(sizeof(*cwork));
2030 if (cwork == NULL)
2031 return;
2032
2033 cwork->bss = bss;
2034 cwork->ssid = ssid;
2035
2036 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2037 wpas_start_assoc_cb, cwork) < 0) {
2038 os_free(cwork);
2039 }
2040}
2041
2042
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002043static int bss_is_ibss(struct wpa_bss *bss)
2044{
2045 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2046 IEEE80211_CAP_IBSS;
2047}
2048
2049
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002050static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2051 const struct wpa_ssid *ssid)
2052{
2053 enum hostapd_hw_mode hw_mode;
2054 struct hostapd_hw_modes *mode = NULL;
2055 u8 channel;
2056 int i;
2057
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002058 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2059 if (hw_mode == NUM_HOSTAPD_MODES)
2060 return 0;
2061 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2062 if (wpa_s->hw.modes[i].mode == hw_mode) {
2063 mode = &wpa_s->hw.modes[i];
2064 break;
2065 }
2066 }
2067
2068 if (!mode)
2069 return 0;
2070
2071 return mode->vht_capab != 0;
2072}
2073
2074
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002075void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2076 const struct wpa_ssid *ssid,
2077 struct hostapd_freq_params *freq)
2078{
2079 enum hostapd_hw_mode hw_mode;
2080 struct hostapd_hw_modes *mode = NULL;
2081 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2082 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002083 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002084 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2085 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002086 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002087 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002088 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002089 int chwidth, seg0, seg1;
2090 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002091
2092 freq->freq = ssid->frequency;
2093
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002094 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2095 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2096
2097 if (ssid->mode != WPAS_MODE_IBSS)
2098 break;
2099
2100 /* Don't adjust control freq in case of fixed_freq */
2101 if (ssid->fixed_freq)
2102 break;
2103
2104 if (!bss_is_ibss(bss))
2105 continue;
2106
2107 if (ssid->ssid_len == bss->ssid_len &&
2108 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2109 wpa_printf(MSG_DEBUG,
2110 "IBSS already found in scan results, adjust control freq: %d",
2111 bss->freq);
2112 freq->freq = bss->freq;
2113 obss_scan = 0;
2114 break;
2115 }
2116 }
2117
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002118 /* For IBSS check HT_IBSS flag */
2119 if (ssid->mode == WPAS_MODE_IBSS &&
2120 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2121 return;
2122
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002123 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2124 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2125 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2126 wpa_printf(MSG_DEBUG,
2127 "IBSS: WEP/TKIP detected, do not try to enable HT");
2128 return;
2129 }
2130
2131 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002132 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2133 if (wpa_s->hw.modes[i].mode == hw_mode) {
2134 mode = &wpa_s->hw.modes[i];
2135 break;
2136 }
2137 }
2138
2139 if (!mode)
2140 return;
2141
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002142#ifdef CONFIG_HT_OVERRIDES
2143 if (ssid->disable_ht) {
2144 freq->ht_enabled = 0;
2145 return;
2146 }
2147#endif /* CONFIG_HT_OVERRIDES */
2148
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002149 freq->ht_enabled = ht_supported(mode);
2150 if (!freq->ht_enabled)
2151 return;
2152
2153 /* Setup higher BW only for 5 GHz */
2154 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2155 return;
2156
2157 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2158 pri_chan = &mode->channels[chan_idx];
2159 if (pri_chan->chan == channel)
2160 break;
2161 pri_chan = NULL;
2162 }
2163 if (!pri_chan)
2164 return;
2165
2166 /* Check primary channel flags */
2167 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2168 return;
2169
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002170#ifdef CONFIG_HT_OVERRIDES
2171 if (ssid->disable_ht40)
2172 return;
2173#endif /* CONFIG_HT_OVERRIDES */
2174
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002175 /* Check/setup HT40+/HT40- */
2176 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2177 if (ht40plus[j] == channel) {
2178 ht40 = 1;
2179 break;
2180 }
2181 }
2182
2183 /* Find secondary channel */
2184 for (i = 0; i < mode->num_channels; i++) {
2185 sec_chan = &mode->channels[i];
2186 if (sec_chan->chan == channel + ht40 * 4)
2187 break;
2188 sec_chan = NULL;
2189 }
2190 if (!sec_chan)
2191 return;
2192
2193 /* Check secondary channel flags */
2194 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2195 return;
2196
2197 freq->channel = pri_chan->chan;
2198
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002199 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002200 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2201 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002202 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002203 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2204 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002205 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002206 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002207
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002208 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002209 struct wpa_scan_results *scan_res;
2210
2211 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2212 if (scan_res == NULL) {
2213 /* Back to HT20 */
2214 freq->sec_channel_offset = 0;
2215 return;
2216 }
2217
2218 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2219 sec_chan->chan);
2220 switch (res) {
2221 case 0:
2222 /* Back to HT20 */
2223 freq->sec_channel_offset = 0;
2224 break;
2225 case 1:
2226 /* Configuration allowed */
2227 break;
2228 case 2:
2229 /* Switch pri/sec channels */
2230 freq->freq = hw_get_freq(mode, sec_chan->chan);
2231 freq->sec_channel_offset = -freq->sec_channel_offset;
2232 freq->channel = sec_chan->chan;
2233 break;
2234 default:
2235 freq->sec_channel_offset = 0;
2236 break;
2237 }
2238
2239 wpa_scan_results_free(scan_res);
2240 }
2241
2242 wpa_printf(MSG_DEBUG,
2243 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2244 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002245
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002246 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002247 return;
2248
2249 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002250 if (ssid->mode == WPAS_MODE_IBSS &&
2251 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002252 return;
2253
2254 vht_freq = *freq;
2255
Paul Stewart092955c2017-02-06 09:13:09 -08002256#ifdef CONFIG_VHT_OVERRIDES
2257 if (ssid->disable_vht) {
2258 freq->vht_enabled = 0;
2259 return;
2260 }
2261#endif /* CONFIG_VHT_OVERRIDES */
2262
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002263 vht_freq.vht_enabled = vht_supported(mode);
2264 if (!vht_freq.vht_enabled)
2265 return;
2266
2267 /* setup center_freq1, bandwidth */
2268 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2269 if (freq->channel >= vht80[j] &&
2270 freq->channel < vht80[j] + 16)
2271 break;
2272 }
2273
2274 if (j == ARRAY_SIZE(vht80))
2275 return;
2276
2277 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2278 struct hostapd_channel_data *chan;
2279
2280 chan = hw_get_channel_chan(mode, i, NULL);
2281 if (!chan)
2282 return;
2283
2284 /* Back to HT configuration if channel not usable */
2285 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2286 return;
2287 }
2288
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002289 chwidth = VHT_CHANWIDTH_80MHZ;
2290 seg0 = vht80[j] + 6;
2291 seg1 = 0;
2292
2293 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2294 /* setup center_freq2, bandwidth */
2295 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2296 /* Only accept 80 MHz segments separated by a gap */
2297 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2298 continue;
2299 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2300 struct hostapd_channel_data *chan;
2301
2302 chan = hw_get_channel_chan(mode, i, NULL);
2303 if (!chan)
2304 continue;
2305
2306 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2307 HOSTAPD_CHAN_NO_IR |
2308 HOSTAPD_CHAN_RADAR))
2309 continue;
2310
2311 /* Found a suitable second segment for 80+80 */
2312 chwidth = VHT_CHANWIDTH_80P80MHZ;
2313 vht_caps |=
2314 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2315 seg1 = vht80[k] + 6;
2316 }
2317
2318 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2319 break;
2320 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002321 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2322 if (freq->freq == 5180) {
2323 chwidth = VHT_CHANWIDTH_160MHZ;
2324 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2325 seg0 = 50;
2326 } else if (freq->freq == 5520) {
2327 chwidth = VHT_CHANWIDTH_160MHZ;
2328 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2329 seg0 = 114;
2330 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002331 }
2332
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002333 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2334 freq->channel, freq->ht_enabled,
2335 vht_freq.vht_enabled,
2336 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002337 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002338 return;
2339
2340 *freq = vht_freq;
2341
2342 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2343 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002344}
2345
2346
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002347#ifdef CONFIG_FILS
2348static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2349 size_t ie_buf_len)
2350{
2351 struct fils_hlp_req *req;
2352 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2353 const u8 *pos;
2354 u8 *buf = ie_buf;
2355
2356 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2357 list) {
2358 rem_len = ie_buf_len - ie_len;
2359 pos = wpabuf_head(req->pkt);
2360 hdr_len = 1 + 2 * ETH_ALEN + 6;
2361 hlp_len = wpabuf_len(req->pkt);
2362
2363 if (rem_len < 2 + hdr_len + hlp_len) {
2364 wpa_printf(MSG_ERROR,
2365 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2366 (unsigned long) rem_len,
2367 (unsigned long) (2 + hdr_len + hlp_len));
2368 break;
2369 }
2370
2371 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2372 /* Element ID */
2373 *buf++ = WLAN_EID_EXTENSION;
2374 /* Length */
2375 *buf++ = len;
2376 /* Element ID Extension */
2377 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2378 /* Destination MAC address */
2379 os_memcpy(buf, req->dst, ETH_ALEN);
2380 buf += ETH_ALEN;
2381 /* Source MAC address */
2382 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2383 buf += ETH_ALEN;
2384 /* LLC/SNAP Header */
2385 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2386 buf += 6;
2387 /* HLP Packet */
2388 os_memcpy(buf, pos, len - hdr_len);
2389 buf += len - hdr_len;
2390 pos += len - hdr_len;
2391
2392 hlp_len -= len - hdr_len;
2393 ie_len += 2 + len;
2394 rem_len -= 2 + len;
2395
2396 while (hlp_len) {
2397 len = (hlp_len > 255) ? 255 : hlp_len;
2398 if (rem_len < 2 + len)
2399 break;
2400 *buf++ = WLAN_EID_FRAGMENT;
2401 *buf++ = len;
2402 os_memcpy(buf, pos, len);
2403 buf += len;
2404 pos += len;
2405
2406 hlp_len -= len;
2407 ie_len += 2 + len;
2408 rem_len -= 2 + len;
2409 }
2410 }
2411
2412 return ie_len;
2413}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002414
2415
2416int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2417{
2418 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2419 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2420 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2421 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2422}
2423
2424
2425int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2426{
2427#ifdef CONFIG_FILS_SK_PFS
2428 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2429 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2430#else /* CONFIG_FILS_SK_PFS */
2431 return 0;
2432#endif /* CONFIG_FILS_SK_PFS */
2433}
2434
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002435#endif /* CONFIG_FILS */
2436
2437
2438static u8 * wpas_populate_assoc_ies(
2439 struct wpa_supplicant *wpa_s,
2440 struct wpa_bss *bss, struct wpa_ssid *ssid,
2441 struct wpa_driver_associate_params *params,
2442 enum wpa_drv_update_connect_params_mask *mask)
2443{
2444 u8 *wpa_ie;
2445 size_t max_wpa_ie_len = 500;
2446 size_t wpa_ie_len;
2447 int algs = WPA_AUTH_ALG_OPEN;
Hai Shalomce48b4a2018-09-05 11:41:35 -07002448#ifdef CONFIG_MBO
2449 const u8 *mbo_ie;
2450#endif
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002451#ifdef CONFIG_FILS
2452 const u8 *realm, *username, *rrk;
2453 size_t realm_len, username_len, rrk_len;
2454 u16 next_seq_num;
2455 struct fils_hlp_req *req;
2456
2457 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2458 list) {
2459 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2460 2 + 2 * wpabuf_len(req->pkt) / 255;
2461 }
2462#endif /* CONFIG_FILS */
2463
2464 wpa_ie = os_malloc(max_wpa_ie_len);
2465 if (!wpa_ie) {
2466 wpa_printf(MSG_ERROR,
2467 "Failed to allocate connect IE buffer for %lu bytes",
2468 (unsigned long) max_wpa_ie_len);
2469 return NULL;
2470 }
2471
2472 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2473 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2474 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2475 int try_opportunistic;
2476 const u8 *cache_id = NULL;
2477
2478 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2479 wpa_s->conf->okc :
2480 ssid->proactive_key_caching) &&
2481 (ssid->proto & WPA_PROTO_RSN);
2482#ifdef CONFIG_FILS
2483 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2484 cache_id = wpa_bss_get_fils_cache_id(bss);
2485#endif /* CONFIG_FILS */
2486 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2487 ssid, try_opportunistic,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002488 cache_id, 0) == 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002489 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
2490 wpa_ie_len = max_wpa_ie_len;
2491 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2492 wpa_ie, &wpa_ie_len)) {
2493 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2494 "key management and encryption suites");
2495 os_free(wpa_ie);
2496 return NULL;
2497 }
2498 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2499 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2500 /*
2501 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2502 * use non-WPA since the scan results did not indicate that the
2503 * AP is using WPA or WPA2.
2504 */
2505 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2506 wpa_ie_len = 0;
2507 wpa_s->wpa_proto = 0;
2508 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2509 wpa_ie_len = max_wpa_ie_len;
2510 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2511 wpa_ie, &wpa_ie_len)) {
2512 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2513 "key management and encryption suites (no "
2514 "scan results)");
2515 os_free(wpa_ie);
2516 return NULL;
2517 }
2518#ifdef CONFIG_WPS
2519 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2520 struct wpabuf *wps_ie;
2521 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2522 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2523 wpa_ie_len = wpabuf_len(wps_ie);
2524 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2525 } else
2526 wpa_ie_len = 0;
2527 wpabuf_free(wps_ie);
2528 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2529 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2530 params->wps = WPS_MODE_PRIVACY;
2531 else
2532 params->wps = WPS_MODE_OPEN;
2533 wpa_s->wpa_proto = 0;
2534#endif /* CONFIG_WPS */
2535 } else {
2536 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2537 wpa_ie_len = 0;
2538 wpa_s->wpa_proto = 0;
2539 }
2540
2541#ifdef IEEE8021X_EAPOL
2542 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2543 if (ssid->leap) {
2544 if (ssid->non_leap == 0)
2545 algs = WPA_AUTH_ALG_LEAP;
2546 else
2547 algs |= WPA_AUTH_ALG_LEAP;
2548 }
2549 }
2550
2551#ifdef CONFIG_FILS
2552 /* Clear FILS association */
2553 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2554
2555 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2556 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2557 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2558 &username_len, &realm, &realm_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002559 &next_seq_num, &rrk, &rrk_len) == 0 &&
2560 (!wpa_s->last_con_fail_realm ||
2561 wpa_s->last_con_fail_realm_len != realm_len ||
2562 os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002563 algs = WPA_AUTH_ALG_FILS;
2564 params->fils_erp_username = username;
2565 params->fils_erp_username_len = username_len;
2566 params->fils_erp_realm = realm;
2567 params->fils_erp_realm_len = realm_len;
2568 params->fils_erp_next_seq_num = next_seq_num;
2569 params->fils_erp_rrk = rrk;
2570 params->fils_erp_rrk_len = rrk_len;
2571
2572 if (mask)
2573 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2574 }
2575#endif /* CONFIG_FILS */
2576#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002577#ifdef CONFIG_SAE
2578 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2579 algs = WPA_AUTH_ALG_SAE;
2580#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002581
2582 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2583 if (ssid->auth_alg) {
2584 algs = ssid->auth_alg;
2585 wpa_dbg(wpa_s, MSG_DEBUG,
2586 "Overriding auth_alg selection: 0x%x", algs);
2587 }
2588
2589#ifdef CONFIG_P2P
2590 if (wpa_s->global->p2p) {
2591 u8 *pos;
2592 size_t len;
2593 int res;
2594 pos = wpa_ie + wpa_ie_len;
2595 len = max_wpa_ie_len - wpa_ie_len;
2596 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2597 ssid->p2p_group);
2598 if (res >= 0)
2599 wpa_ie_len += res;
2600 }
2601
2602 wpa_s->cross_connect_disallowed = 0;
2603 if (bss) {
2604 struct wpabuf *p2p;
2605 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2606 if (p2p) {
2607 wpa_s->cross_connect_disallowed =
2608 p2p_get_cross_connect_disallowed(p2p);
2609 wpabuf_free(p2p);
2610 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2611 "connection",
2612 wpa_s->cross_connect_disallowed ?
2613 "disallows" : "allows");
2614 }
2615 }
2616
2617 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2618#endif /* CONFIG_P2P */
2619
2620 if (bss) {
2621 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
2622 wpa_ie + wpa_ie_len,
2623 max_wpa_ie_len -
2624 wpa_ie_len);
2625 }
2626
2627 /*
2628 * Workaround: Add Extended Capabilities element only if the AP
2629 * included this element in Beacon/Probe Response frames. Some older
2630 * APs seem to have interoperability issues if this element is
2631 * included, so while the standard may require us to include the
2632 * element in all cases, it is justifiable to skip it to avoid
2633 * interoperability issues.
2634 */
2635 if (ssid->p2p_group)
2636 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2637 else
2638 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2639
2640 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2641 u8 ext_capab[18];
2642 int ext_capab_len;
2643 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2644 sizeof(ext_capab));
2645 if (ext_capab_len > 0 &&
2646 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2647 u8 *pos = wpa_ie;
2648 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2649 pos += 2 + pos[1];
2650 os_memmove(pos + ext_capab_len, pos,
2651 wpa_ie_len - (pos - wpa_ie));
2652 wpa_ie_len += ext_capab_len;
2653 os_memcpy(pos, ext_capab, ext_capab_len);
2654 }
2655 }
2656
2657#ifdef CONFIG_HS20
2658 if (is_hs20_network(wpa_s, ssid, bss)) {
2659 struct wpabuf *hs20;
2660
Roshan Pius3a1667e2018-07-03 15:17:14 -07002661 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002662 if (hs20) {
2663 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2664 size_t len;
2665
2666 wpas_hs20_add_indication(hs20, pps_mo_id);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002667 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002668 len = max_wpa_ie_len - wpa_ie_len;
2669 if (wpabuf_len(hs20) <= len) {
2670 os_memcpy(wpa_ie + wpa_ie_len,
2671 wpabuf_head(hs20), wpabuf_len(hs20));
2672 wpa_ie_len += wpabuf_len(hs20);
2673 }
2674 wpabuf_free(hs20);
2675
2676 hs20_configure_frame_filters(wpa_s);
2677 }
2678 }
2679#endif /* CONFIG_HS20 */
2680
2681 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2682 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2683 size_t len;
2684
2685 len = max_wpa_ie_len - wpa_ie_len;
2686 if (wpabuf_len(buf) <= len) {
2687 os_memcpy(wpa_ie + wpa_ie_len,
2688 wpabuf_head(buf), wpabuf_len(buf));
2689 wpa_ie_len += wpabuf_len(buf);
2690 }
2691 }
2692
2693#ifdef CONFIG_FST
2694 if (wpa_s->fst_ies) {
2695 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2696
2697 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
2698 os_memcpy(wpa_ie + wpa_ie_len,
2699 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2700 wpa_ie_len += fst_ies_len;
2701 }
2702 }
2703#endif /* CONFIG_FST */
2704
2705#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07002706 mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL;
2707 if (mbo_ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002708 int len;
2709
2710 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
Hai Shalomce48b4a2018-09-05 11:41:35 -07002711 max_wpa_ie_len - wpa_ie_len,
2712 !!mbo_attr_from_mbo_ie(mbo_ie,
2713 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002714 if (len >= 0)
2715 wpa_ie_len += len;
2716 }
2717#endif /* CONFIG_MBO */
2718
2719#ifdef CONFIG_FILS
2720 if (algs == WPA_AUTH_ALG_FILS) {
2721 size_t len;
2722
2723 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
2724 max_wpa_ie_len - wpa_ie_len);
2725 wpa_ie_len += len;
2726 }
2727#endif /* CONFIG_FILS */
2728
2729#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002730#ifdef CONFIG_TESTING_OPTIONS
2731 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
2732 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2733 } else
2734#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002735 if (algs == WPA_AUTH_ALG_OPEN &&
2736 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
2737 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002738 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002739
Roshan Pius3a1667e2018-07-03 15:17:14 -07002740 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002741 group = ssid->owe_group;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002742 } else {
2743 if (wpa_s->last_owe_group == 19)
2744 group = 20;
2745 else if (wpa_s->last_owe_group == 20)
2746 group = 21;
2747 else
2748 group = OWE_DH_GROUP;
2749 }
2750 wpa_s->last_owe_group = group;
2751 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002752 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2753 if (owe_ie &&
2754 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
2755 os_memcpy(wpa_ie + wpa_ie_len,
2756 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2757 wpa_ie_len += wpabuf_len(owe_ie);
2758 wpabuf_free(owe_ie);
2759 }
2760 }
2761#endif /* CONFIG_OWE */
2762
Roshan Pius3a1667e2018-07-03 15:17:14 -07002763#ifdef CONFIG_IEEE80211R
2764 /*
2765 * Add MDIE under these conditions: the network profile allows FT,
2766 * the AP supports FT, and the mobility domain ID matches.
2767 */
2768 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
2769 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2770
2771 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
2772 size_t len = 0;
2773 const u8 *md = mdie + 2;
2774 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
2775
2776 if (os_memcmp(md, wpa_md,
2777 MOBILITY_DOMAIN_ID_LEN) == 0) {
2778 /* Add mobility domain IE */
2779 len = wpa_ft_add_mdie(
2780 wpa_s->wpa, wpa_ie + wpa_ie_len,
2781 max_wpa_ie_len - wpa_ie_len, mdie);
2782 wpa_ie_len += len;
2783 }
2784#ifdef CONFIG_SME
2785 if (len > 0 && wpa_s->sme.ft_used &&
2786 wpa_sm_has_ptk(wpa_s->wpa)) {
2787 wpa_dbg(wpa_s, MSG_DEBUG,
2788 "SME: Trying to use FT over-the-air");
2789 algs |= WPA_AUTH_ALG_FT;
2790 }
2791#endif /* CONFIG_SME */
2792 }
2793 }
2794#endif /* CONFIG_IEEE80211R */
2795
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002796 params->wpa_ie = wpa_ie;
2797 params->wpa_ie_len = wpa_ie_len;
2798 params->auth_alg = algs;
2799 if (mask)
2800 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
2801
2802 return wpa_ie;
2803}
2804
2805
2806#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
2807static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
2808{
2809 struct wpa_driver_associate_params params;
2810 enum wpa_drv_update_connect_params_mask mask = 0;
2811 u8 *wpa_ie;
2812
2813 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
2814 return; /* nothing to do */
2815
2816 os_memset(&params, 0, sizeof(params));
2817 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
2818 wpa_s->current_ssid, &params, &mask);
2819 if (!wpa_ie)
2820 return;
2821
2822 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
2823 os_free(wpa_ie);
2824 return;
2825 }
2826
2827 wpa_s->auth_alg = params.auth_alg;
2828 wpa_drv_update_connect_params(wpa_s, &params, mask);
2829 os_free(wpa_ie);
2830}
2831#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
2832
2833
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002834static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2835{
2836 struct wpa_connect_work *cwork = work->ctx;
2837 struct wpa_bss *bss = cwork->bss;
2838 struct wpa_ssid *ssid = cwork->ssid;
2839 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002840 u8 *wpa_ie;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002841 int use_crypt, ret, i, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002842 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002843 struct wpa_driver_associate_params params;
2844 int wep_keys_set = 0;
2845 int assoc_failed = 0;
2846 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002847 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002848#ifdef CONFIG_HT_OVERRIDES
2849 struct ieee80211_ht_capabilities htcaps;
2850 struct ieee80211_ht_capabilities htcaps_mask;
2851#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002852#ifdef CONFIG_VHT_OVERRIDES
2853 struct ieee80211_vht_capabilities vhtcaps;
2854 struct ieee80211_vht_capabilities vhtcaps_mask;
2855#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002856
2857 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002858 if (work->started) {
2859 wpa_s->connect_work = NULL;
2860
2861 /* cancel possible auth. timeout */
2862 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2863 NULL);
2864 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002865 wpas_connect_work_free(cwork);
2866 return;
2867 }
2868
2869 wpa_s->connect_work = work;
2870
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002871 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2872 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002873 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2874 wpas_connect_work_done(wpa_s);
2875 return;
2876 }
2877
Dmitry Shmidte4663042016-04-04 10:07:49 -07002878 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002879 os_memset(&params, 0, sizeof(params));
2880 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002881 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002882 if (bss &&
2883 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002884#ifdef CONFIG_IEEE80211R
2885 const u8 *ie, *md = NULL;
2886#endif /* CONFIG_IEEE80211R */
2887 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2888 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2889 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2890 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2891 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2892 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2893 if (bssid_changed)
2894 wpas_notify_bssid_changed(wpa_s);
2895#ifdef CONFIG_IEEE80211R
2896 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2897 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2898 md = ie + 2;
2899 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2900 if (md) {
2901 /* Prepare for the next transition */
2902 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2903 }
2904#endif /* CONFIG_IEEE80211R */
2905#ifdef CONFIG_WPS
2906 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2907 wpa_s->conf->ap_scan == 2 &&
2908 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2909 /* Use ap_scan==1 style network selection to find the network
2910 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002911 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002912 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002913 wpa_s->reassociate = 1;
2914 wpa_supplicant_req_scan(wpa_s, 0, 0);
2915 return;
2916#endif /* CONFIG_WPS */
2917 } else {
2918 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2919 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002920 if (bss)
2921 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2922 else
2923 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002925 if (!wpa_s->pno)
2926 wpa_supplicant_cancel_sched_scan(wpa_s);
2927
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928 wpa_supplicant_cancel_scan(wpa_s);
2929
2930 /* Starting new association, so clear the possibly used WPA IE from the
2931 * previous association. */
2932 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2933
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002934 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
2935 if (!wpa_ie) {
2936 wpas_connect_work_done(wpa_s);
2937 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002938 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002939
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002940 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2941 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002942 cipher_pairwise = wpa_s->pairwise_cipher;
2943 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002944 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002945 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2946 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2947 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2948 use_crypt = 0;
2949 if (wpa_set_wep_keys(wpa_s, ssid)) {
2950 use_crypt = 1;
2951 wep_keys_set = 1;
2952 }
2953 }
2954 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2955 use_crypt = 0;
2956
2957#ifdef IEEE8021X_EAPOL
2958 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2959 if ((ssid->eapol_flags &
2960 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2961 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2962 !wep_keys_set) {
2963 use_crypt = 0;
2964 } else {
2965 /* Assume that dynamic WEP-104 keys will be used and
2966 * set cipher suites in order for drivers to expect
2967 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002968 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002969 }
2970 }
2971#endif /* IEEE8021X_EAPOL */
2972
2973 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2974 /* Set the key before (and later after) association */
2975 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2976 }
2977
2978 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2979 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 params.ssid = bss->ssid;
2981 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002982 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2983 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002984 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2985 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002986 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002987 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002988 ssid->bssid_set,
2989 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002990 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002991 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002992 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002993 params.bssid_hint = bss->bssid;
2994 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002995 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002996 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002997 if (ssid->bssid_hint_set)
2998 params.bssid_hint = ssid->bssid_hint;
2999
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003000 params.ssid = ssid->ssid;
3001 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003002 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003003 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003004
3005 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
3006 wpa_s->conf->ap_scan == 2) {
3007 params.bssid = ssid->bssid;
3008 params.fixed_bssid = 1;
3009 }
3010
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003011 /* Initial frequency for IBSS/mesh */
3012 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003013 ssid->frequency > 0 && params.freq.freq == 0)
3014 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003015
3016 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003017 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003018 if (ssid->beacon_int)
3019 params.beacon_int = ssid->beacon_int;
3020 else
3021 params.beacon_int = wpa_s->conf->beacon_int;
3022 }
3023
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003024 params.pairwise_suite = cipher_pairwise;
3025 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003026 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003027 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003028 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003029 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003030 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003031 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003032 for (i = 0; i < NUM_WEP_KEYS; i++) {
3033 if (ssid->wep_key_len[i])
3034 params.wep_key[i] = ssid->wep_key[i];
3035 params.wep_key_len[i] = ssid->wep_key_len[i];
3036 }
3037 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
3038
3039 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003040 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3041 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003042 params.passphrase = ssid->passphrase;
3043 if (ssid->psk_set)
3044 params.psk = ssid->psk;
3045 }
3046
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003047 if (wpa_s->conf->key_mgmt_offload) {
3048 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3049 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003050 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3051 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003052 params.req_key_mgmt_offload =
3053 ssid->proactive_key_caching < 0 ?
3054 wpa_s->conf->okc : ssid->proactive_key_caching;
3055 else
3056 params.req_key_mgmt_offload = 1;
3057
3058 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3059 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3060 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3061 ssid->psk_set)
3062 params.psk = ssid->psk;
3063 }
3064
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003065 params.drop_unencrypted = use_crypt;
3066
3067#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003068 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003069 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003070 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3071 struct wpa_ie_data ie;
3072 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3073 ie.capabilities &
3074 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3075 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3076 "MFP: require MFP");
3077 params.mgmt_frame_protection =
3078 MGMT_FRAME_PROTECTION_REQUIRED;
3079 }
3080 }
3081#endif /* CONFIG_IEEE80211W */
3082
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003083 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003084
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003085 if (wpa_s->p2pdev->set_sta_uapsd)
3086 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003087 else
3088 params.uapsd = -1;
3089
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003090#ifdef CONFIG_HT_OVERRIDES
3091 os_memset(&htcaps, 0, sizeof(htcaps));
3092 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3093 params.htcaps = (u8 *) &htcaps;
3094 params.htcaps_mask = (u8 *) &htcaps_mask;
3095 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3096#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003097#ifdef CONFIG_VHT_OVERRIDES
3098 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3099 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3100 params.vhtcaps = &vhtcaps;
3101 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003102 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003103#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003104
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003105#ifdef CONFIG_P2P
3106 /*
3107 * If multi-channel concurrency is not supported, check for any
3108 * frequency conflict. In case of any frequency conflict, remove the
3109 * least prioritized connection.
3110 */
3111 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003112 int freq, num;
3113 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003114 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003115 wpa_printf(MSG_DEBUG,
3116 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003117 freq, params.freq.freq);
3118 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003119 wpa_s, params.freq.freq, ssid) < 0) {
3120 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003121 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003122 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003123 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003124 }
3125 }
3126#endif /* CONFIG_P2P */
3127
Dmitry Shmidte4663042016-04-04 10:07:49 -07003128 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3129 wpa_s->current_ssid)
3130 params.prev_bssid = prev_bssid;
3131
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003132 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003133 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003134 if (ret < 0) {
3135 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3136 "failed");
3137 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3138 /*
3139 * The driver is known to mean what is saying, so we
3140 * can stop right here; the association will not
3141 * succeed.
3142 */
3143 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003144 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003145 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3146 return;
3147 }
3148 /* try to continue anyway; new association will be tried again
3149 * after timeout */
3150 assoc_failed = 1;
3151 }
3152
3153 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3154 /* Set the key after the association just in case association
3155 * cleared the previously configured key. */
3156 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3157 /* No need to timeout authentication since there is no key
3158 * management. */
3159 wpa_supplicant_cancel_auth_timeout(wpa_s);
3160 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3161#ifdef CONFIG_IBSS_RSN
3162 } else if (ssid->mode == WPAS_MODE_IBSS &&
3163 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3164 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3165 /*
3166 * RSN IBSS authentication is per-STA and we can disable the
3167 * per-BSSID authentication.
3168 */
3169 wpa_supplicant_cancel_auth_timeout(wpa_s);
3170#endif /* CONFIG_IBSS_RSN */
3171 } else {
3172 /* Timeout for IEEE 802.11 authentication and association */
3173 int timeout = 60;
3174
3175 if (assoc_failed) {
3176 /* give IBSS a bit more time */
3177 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3178 } else if (wpa_s->conf->ap_scan == 1) {
3179 /* give IBSS a bit more time */
3180 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3181 }
3182 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3183 }
3184
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003185 if (wep_keys_set &&
3186 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003187 /* Set static WEP keys again */
3188 wpa_set_wep_keys(wpa_s, ssid);
3189 }
3190
3191 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3192 /*
3193 * Do not allow EAP session resumption between different
3194 * network configurations.
3195 */
3196 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3197 }
3198 old_ssid = wpa_s->current_ssid;
3199 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003200
3201 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003202 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003203#ifdef CONFIG_HS20
3204 hs20_configure_frame_filters(wpa_s);
3205#endif /* CONFIG_HS20 */
3206 }
3207
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003208 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3209 wpa_supplicant_initiate_eapol(wpa_s);
3210 if (old_ssid != wpa_s->current_ssid)
3211 wpas_notify_network_changed(wpa_s);
3212}
3213
3214
3215static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3216 const u8 *addr)
3217{
3218 struct wpa_ssid *old_ssid;
3219
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003220 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003221 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003222 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003223 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003224 wpa_sm_set_config(wpa_s->wpa, NULL);
3225 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3226 if (old_ssid != wpa_s->current_ssid)
3227 wpas_notify_network_changed(wpa_s);
3228 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3229}
3230
3231
3232/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003233 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3234 * @wpa_s: Pointer to wpa_supplicant data
3235 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3236 *
3237 * This function is used to request %wpa_supplicant to deauthenticate from the
3238 * current AP.
3239 */
3240void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
3241 int reason_code)
3242{
3243 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003244 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003245 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003246
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003247 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
3248 " pending_bssid=" MACSTR " reason=%d state=%s",
3249 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
3250 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
3251
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003252 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3253 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3254 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003255 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003256 else if (!is_zero_ether_addr(wpa_s->bssid))
3257 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003258 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3259 /*
3260 * When using driver-based BSS selection, we may not know the
3261 * BSSID with which we are currently trying to associate. We
3262 * need to notify the driver of this disconnection even in such
3263 * a case, so use the all zeros address here.
3264 */
3265 addr = wpa_s->bssid;
3266 zero_addr = 1;
3267 }
3268
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003269#ifdef CONFIG_TDLS
3270 wpa_tdls_teardown_peers(wpa_s->wpa);
3271#endif /* CONFIG_TDLS */
3272
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003273#ifdef CONFIG_MESH
3274 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003275 struct mesh_conf *mconf;
3276
3277 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003278 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3279 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003280 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3281 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003282 wpa_supplicant_leave_mesh(wpa_s);
3283 }
3284#endif /* CONFIG_MESH */
3285
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003286 if (addr) {
3287 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003288 os_memset(&event, 0, sizeof(event));
3289 event.deauth_info.reason_code = (u16) reason_code;
3290 event.deauth_info.locally_generated = 1;
3291 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003292 if (zero_addr)
3293 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003294 }
3295
3296 wpa_supplicant_clear_connection(wpa_s, addr);
3297}
3298
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003299static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3300 struct wpa_ssid *ssid)
3301{
3302 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3303 return;
3304
3305 ssid->disabled = 0;
3306 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3307 wpas_notify_network_enabled_changed(wpa_s, ssid);
3308
3309 /*
3310 * Try to reassociate since there is no current configuration and a new
3311 * network was made available.
3312 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003313 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003314 wpa_s->reassociate = 1;
3315}
3316
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003317
Roshan Pius950bec92016-07-19 09:49:24 -07003318/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003319 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003320 * @wpa_s: wpa_supplicant structure for a network interface
3321 * Returns: The new network configuration or %NULL if operation failed
3322 *
3323 * This function performs the following operations:
3324 * 1. Adds a new network.
3325 * 2. Send network addition notification.
3326 * 3. Marks the network disabled.
3327 * 4. Set network default parameters.
3328 */
3329struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3330{
3331 struct wpa_ssid *ssid;
3332
3333 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003334 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003335 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003336 wpas_notify_network_added(wpa_s, ssid);
3337 ssid->disabled = 1;
3338 wpa_config_set_network_defaults(ssid);
3339
3340 return ssid;
3341}
3342
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003343
Roshan Pius950bec92016-07-19 09:49:24 -07003344/**
3345 * wpa_supplicant_remove_network - Remove a configured network based on id
3346 * @wpa_s: wpa_supplicant structure for a network interface
3347 * @id: Unique network id to search for
3348 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3349 * could not be removed
3350 *
3351 * This function performs the following operations:
3352 * 1. Removes the network.
3353 * 2. Send network removal notification.
3354 * 3. Update internal state machines.
3355 * 4. Stop any running sched scans.
3356 */
3357int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
3358{
3359 struct wpa_ssid *ssid;
3360 int was_disabled;
3361
3362 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003363 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003364 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003365 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07003366
3367 if (wpa_s->last_ssid == ssid)
3368 wpa_s->last_ssid = NULL;
3369
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003370 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07003371#ifdef CONFIG_SME
3372 wpa_s->sme.prev_bssid_set = 0;
3373#endif /* CONFIG_SME */
3374 /*
3375 * Invalidate the EAP session cache if the current or
3376 * previously used network is removed.
3377 */
3378 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3379 }
3380
3381 if (ssid == wpa_s->current_ssid) {
3382 wpa_sm_set_config(wpa_s->wpa, NULL);
3383 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3384
3385 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3386 wpa_s->own_disconnect_req = 1;
3387 wpa_supplicant_deauthenticate(wpa_s,
3388 WLAN_REASON_DEAUTH_LEAVING);
3389 }
3390
3391 was_disabled = ssid->disabled;
3392
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003393 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07003394 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07003395
3396 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003397 wpa_printf(MSG_DEBUG,
3398 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07003399 wpa_supplicant_cancel_sched_scan(wpa_s);
3400 wpa_supplicant_req_scan(wpa_s, 0, 0);
3401 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003402
Roshan Pius950bec92016-07-19 09:49:24 -07003403 return 0;
3404}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003405
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003406
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003407/**
3408 * wpa_supplicant_enable_network - Mark a configured network as enabled
3409 * @wpa_s: wpa_supplicant structure for a network interface
3410 * @ssid: wpa_ssid structure for a configured network or %NULL
3411 *
3412 * Enables the specified network or all networks if no network specified.
3413 */
3414void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
3415 struct wpa_ssid *ssid)
3416{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003417 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003418 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3419 wpa_supplicant_enable_one_network(wpa_s, ssid);
3420 } else
3421 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003422
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003423 if (wpa_s->reassociate && !wpa_s->disconnected &&
3424 (!wpa_s->current_ssid ||
3425 wpa_s->wpa_state == WPA_DISCONNECTED ||
3426 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003427 if (wpa_s->sched_scanning) {
3428 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
3429 "new network to scan filters");
3430 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003431 }
3432
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003433 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3434 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003435 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003436 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003437 }
3438}
3439
3440
3441/**
3442 * wpa_supplicant_disable_network - Mark a configured network as disabled
3443 * @wpa_s: wpa_supplicant structure for a network interface
3444 * @ssid: wpa_ssid structure for a configured network or %NULL
3445 *
3446 * Disables the specified network or all networks if no network specified.
3447 */
3448void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
3449 struct wpa_ssid *ssid)
3450{
3451 struct wpa_ssid *other_ssid;
3452 int was_disabled;
3453
3454 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003455 if (wpa_s->sched_scanning)
3456 wpa_supplicant_cancel_sched_scan(wpa_s);
3457
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003458 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3459 other_ssid = other_ssid->next) {
3460 was_disabled = other_ssid->disabled;
3461 if (was_disabled == 2)
3462 continue; /* do not change persistent P2P group
3463 * data */
3464
3465 other_ssid->disabled = 1;
3466
3467 if (was_disabled != other_ssid->disabled)
3468 wpas_notify_network_enabled_changed(
3469 wpa_s, other_ssid);
3470 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003471 if (wpa_s->current_ssid) {
3472 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3473 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003474 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003475 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003476 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003478 if (ssid == wpa_s->current_ssid) {
3479 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3480 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003481 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003482 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003483 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003484
3485 was_disabled = ssid->disabled;
3486
3487 ssid->disabled = 1;
3488
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003489 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003490 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003491 if (wpa_s->sched_scanning) {
3492 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3493 "to remove network from filters");
3494 wpa_supplicant_cancel_sched_scan(wpa_s);
3495 wpa_supplicant_req_scan(wpa_s, 0, 0);
3496 }
3497 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003498 }
3499}
3500
3501
3502/**
3503 * wpa_supplicant_select_network - Attempt association with a network
3504 * @wpa_s: wpa_supplicant structure for a network interface
3505 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3506 */
3507void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3508 struct wpa_ssid *ssid)
3509{
3510
3511 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003512 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003513
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003514 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003515 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3516 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003517 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003519 disconnected = 1;
3520 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003521
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003522 if (ssid)
3523 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3524
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003525 /*
3526 * Mark all other networks disabled or mark all networks enabled if no
3527 * network specified.
3528 */
3529 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3530 other_ssid = other_ssid->next) {
3531 int was_disabled = other_ssid->disabled;
3532 if (was_disabled == 2)
3533 continue; /* do not change persistent P2P group data */
3534
3535 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003536 if (was_disabled && !other_ssid->disabled)
3537 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003538
3539 if (was_disabled != other_ssid->disabled)
3540 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3541 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003542
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003543 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3544 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003545 /* We are already associated with the selected network */
3546 wpa_printf(MSG_DEBUG, "Already associated with the "
3547 "selected network - do nothing");
3548 return;
3549 }
3550
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003551 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003552 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003553 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003554 wpa_s->connect_without_scan =
3555 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003556
3557 /*
3558 * Don't optimize next scan freqs since a new ESS has been
3559 * selected.
3560 */
3561 os_free(wpa_s->next_scan_freqs);
3562 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003563 } else {
3564 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003565 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003566
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003567 wpa_s->disconnected = 0;
3568 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003569 wpa_s->last_owe_group = 0;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003570
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003571 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003572 wpa_supplicant_fast_associate(wpa_s) != 1) {
3573 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003574 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003575 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003576 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003577
3578 if (ssid)
3579 wpas_notify_network_selected(wpa_s, ssid);
3580}
3581
3582
3583/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003584 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3585 * @wpa_s: wpa_supplicant structure for a network interface
3586 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3587 * @pkcs11_module_path: PKCS #11 module path or NULL
3588 * Returns: 0 on success; -1 on failure
3589 *
3590 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3591 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3592 * module path fails the paths will be reset to the default value (NULL).
3593 */
3594int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3595 const char *pkcs11_engine_path,
3596 const char *pkcs11_module_path)
3597{
3598 char *pkcs11_engine_path_copy = NULL;
3599 char *pkcs11_module_path_copy = NULL;
3600
3601 if (pkcs11_engine_path != NULL) {
3602 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3603 if (pkcs11_engine_path_copy == NULL)
3604 return -1;
3605 }
3606 if (pkcs11_module_path != NULL) {
3607 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003608 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003609 os_free(pkcs11_engine_path_copy);
3610 return -1;
3611 }
3612 }
3613
3614 os_free(wpa_s->conf->pkcs11_engine_path);
3615 os_free(wpa_s->conf->pkcs11_module_path);
3616 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3617 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3618
3619 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3620 eapol_sm_deinit(wpa_s->eapol);
3621 wpa_s->eapol = NULL;
3622 if (wpa_supplicant_init_eapol(wpa_s)) {
3623 /* Error -> Reset paths to the default value (NULL) once. */
3624 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3625 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3626 NULL);
3627
3628 return -1;
3629 }
3630 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3631
3632 return 0;
3633}
3634
3635
3636/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003637 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3638 * @wpa_s: wpa_supplicant structure for a network interface
3639 * @ap_scan: AP scan mode
3640 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3641 *
3642 */
3643int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3644{
3645
3646 int old_ap_scan;
3647
3648 if (ap_scan < 0 || ap_scan > 2)
3649 return -1;
3650
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003651 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3652 wpa_printf(MSG_INFO,
3653 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3654 }
3655
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003656#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003657 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3658 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3659 wpa_s->wpa_state < WPA_COMPLETED) {
3660 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3661 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003662 return 0;
3663 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003664#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003665
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003666 old_ap_scan = wpa_s->conf->ap_scan;
3667 wpa_s->conf->ap_scan = ap_scan;
3668
3669 if (old_ap_scan != wpa_s->conf->ap_scan)
3670 wpas_notify_ap_scan_changed(wpa_s);
3671
3672 return 0;
3673}
3674
3675
3676/**
3677 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3678 * @wpa_s: wpa_supplicant structure for a network interface
3679 * @expire_age: Expiration age in seconds
3680 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3681 *
3682 */
3683int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3684 unsigned int bss_expire_age)
3685{
3686 if (bss_expire_age < 10) {
3687 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3688 bss_expire_age);
3689 return -1;
3690 }
3691 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3692 bss_expire_age);
3693 wpa_s->conf->bss_expiration_age = bss_expire_age;
3694
3695 return 0;
3696}
3697
3698
3699/**
3700 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3701 * @wpa_s: wpa_supplicant structure for a network interface
3702 * @expire_count: number of scans after which an unseen BSS is reclaimed
3703 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3704 *
3705 */
3706int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3707 unsigned int bss_expire_count)
3708{
3709 if (bss_expire_count < 1) {
3710 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3711 bss_expire_count);
3712 return -1;
3713 }
3714 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3715 bss_expire_count);
3716 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3717
3718 return 0;
3719}
3720
3721
3722/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003723 * wpa_supplicant_set_scan_interval - Set scan interval
3724 * @wpa_s: wpa_supplicant structure for a network interface
3725 * @scan_interval: scan interval in seconds
3726 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3727 *
3728 */
3729int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3730 int scan_interval)
3731{
3732 if (scan_interval < 0) {
3733 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3734 scan_interval);
3735 return -1;
3736 }
3737 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3738 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003739 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003740
3741 return 0;
3742}
3743
3744
3745/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003746 * wpa_supplicant_set_debug_params - Set global debug params
3747 * @global: wpa_global structure
3748 * @debug_level: debug level
3749 * @debug_timestamp: determines if show timestamp in debug data
3750 * @debug_show_keys: determines if show keys in debug data
3751 * Returns: 0 if succeed or -1 if debug_level has wrong value
3752 */
3753int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3754 int debug_timestamp, int debug_show_keys)
3755{
3756
3757 int old_level, old_timestamp, old_show_keys;
3758
3759 /* check for allowed debuglevels */
3760 if (debug_level != MSG_EXCESSIVE &&
3761 debug_level != MSG_MSGDUMP &&
3762 debug_level != MSG_DEBUG &&
3763 debug_level != MSG_INFO &&
3764 debug_level != MSG_WARNING &&
3765 debug_level != MSG_ERROR)
3766 return -1;
3767
3768 old_level = wpa_debug_level;
3769 old_timestamp = wpa_debug_timestamp;
3770 old_show_keys = wpa_debug_show_keys;
3771
3772 wpa_debug_level = debug_level;
3773 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3774 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3775
3776 if (wpa_debug_level != old_level)
3777 wpas_notify_debug_level_changed(global);
3778 if (wpa_debug_timestamp != old_timestamp)
3779 wpas_notify_debug_timestamp_changed(global);
3780 if (wpa_debug_show_keys != old_show_keys)
3781 wpas_notify_debug_show_keys_changed(global);
3782
3783 return 0;
3784}
3785
3786
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003787#ifdef CONFIG_OWE
3788static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
3789 const u8 *entry_ssid, size_t entry_ssid_len)
3790{
3791 const u8 *owe, *pos, *end;
3792 u8 ssid_len;
3793 struct wpa_bss *bss;
3794
3795 /* Check network profile SSID aganst the SSID in the
3796 * OWE Transition Mode element. */
3797
3798 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
3799 if (!bss)
3800 return 0;
3801
3802 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3803 if (!owe)
3804 return 0;
3805
3806 pos = owe + 6;
3807 end = owe + 2 + owe[1];
3808
3809 if (end - pos < ETH_ALEN + 1)
3810 return 0;
3811 pos += ETH_ALEN;
3812 ssid_len = *pos++;
3813 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
3814 return 0;
3815
3816 return entry_ssid_len == ssid_len &&
3817 os_memcmp(pos, entry_ssid, ssid_len) == 0;
3818}
3819#endif /* CONFIG_OWE */
3820
3821
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003822/**
3823 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3824 * @wpa_s: Pointer to wpa_supplicant data
3825 * Returns: A pointer to the current network structure or %NULL on failure
3826 */
3827struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3828{
3829 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003830 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003831 int res;
3832 size_t ssid_len;
3833 u8 bssid[ETH_ALEN];
3834 int wired;
3835
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003836 res = wpa_drv_get_ssid(wpa_s, ssid);
3837 if (res < 0) {
3838 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3839 "driver");
3840 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003841 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003842 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003843
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003844 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003845 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3846 "driver");
3847 return NULL;
3848 }
3849
3850 wired = wpa_s->conf->ap_scan == 0 &&
3851 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3852
3853 entry = wpa_s->conf->ssid;
3854 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003855 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003856 ((ssid_len == entry->ssid_len &&
3857 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3858 (!entry->bssid_set ||
3859 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3860 return entry;
3861#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003862 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003863 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3864 (entry->ssid == NULL || entry->ssid_len == 0) &&
3865 (!entry->bssid_set ||
3866 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3867 return entry;
3868#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003869
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003870#ifdef CONFIG_OWE
3871 if (!wpas_network_disabled(wpa_s, entry) &&
3872 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
3873 entry->ssid_len) &&
3874 (!entry->bssid_set ||
3875 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3876 return entry;
3877#endif /* CONFIG_OWE */
3878
Dmitry Shmidt04949592012-07-19 12:16:46 -07003879 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003880 entry->ssid_len == 0 &&
3881 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3882 return entry;
3883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003884 entry = entry->next;
3885 }
3886
3887 return NULL;
3888}
3889
3890
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003891static int select_driver(struct wpa_supplicant *wpa_s, int i)
3892{
3893 struct wpa_global *global = wpa_s->global;
3894
3895 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003896 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003897 if (global->drv_priv[i] == NULL) {
3898 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3899 "'%s'", wpa_drivers[i]->name);
3900 return -1;
3901 }
3902 }
3903
3904 wpa_s->driver = wpa_drivers[i];
3905 wpa_s->global_drv_priv = global->drv_priv[i];
3906
3907 return 0;
3908}
3909
3910
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003911static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3912 const char *name)
3913{
3914 int i;
3915 size_t len;
3916 const char *pos, *driver = name;
3917
3918 if (wpa_s == NULL)
3919 return -1;
3920
3921 if (wpa_drivers[0] == NULL) {
3922 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3923 "wpa_supplicant");
3924 return -1;
3925 }
3926
3927 if (name == NULL) {
3928 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003929 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003930 }
3931
3932 do {
3933 pos = os_strchr(driver, ',');
3934 if (pos)
3935 len = pos - driver;
3936 else
3937 len = os_strlen(driver);
3938
3939 for (i = 0; wpa_drivers[i]; i++) {
3940 if (os_strlen(wpa_drivers[i]->name) == len &&
3941 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003942 0) {
3943 /* First driver that succeeds wins */
3944 if (select_driver(wpa_s, i) == 0)
3945 return 0;
3946 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003947 }
3948
3949 driver = pos + 1;
3950 } while (pos);
3951
3952 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3953 return -1;
3954}
3955
3956
3957/**
3958 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3959 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3960 * with struct wpa_driver_ops::init()
3961 * @src_addr: Source address of the EAPOL frame
3962 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3963 * @len: Length of the EAPOL data
3964 *
3965 * This function is called for each received EAPOL frame. Most driver
3966 * interfaces rely on more generic OS mechanism for receiving frames through
3967 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3968 * take care of received EAPOL frames and deliver them to the core supplicant
3969 * code by calling this function.
3970 */
3971void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3972 const u8 *buf, size_t len)
3973{
3974 struct wpa_supplicant *wpa_s = ctx;
3975
3976 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3977 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3978
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003979#ifdef CONFIG_TESTING_OPTIONS
3980 if (wpa_s->ignore_auth_resp) {
3981 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3982 return;
3983 }
3984#endif /* CONFIG_TESTING_OPTIONS */
3985
Jouni Malinena05074c2012-12-21 21:35:35 +02003986 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3987 (wpa_s->last_eapol_matches_bssid &&
3988#ifdef CONFIG_AP
3989 !wpa_s->ap_iface &&
3990#endif /* CONFIG_AP */
3991 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003992 /*
3993 * There is possible race condition between receiving the
3994 * association event and the EAPOL frame since they are coming
3995 * through different paths from the driver. In order to avoid
3996 * issues in trying to process the EAPOL frame before receiving
3997 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003998 * the association event is received. This may also be needed in
3999 * driver-based roaming case, so also use src_addr != BSSID as a
4000 * trigger if we have previously confirmed that the
4001 * Authenticator uses BSSID as the src_addr (which is not the
4002 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004003 */
4004 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02004005 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
4006 wpa_supplicant_state_txt(wpa_s->wpa_state),
4007 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004008 wpabuf_free(wpa_s->pending_eapol_rx);
4009 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
4010 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004011 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004012 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
4013 ETH_ALEN);
4014 }
4015 return;
4016 }
4017
Jouni Malinena05074c2012-12-21 21:35:35 +02004018 wpa_s->last_eapol_matches_bssid =
4019 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4020
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004021#ifdef CONFIG_AP
4022 if (wpa_s->ap_iface) {
4023 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4024 return;
4025 }
4026#endif /* CONFIG_AP */
4027
4028 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4029 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4030 "no key management is configured");
4031 return;
4032 }
4033
4034 if (wpa_s->eapol_received == 0 &&
4035 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
4036 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4037 wpa_s->wpa_state != WPA_COMPLETED) &&
4038 (wpa_s->current_ssid == NULL ||
4039 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
4040 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004041 int timeout = 10;
4042
4043 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4044 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4045 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4046 /* Use longer timeout for IEEE 802.1X/EAP */
4047 timeout = 70;
4048 }
4049
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004050#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004051 if (wpa_s->current_ssid && wpa_s->current_bss &&
4052 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4053 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4054 /*
4055 * Use shorter timeout if going through WPS AP iteration
4056 * for PIN config method with an AP that does not
4057 * advertise Selected Registrar.
4058 */
4059 struct wpabuf *wps_ie;
4060
4061 wps_ie = wpa_bss_get_vendor_ie_multi(
4062 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4063 if (wps_ie &&
4064 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4065 timeout = 10;
4066 wpabuf_free(wps_ie);
4067 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004068#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004069
4070 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004071 }
4072 wpa_s->eapol_received++;
4073
4074 if (wpa_s->countermeasures) {
4075 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4076 "EAPOL packet");
4077 return;
4078 }
4079
4080#ifdef CONFIG_IBSS_RSN
4081 if (wpa_s->current_ssid &&
4082 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4083 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4084 return;
4085 }
4086#endif /* CONFIG_IBSS_RSN */
4087
4088 /* Source address of the incoming EAPOL frame could be compared to the
4089 * current BSSID. However, it is possible that a centralized
4090 * Authenticator could be using another MAC address than the BSSID of
4091 * an AP, so just allow any address to be used for now. The replies are
4092 * still sent to the current BSSID (if available), though. */
4093
4094 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4095 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004096 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4097 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004098 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4099 return;
4100 wpa_drv_poll(wpa_s);
4101 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
4102 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4103 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4104 /*
4105 * Set portValid = TRUE here since we are going to skip 4-way
4106 * handshake processing which would normally set portValid. We
4107 * need this to allow the EAPOL state machines to be completed
4108 * without going through EAPOL-Key handshake.
4109 */
4110 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
4111 }
4112}
4113
4114
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004115int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004117 if ((!wpa_s->p2p_mgmt ||
4118 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4119 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004120 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004121 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4122 wpa_drv_get_mac_addr(wpa_s),
4123 ETH_P_EAPOL,
4124 wpa_supplicant_rx_eapol, wpa_s, 0);
4125 if (wpa_s->l2 == NULL)
4126 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004127
4128 if (l2_packet_set_packet_filter(wpa_s->l2,
4129 L2_PACKET_FILTER_PKTTYPE))
4130 wpa_dbg(wpa_s, MSG_DEBUG,
4131 "Failed to attach pkt_type filter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004132 } else {
4133 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4134 if (addr)
4135 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4136 }
4137
4138 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4139 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
4140 return -1;
4141 }
4142
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004143 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4144
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004145 return 0;
4146}
4147
4148
Dmitry Shmidt04949592012-07-19 12:16:46 -07004149static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4150 const u8 *buf, size_t len)
4151{
4152 struct wpa_supplicant *wpa_s = ctx;
4153 const struct l2_ethhdr *eth;
4154
4155 if (len < sizeof(*eth))
4156 return;
4157 eth = (const struct l2_ethhdr *) buf;
4158
4159 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4160 !(eth->h_dest[0] & 0x01)) {
4161 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4162 " (bridge - not for this interface - ignore)",
4163 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4164 return;
4165 }
4166
4167 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4168 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4169 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4170 len - sizeof(*eth));
4171}
4172
4173
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004174/**
4175 * wpa_supplicant_driver_init - Initialize driver interface parameters
4176 * @wpa_s: Pointer to wpa_supplicant data
4177 * Returns: 0 on success, -1 on failure
4178 *
4179 * This function is called to initialize driver interface parameters.
4180 * wpa_drv_init() must have been called before this function to initialize the
4181 * driver interface.
4182 */
4183int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4184{
4185 static int interface_count = 0;
4186
4187 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4188 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004189
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004190 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4191 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004192 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004193 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4194
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004195 if (wpa_s->bridge_ifname[0]) {
4196 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4197 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004198 wpa_s->l2_br = l2_packet_init_bridge(
4199 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4200 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004201 if (wpa_s->l2_br == NULL) {
4202 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4203 "connection for the bridge interface '%s'",
4204 wpa_s->bridge_ifname);
4205 return -1;
4206 }
4207 }
4208
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004209 if (wpa_s->conf->ap_scan == 2 &&
4210 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4211 wpa_printf(MSG_INFO,
4212 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4213 }
4214
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004215 wpa_clear_keys(wpa_s, NULL);
4216
4217 /* Make sure that TKIP countermeasures are not left enabled (could
4218 * happen if wpa_supplicant is killed during countermeasures. */
4219 wpa_drv_set_countermeasures(wpa_s, 0);
4220
4221 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4222 wpa_drv_flush_pmkid(wpa_s);
4223
4224 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004225 wpa_s->prev_scan_wildcard = 0;
4226
Dmitry Shmidt04949592012-07-19 12:16:46 -07004227 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004228 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4229 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4230 interface_count = 0;
4231 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004232#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004233 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004234 wpa_supplicant_delayed_sched_scan(wpa_s,
4235 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004236 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004237 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004238 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004239#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004240 interface_count++;
4241 } else
4242 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4243
4244 return 0;
4245}
4246
4247
4248static int wpa_supplicant_daemon(const char *pid_file)
4249{
4250 wpa_printf(MSG_DEBUG, "Daemonize..");
4251 return os_daemonize(pid_file);
4252}
4253
4254
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004255static struct wpa_supplicant *
4256wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004257{
4258 struct wpa_supplicant *wpa_s;
4259
4260 wpa_s = os_zalloc(sizeof(*wpa_s));
4261 if (wpa_s == NULL)
4262 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004263 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004264 wpa_s->scan_interval = 5;
4265 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004266 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004267 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004268 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004269
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004270 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004271 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004272
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004273 return wpa_s;
4274}
4275
4276
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004277#ifdef CONFIG_HT_OVERRIDES
4278
4279static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4280 struct ieee80211_ht_capabilities *htcaps,
4281 struct ieee80211_ht_capabilities *htcaps_mask,
4282 const char *ht_mcs)
4283{
4284 /* parse ht_mcs into hex array */
4285 int i;
4286 const char *tmp = ht_mcs;
4287 char *end = NULL;
4288
4289 /* If ht_mcs is null, do not set anything */
4290 if (!ht_mcs)
4291 return 0;
4292
4293 /* This is what we are setting in the kernel */
4294 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4295
4296 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4297
4298 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004299 long v;
4300
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004301 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004302 v = strtol(tmp, &end, 16);
4303
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004304 if (errno == 0) {
4305 wpa_msg(wpa_s, MSG_DEBUG,
4306 "htcap value[%i]: %ld end: %p tmp: %p",
4307 i, v, end, tmp);
4308 if (end == tmp)
4309 break;
4310
4311 htcaps->supported_mcs_set[i] = v;
4312 tmp = end;
4313 } else {
4314 wpa_msg(wpa_s, MSG_ERROR,
4315 "Failed to parse ht-mcs: %s, error: %s\n",
4316 ht_mcs, strerror(errno));
4317 return -1;
4318 }
4319 }
4320
4321 /*
4322 * If we were able to parse any values, then set mask for the MCS set.
4323 */
4324 if (i) {
4325 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4326 IEEE80211_HT_MCS_MASK_LEN - 1);
4327 /* skip the 3 reserved bits */
4328 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4329 0x1f;
4330 }
4331
4332 return 0;
4333}
4334
4335
4336static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4337 struct ieee80211_ht_capabilities *htcaps,
4338 struct ieee80211_ht_capabilities *htcaps_mask,
4339 int disabled)
4340{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004341 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004342
4343 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
4344
4345 if (disabled == -1)
4346 return 0;
4347
4348 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
4349 htcaps_mask->ht_capabilities_info |= msk;
4350 if (disabled)
4351 htcaps->ht_capabilities_info &= msk;
4352 else
4353 htcaps->ht_capabilities_info |= msk;
4354
4355 return 0;
4356}
4357
4358
4359static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
4360 struct ieee80211_ht_capabilities *htcaps,
4361 struct ieee80211_ht_capabilities *htcaps_mask,
4362 int factor)
4363{
4364 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
4365
4366 if (factor == -1)
4367 return 0;
4368
4369 if (factor < 0 || factor > 3) {
4370 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
4371 "Must be 0-3 or -1", factor);
4372 return -EINVAL;
4373 }
4374
4375 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
4376 htcaps->a_mpdu_params &= ~0x3;
4377 htcaps->a_mpdu_params |= factor & 0x3;
4378
4379 return 0;
4380}
4381
4382
4383static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
4384 struct ieee80211_ht_capabilities *htcaps,
4385 struct ieee80211_ht_capabilities *htcaps_mask,
4386 int density)
4387{
4388 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
4389
4390 if (density == -1)
4391 return 0;
4392
4393 if (density < 0 || density > 7) {
4394 wpa_msg(wpa_s, MSG_ERROR,
4395 "ampdu_density: %d out of range. Must be 0-7 or -1.",
4396 density);
4397 return -EINVAL;
4398 }
4399
4400 htcaps_mask->a_mpdu_params |= 0x1C;
4401 htcaps->a_mpdu_params &= ~(0x1C);
4402 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
4403
4404 return 0;
4405}
4406
4407
4408static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
4409 struct ieee80211_ht_capabilities *htcaps,
4410 struct ieee80211_ht_capabilities *htcaps_mask,
4411 int disabled)
4412{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004413 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
4414
Paul Stewart092955c2017-02-06 09:13:09 -08004415 set_disable_ht40(htcaps, disabled);
4416 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004417
4418 return 0;
4419}
4420
4421
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004422static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
4423 struct ieee80211_ht_capabilities *htcaps,
4424 struct ieee80211_ht_capabilities *htcaps_mask,
4425 int disabled)
4426{
4427 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004428 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
4429 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004430
4431 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
4432
4433 if (disabled)
4434 htcaps->ht_capabilities_info &= ~msk;
4435 else
4436 htcaps->ht_capabilities_info |= msk;
4437
4438 htcaps_mask->ht_capabilities_info |= msk;
4439
4440 return 0;
4441}
4442
4443
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004444static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
4445 struct ieee80211_ht_capabilities *htcaps,
4446 struct ieee80211_ht_capabilities *htcaps_mask,
4447 int disabled)
4448{
4449 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004450 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004451
4452 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
4453
4454 if (disabled)
4455 htcaps->ht_capabilities_info &= ~msk;
4456 else
4457 htcaps->ht_capabilities_info |= msk;
4458
4459 htcaps_mask->ht_capabilities_info |= msk;
4460
4461 return 0;
4462}
4463
4464
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004465void wpa_supplicant_apply_ht_overrides(
4466 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4467 struct wpa_driver_associate_params *params)
4468{
4469 struct ieee80211_ht_capabilities *htcaps;
4470 struct ieee80211_ht_capabilities *htcaps_mask;
4471
4472 if (!ssid)
4473 return;
4474
4475 params->disable_ht = ssid->disable_ht;
4476 if (!params->htcaps || !params->htcaps_mask)
4477 return;
4478
4479 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
4480 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
4481 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
4482 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
4483 ssid->disable_max_amsdu);
4484 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
4485 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
4486 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004487 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004488 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004489
4490 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004491 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004492 htcaps->ht_capabilities_info |= bit;
4493 htcaps_mask->ht_capabilities_info |= bit;
4494 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004495}
4496
4497#endif /* CONFIG_HT_OVERRIDES */
4498
4499
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004500#ifdef CONFIG_VHT_OVERRIDES
4501void wpa_supplicant_apply_vht_overrides(
4502 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4503 struct wpa_driver_associate_params *params)
4504{
4505 struct ieee80211_vht_capabilities *vhtcaps;
4506 struct ieee80211_vht_capabilities *vhtcaps_mask;
4507
4508 if (!ssid)
4509 return;
4510
4511 params->disable_vht = ssid->disable_vht;
4512
4513 vhtcaps = (void *) params->vhtcaps;
4514 vhtcaps_mask = (void *) params->vhtcaps_mask;
4515
4516 if (!vhtcaps || !vhtcaps_mask)
4517 return;
4518
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004519 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
4520 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004521
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004522#ifdef CONFIG_HT_OVERRIDES
4523 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004524 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
4525 int max_ampdu;
4526
4527 max_ampdu = (ssid->vht_capa &
4528 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4529 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004530
4531 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4532 wpa_set_ampdu_factor(wpa_s,
4533 (void *) params->htcaps,
4534 (void *) params->htcaps_mask,
4535 max_ampdu);
4536 }
4537#endif /* CONFIG_HT_OVERRIDES */
4538
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004539#define OVERRIDE_MCS(i) \
4540 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4541 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004542 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004543 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004544 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4545 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004546 } \
4547 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4548 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004549 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004550 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004551 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4552 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004553 }
4554
4555 OVERRIDE_MCS(1);
4556 OVERRIDE_MCS(2);
4557 OVERRIDE_MCS(3);
4558 OVERRIDE_MCS(4);
4559 OVERRIDE_MCS(5);
4560 OVERRIDE_MCS(6);
4561 OVERRIDE_MCS(7);
4562 OVERRIDE_MCS(8);
4563}
4564#endif /* CONFIG_VHT_OVERRIDES */
4565
4566
Dmitry Shmidt04949592012-07-19 12:16:46 -07004567static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4568{
4569#ifdef PCSC_FUNCS
4570 size_t len;
4571
4572 if (!wpa_s->conf->pcsc_reader)
4573 return 0;
4574
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004575 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004576 if (!wpa_s->scard)
4577 return 1;
4578
4579 if (wpa_s->conf->pcsc_pin &&
4580 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4581 scard_deinit(wpa_s->scard);
4582 wpa_s->scard = NULL;
4583 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4584 return -1;
4585 }
4586
4587 len = sizeof(wpa_s->imsi) - 1;
4588 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4589 scard_deinit(wpa_s->scard);
4590 wpa_s->scard = NULL;
4591 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4592 return -1;
4593 }
4594 wpa_s->imsi[len] = '\0';
4595
4596 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4597
4598 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4599 wpa_s->imsi, wpa_s->mnc_len);
4600
4601 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4602 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4603#endif /* PCSC_FUNCS */
4604
4605 return 0;
4606}
4607
4608
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004609int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4610{
4611 char *val, *pos;
4612
4613 ext_password_deinit(wpa_s->ext_pw);
4614 wpa_s->ext_pw = NULL;
4615 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4616
4617 if (!wpa_s->conf->ext_password_backend)
4618 return 0;
4619
4620 val = os_strdup(wpa_s->conf->ext_password_backend);
4621 if (val == NULL)
4622 return -1;
4623 pos = os_strchr(val, ':');
4624 if (pos)
4625 *pos++ = '\0';
4626
4627 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4628
4629 wpa_s->ext_pw = ext_password_init(val, pos);
4630 os_free(val);
4631 if (wpa_s->ext_pw == NULL) {
4632 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4633 return -1;
4634 }
4635 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4636
4637 return 0;
4638}
4639
4640
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004641#ifdef CONFIG_FST
4642
4643static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4644{
4645 struct wpa_supplicant *wpa_s = ctx;
4646
4647 return (is_zero_ether_addr(wpa_s->bssid) ||
4648 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4649}
4650
4651
4652static void wpas_fst_get_channel_info_cb(void *ctx,
4653 enum hostapd_hw_mode *hw_mode,
4654 u8 *channel)
4655{
4656 struct wpa_supplicant *wpa_s = ctx;
4657
4658 if (wpa_s->current_bss) {
4659 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4660 channel);
4661 } else if (wpa_s->hw.num_modes) {
4662 *hw_mode = wpa_s->hw.modes[0].mode;
4663 } else {
4664 WPA_ASSERT(0);
4665 *hw_mode = 0;
4666 }
4667}
4668
4669
4670static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4671{
4672 struct wpa_supplicant *wpa_s = ctx;
4673
4674 *modes = wpa_s->hw.modes;
4675 return wpa_s->hw.num_modes;
4676}
4677
4678
4679static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4680{
4681 struct wpa_supplicant *wpa_s = ctx;
4682
4683 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4684 wpa_s->fst_ies = fst_ies;
4685}
4686
4687
4688static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4689{
4690 struct wpa_supplicant *wpa_s = ctx;
4691
Paul Stewart092955c2017-02-06 09:13:09 -08004692 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
4693 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
4694 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
4695 return -1;
4696 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004697 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08004698 wpa_s->own_addr, wpa_s->bssid,
4699 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004700 0);
4701}
4702
4703
4704static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4705{
4706 struct wpa_supplicant *wpa_s = ctx;
4707
4708 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4709 return wpa_s->received_mb_ies;
4710}
4711
4712
4713static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4714 const u8 *buf, size_t size)
4715{
4716 struct wpa_supplicant *wpa_s = ctx;
4717 struct mb_ies_info info;
4718
4719 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4720
4721 if (!mb_ies_info_by_ies(&info, buf, size)) {
4722 wpabuf_free(wpa_s->received_mb_ies);
4723 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4724 }
4725}
4726
4727
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004728static const u8 * wpas_fst_get_peer_first(void *ctx,
4729 struct fst_get_peer_ctx **get_ctx,
4730 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004731{
4732 struct wpa_supplicant *wpa_s = ctx;
4733
4734 *get_ctx = NULL;
4735 if (!is_zero_ether_addr(wpa_s->bssid))
4736 return (wpa_s->received_mb_ies || !mb_only) ?
4737 wpa_s->bssid : NULL;
4738 return NULL;
4739}
4740
4741
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004742static const u8 * wpas_fst_get_peer_next(void *ctx,
4743 struct fst_get_peer_ctx **get_ctx,
4744 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004745{
4746 return NULL;
4747}
4748
4749void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4750 struct fst_wpa_obj *iface_obj)
4751{
4752 iface_obj->ctx = wpa_s;
4753 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4754 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4755 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4756 iface_obj->set_ies = wpas_fst_set_ies_cb;
4757 iface_obj->send_action = wpas_fst_send_action_cb;
4758 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4759 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4760 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4761 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4762}
4763#endif /* CONFIG_FST */
4764
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004765static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004766 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004767{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004768 struct wowlan_triggers *triggers;
4769 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004770
4771 if (!wpa_s->conf->wowlan_triggers)
4772 return 0;
4773
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004774 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4775 if (triggers) {
4776 ret = wpa_drv_wowlan(wpa_s, triggers);
4777 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004778 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004779 return ret;
4780}
4781
4782
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004783enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004784{
4785 if (freq < 3000)
4786 return BAND_2_4_GHZ;
4787 if (freq > 50000)
4788 return BAND_60_GHZ;
4789 return BAND_5_GHZ;
4790}
4791
4792
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004793unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004794{
4795 int i;
4796 unsigned int band = 0;
4797
4798 if (freqs) {
4799 /* freqs are specified for the radio work */
4800 for (i = 0; freqs[i]; i++)
4801 band |= wpas_freq_to_band(freqs[i]);
4802 } else {
4803 /*
4804 * freqs are not specified, implies all
4805 * the supported freqs by HW
4806 */
4807 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4808 if (wpa_s->hw.modes[i].num_channels != 0) {
4809 if (wpa_s->hw.modes[i].mode ==
4810 HOSTAPD_MODE_IEEE80211B ||
4811 wpa_s->hw.modes[i].mode ==
4812 HOSTAPD_MODE_IEEE80211G)
4813 band |= BAND_2_4_GHZ;
4814 else if (wpa_s->hw.modes[i].mode ==
4815 HOSTAPD_MODE_IEEE80211A)
4816 band |= BAND_5_GHZ;
4817 else if (wpa_s->hw.modes[i].mode ==
4818 HOSTAPD_MODE_IEEE80211AD)
4819 band |= BAND_60_GHZ;
4820 else if (wpa_s->hw.modes[i].mode ==
4821 HOSTAPD_MODE_IEEE80211ANY)
4822 band = BAND_2_4_GHZ | BAND_5_GHZ |
4823 BAND_60_GHZ;
4824 }
4825 }
4826 }
4827
4828 return band;
4829}
4830
4831
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004832static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4833 const char *rn)
4834{
4835 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4836 struct wpa_radio *radio;
4837
4838 while (rn && iface) {
4839 radio = iface->radio;
4840 if (radio && os_strcmp(rn, radio->name) == 0) {
4841 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4842 wpa_s->ifname, rn);
4843 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4844 return radio;
4845 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004846
4847 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004848 }
4849
4850 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4851 wpa_s->ifname, rn ? rn : "N/A");
4852 radio = os_zalloc(sizeof(*radio));
4853 if (radio == NULL)
4854 return NULL;
4855
4856 if (rn)
4857 os_strlcpy(radio->name, rn, sizeof(radio->name));
4858 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004859 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004860 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4861
4862 return radio;
4863}
4864
4865
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004866static void radio_work_free(struct wpa_radio_work *work)
4867{
4868 if (work->wpa_s->scan_work == work) {
4869 /* This should not really happen. */
4870 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4871 work->type, work, work->started);
4872 work->wpa_s->scan_work = NULL;
4873 }
4874
4875#ifdef CONFIG_P2P
4876 if (work->wpa_s->p2p_scan_work == work) {
4877 /* This should not really happen. */
4878 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4879 work->type, work, work->started);
4880 work->wpa_s->p2p_scan_work = NULL;
4881 }
4882#endif /* CONFIG_P2P */
4883
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004884 if (work->started) {
4885 work->wpa_s->radio->num_active_works--;
4886 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004887 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004888 work->type, work,
4889 work->wpa_s->radio->num_active_works);
4890 }
4891
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004892 dl_list_del(&work->list);
4893 os_free(work);
4894}
4895
4896
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004897static int radio_work_is_connect(struct wpa_radio_work *work)
4898{
4899 return os_strcmp(work->type, "sme-connect") == 0 ||
4900 os_strcmp(work->type, "connect") == 0;
4901}
4902
4903
4904static int radio_work_is_scan(struct wpa_radio_work *work)
4905{
4906 return os_strcmp(work->type, "scan") == 0 ||
4907 os_strcmp(work->type, "p2p-scan") == 0;
4908}
4909
4910
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004911static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4912{
4913 struct wpa_radio_work *active_work = NULL;
4914 struct wpa_radio_work *tmp;
4915
4916 /* Get the active work to know the type and band. */
4917 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4918 if (tmp->started) {
4919 active_work = tmp;
4920 break;
4921 }
4922 }
4923
4924 if (!active_work) {
4925 /* No active work, start one */
4926 radio->num_active_works = 0;
4927 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4928 list) {
4929 if (os_strcmp(tmp->type, "scan") == 0 &&
4930 radio->external_scan_running &&
4931 (((struct wpa_driver_scan_params *)
4932 tmp->ctx)->only_new_results ||
4933 tmp->wpa_s->clear_driver_scan_cache))
4934 continue;
4935 return tmp;
4936 }
4937 return NULL;
4938 }
4939
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004940 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004941 /*
4942 * If the active work is either connect or sme-connect,
4943 * do not parallelize them with other radio works.
4944 */
4945 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4946 "Do not parallelize radio work with %s",
4947 active_work->type);
4948 return NULL;
4949 }
4950
4951 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4952 if (tmp->started)
4953 continue;
4954
4955 /*
4956 * If connect or sme-connect are enqueued, parallelize only
4957 * those operations ahead of them in the queue.
4958 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004959 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004960 break;
4961
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004962 /* Serialize parallel scan and p2p_scan operations on the same
4963 * interface since the driver_nl80211 mechanism for tracking
4964 * scan cookies does not yet have support for this. */
4965 if (active_work->wpa_s == tmp->wpa_s &&
4966 radio_work_is_scan(active_work) &&
4967 radio_work_is_scan(tmp)) {
4968 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4969 "Do not start work '%s' when another work '%s' is already scheduled",
4970 tmp->type, active_work->type);
4971 continue;
4972 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004973 /*
4974 * Check that the radio works are distinct and
4975 * on different bands.
4976 */
4977 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4978 (active_work->bands != tmp->bands)) {
4979 /*
4980 * If a scan has to be scheduled through nl80211 scan
4981 * interface and if an external scan is already running,
4982 * do not schedule the scan since it is likely to get
4983 * rejected by kernel.
4984 */
4985 if (os_strcmp(tmp->type, "scan") == 0 &&
4986 radio->external_scan_running &&
4987 (((struct wpa_driver_scan_params *)
4988 tmp->ctx)->only_new_results ||
4989 tmp->wpa_s->clear_driver_scan_cache))
4990 continue;
4991
4992 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4993 "active_work:%s new_work:%s",
4994 active_work->type, tmp->type);
4995 return tmp;
4996 }
4997 }
4998
4999 /* Did not find a radio work to schedule in parallel. */
5000 return NULL;
5001}
5002
5003
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005004static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
5005{
5006 struct wpa_radio *radio = eloop_ctx;
5007 struct wpa_radio_work *work;
5008 struct os_reltime now, diff;
5009 struct wpa_supplicant *wpa_s;
5010
5011 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005012 if (work == NULL) {
5013 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005014 return;
5015 }
5016
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005017 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5018 radio_list);
5019
5020 if (!(wpa_s &&
5021 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5022 if (work->started)
5023 return; /* already started and still in progress */
5024
5025 if (wpa_s && wpa_s->radio->external_scan_running) {
5026 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5027 return;
5028 }
5029 } else {
5030 work = NULL;
5031 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5032 /* get the work to schedule next */
5033 work = radio_work_get_next_work(radio);
5034 }
5035 if (!work)
5036 return;
5037 }
5038
5039 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005040 os_get_reltime(&now);
5041 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005042 wpa_dbg(wpa_s, MSG_DEBUG,
5043 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005044 work->type, work, diff.sec, diff.usec);
5045 work->started = 1;
5046 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005047 radio->num_active_works++;
5048
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005049 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005050
5051 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5052 radio->num_active_works < MAX_ACTIVE_WORKS)
5053 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005054}
5055
5056
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005057/*
5058 * This function removes both started and pending radio works running on
5059 * the provided interface's radio.
5060 * Prior to the removal of the radio work, its callback (cb) is called with
5061 * deinit set to be 1. Each work's callback is responsible for clearing its
5062 * internal data and restoring to a correct state.
5063 * @wpa_s: wpa_supplicant data
5064 * @type: type of works to be removed
5065 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5066 * this interface's works.
5067 */
5068void radio_remove_works(struct wpa_supplicant *wpa_s,
5069 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005070{
5071 struct wpa_radio_work *work, *tmp;
5072 struct wpa_radio *radio = wpa_s->radio;
5073
5074 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5075 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005076 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005077 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005078
5079 /* skip other ifaces' works */
5080 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005081 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005082
5083 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5084 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005085 work->cb(work, 1);
5086 radio_work_free(work);
5087 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005088
5089 /* in case we removed the started work */
5090 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005091}
5092
5093
Roshan Pius3a1667e2018-07-03 15:17:14 -07005094void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5095{
5096 struct wpa_radio_work *work;
5097 struct wpa_radio *radio = wpa_s->radio;
5098
5099 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5100 if (work->ctx != ctx)
5101 continue;
5102 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5103 work->type, work, work->started ? " (started)" : "");
5104 radio_work_free(work);
5105 break;
5106 }
5107}
5108
5109
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005110static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5111{
5112 struct wpa_radio *radio = wpa_s->radio;
5113
5114 if (!radio)
5115 return;
5116
5117 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5118 wpa_s->ifname, radio->name);
5119 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005120 radio_remove_works(wpa_s, NULL, 0);
5121 wpa_s->radio = NULL;
5122 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005123 return; /* Interfaces remain for this radio */
5124
5125 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005126 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005127 os_free(radio);
5128}
5129
5130
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005131void radio_work_check_next(struct wpa_supplicant *wpa_s)
5132{
5133 struct wpa_radio *radio = wpa_s->radio;
5134
5135 if (dl_list_empty(&radio->work))
5136 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005137 if (wpa_s->ext_work_in_progress) {
5138 wpa_printf(MSG_DEBUG,
5139 "External radio work in progress - delay start of pending item");
5140 return;
5141 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005142 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5143 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5144}
5145
5146
5147/**
5148 * radio_add_work - Add a radio work item
5149 * @wpa_s: Pointer to wpa_supplicant data
5150 * @freq: Frequency of the offchannel operation in MHz or 0
5151 * @type: Unique identifier for each type of work
5152 * @next: Force as the next work to be executed
5153 * @cb: Callback function for indicating when radio is available
5154 * @ctx: Context pointer for the work (work->ctx in cb())
5155 * Returns: 0 on success, -1 on failure
5156 *
5157 * This function is used to request time for an operation that requires
5158 * exclusive radio control. Once the radio is available, the registered callback
5159 * function will be called. radio_work_done() must be called once the exclusive
5160 * radio operation has been completed, so that the radio is freed for other
5161 * operations. The special case of deinit=1 is used to free the context data
5162 * during interface removal. That does not allow the callback function to start
5163 * the radio operation, i.e., it must free any resources allocated for the radio
5164 * work and return.
5165 *
5166 * The @freq parameter can be used to indicate a single channel on which the
5167 * offchannel operation will occur. This may allow multiple radio work
5168 * operations to be performed in parallel if they apply for the same channel.
5169 * Setting this to 0 indicates that the work item may use multiple channels or
5170 * requires exclusive control of the radio.
5171 */
5172int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5173 const char *type, int next,
5174 void (*cb)(struct wpa_radio_work *work, int deinit),
5175 void *ctx)
5176{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005177 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005178 struct wpa_radio_work *work;
5179 int was_empty;
5180
5181 work = os_zalloc(sizeof(*work));
5182 if (work == NULL)
5183 return -1;
5184 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5185 os_get_reltime(&work->time);
5186 work->freq = freq;
5187 work->type = type;
5188 work->wpa_s = wpa_s;
5189 work->cb = cb;
5190 work->ctx = ctx;
5191
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005192 if (freq)
5193 work->bands = wpas_freq_to_band(freq);
5194 else if (os_strcmp(type, "scan") == 0 ||
5195 os_strcmp(type, "p2p-scan") == 0)
5196 work->bands = wpas_get_bands(wpa_s,
5197 ((struct wpa_driver_scan_params *)
5198 ctx)->freqs);
5199 else
5200 work->bands = wpas_get_bands(wpa_s, NULL);
5201
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005202 was_empty = dl_list_empty(&wpa_s->radio->work);
5203 if (next)
5204 dl_list_add(&wpa_s->radio->work, &work->list);
5205 else
5206 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5207 if (was_empty) {
5208 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5209 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005210 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5211 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5212 wpa_dbg(wpa_s, MSG_DEBUG,
5213 "Try to schedule a radio work (num_active_works=%u)",
5214 radio->num_active_works);
5215 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005216 }
5217
5218 return 0;
5219}
5220
5221
5222/**
5223 * radio_work_done - Indicate that a radio work item has been completed
5224 * @work: Completed work
5225 *
5226 * This function is called once the callback function registered with
5227 * radio_add_work() has completed its work.
5228 */
5229void radio_work_done(struct wpa_radio_work *work)
5230{
5231 struct wpa_supplicant *wpa_s = work->wpa_s;
5232 struct os_reltime now, diff;
5233 unsigned int started = work->started;
5234
5235 os_get_reltime(&now);
5236 os_reltime_sub(&now, &work->time, &diff);
5237 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5238 work->type, work, started ? "done" : "canceled",
5239 diff.sec, diff.usec);
5240 radio_work_free(work);
5241 if (started)
5242 radio_work_check_next(wpa_s);
5243}
5244
5245
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005246struct wpa_radio_work *
5247radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005248{
5249 struct wpa_radio_work *work;
5250 struct wpa_radio *radio = wpa_s->radio;
5251
5252 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5253 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005254 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005255 }
5256
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005257 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005258}
5259
5260
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005261static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005262 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005263{
5264 const char *ifname, *driver, *rn;
5265
5266 driver = iface->driver;
5267next_driver:
5268 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
5269 return -1;
5270
5271 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
5272 if (wpa_s->drv_priv == NULL) {
5273 const char *pos;
5274 pos = driver ? os_strchr(driver, ',') : NULL;
5275 if (pos) {
5276 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
5277 "driver interface - try next driver wrapper");
5278 driver = pos + 1;
5279 goto next_driver;
5280 }
5281 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
5282 "interface");
5283 return -1;
5284 }
5285 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
5286 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
5287 "driver_param '%s'", wpa_s->conf->driver_param);
5288 return -1;
5289 }
5290
5291 ifname = wpa_drv_get_ifname(wpa_s);
5292 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
5293 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
5294 "interface name with '%s'", ifname);
5295 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
5296 }
5297
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005298 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005299 if (rn && rn[0] == '\0')
5300 rn = NULL;
5301
5302 wpa_s->radio = radio_add_interface(wpa_s, rn);
5303 if (wpa_s->radio == NULL)
5304 return -1;
5305
5306 return 0;
5307}
5308
5309
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005310#ifdef CONFIG_GAS_SERVER
5311
5312static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
5313 unsigned int freq, const u8 *dst,
5314 const u8 *src, const u8 *bssid,
5315 const u8 *data, size_t data_len,
5316 enum offchannel_send_action_result result)
5317{
5318 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
5319 " result=%s",
5320 freq, MAC2STR(dst),
5321 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
5322 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
5323 "FAILED"));
5324 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
5325 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
5326}
5327
5328
5329static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
5330 struct wpabuf *buf, unsigned int wait_time)
5331{
5332 struct wpa_supplicant *wpa_s = ctx;
5333 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
5334
5335 if (wait_time > wpa_s->max_remain_on_chan)
5336 wait_time = wpa_s->max_remain_on_chan;
5337
5338 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
5339 wpabuf_head(buf), wpabuf_len(buf),
5340 wait_time, wpas_gas_server_tx_status, 0);
5341}
5342
5343#endif /* CONFIG_GAS_SERVER */
5344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005345static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005346 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005347{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005348 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005349 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005350 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005351
5352 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
5353 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
5354 iface->confname ? iface->confname : "N/A",
5355 iface->driver ? iface->driver : "default",
5356 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
5357 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
5358
5359 if (iface->confname) {
5360#ifdef CONFIG_BACKEND_FILE
5361 wpa_s->confname = os_rel2abs_path(iface->confname);
5362 if (wpa_s->confname == NULL) {
5363 wpa_printf(MSG_ERROR, "Failed to get absolute path "
5364 "for configuration file '%s'.",
5365 iface->confname);
5366 return -1;
5367 }
5368 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
5369 iface->confname, wpa_s->confname);
5370#else /* CONFIG_BACKEND_FILE */
5371 wpa_s->confname = os_strdup(iface->confname);
5372#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005373 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005374 if (wpa_s->conf == NULL) {
5375 wpa_printf(MSG_ERROR, "Failed to read or parse "
5376 "configuration '%s'.", wpa_s->confname);
5377 return -1;
5378 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005379 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005380 if (wpa_s->confanother &&
5381 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
5382 wpa_printf(MSG_ERROR,
5383 "Failed to read or parse configuration '%s'.",
5384 wpa_s->confanother);
5385 return -1;
5386 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005387
5388 /*
5389 * Override ctrl_interface and driver_param if set on command
5390 * line.
5391 */
5392 if (iface->ctrl_interface) {
5393 os_free(wpa_s->conf->ctrl_interface);
5394 wpa_s->conf->ctrl_interface =
5395 os_strdup(iface->ctrl_interface);
5396 }
5397
5398 if (iface->driver_param) {
5399 os_free(wpa_s->conf->driver_param);
5400 wpa_s->conf->driver_param =
5401 os_strdup(iface->driver_param);
5402 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005403
5404 if (iface->p2p_mgmt && !iface->ctrl_interface) {
5405 os_free(wpa_s->conf->ctrl_interface);
5406 wpa_s->conf->ctrl_interface = NULL;
5407 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005408 } else
5409 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
5410 iface->driver_param);
5411
5412 if (wpa_s->conf == NULL) {
5413 wpa_printf(MSG_ERROR, "\nNo configuration found.");
5414 return -1;
5415 }
5416
5417 if (iface->ifname == NULL) {
5418 wpa_printf(MSG_ERROR, "\nInterface name is required.");
5419 return -1;
5420 }
5421 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
5422 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
5423 iface->ifname);
5424 return -1;
5425 }
5426 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
5427
5428 if (iface->bridge_ifname) {
5429 if (os_strlen(iface->bridge_ifname) >=
5430 sizeof(wpa_s->bridge_ifname)) {
5431 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
5432 "name '%s'.", iface->bridge_ifname);
5433 return -1;
5434 }
5435 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
5436 sizeof(wpa_s->bridge_ifname));
5437 }
5438
5439 /* RSNA Supplicant Key Management - INITIALIZE */
5440 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
5441 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
5442
5443 /* Initialize driver interface and register driver event handler before
5444 * L2 receive handler so that association events are processed before
5445 * EAPOL-Key packets if both become available for the same select()
5446 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005447 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005448 return -1;
5449
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005450 if (wpa_supplicant_init_wpa(wpa_s) < 0)
5451 return -1;
5452
5453 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
5454 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
5455 NULL);
5456 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
5457
5458 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
5459 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
5460 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
5461 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5462 "dot11RSNAConfigPMKLifetime");
5463 return -1;
5464 }
5465
5466 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
5467 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
5468 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
5469 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5470 "dot11RSNAConfigPMKReauthThreshold");
5471 return -1;
5472 }
5473
5474 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
5475 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
5476 wpa_s->conf->dot11RSNAConfigSATimeout)) {
5477 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5478 "dot11RSNAConfigSATimeout");
5479 return -1;
5480 }
5481
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005482 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
5483 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005484 &wpa_s->hw.flags,
5485 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005486 if (wpa_s->hw.modes) {
5487 u16 i;
5488
5489 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5490 if (wpa_s->hw.modes[i].vht_capab) {
5491 wpa_s->hw_capab = CAPAB_VHT;
5492 break;
5493 }
5494
5495 if (wpa_s->hw.modes[i].ht_capab &
5496 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
5497 wpa_s->hw_capab = CAPAB_HT40;
5498 else if (wpa_s->hw.modes[i].ht_capab &&
5499 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
5500 wpa_s->hw_capab = CAPAB_HT;
5501 }
5502 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005503
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005504 capa_res = wpa_drv_get_capa(wpa_s, &capa);
5505 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005506 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005507 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005508 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005509 wpa_s->drv_smps_modes = capa.smps_modes;
5510 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005511 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005512 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005513 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005514 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
5515 wpa_s->max_sched_scan_plan_interval =
5516 capa.max_sched_scan_plan_interval;
5517 wpa_s->max_sched_scan_plan_iterations =
5518 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005519 wpa_s->sched_scan_supported = capa.sched_scan_supported;
5520 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005521 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
5522 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005523 wpa_s->extended_capa = capa.extended_capa;
5524 wpa_s->extended_capa_mask = capa.extended_capa_mask;
5525 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005526 wpa_s->num_multichan_concurrent =
5527 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005528 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
5529
5530 if (capa.mac_addr_rand_scan_supported)
5531 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
5532 if (wpa_s->sched_scan_supported &&
5533 capa.mac_addr_rand_sched_scan_supported)
5534 wpa_s->mac_addr_rand_supported |=
5535 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005536 }
5537 if (wpa_s->max_remain_on_chan == 0)
5538 wpa_s->max_remain_on_chan = 1000;
5539
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005540 /*
5541 * Only take p2p_mgmt parameters when P2P Device is supported.
5542 * Doing it here as it determines whether l2_packet_init() will be done
5543 * during wpa_supplicant_driver_init().
5544 */
5545 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
5546 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005547
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005548 if (wpa_s->num_multichan_concurrent == 0)
5549 wpa_s->num_multichan_concurrent = 1;
5550
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005551 if (wpa_supplicant_driver_init(wpa_s) < 0)
5552 return -1;
5553
5554#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07005555 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005556 return -1;
5557#endif /* CONFIG_TDLS */
5558
5559 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
5560 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
5561 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
5562 return -1;
5563 }
5564
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005565#ifdef CONFIG_FST
5566 if (wpa_s->conf->fst_group_id) {
5567 struct fst_iface_cfg cfg;
5568 struct fst_wpa_obj iface_obj;
5569
5570 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
5571 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
5572 sizeof(cfg.group_id));
5573 cfg.priority = wpa_s->conf->fst_priority;
5574 cfg.llt = wpa_s->conf->fst_llt;
5575
5576 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
5577 &iface_obj, &cfg);
5578 if (!wpa_s->fst) {
5579 wpa_msg(wpa_s, MSG_ERROR,
5580 "FST: Cannot attach iface %s to group %s",
5581 wpa_s->ifname, cfg.group_id);
5582 return -1;
5583 }
5584 }
5585#endif /* CONFIG_FST */
5586
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005587 if (wpas_wps_init(wpa_s))
5588 return -1;
5589
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005590#ifdef CONFIG_GAS_SERVER
5591 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
5592 if (!wpa_s->gas_server) {
5593 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
5594 return -1;
5595 }
5596#endif /* CONFIG_GAS_SERVER */
5597
5598#ifdef CONFIG_DPP
5599 if (wpas_dpp_init(wpa_s) < 0)
5600 return -1;
5601#endif /* CONFIG_DPP */
5602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005603 if (wpa_supplicant_init_eapol(wpa_s) < 0)
5604 return -1;
5605 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5606
5607 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
5608 if (wpa_s->ctrl_iface == NULL) {
5609 wpa_printf(MSG_ERROR,
5610 "Failed to initialize control interface '%s'.\n"
5611 "You may have another wpa_supplicant process "
5612 "already running or the file was\n"
5613 "left by an unclean termination of wpa_supplicant "
5614 "in which case you will need\n"
5615 "to manually remove this file before starting "
5616 "wpa_supplicant again.\n",
5617 wpa_s->conf->ctrl_interface);
5618 return -1;
5619 }
5620
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005621 wpa_s->gas = gas_query_init(wpa_s);
5622 if (wpa_s->gas == NULL) {
5623 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5624 return -1;
5625 }
5626
Roshan Pius3a1667e2018-07-03 15:17:14 -07005627 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
5628 wpa_s->p2p_mgmt) &&
5629 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005630 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5631 return -1;
5632 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005633
5634 if (wpa_bss_init(wpa_s) < 0)
5635 return -1;
5636
Paul Stewart092955c2017-02-06 09:13:09 -08005637#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5638#ifdef CONFIG_MESH
5639 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
5640#endif /* CONFIG_MESH */
5641#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5642
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005643 /*
5644 * Set Wake-on-WLAN triggers, if configured.
5645 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5646 * have effect anyway when the interface is down).
5647 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005648 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005649 return -1;
5650
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005651#ifdef CONFIG_EAP_PROXY
5652{
5653 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005654 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
5655 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005656 if (wpa_s->mnc_len > 0) {
5657 wpa_s->imsi[len] = '\0';
5658 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5659 wpa_s->imsi, wpa_s->mnc_len);
5660 } else {
5661 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5662 }
5663}
5664#endif /* CONFIG_EAP_PROXY */
5665
Dmitry Shmidt04949592012-07-19 12:16:46 -07005666 if (pcsc_reader_init(wpa_s) < 0)
5667 return -1;
5668
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005669 if (wpas_init_ext_pw(wpa_s) < 0)
5670 return -1;
5671
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005672 wpas_rrm_reset(wpa_s);
5673
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005674 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5675
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005676#ifdef CONFIG_HS20
5677 hs20_init(wpa_s);
5678#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005679#ifdef CONFIG_MBO
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005680 if (wpa_s->conf->oce) {
5681 if ((wpa_s->conf->oce & OCE_STA) &&
5682 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
5683 wpa_s->enable_oce = OCE_STA;
5684 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
5685 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
5686 /* TODO: Need to add STA-CFON support */
5687 wpa_printf(MSG_ERROR,
5688 "OCE STA-CFON feature is not yet supported");
5689 }
5690 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005691 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5692#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005693
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005694 wpa_supplicant_set_default_scan_ies(wpa_s);
5695
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005696 return 0;
5697}
5698
5699
5700static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005701 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005702{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005703 struct wpa_global *global = wpa_s->global;
5704 struct wpa_supplicant *iface, *prev;
5705
5706 if (wpa_s == wpa_s->parent)
5707 wpas_p2p_group_remove(wpa_s, "*");
5708
5709 iface = global->ifaces;
5710 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005711 if (iface->p2pdev == wpa_s)
5712 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005713 if (iface == wpa_s || iface->parent != wpa_s) {
5714 iface = iface->next;
5715 continue;
5716 }
5717 wpa_printf(MSG_DEBUG,
5718 "Remove remaining child interface %s from parent %s",
5719 iface->ifname, wpa_s->ifname);
5720 prev = iface;
5721 iface = iface->next;
5722 wpa_supplicant_remove_iface(global, prev, terminate);
5723 }
5724
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005725 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005726 if (wpa_s->drv_priv) {
5727 wpa_supplicant_deauthenticate(wpa_s,
5728 WLAN_REASON_DEAUTH_LEAVING);
5729
5730 wpa_drv_set_countermeasures(wpa_s, 0);
5731 wpa_clear_keys(wpa_s, NULL);
5732 }
5733
5734 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005735 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005736
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005737 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005738 radio_remove_interface(wpa_s);
5739
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005740#ifdef CONFIG_FST
5741 if (wpa_s->fst) {
5742 fst_detach(wpa_s->fst);
5743 wpa_s->fst = NULL;
5744 }
5745 if (wpa_s->received_mb_ies) {
5746 wpabuf_free(wpa_s->received_mb_ies);
5747 wpa_s->received_mb_ies = NULL;
5748 }
5749#endif /* CONFIG_FST */
5750
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005751 if (wpa_s->drv_priv)
5752 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005753
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005754 if (notify)
5755 wpas_notify_iface_removed(wpa_s);
5756
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005757 if (terminate)
5758 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005759
5760 if (wpa_s->ctrl_iface) {
5761 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5762 wpa_s->ctrl_iface = NULL;
5763 }
5764
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005765#ifdef CONFIG_MESH
5766 if (wpa_s->ifmsh) {
5767 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5768 wpa_s->ifmsh = NULL;
5769 }
5770#endif /* CONFIG_MESH */
5771
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005772 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005773 wpa_config_free(wpa_s->conf);
5774 wpa_s->conf = NULL;
5775 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005776
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005777 os_free(wpa_s->ssids_from_scan_req);
5778
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005779 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005780}
5781
5782
Dmitry Shmidte4663042016-04-04 10:07:49 -07005783#ifdef CONFIG_MATCH_IFACE
5784
5785/**
5786 * wpa_supplicant_match_iface - Match an interface description to a name
5787 * @global: Pointer to global data from wpa_supplicant_init()
5788 * @ifname: Name of the interface to match
5789 * Returns: Pointer to the created interface description or %NULL on failure
5790 */
5791struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5792 const char *ifname)
5793{
5794 int i;
5795 struct wpa_interface *iface, *miface;
5796
5797 for (i = 0; i < global->params.match_iface_count; i++) {
5798 miface = &global->params.match_ifaces[i];
5799 if (!miface->ifname ||
5800 fnmatch(miface->ifname, ifname, 0) == 0) {
5801 iface = os_zalloc(sizeof(*iface));
5802 if (!iface)
5803 return NULL;
5804 *iface = *miface;
5805 iface->ifname = ifname;
5806 return iface;
5807 }
5808 }
5809
5810 return NULL;
5811}
5812
5813
5814/**
5815 * wpa_supplicant_match_existing - Match existing interfaces
5816 * @global: Pointer to global data from wpa_supplicant_init()
5817 * Returns: 0 on success, -1 on failure
5818 */
5819static int wpa_supplicant_match_existing(struct wpa_global *global)
5820{
5821 struct if_nameindex *ifi, *ifp;
5822 struct wpa_supplicant *wpa_s;
5823 struct wpa_interface *iface;
5824
5825 ifp = if_nameindex();
5826 if (!ifp) {
5827 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5828 return -1;
5829 }
5830
5831 for (ifi = ifp; ifi->if_name; ifi++) {
5832 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5833 if (wpa_s)
5834 continue;
5835 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5836 if (iface) {
5837 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5838 os_free(iface);
5839 if (wpa_s)
5840 wpa_s->matched = 1;
5841 }
5842 }
5843
5844 if_freenameindex(ifp);
5845 return 0;
5846}
5847
5848#endif /* CONFIG_MATCH_IFACE */
5849
5850
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005851/**
5852 * wpa_supplicant_add_iface - Add a new network interface
5853 * @global: Pointer to global data from wpa_supplicant_init()
5854 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005855 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005856 * Returns: Pointer to the created interface or %NULL on failure
5857 *
5858 * This function is used to add new network interfaces for %wpa_supplicant.
5859 * This can be called before wpa_supplicant_run() to add interfaces before the
5860 * main event loop has been started. In addition, new interfaces can be added
5861 * dynamically while %wpa_supplicant is already running. This could happen,
5862 * e.g., when a hotplug network adapter is inserted.
5863 */
5864struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005865 struct wpa_interface *iface,
5866 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005867{
5868 struct wpa_supplicant *wpa_s;
5869 struct wpa_interface t_iface;
5870 struct wpa_ssid *ssid;
5871
5872 if (global == NULL || iface == NULL)
5873 return NULL;
5874
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005875 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005876 if (wpa_s == NULL)
5877 return NULL;
5878
5879 wpa_s->global = global;
5880
5881 t_iface = *iface;
5882 if (global->params.override_driver) {
5883 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5884 "('%s' -> '%s')",
5885 iface->driver, global->params.override_driver);
5886 t_iface.driver = global->params.override_driver;
5887 }
5888 if (global->params.override_ctrl_interface) {
5889 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5890 "ctrl_interface ('%s' -> '%s')",
5891 iface->ctrl_interface,
5892 global->params.override_ctrl_interface);
5893 t_iface.ctrl_interface =
5894 global->params.override_ctrl_interface;
5895 }
5896 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5897 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5898 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005899 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005900 return NULL;
5901 }
5902
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005903 /* Notify the control interfaces about new iface */
5904 if (wpas_notify_iface_added(wpa_s)) {
5905 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5906 return NULL;
5907 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005908
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005909 /* Notify the control interfaces about new networks for non p2p mgmt
5910 * ifaces. */
5911 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005912 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5913 wpas_notify_network_added(wpa_s, ssid);
5914 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005915
5916 wpa_s->next = global->ifaces;
5917 global->ifaces = wpa_s;
5918
5919 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005920 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005921
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005922#ifdef CONFIG_P2P
5923 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005924 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005925 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005926 wpas_p2p_add_p2pdev_interface(
5927 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005928 wpa_printf(MSG_INFO,
5929 "P2P: Failed to enable P2P Device interface");
5930 /* Try to continue without. P2P will be disabled. */
5931 }
5932#endif /* CONFIG_P2P */
5933
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005934 return wpa_s;
5935}
5936
5937
5938/**
5939 * wpa_supplicant_remove_iface - Remove a network interface
5940 * @global: Pointer to global data from wpa_supplicant_init()
5941 * @wpa_s: Pointer to the network interface to be removed
5942 * Returns: 0 if interface was removed, -1 if interface was not found
5943 *
5944 * This function can be used to dynamically remove network interfaces from
5945 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5946 * addition, this function is used to remove all remaining interfaces when
5947 * %wpa_supplicant is terminated.
5948 */
5949int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005950 struct wpa_supplicant *wpa_s,
5951 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005952{
5953 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005954#ifdef CONFIG_MESH
5955 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5956 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005957 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005958#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005959
5960 /* Remove interface from the global list of interfaces */
5961 prev = global->ifaces;
5962 if (prev == wpa_s) {
5963 global->ifaces = wpa_s->next;
5964 } else {
5965 while (prev && prev->next != wpa_s)
5966 prev = prev->next;
5967 if (prev == NULL)
5968 return -1;
5969 prev->next = wpa_s->next;
5970 }
5971
5972 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5973
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005974#ifdef CONFIG_MESH
5975 if (mesh_if_created) {
5976 ifname = os_strdup(wpa_s->ifname);
5977 if (ifname == NULL) {
5978 wpa_dbg(wpa_s, MSG_ERROR,
5979 "mesh: Failed to malloc ifname");
5980 return -1;
5981 }
5982 }
5983#endif /* CONFIG_MESH */
5984
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005985 if (global->p2p_group_formation == wpa_s)
5986 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005987 if (global->p2p_invite_group == wpa_s)
5988 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005989 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005990
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005991#ifdef CONFIG_MESH
5992 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005993 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005994 os_free(ifname);
5995 }
5996#endif /* CONFIG_MESH */
5997
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005998 return 0;
5999}
6000
6001
6002/**
6003 * wpa_supplicant_get_eap_mode - Get the current EAP mode
6004 * @wpa_s: Pointer to the network interface
6005 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
6006 */
6007const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
6008{
6009 const char *eapol_method;
6010
6011 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
6012 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
6013 return "NO-EAP";
6014 }
6015
6016 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6017 if (eapol_method == NULL)
6018 return "UNKNOWN-EAP";
6019
6020 return eapol_method;
6021}
6022
6023
6024/**
6025 * wpa_supplicant_get_iface - Get a new network interface
6026 * @global: Pointer to global data from wpa_supplicant_init()
6027 * @ifname: Interface name
6028 * Returns: Pointer to the interface or %NULL if not found
6029 */
6030struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6031 const char *ifname)
6032{
6033 struct wpa_supplicant *wpa_s;
6034
6035 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6036 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6037 return wpa_s;
6038 }
6039 return NULL;
6040}
6041
6042
6043#ifndef CONFIG_NO_WPA_MSG
6044static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6045{
6046 struct wpa_supplicant *wpa_s = ctx;
6047 if (wpa_s == NULL)
6048 return NULL;
6049 return wpa_s->ifname;
6050}
6051#endif /* CONFIG_NO_WPA_MSG */
6052
6053
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006054#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6055#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6056#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6057
6058/* Periodic cleanup tasks */
6059static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6060{
6061 struct wpa_global *global = eloop_ctx;
6062 struct wpa_supplicant *wpa_s;
6063
6064 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6065 wpas_periodic, global, NULL);
6066
6067#ifdef CONFIG_P2P
6068 if (global->p2p)
6069 p2p_expire_peers(global->p2p);
6070#endif /* CONFIG_P2P */
6071
6072 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6073 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6074#ifdef CONFIG_AP
6075 ap_periodic(wpa_s);
6076#endif /* CONFIG_AP */
6077 }
6078}
6079
6080
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006081/**
6082 * wpa_supplicant_init - Initialize %wpa_supplicant
6083 * @params: Parameters for %wpa_supplicant
6084 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6085 *
6086 * This function is used to initialize %wpa_supplicant. After successful
6087 * initialization, the returned data pointer can be used to add and remove
6088 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6089 */
6090struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6091{
6092 struct wpa_global *global;
6093 int ret, i;
6094
6095 if (params == NULL)
6096 return NULL;
6097
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006098#ifdef CONFIG_DRIVER_NDIS
6099 {
6100 void driver_ndis_init_ops(void);
6101 driver_ndis_init_ops();
6102 }
6103#endif /* CONFIG_DRIVER_NDIS */
6104
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006105#ifndef CONFIG_NO_WPA_MSG
6106 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6107#endif /* CONFIG_NO_WPA_MSG */
6108
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006109 if (params->wpa_debug_file_path)
6110 wpa_debug_open_file(params->wpa_debug_file_path);
6111 else
6112 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006113 if (params->wpa_debug_syslog)
6114 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006115 if (params->wpa_debug_tracing) {
6116 ret = wpa_debug_open_linux_tracing();
6117 if (ret) {
6118 wpa_printf(MSG_ERROR,
6119 "Failed to enable trace logging");
6120 return NULL;
6121 }
6122 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006123
6124 ret = eap_register_methods();
6125 if (ret) {
6126 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6127 if (ret == -2)
6128 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6129 "the same EAP type.");
6130 return NULL;
6131 }
6132
6133 global = os_zalloc(sizeof(*global));
6134 if (global == NULL)
6135 return NULL;
6136 dl_list_init(&global->p2p_srv_bonjour);
6137 dl_list_init(&global->p2p_srv_upnp);
6138 global->params.daemonize = params->daemonize;
6139 global->params.wait_for_monitor = params->wait_for_monitor;
6140 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6141 if (params->pid_file)
6142 global->params.pid_file = os_strdup(params->pid_file);
6143 if (params->ctrl_interface)
6144 global->params.ctrl_interface =
6145 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006146 if (params->ctrl_interface_group)
6147 global->params.ctrl_interface_group =
6148 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006149 if (params->override_driver)
6150 global->params.override_driver =
6151 os_strdup(params->override_driver);
6152 if (params->override_ctrl_interface)
6153 global->params.override_ctrl_interface =
6154 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006155#ifdef CONFIG_MATCH_IFACE
6156 global->params.match_iface_count = params->match_iface_count;
6157 if (params->match_iface_count) {
6158 global->params.match_ifaces =
6159 os_calloc(params->match_iface_count,
6160 sizeof(struct wpa_interface));
6161 os_memcpy(global->params.match_ifaces,
6162 params->match_ifaces,
6163 params->match_iface_count *
6164 sizeof(struct wpa_interface));
6165 }
6166#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006167#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006168 if (params->conf_p2p_dev)
6169 global->params.conf_p2p_dev =
6170 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006171#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006172 wpa_debug_level = global->params.wpa_debug_level =
6173 params->wpa_debug_level;
6174 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6175 params->wpa_debug_show_keys;
6176 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6177 params->wpa_debug_timestamp;
6178
6179 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
6180
6181 if (eloop_init()) {
6182 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6183 wpa_supplicant_deinit(global);
6184 return NULL;
6185 }
6186
Jouni Malinen75ecf522011-06-27 15:19:46 -07006187 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006188
6189 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6190 if (global->ctrl_iface == NULL) {
6191 wpa_supplicant_deinit(global);
6192 return NULL;
6193 }
6194
6195 if (wpas_notify_supplicant_initialized(global)) {
6196 wpa_supplicant_deinit(global);
6197 return NULL;
6198 }
6199
6200 for (i = 0; wpa_drivers[i]; i++)
6201 global->drv_count++;
6202 if (global->drv_count == 0) {
6203 wpa_printf(MSG_ERROR, "No drivers enabled");
6204 wpa_supplicant_deinit(global);
6205 return NULL;
6206 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006207 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006208 if (global->drv_priv == NULL) {
6209 wpa_supplicant_deinit(global);
6210 return NULL;
6211 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006212
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006213#ifdef CONFIG_WIFI_DISPLAY
6214 if (wifi_display_init(global) < 0) {
6215 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6216 wpa_supplicant_deinit(global);
6217 return NULL;
6218 }
6219#endif /* CONFIG_WIFI_DISPLAY */
6220
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006221 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6222 wpas_periodic, global, NULL);
6223
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006224 return global;
6225}
6226
6227
6228/**
6229 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6230 * @global: Pointer to global data from wpa_supplicant_init()
6231 * Returns: 0 after successful event loop run, -1 on failure
6232 *
6233 * This function starts the main event loop and continues running as long as
6234 * there are any remaining events. In most cases, this function is running as
6235 * long as the %wpa_supplicant process in still in use.
6236 */
6237int wpa_supplicant_run(struct wpa_global *global)
6238{
6239 struct wpa_supplicant *wpa_s;
6240
6241 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006242 (wpa_supplicant_daemon(global->params.pid_file) ||
6243 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006244 return -1;
6245
Dmitry Shmidte4663042016-04-04 10:07:49 -07006246#ifdef CONFIG_MATCH_IFACE
6247 if (wpa_supplicant_match_existing(global))
6248 return -1;
6249#endif
6250
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006251 if (global->params.wait_for_monitor) {
6252 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08006253 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006254 wpa_supplicant_ctrl_iface_wait(
6255 wpa_s->ctrl_iface);
6256 }
6257
6258 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
6259 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
6260
6261 eloop_run();
6262
6263 return 0;
6264}
6265
6266
6267/**
6268 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
6269 * @global: Pointer to global data from wpa_supplicant_init()
6270 *
6271 * This function is called to deinitialize %wpa_supplicant and to free all
6272 * allocated resources. Remaining network interfaces will also be removed.
6273 */
6274void wpa_supplicant_deinit(struct wpa_global *global)
6275{
6276 int i;
6277
6278 if (global == NULL)
6279 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006280
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006281 eloop_cancel_timeout(wpas_periodic, global, NULL);
6282
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006283#ifdef CONFIG_WIFI_DISPLAY
6284 wifi_display_deinit(global);
6285#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006286
6287 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006288 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006289
6290 if (global->ctrl_iface)
6291 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
6292
6293 wpas_notify_supplicant_deinitialized(global);
6294
6295 eap_peer_unregister_methods();
6296#ifdef CONFIG_AP
6297 eap_server_unregister_methods();
6298#endif /* CONFIG_AP */
6299
6300 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
6301 if (!global->drv_priv[i])
6302 continue;
6303 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
6304 }
6305 os_free(global->drv_priv);
6306
6307 random_deinit();
6308
6309 eloop_destroy();
6310
6311 if (global->params.pid_file) {
6312 os_daemonize_terminate(global->params.pid_file);
6313 os_free(global->params.pid_file);
6314 }
6315 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006316 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006317 os_free(global->params.override_driver);
6318 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006319#ifdef CONFIG_MATCH_IFACE
6320 os_free(global->params.match_ifaces);
6321#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006322#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006323 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006324#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006325
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07006326 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006327 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006328 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006330 os_free(global);
6331 wpa_debug_close_syslog();
6332 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006333 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006334}
6335
6336
6337void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
6338{
6339 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
6340 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
6341 char country[3];
6342 country[0] = wpa_s->conf->country[0];
6343 country[1] = wpa_s->conf->country[1];
6344 country[2] = '\0';
6345 if (wpa_drv_set_country(wpa_s, country) < 0) {
6346 wpa_printf(MSG_ERROR, "Failed to set country code "
6347 "'%s'", country);
6348 }
6349 }
6350
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006351 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
6352 wpas_init_ext_pw(wpa_s);
6353
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006354 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
6355 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6356
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006357 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
6358 struct wpa_driver_capa capa;
6359 int res = wpa_drv_get_capa(wpa_s, &capa);
6360
6361 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
6362 wpa_printf(MSG_ERROR,
6363 "Failed to update wowlan_triggers to '%s'",
6364 wpa_s->conf->wowlan_triggers);
6365 }
6366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006367#ifdef CONFIG_WPS
6368 wpas_wps_update_config(wpa_s);
6369#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006370 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006371 wpa_s->conf->changed_parameters = 0;
6372}
6373
6374
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006375void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006376{
6377 int i;
6378
6379 for (i = 0; i < *num_freqs; i++) {
6380 if (freqs[i] == freq)
6381 return;
6382 }
6383
6384 freqs[*num_freqs] = freq;
6385 (*num_freqs)++;
6386}
6387
6388
6389static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
6390{
6391 struct wpa_bss *bss, *cbss;
6392 const int max_freqs = 10;
6393 int *freqs;
6394 int num_freqs = 0;
6395
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006396 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006397 if (freqs == NULL)
6398 return NULL;
6399
6400 cbss = wpa_s->current_bss;
6401
6402 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
6403 if (bss == cbss)
6404 continue;
6405 if (bss->ssid_len == cbss->ssid_len &&
6406 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
6407 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
6408 add_freq(freqs, &num_freqs, bss->freq);
6409 if (num_freqs == max_freqs)
6410 break;
6411 }
6412 }
6413
6414 if (num_freqs == 0) {
6415 os_free(freqs);
6416 freqs = NULL;
6417 }
6418
6419 return freqs;
6420}
6421
6422
6423void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6424{
6425 int timeout;
6426 int count;
6427 int *freqs = NULL;
6428
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006429 wpas_connect_work_done(wpa_s);
6430
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006431 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006432 * Remove possible authentication timeout since the connection failed.
6433 */
6434 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
6435
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006436 /*
6437 * There is no point in blacklisting the AP if this event is
6438 * generated based on local request to disconnect.
6439 */
6440 if (wpa_s->own_disconnect_req) {
6441 wpa_s->own_disconnect_req = 0;
6442 wpa_dbg(wpa_s, MSG_DEBUG,
6443 "Ignore connection failure due to local request to disconnect");
6444 return;
6445 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006446 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006447 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6448 "indication since interface has been put into "
6449 "disconnected state");
6450 return;
6451 }
6452
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006453 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006454 * Add the failed BSSID into the blacklist and speed up next scan
6455 * attempt if there could be other APs that could accept association.
6456 * The current blacklist count indicates how many times we have tried
6457 * connecting to this AP and multiple attempts mean that other APs are
6458 * either not available or has already been tried, so that we can start
6459 * increasing the delay here to avoid constant scanning.
6460 */
6461 count = wpa_blacklist_add(wpa_s, bssid);
6462 if (count == 1 && wpa_s->current_bss) {
6463 /*
6464 * This BSS was not in the blacklist before. If there is
6465 * another BSS available for the same ESS, we should try that
6466 * next. Otherwise, we may as well try this one once more
6467 * before allowing other, likely worse, ESSes to be considered.
6468 */
6469 freqs = get_bss_freqs_in_ess(wpa_s);
6470 if (freqs) {
6471 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
6472 "has been seen; try it next");
6473 wpa_blacklist_add(wpa_s, bssid);
6474 /*
6475 * On the next scan, go through only the known channels
6476 * used in this ESS based on previous scans to speed up
6477 * common load balancing use case.
6478 */
6479 os_free(wpa_s->next_scan_freqs);
6480 wpa_s->next_scan_freqs = freqs;
6481 }
6482 }
6483
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006484 /*
6485 * Add previous failure count in case the temporary blacklist was
6486 * cleared due to no other BSSes being available.
6487 */
6488 count += wpa_s->extra_blacklist_count;
6489
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006490 if (count > 3 && wpa_s->current_ssid) {
6491 wpa_printf(MSG_DEBUG, "Continuous association failures - "
6492 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006493 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006494 }
6495
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006496 switch (count) {
6497 case 1:
6498 timeout = 100;
6499 break;
6500 case 2:
6501 timeout = 500;
6502 break;
6503 case 3:
6504 timeout = 1000;
6505 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006506 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006507 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006508 break;
6509 default:
6510 timeout = 10000;
6511 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006512 }
6513
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006514 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
6515 "ms", count, timeout);
6516
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006517 /*
6518 * TODO: if more than one possible AP is available in scan results,
6519 * could try the other ones before requesting a new scan.
6520 */
6521 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
6522 1000 * (timeout % 1000));
6523}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006524
6525
Hai Shalomce48b4a2018-09-05 11:41:35 -07006526#ifdef CONFIG_FILS
6527void fils_connection_failure(struct wpa_supplicant *wpa_s)
6528{
6529 struct wpa_ssid *ssid = wpa_s->current_ssid;
6530 const u8 *realm, *username, *rrk;
6531 size_t realm_len, username_len, rrk_len;
6532 u16 next_seq_num;
6533
6534 if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) ||
6535 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
6536 &username, &username_len,
6537 &realm, &realm_len, &next_seq_num,
6538 &rrk, &rrk_len) != 0 ||
6539 !realm)
6540 return;
6541
6542 wpa_hexdump_ascii(MSG_DEBUG,
6543 "FILS: Store last connection failure realm",
6544 realm, realm_len);
6545 os_free(wpa_s->last_con_fail_realm);
6546 wpa_s->last_con_fail_realm = os_malloc(realm_len);
6547 if (wpa_s->last_con_fail_realm) {
6548 wpa_s->last_con_fail_realm_len = realm_len;
6549 os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len);
6550 }
6551}
6552#endif /* CONFIG_FILS */
6553
6554
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006555int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
6556{
6557 return wpa_s->conf->ap_scan == 2 ||
6558 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
6559}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006560
Dmitry Shmidt04949592012-07-19 12:16:46 -07006561
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006562#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006563int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6564 struct wpa_ssid *ssid,
6565 const char *field,
6566 const char *value)
6567{
6568#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006569 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006570
6571 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
6572 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
6573 (const u8 *) value, os_strlen(value));
6574
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006575 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07006576 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006577#else /* IEEE8021X_EAPOL */
6578 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6579 return -1;
6580#endif /* IEEE8021X_EAPOL */
6581}
6582
6583int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6584 struct wpa_ssid *ssid,
6585 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07006586 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006587{
6588#ifdef IEEE8021X_EAPOL
6589 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08006590 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006591
6592 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07006593 case WPA_CTRL_REQ_EAP_IDENTITY:
6594 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08006595 os_free(eap->imsi_identity);
6596 if (value == NULL)
6597 return -1;
6598 identity = os_strchr(value, ':');
6599 if (identity == NULL) {
6600 /* plain identity */
6601 eap->identity = (u8 *)os_strdup(value);
6602 eap->identity_len = os_strlen(value);
6603 } else {
6604 /* have both plain identity and encrypted identity */
6605 imsi_identity = value;
6606 *identity++ = '\0';
6607 /* plain identity */
6608 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
6609 eap->imsi_identity_len = strlen(imsi_identity);
6610 /* encrypted identity */
6611 eap->identity = (u8 *)dup_binstr(identity,
6612 value_len - strlen(imsi_identity) - 1);
6613 eap->identity_len = value_len - strlen(imsi_identity) - 1;
6614 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006615 eap->pending_req_identity = 0;
6616 if (ssid == wpa_s->current_ssid)
6617 wpa_s->reassociate = 1;
6618 break;
6619 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006620 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006621 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006622 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006623 eap->pending_req_password = 0;
6624 if (ssid == wpa_s->current_ssid)
6625 wpa_s->reassociate = 1;
6626 break;
6627 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006628 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006629 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006630 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006631 eap->pending_req_new_password = 0;
6632 if (ssid == wpa_s->current_ssid)
6633 wpa_s->reassociate = 1;
6634 break;
6635 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006636 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006637 eap->pin = os_strdup(value);
6638 eap->pending_req_pin = 0;
6639 if (ssid == wpa_s->current_ssid)
6640 wpa_s->reassociate = 1;
6641 break;
6642 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006643 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006644 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006645 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006646 os_free(eap->pending_req_otp);
6647 eap->pending_req_otp = NULL;
6648 eap->pending_req_otp_len = 0;
6649 break;
6650 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006651 str_clear_free(eap->private_key_passwd);
6652 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006653 eap->pending_req_passphrase = 0;
6654 if (ssid == wpa_s->current_ssid)
6655 wpa_s->reassociate = 1;
6656 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006657 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006658 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07006659 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006660 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006661 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006662 case WPA_CTRL_REQ_PSK_PASSPHRASE:
6663 if (wpa_config_set(ssid, "psk", value, 0) < 0)
6664 return -1;
6665 ssid->mem_only_psk = 1;
6666 if (ssid->passphrase)
6667 wpa_config_update_psk(ssid);
6668 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
6669 wpa_supplicant_req_scan(wpa_s, 0, 0);
6670 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006671 case WPA_CTRL_REQ_EXT_CERT_CHECK:
6672 if (eap->pending_ext_cert_check != PENDING_CHECK)
6673 return -1;
6674 if (os_strcmp(value, "good") == 0)
6675 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
6676 else if (os_strcmp(value, "bad") == 0)
6677 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
6678 else
6679 return -1;
6680 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006681 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006682 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006683 return -1;
6684 }
6685
6686 return 0;
6687#else /* IEEE8021X_EAPOL */
6688 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6689 return -1;
6690#endif /* IEEE8021X_EAPOL */
6691}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006692#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006693
6694
6695int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6696{
6697 int i;
6698 unsigned int drv_enc;
6699
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006700 if (wpa_s->p2p_mgmt)
6701 return 1; /* no normal network profiles on p2p_mgmt interface */
6702
Dmitry Shmidt04949592012-07-19 12:16:46 -07006703 if (ssid == NULL)
6704 return 1;
6705
6706 if (ssid->disabled)
6707 return 1;
6708
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006709 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006710 drv_enc = wpa_s->drv_enc;
6711 else
6712 drv_enc = (unsigned int) -1;
6713
6714 for (i = 0; i < NUM_WEP_KEYS; i++) {
6715 size_t len = ssid->wep_key_len[i];
6716 if (len == 0)
6717 continue;
6718 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
6719 continue;
6720 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
6721 continue;
6722 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
6723 continue;
6724 return 1; /* invalid WEP key */
6725 }
6726
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006727 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006728 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006729 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006730 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006731 return 1;
6732
Dmitry Shmidt04949592012-07-19 12:16:46 -07006733 return 0;
6734}
6735
6736
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006737int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6738{
6739#ifdef CONFIG_IEEE80211W
6740 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6741 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6742 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6743 /*
6744 * Driver does not support BIP -- ignore pmf=1 default
6745 * since the connection with PMF would fail and the
6746 * configuration does not require PMF to be enabled.
6747 */
6748 return NO_MGMT_FRAME_PROTECTION;
6749 }
6750
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006751 if (ssid &&
6752 (ssid->key_mgmt &
6753 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6754 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6755 /*
6756 * Do not use the default PMF value for non-RSN networks
6757 * since PMF is available only with RSN and pmf=2
6758 * configuration would otherwise prevent connections to
6759 * all open networks.
6760 */
6761 return NO_MGMT_FRAME_PROTECTION;
6762 }
6763
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006764 return wpa_s->conf->pmf;
6765 }
6766
6767 return ssid->ieee80211w;
6768#else /* CONFIG_IEEE80211W */
6769 return NO_MGMT_FRAME_PROTECTION;
6770#endif /* CONFIG_IEEE80211W */
6771}
6772
6773
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006774int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006775{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006776 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006777 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006778 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006779 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006780 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006781}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006782
6783
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006784void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006785{
6786 struct wpa_ssid *ssid = wpa_s->current_ssid;
6787 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006788 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006789
6790 if (ssid == NULL) {
6791 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6792 "SSID block");
6793 return;
6794 }
6795
6796 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6797 return;
6798
6799 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006800
6801#ifdef CONFIG_P2P
6802 if (ssid->p2p_group &&
6803 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6804 /*
6805 * Skip the wait time since there is a short timeout on the
6806 * connection to a P2P group.
6807 */
6808 return;
6809 }
6810#endif /* CONFIG_P2P */
6811
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006812 if (ssid->auth_failures > 50)
6813 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006814 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006815 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006816 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006817 dur = 90;
6818 else if (ssid->auth_failures > 3)
6819 dur = 60;
6820 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006821 dur = 30;
6822 else if (ssid->auth_failures > 1)
6823 dur = 20;
6824 else
6825 dur = 10;
6826
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006827 if (ssid->auth_failures > 1 &&
6828 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6829 dur += os_random() % (ssid->auth_failures * 10);
6830
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006831 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006832 if (now.sec + dur <= ssid->disabled_until.sec)
6833 return;
6834
6835 ssid->disabled_until.sec = now.sec + dur;
6836
6837 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006838 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006839 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006840 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006841}
6842
6843
6844void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6845 struct wpa_ssid *ssid, int clear_failures)
6846{
6847 if (ssid == NULL)
6848 return;
6849
6850 if (ssid->disabled_until.sec) {
6851 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6852 "id=%d ssid=\"%s\"",
6853 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6854 }
6855 ssid->disabled_until.sec = 0;
6856 ssid->disabled_until.usec = 0;
6857 if (clear_failures)
6858 ssid->auth_failures = 0;
6859}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006860
6861
6862int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6863{
6864 size_t i;
6865
6866 if (wpa_s->disallow_aps_bssid == NULL)
6867 return 0;
6868
6869 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6870 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6871 bssid, ETH_ALEN) == 0)
6872 return 1;
6873 }
6874
6875 return 0;
6876}
6877
6878
6879int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6880 size_t ssid_len)
6881{
6882 size_t i;
6883
6884 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6885 return 0;
6886
6887 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6888 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6889 if (ssid_len == s->ssid_len &&
6890 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6891 return 1;
6892 }
6893
6894 return 0;
6895}
6896
6897
6898/**
6899 * wpas_request_connection - Request a new connection
6900 * @wpa_s: Pointer to the network interface
6901 *
6902 * This function is used to request a new connection to be found. It will mark
6903 * the interface to allow reassociation and request a new scan to find a
6904 * suitable network to connect to.
6905 */
6906void wpas_request_connection(struct wpa_supplicant *wpa_s)
6907{
6908 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006909 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006910 wpa_supplicant_reinit_autoscan(wpa_s);
6911 wpa_s->extra_blacklist_count = 0;
6912 wpa_s->disconnected = 0;
6913 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006914 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006915
6916 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6917 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006918 else
6919 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006920}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006921
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006922
Roshan Pius02242d72016-08-09 15:31:48 -07006923/**
6924 * wpas_request_disconnection - Request disconnection
6925 * @wpa_s: Pointer to the network interface
6926 *
6927 * This function is used to request disconnection from the currently connected
6928 * network. This will stop any ongoing scans and initiate deauthentication.
6929 */
6930void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6931{
6932#ifdef CONFIG_SME
6933 wpa_s->sme.prev_bssid_set = 0;
6934#endif /* CONFIG_SME */
6935 wpa_s->reassociate = 0;
6936 wpa_s->disconnected = 1;
6937 wpa_supplicant_cancel_sched_scan(wpa_s);
6938 wpa_supplicant_cancel_scan(wpa_s);
6939 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6940 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6941}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006942
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006943
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006944void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6945 struct wpa_used_freq_data *freqs_data,
6946 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006947{
6948 unsigned int i;
6949
6950 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6951 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006952 for (i = 0; i < len; i++) {
6953 struct wpa_used_freq_data *cur = &freqs_data[i];
6954 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6955 i, cur->freq, cur->flags);
6956 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006957}
6958
6959
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006960/*
6961 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006962 * are using the same radio as the current interface, and in addition, get
6963 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006964 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006965int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6966 struct wpa_used_freq_data *freqs_data,
6967 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006968{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006969 struct wpa_supplicant *ifs;
6970 u8 bssid[ETH_ALEN];
6971 int freq;
6972 unsigned int idx = 0, i;
6973
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006974 wpa_dbg(wpa_s, MSG_DEBUG,
6975 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006976 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006977
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006978 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6979 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006980 if (idx == len)
6981 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006982
6983 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6984 continue;
6985
6986 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006987 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6988 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006989 freq = ifs->current_ssid->frequency;
6990 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6991 freq = ifs->assoc_freq;
6992 else
6993 continue;
6994
6995 /* Hold only distinct freqs */
6996 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006997 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006998 break;
6999
7000 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007001 freqs_data[idx++].freq = freq;
7002
7003 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007004 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007005 WPA_FREQ_USED_BY_P2P_CLIENT :
7006 WPA_FREQ_USED_BY_INFRA_STATION;
7007 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007008 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08007009
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007010 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007011 return idx;
7012}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007013
7014
7015/*
7016 * Find the operating frequencies of any of the virtual interfaces that
7017 * are using the same radio as the current interface.
7018 */
7019int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
7020 int *freq_array, unsigned int len)
7021{
7022 struct wpa_used_freq_data *freqs_data;
7023 int num, i;
7024
7025 os_memset(freq_array, 0, sizeof(int) * len);
7026
7027 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
7028 if (!freqs_data)
7029 return -1;
7030
7031 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
7032 for (i = 0; i < num; i++)
7033 freq_array[i] = freqs_data[i].freq;
7034
7035 os_free(freqs_data);
7036
7037 return num;
7038}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007039
7040
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007041struct wpa_supplicant *
7042wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
7043{
7044 switch (frame) {
7045#ifdef CONFIG_P2P
7046 case VENDOR_ELEM_PROBE_REQ_P2P:
7047 case VENDOR_ELEM_PROBE_RESP_P2P:
7048 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7049 case VENDOR_ELEM_BEACON_P2P_GO:
7050 case VENDOR_ELEM_P2P_PD_REQ:
7051 case VENDOR_ELEM_P2P_PD_RESP:
7052 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7053 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7054 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7055 case VENDOR_ELEM_P2P_INV_REQ:
7056 case VENDOR_ELEM_P2P_INV_RESP:
7057 case VENDOR_ELEM_P2P_ASSOC_REQ:
7058 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007059 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007060#endif /* CONFIG_P2P */
7061 default:
7062 return wpa_s;
7063 }
7064}
7065
7066
7067void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7068{
7069 unsigned int i;
7070 char buf[30];
7071
7072 wpa_printf(MSG_DEBUG, "Update vendor elements");
7073
7074 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7075 if (wpa_s->vendor_elem[i]) {
7076 int res;
7077
7078 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7079 if (!os_snprintf_error(sizeof(buf), res)) {
7080 wpa_hexdump_buf(MSG_DEBUG, buf,
7081 wpa_s->vendor_elem[i]);
7082 }
7083 }
7084 }
7085
7086#ifdef CONFIG_P2P
7087 if (wpa_s->parent == wpa_s &&
7088 wpa_s->global->p2p &&
7089 !wpa_s->global->p2p_disabled)
7090 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7091#endif /* CONFIG_P2P */
7092}
7093
7094
7095int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7096 const u8 *elem, size_t len)
7097{
7098 u8 *ie, *end;
7099
7100 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7101 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7102
7103 for (; ie + 1 < end; ie += 2 + ie[1]) {
7104 if (ie + len > end)
7105 break;
7106 if (os_memcmp(ie, elem, len) != 0)
7107 continue;
7108
7109 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7110 wpabuf_free(wpa_s->vendor_elem[frame]);
7111 wpa_s->vendor_elem[frame] = NULL;
7112 } else {
7113 os_memmove(ie, ie + len, end - (ie + len));
7114 wpa_s->vendor_elem[frame]->used -= len;
7115 }
7116 wpas_vendor_elem_update(wpa_s);
7117 return 0;
7118 }
7119
7120 return -1;
7121}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007122
7123
7124struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
7125 u16 num_modes, enum hostapd_hw_mode mode)
7126{
7127 u16 i;
7128
7129 for (i = 0; i < num_modes; i++) {
7130 if (modes[i].mode == mode)
7131 return &modes[i];
7132 }
7133
7134 return NULL;
7135}
7136
7137
7138static struct
7139wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7140 const u8 *bssid)
7141{
7142 struct wpa_bss_tmp_disallowed *bss;
7143
7144 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7145 struct wpa_bss_tmp_disallowed, list) {
7146 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7147 return bss;
7148 }
7149
7150 return NULL;
7151}
7152
7153
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007154static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7155{
7156 struct wpa_bss_tmp_disallowed *tmp;
7157 unsigned int num_bssid = 0;
7158 u8 *bssids;
7159 int ret;
7160
7161 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7162 if (!bssids)
7163 return -1;
7164 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7165 struct wpa_bss_tmp_disallowed, list) {
7166 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7167 ETH_ALEN);
7168 num_bssid++;
7169 }
7170 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7171 os_free(bssids);
7172 return ret;
7173}
7174
7175
7176static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7177{
7178 struct wpa_supplicant *wpa_s = eloop_ctx;
7179 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7180
7181 /* Make sure the bss is not already freed */
7182 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7183 struct wpa_bss_tmp_disallowed, list) {
7184 if (bss == tmp) {
7185 dl_list_del(&tmp->list);
7186 os_free(tmp);
7187 wpa_set_driver_tmp_disallow_list(wpa_s);
7188 break;
7189 }
7190 }
7191}
7192
7193
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007194void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
7195 unsigned int sec)
7196{
7197 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007198
7199 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7200 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007201 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
7202 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7203 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007204 return;
7205 }
7206
7207 bss = os_malloc(sizeof(*bss));
7208 if (!bss) {
7209 wpa_printf(MSG_DEBUG,
7210 "Failed to allocate memory for temp disallow BSS");
7211 return;
7212 }
7213
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007214 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7215 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007216 wpa_set_driver_tmp_disallow_list(wpa_s);
7217 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7218 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007219}
7220
7221
7222int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7223{
7224 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007225
7226 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7227 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007228 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
7229 bss = tmp;
7230 break;
7231 }
7232 }
7233 if (!bss)
7234 return 0;
7235
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007236 return 1;
7237}