blob: c2529e63c576ae0c05b642411fa219ed79fc4374 [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);
284}
285
286
287/**
288 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
289 * @wpa_s: Pointer to wpa_supplicant data
290 *
291 * This function is used to configure EAPOL state machine based on the selected
292 * authentication mode.
293 */
294void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
295{
296#ifdef IEEE8021X_EAPOL
297 struct eapol_config eapol_conf;
298 struct wpa_ssid *ssid = wpa_s->current_ssid;
299
300#ifdef CONFIG_IBSS_RSN
301 if (ssid->mode == WPAS_MODE_IBSS &&
302 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
303 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
304 /*
305 * RSN IBSS authentication is per-STA and we can disable the
306 * per-BSSID EAPOL authentication.
307 */
308 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
309 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
310 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
311 return;
312 }
313#endif /* CONFIG_IBSS_RSN */
314
315 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
316 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
317
318 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
319 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
320 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
321 else
322 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
323
324 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
325 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
326 eapol_conf.accept_802_1x_keys = 1;
327 eapol_conf.required_keys = 0;
328 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
329 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
330 }
331 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
332 eapol_conf.required_keys |=
333 EAPOL_REQUIRE_KEY_BROADCAST;
334 }
335
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700336 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700337 eapol_conf.required_keys = 0;
338 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700339 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700340 eapol_conf.workaround = ssid->eap_workaround;
341 eapol_conf.eap_disabled =
342 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
343 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
344 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700345 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800346
347#ifdef CONFIG_WPS
348 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
349 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
350 if (wpa_s->current_bss) {
351 struct wpabuf *ie;
352 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
353 WPS_IE_VENDOR_TYPE);
354 if (ie) {
355 if (wps_is_20(ie))
356 eapol_conf.wps |=
357 EAPOL_PEER_IS_WPS20_AP;
358 wpabuf_free(ie);
359 }
360 }
361 }
362#endif /* CONFIG_WPS */
363
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700364 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700365
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800366#ifdef CONFIG_MACSEC
367 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
368 ieee802_1x_create_preshared_mka(wpa_s, ssid);
369 else
370 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
371#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800372#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700373}
374
375
376/**
377 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
378 * @wpa_s: Pointer to wpa_supplicant data
379 * @ssid: Configuration data for the network
380 *
381 * This function is used to configure WPA state machine and related parameters
382 * to a mode where WPA is not enabled. This is called as part of the
383 * authentication configuration when the selected network does not use WPA.
384 */
385void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
386 struct wpa_ssid *ssid)
387{
388 int i;
389
390 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
391 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
392 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
393 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
394 else
395 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
396 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
397 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
398 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
399 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
400 wpa_s->group_cipher = WPA_CIPHER_NONE;
401 wpa_s->mgmt_group_cipher = 0;
402
403 for (i = 0; i < NUM_WEP_KEYS; i++) {
404 if (ssid->wep_key_len[i] > 5) {
405 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
406 wpa_s->group_cipher = WPA_CIPHER_WEP104;
407 break;
408 } else if (ssid->wep_key_len[i] > 0) {
409 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
410 wpa_s->group_cipher = WPA_CIPHER_WEP40;
411 break;
412 }
413 }
414
415 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
416 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
417 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
418 wpa_s->pairwise_cipher);
419 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
420#ifdef CONFIG_IEEE80211W
421 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
422 wpa_s->mgmt_group_cipher);
423#endif /* CONFIG_IEEE80211W */
424
425 pmksa_cache_clear_current(wpa_s->wpa);
426}
427
428
Dmitry Shmidt04949592012-07-19 12:16:46 -0700429void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800430{
431 int i;
432 if (wpa_s->hw.modes == NULL)
433 return;
434
435 for (i = 0; i < wpa_s->hw.num_modes; i++) {
436 os_free(wpa_s->hw.modes[i].channels);
437 os_free(wpa_s->hw.modes[i].rates);
438 }
439
440 os_free(wpa_s->hw.modes);
441 wpa_s->hw.modes = NULL;
442}
443
444
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800445static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
446{
447 struct wpa_bss_tmp_disallowed *bss, *prev;
448
449 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
450 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700451 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800452 dl_list_del(&bss->list);
453 os_free(bss);
454 }
455}
456
457
Paul Stewart092955c2017-02-06 09:13:09 -0800458void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
459{
460 struct fils_hlp_req *req;
461
462 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
463 list)) != NULL) {
464 dl_list_del(&req->list);
465 wpabuf_free(req->pkt);
466 os_free(req);
467 }
468}
469
470
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700471static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
472{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700473 int i;
474
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700475 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700476 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700477 scard_deinit(wpa_s->scard);
478 wpa_s->scard = NULL;
479 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
480 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
481 l2_packet_deinit(wpa_s->l2);
482 wpa_s->l2 = NULL;
483 if (wpa_s->l2_br) {
484 l2_packet_deinit(wpa_s->l2_br);
485 wpa_s->l2_br = NULL;
486 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800487#ifdef CONFIG_TESTING_OPTIONS
488 l2_packet_deinit(wpa_s->l2_test);
489 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800490 os_free(wpa_s->get_pref_freq_list_override);
491 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700492 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
493 wpa_s->last_assoc_req_wpa_ie = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800494#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700495
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700496 if (wpa_s->conf != NULL) {
497 struct wpa_ssid *ssid;
498 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
499 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700500 }
501
502 os_free(wpa_s->confname);
503 wpa_s->confname = NULL;
504
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700505 os_free(wpa_s->confanother);
506 wpa_s->confanother = NULL;
507
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700508 wpa_sm_set_eapol(wpa_s->wpa, NULL);
509 eapol_sm_deinit(wpa_s->eapol);
510 wpa_s->eapol = NULL;
511
512 rsn_preauth_deinit(wpa_s->wpa);
513
514#ifdef CONFIG_TDLS
515 wpa_tdls_deinit(wpa_s->wpa);
516#endif /* CONFIG_TDLS */
517
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800518 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700519 pmksa_candidate_free(wpa_s->wpa);
520 wpa_sm_deinit(wpa_s->wpa);
521 wpa_s->wpa = NULL;
522 wpa_blacklist_clear(wpa_s);
523
524 wpa_bss_deinit(wpa_s);
525
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700526 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700527 wpa_supplicant_cancel_scan(wpa_s);
528 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800529 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
530#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
531 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
532 wpa_s, NULL);
533#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700534
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700535 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
536
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700537 wpas_wps_deinit(wpa_s);
538
539 wpabuf_free(wpa_s->pending_eapol_rx);
540 wpa_s->pending_eapol_rx = NULL;
541
542#ifdef CONFIG_IBSS_RSN
543 ibss_rsn_deinit(wpa_s->ibss_rsn);
544 wpa_s->ibss_rsn = NULL;
545#endif /* CONFIG_IBSS_RSN */
546
547 sme_deinit(wpa_s);
548
549#ifdef CONFIG_AP
550 wpa_supplicant_ap_deinit(wpa_s);
551#endif /* CONFIG_AP */
552
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700553 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700554
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800555#ifdef CONFIG_OFFCHANNEL
556 offchannel_deinit(wpa_s);
557#endif /* CONFIG_OFFCHANNEL */
558
559 wpa_supplicant_cancel_sched_scan(wpa_s);
560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561 os_free(wpa_s->next_scan_freqs);
562 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800563
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800564 os_free(wpa_s->manual_scan_freqs);
565 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700566 os_free(wpa_s->select_network_scan_freqs);
567 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800568
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700569 os_free(wpa_s->manual_sched_scan_freqs);
570 wpa_s->manual_sched_scan_freqs = NULL;
571
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800572 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
573
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700574 /*
575 * Need to remove any pending gas-query radio work before the
576 * gas_query_deinit() call because gas_query::work has not yet been set
577 * for works that have not been started. gas_query_free() will be unable
578 * to cancel such pending radio works and once the pending gas-query
579 * radio work eventually gets removed, the deinit notification call to
580 * gas_query_start_cb() would result in dereferencing freed memory.
581 */
582 if (wpa_s->radio)
583 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800584 gas_query_deinit(wpa_s->gas);
585 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700586 gas_server_deinit(wpa_s->gas_server);
587 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800588
589 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700590
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700591 ieee802_1x_dealloc_kay_sm(wpa_s);
592
Dmitry Shmidt04949592012-07-19 12:16:46 -0700593 os_free(wpa_s->bssid_filter);
594 wpa_s->bssid_filter = NULL;
595
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800596 os_free(wpa_s->disallow_aps_bssid);
597 wpa_s->disallow_aps_bssid = NULL;
598 os_free(wpa_s->disallow_aps_ssid);
599 wpa_s->disallow_aps_ssid = NULL;
600
Dmitry Shmidt04949592012-07-19 12:16:46 -0700601 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700602#ifdef CONFIG_WNM
603 wnm_deallocate_memory(wpa_s);
604#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700605
606 ext_password_deinit(wpa_s->ext_pw);
607 wpa_s->ext_pw = NULL;
608
609 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800610 wpa_s->last_gas_resp = NULL;
611 wpabuf_free(wpa_s->prev_gas_resp);
612 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700613
614 os_free(wpa_s->last_scan_res);
615 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800616
617#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700618 if (wpa_s->drv_priv)
619 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700620 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800621#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700622
623 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
624 wpabuf_free(wpa_s->vendor_elem[i]);
625 wpa_s->vendor_elem[i] = NULL;
626 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800627
628 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800629
630 wpa_s->sched_scan_plans_num = 0;
631 os_free(wpa_s->sched_scan_plans);
632 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800633
634#ifdef CONFIG_MBO
635 wpa_s->non_pref_chan_num = 0;
636 os_free(wpa_s->non_pref_chan);
637 wpa_s->non_pref_chan = NULL;
638#endif /* CONFIG_MBO */
639
640 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700641
642 wpabuf_free(wpa_s->lci);
643 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800644 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800645
646#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
647#ifdef CONFIG_MESH
648 {
649 struct external_pmksa_cache *entry;
650
651 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
652 struct external_pmksa_cache,
653 list)) != NULL) {
654 dl_list_del(&entry->list);
655 os_free(entry->pmksa_cache);
656 os_free(entry);
657 }
658 }
659#endif /* CONFIG_MESH */
660#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
661
662 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800663
664 wpabuf_free(wpa_s->ric_ies);
665 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700666
667#ifdef CONFIG_DPP
668 wpas_dpp_deinit(wpa_s);
669#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700670}
671
672
673/**
674 * wpa_clear_keys - Clear keys configured for the driver
675 * @wpa_s: Pointer to wpa_supplicant data
676 * @addr: Previously used BSSID or %NULL if not available
677 *
678 * This function clears the encryption keys that has been previously configured
679 * for the driver.
680 */
681void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
682{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800683 int i, max;
684
685#ifdef CONFIG_IEEE80211W
686 max = 6;
687#else /* CONFIG_IEEE80211W */
688 max = 4;
689#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700690
691 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800692 for (i = 0; i < max; i++) {
693 if (wpa_s->keys_cleared & BIT(i))
694 continue;
695 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
696 NULL, 0);
697 }
698 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
699 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700700 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
701 0);
702 /* MLME-SETPROTECTION.request(None) */
703 wpa_drv_mlme_setprotection(
704 wpa_s, addr,
705 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
706 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
707 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800708 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709}
710
711
712/**
713 * wpa_supplicant_state_txt - Get the connection state name as a text string
714 * @state: State (wpa_state; WPA_*)
715 * Returns: The state name as a printable text string
716 */
717const char * wpa_supplicant_state_txt(enum wpa_states state)
718{
719 switch (state) {
720 case WPA_DISCONNECTED:
721 return "DISCONNECTED";
722 case WPA_INACTIVE:
723 return "INACTIVE";
724 case WPA_INTERFACE_DISABLED:
725 return "INTERFACE_DISABLED";
726 case WPA_SCANNING:
727 return "SCANNING";
728 case WPA_AUTHENTICATING:
729 return "AUTHENTICATING";
730 case WPA_ASSOCIATING:
731 return "ASSOCIATING";
732 case WPA_ASSOCIATED:
733 return "ASSOCIATED";
734 case WPA_4WAY_HANDSHAKE:
735 return "4WAY_HANDSHAKE";
736 case WPA_GROUP_HANDSHAKE:
737 return "GROUP_HANDSHAKE";
738 case WPA_COMPLETED:
739 return "COMPLETED";
740 default:
741 return "UNKNOWN";
742 }
743}
744
745
746#ifdef CONFIG_BGSCAN
747
748static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
749{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800750 const char *name;
751
752 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
753 name = wpa_s->current_ssid->bgscan;
754 else
755 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800756 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800757 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800758 if (wpas_driver_bss_selection(wpa_s))
759 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700760 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
761 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800762#ifdef CONFIG_P2P
763 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
764 return;
765#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766
767 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800768 if (wpa_s->current_ssid) {
769 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700770 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
771 "bgscan");
772 /*
773 * Live without bgscan; it is only used as a roaming
774 * optimization, so the initial connection is not
775 * affected.
776 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700777 } else {
778 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700780 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
781 0);
782 if (scan_res) {
783 bgscan_notify_scan(wpa_s, scan_res);
784 wpa_scan_results_free(scan_res);
785 }
786 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700787 } else
788 wpa_s->bgscan_ssid = NULL;
789}
790
791
792static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
793{
794 if (wpa_s->bgscan_ssid != NULL) {
795 bgscan_deinit(wpa_s);
796 wpa_s->bgscan_ssid = NULL;
797 }
798}
799
800#endif /* CONFIG_BGSCAN */
801
802
Dmitry Shmidt04949592012-07-19 12:16:46 -0700803static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
804{
805 if (autoscan_init(wpa_s, 0))
806 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
807}
808
809
810static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
811{
812 autoscan_deinit(wpa_s);
813}
814
815
816void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
817{
818 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
819 wpa_s->wpa_state == WPA_SCANNING) {
820 autoscan_deinit(wpa_s);
821 wpa_supplicant_start_autoscan(wpa_s);
822 }
823}
824
825
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700826/**
827 * wpa_supplicant_set_state - Set current connection state
828 * @wpa_s: Pointer to wpa_supplicant data
829 * @state: The new connection state
830 *
831 * This function is called whenever the connection state changes, e.g.,
832 * association is completed for WPA/WPA2 4-Way Handshake is started.
833 */
834void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
835 enum wpa_states state)
836{
837 enum wpa_states old_state = wpa_s->wpa_state;
838
839 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
840 wpa_supplicant_state_txt(wpa_s->wpa_state),
841 wpa_supplicant_state_txt(state));
842
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800843 if (state == WPA_INTERFACE_DISABLED) {
844 /* Assure normal scan when interface is restored */
845 wpa_s->normal_scans = 0;
846 }
847
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700848 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800849 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700850 /* Reinitialize normal_scan counter */
851 wpa_s->normal_scans = 0;
852 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800853
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700854#ifdef CONFIG_P2P
855 /*
856 * P2PS client has to reply to Probe Request frames received on the
857 * group operating channel. Enable Probe Request frame reporting for
858 * P2P connected client in case p2p_cli_probe configuration property is
859 * set to 1.
860 */
861 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
862 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
863 wpa_s->current_ssid->p2p_group) {
864 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
865 wpa_dbg(wpa_s, MSG_DEBUG,
866 "P2P: Enable CLI Probe Request RX reporting");
867 wpa_s->p2p_cli_probe =
868 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
869 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
870 wpa_dbg(wpa_s, MSG_DEBUG,
871 "P2P: Disable CLI Probe Request RX reporting");
872 wpa_s->p2p_cli_probe = 0;
873 wpa_drv_probe_req_report(wpa_s, 0);
874 }
875 }
876#endif /* CONFIG_P2P */
877
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700878 if (state != WPA_SCANNING)
879 wpa_supplicant_notify_scanning(wpa_s, 0);
880
881 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700882 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700883 int fils_hlp_sent = 0;
884
885#ifdef CONFIG_SME
886 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
887 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
888 fils_hlp_sent = 1;
889#endif /* CONFIG_SME */
890 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
891 wpa_auth_alg_fils(wpa_s->auth_alg))
892 fils_hlp_sent = 1;
893
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700894#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700895 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700896 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800897 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700898 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700899 ssid && ssid->id_str ? ssid->id_str : "",
900 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700901#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700902 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700903 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800904 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700905 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700906 wpa_drv_set_operstate(wpa_s, 1);
907#ifndef IEEE8021X_EAPOL
908 wpa_drv_set_supp_port(wpa_s, 1);
909#endif /* IEEE8021X_EAPOL */
910 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700911 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700912 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700913
914 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700915
916#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
917 if (!fils_hlp_sent && ssid && ssid->eap.erp)
918 wpas_update_fils_connect_params(wpa_s);
919#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700920 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
921 state == WPA_ASSOCIATED) {
922 wpa_s->new_connection = 1;
923 wpa_drv_set_operstate(wpa_s, 0);
924#ifndef IEEE8021X_EAPOL
925 wpa_drv_set_supp_port(wpa_s, 0);
926#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700927 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700928 }
929 wpa_s->wpa_state = state;
930
931#ifdef CONFIG_BGSCAN
932 if (state == WPA_COMPLETED)
933 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800934 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935 wpa_supplicant_stop_bgscan(wpa_s);
936#endif /* CONFIG_BGSCAN */
937
Dmitry Shmidt04949592012-07-19 12:16:46 -0700938 if (state == WPA_AUTHENTICATING)
939 wpa_supplicant_stop_autoscan(wpa_s);
940
941 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
942 wpa_supplicant_start_autoscan(wpa_s);
943
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800944 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
945 wmm_ac_notify_disassoc(wpa_s);
946
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700947 if (wpa_s->wpa_state != old_state) {
948 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
949
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700950 /*
951 * Notify the P2P Device interface about a state change in one
952 * of the interfaces.
953 */
954 wpas_p2p_indicate_state_change(wpa_s);
955
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956 if (wpa_s->wpa_state == WPA_COMPLETED ||
957 old_state == WPA_COMPLETED)
958 wpas_notify_auth_changed(wpa_s);
959 }
960}
961
962
963void wpa_supplicant_terminate_proc(struct wpa_global *global)
964{
965 int pending = 0;
966#ifdef CONFIG_WPS
967 struct wpa_supplicant *wpa_s = global->ifaces;
968 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800969 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700970 if (wpas_wps_terminate_pending(wpa_s) == 1)
971 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700972#ifdef CONFIG_P2P
973 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
974 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
975 wpas_p2p_disconnect(wpa_s);
976#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800977 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700978 }
979#endif /* CONFIG_WPS */
980 if (pending)
981 return;
982 eloop_terminate();
983}
984
985
986static void wpa_supplicant_terminate(int sig, void *signal_ctx)
987{
988 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989 wpa_supplicant_terminate_proc(global);
990}
991
992
993void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
994{
995 enum wpa_states old_state = wpa_s->wpa_state;
996
997 wpa_s->pairwise_cipher = 0;
998 wpa_s->group_cipher = 0;
999 wpa_s->mgmt_group_cipher = 0;
1000 wpa_s->key_mgmt = 0;
1001 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001002 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003
1004 if (wpa_s->wpa_state != old_state)
1005 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
1006}
1007
1008
1009/**
1010 * wpa_supplicant_reload_configuration - Reload configuration data
1011 * @wpa_s: Pointer to wpa_supplicant data
1012 * Returns: 0 on success or -1 if configuration parsing failed
1013 *
1014 * This function can be used to request that the configuration data is reloaded
1015 * (e.g., after configuration file change). This function is reloading
1016 * configuration only for one interface, so this may need to be called multiple
1017 * times if %wpa_supplicant is controlling multiple interfaces and all
1018 * interfaces need reconfiguration.
1019 */
1020int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1021{
1022 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001023 int reconf_ctrl;
1024 int old_ap_scan;
1025
1026 if (wpa_s->confname == NULL)
1027 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001028 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001029 if (conf == NULL) {
1030 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1031 "file '%s' - exiting", wpa_s->confname);
1032 return -1;
1033 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001034 if (wpa_s->confanother &&
1035 !wpa_config_read(wpa_s->confanother, conf)) {
1036 wpa_msg(wpa_s, MSG_ERROR,
1037 "Failed to parse the configuration file '%s' - exiting",
1038 wpa_s->confanother);
1039 return -1;
1040 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001041
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042 conf->changed_parameters = (unsigned int) -1;
1043
1044 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1045 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1046 os_strcmp(conf->ctrl_interface,
1047 wpa_s->conf->ctrl_interface) != 0);
1048
1049 if (reconf_ctrl && wpa_s->ctrl_iface) {
1050 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1051 wpa_s->ctrl_iface = NULL;
1052 }
1053
1054 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001055 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001056 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1057 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001058 wpa_supplicant_deauthenticate(wpa_s,
1059 WLAN_REASON_DEAUTH_LEAVING);
1060 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001061
1062 /*
1063 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001064 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001065 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001066 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1067 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1068 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069 /*
1070 * Clear forced success to clear EAP state for next
1071 * authentication.
1072 */
1073 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1074 }
1075 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1076 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001077 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001078 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1079 rsn_preauth_deinit(wpa_s->wpa);
1080
1081 old_ap_scan = wpa_s->conf->ap_scan;
1082 wpa_config_free(wpa_s->conf);
1083 wpa_s->conf = conf;
1084 if (old_ap_scan != wpa_s->conf->ap_scan)
1085 wpas_notify_ap_scan_changed(wpa_s);
1086
1087 if (reconf_ctrl)
1088 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1089
1090 wpa_supplicant_update_config(wpa_s);
1091
1092 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001093 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001094 wpa_s->reassociate = 1;
1095 wpa_supplicant_req_scan(wpa_s, 0, 0);
1096 }
1097 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1098 return 0;
1099}
1100
1101
1102static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1103{
1104 struct wpa_global *global = signal_ctx;
1105 struct wpa_supplicant *wpa_s;
1106 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1107 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1108 sig);
1109 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1110 wpa_supplicant_terminate_proc(global);
1111 }
1112 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001113
1114 if (wpa_debug_reopen_file() < 0) {
1115 /* Ignore errors since we cannot really do much to fix this */
1116 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1117 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001118}
1119
1120
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1122 struct wpa_ssid *ssid,
1123 struct wpa_ie_data *ie)
1124{
1125 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1126 if (ret) {
1127 if (ret == -2) {
1128 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1129 "from association info");
1130 }
1131 return -1;
1132 }
1133
1134 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1135 "cipher suites");
1136 if (!(ie->group_cipher & ssid->group_cipher)) {
1137 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1138 "cipher 0x%x (mask 0x%x) - reject",
1139 ie->group_cipher, ssid->group_cipher);
1140 return -1;
1141 }
1142 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1143 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1144 "cipher 0x%x (mask 0x%x) - reject",
1145 ie->pairwise_cipher, ssid->pairwise_cipher);
1146 return -1;
1147 }
1148 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1149 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1150 "management 0x%x (mask 0x%x) - reject",
1151 ie->key_mgmt, ssid->key_mgmt);
1152 return -1;
1153 }
1154
1155#ifdef CONFIG_IEEE80211W
1156 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001157 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001158 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1159 "that does not support management frame protection - "
1160 "reject");
1161 return -1;
1162 }
1163#endif /* CONFIG_IEEE80211W */
1164
1165 return 0;
1166}
1167
1168
1169/**
1170 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1171 * @wpa_s: Pointer to wpa_supplicant data
1172 * @bss: Scan results for the selected BSS, or %NULL if not available
1173 * @ssid: Configuration data for the selected network
1174 * @wpa_ie: Buffer for the WPA/RSN IE
1175 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1176 * used buffer length in case the functions returns success.
1177 * Returns: 0 on success or -1 on failure
1178 *
1179 * This function is used to configure authentication and encryption parameters
1180 * based on the network configuration and scan result for the selected BSS (if
1181 * available).
1182 */
1183int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1184 struct wpa_bss *bss, struct wpa_ssid *ssid,
1185 u8 *wpa_ie, size_t *wpa_ie_len)
1186{
1187 struct wpa_ie_data ie;
1188 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001189 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190
1191 if (bss) {
1192 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1193 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001194 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001195 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001196 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197
1198 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1199 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1200 (ie.group_cipher & ssid->group_cipher) &&
1201 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1202 (ie.key_mgmt & ssid->key_mgmt)) {
1203 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1204 proto = WPA_PROTO_RSN;
1205 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001206 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001207 (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, "WPA: using IEEE 802.11i/D3.0");
1211 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001212#ifdef CONFIG_HS20
1213 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1214 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1215 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001216 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001217 ie.group_cipher = WPA_CIPHER_CCMP;
1218 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1219 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1220 proto = WPA_PROTO_OSEN;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001221 } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
1222 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1223 (ie.group_cipher & ssid->group_cipher) &&
1224 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1225 (ie.key_mgmt & ssid->key_mgmt)) {
1226 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)");
1227 proto = WPA_PROTO_RSN;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001228#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001229 } else if (bss) {
1230 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001231 wpa_dbg(wpa_s, MSG_DEBUG,
1232 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1233 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1234 ssid->key_mgmt);
1235 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1236 MAC2STR(bss->bssid),
1237 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1238 bss_wpa ? " WPA" : "",
1239 bss_rsn ? " RSN" : "",
1240 bss_osen ? " OSEN" : "");
1241 if (bss_rsn) {
1242 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1243 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1244 wpa_dbg(wpa_s, MSG_DEBUG,
1245 "Could not parse RSN element");
1246 } else {
1247 wpa_dbg(wpa_s, MSG_DEBUG,
1248 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1249 ie.pairwise_cipher, ie.group_cipher,
1250 ie.key_mgmt);
1251 }
1252 }
1253 if (bss_wpa) {
1254 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1255 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1256 wpa_dbg(wpa_s, MSG_DEBUG,
1257 "Could not parse WPA element");
1258 } else {
1259 wpa_dbg(wpa_s, MSG_DEBUG,
1260 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1261 ie.pairwise_cipher, ie.group_cipher,
1262 ie.key_mgmt);
1263 }
1264 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001265 return -1;
1266 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001267 if (ssid->proto & WPA_PROTO_OSEN)
1268 proto = WPA_PROTO_OSEN;
1269 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001270 proto = WPA_PROTO_RSN;
1271 else
1272 proto = WPA_PROTO_WPA;
1273 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1274 os_memset(&ie, 0, sizeof(ie));
1275 ie.group_cipher = ssid->group_cipher;
1276 ie.pairwise_cipher = ssid->pairwise_cipher;
1277 ie.key_mgmt = ssid->key_mgmt;
1278#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001279 ie.mgmt_group_cipher = 0;
1280 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1281 if (ssid->group_mgmt_cipher &
1282 WPA_CIPHER_BIP_GMAC_256)
1283 ie.mgmt_group_cipher =
1284 WPA_CIPHER_BIP_GMAC_256;
1285 else if (ssid->group_mgmt_cipher &
1286 WPA_CIPHER_BIP_CMAC_256)
1287 ie.mgmt_group_cipher =
1288 WPA_CIPHER_BIP_CMAC_256;
1289 else if (ssid->group_mgmt_cipher &
1290 WPA_CIPHER_BIP_GMAC_128)
1291 ie.mgmt_group_cipher =
1292 WPA_CIPHER_BIP_GMAC_128;
1293 else
1294 ie.mgmt_group_cipher =
1295 WPA_CIPHER_AES_128_CMAC;
1296 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001297#endif /* CONFIG_IEEE80211W */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001298#ifdef CONFIG_OWE
1299 if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
1300 !ssid->owe_only &&
1301 !bss_wpa && !bss_rsn && !bss_osen) {
1302 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1303 wpa_s->wpa_proto = 0;
1304 *wpa_ie_len = 0;
1305 return 0;
1306 }
1307#endif /* CONFIG_OWE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001308 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1309 "based on configuration");
1310 } else
1311 proto = ie.proto;
1312 }
1313
1314 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1315 "pairwise %d key_mgmt %d proto %d",
1316 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1317#ifdef CONFIG_IEEE80211W
1318 if (ssid->ieee80211w) {
1319 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1320 ie.mgmt_group_cipher);
1321 }
1322#endif /* CONFIG_IEEE80211W */
1323
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001324 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001325 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1326 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001327 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001328
1329 if (bss || !wpa_s->ap_ies_from_associnfo) {
1330 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1331 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1332 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1333 bss_rsn ? 2 + bss_rsn[1] : 0))
1334 return -1;
1335 }
1336
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001337#ifdef CONFIG_NO_WPA
1338 wpa_s->group_cipher = WPA_CIPHER_NONE;
1339 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1340#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001341 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001342 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1343 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001344 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1345 "cipher");
1346 return -1;
1347 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001348 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1349 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001350
1351 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001352 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1353 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001354 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1355 "cipher");
1356 return -1;
1357 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001358 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1359 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001360#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001361
1362 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001363#ifdef CONFIG_SAE
1364 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1365 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1366#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001367 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001368#ifdef CONFIG_SUITEB192
1369 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1370 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1371 wpa_dbg(wpa_s, MSG_DEBUG,
1372 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1373#endif /* CONFIG_SUITEB192 */
1374#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001375 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1376 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1377 wpa_dbg(wpa_s, MSG_DEBUG,
1378 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001379#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001380#ifdef CONFIG_FILS
1381#ifdef CONFIG_IEEE80211R
1382 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1383 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1384 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1385 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1386 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1387 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1388#endif /* CONFIG_IEEE80211R */
1389 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1390 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1391 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1392 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1393 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1394 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1395#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001396#ifdef CONFIG_IEEE80211R
Roshan Pius3a1667e2018-07-03 15:17:14 -07001397#ifdef CONFIG_SHA384
1398 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
1399 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
1400 wpa_dbg(wpa_s, MSG_DEBUG,
1401 "WPA: using KEY_MGMT FT/802.1X-SHA384");
1402 if (pmksa_cache_get_current(wpa_s->wpa)) {
1403 /* PMKSA caching with FT is not fully functional, so
1404 * disable the case for now. */
1405 wpa_dbg(wpa_s, MSG_DEBUG,
1406 "WPA: Disable PMKSA caching for FT/802.1X connection");
1407 pmksa_cache_clear_current(wpa_s->wpa);
1408 }
1409#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001410 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1411 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1412 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001413 if (pmksa_cache_get_current(wpa_s->wpa)) {
1414 /* PMKSA caching with FT is not fully functional, so
1415 * disable the case for now. */
1416 wpa_dbg(wpa_s, MSG_DEBUG,
1417 "WPA: Disable PMKSA caching for FT/802.1X connection");
1418 pmksa_cache_clear_current(wpa_s->wpa);
1419 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1421 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1422 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1423#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001424#ifdef CONFIG_SAE
1425 } else if (sel & WPA_KEY_MGMT_SAE) {
1426 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1427 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1428 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1429 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1430 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1431#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001432#ifdef CONFIG_IEEE80211W
1433 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1434 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1435 wpa_dbg(wpa_s, MSG_DEBUG,
1436 "WPA: using KEY_MGMT 802.1X with SHA256");
1437 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1438 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1439 wpa_dbg(wpa_s, MSG_DEBUG,
1440 "WPA: using KEY_MGMT PSK with SHA256");
1441#endif /* CONFIG_IEEE80211W */
1442 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1443 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1444 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1445 } else if (sel & WPA_KEY_MGMT_PSK) {
1446 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1447 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1448 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1449 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1450 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001451#ifdef CONFIG_HS20
1452 } else if (sel & WPA_KEY_MGMT_OSEN) {
1453 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1454 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1455#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001456#ifdef CONFIG_OWE
1457 } else if (sel & WPA_KEY_MGMT_OWE) {
1458 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1459 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1460#endif /* CONFIG_OWE */
1461#ifdef CONFIG_DPP
1462 } else if (sel & WPA_KEY_MGMT_DPP) {
1463 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1464 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1465#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466 } else {
1467 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1468 "authenticated key management type");
1469 return -1;
1470 }
1471
1472 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1473 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1474 wpa_s->pairwise_cipher);
1475 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1476
1477#ifdef CONFIG_IEEE80211W
1478 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001479 if (ssid->group_mgmt_cipher)
1480 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001481 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001482 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1483 sel = 0;
1484 if (sel & WPA_CIPHER_AES_128_CMAC) {
1485 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1486 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1487 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001488 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1489 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1490 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1491 "BIP-GMAC-128");
1492 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1493 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1494 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1495 "BIP-GMAC-256");
1496 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1497 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1498 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1499 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001500 } else {
1501 wpa_s->mgmt_group_cipher = 0;
1502 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1503 }
1504 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1505 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001506 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001507 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508#endif /* CONFIG_IEEE80211W */
1509
1510 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1511 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1512 return -1;
1513 }
1514
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001515 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001516 int psk_set = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001517 int sae_only;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001518
Roshan Pius3a1667e2018-07-03 15:17:14 -07001519 sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK |
1520 WPA_KEY_MGMT_FT_PSK |
1521 WPA_KEY_MGMT_PSK_SHA256)) == 0;
1522
1523 if (ssid->psk_set && !sae_only) {
1524 wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
1525 ssid->psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001526 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1527 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001528 psk_set = 1;
1529 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001530
Roshan Pius3a1667e2018-07-03 15:17:14 -07001531 if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
1532 (ssid->sae_password || ssid->passphrase))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001533 psk_set = 1;
1534
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001535#ifndef CONFIG_NO_PBKDF2
1536 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001537 ssid->passphrase && !sae_only) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001538 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001539 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1540 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001541 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1542 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001543 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001544 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001545 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001546 }
1547#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001548#ifdef CONFIG_EXT_PASSWORD
Roshan Pius3a1667e2018-07-03 15:17:14 -07001549 if (ssid->ext_psk && !sae_only) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001550 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1551 ssid->ext_psk);
1552 char pw_str[64 + 1];
1553 u8 psk[PMK_LEN];
1554
1555 if (pw == NULL) {
1556 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1557 "found from external storage");
1558 return -1;
1559 }
1560
1561 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1562 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1563 "PSK length %d in external storage",
1564 (int) wpabuf_len(pw));
1565 ext_password_free(pw);
1566 return -1;
1567 }
1568
1569 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1570 pw_str[wpabuf_len(pw)] = '\0';
1571
1572#ifndef CONFIG_NO_PBKDF2
1573 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1574 {
1575 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1576 4096, psk, PMK_LEN);
1577 os_memset(pw_str, 0, sizeof(pw_str));
1578 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1579 "external passphrase)",
1580 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001581 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1582 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001583 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001584 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001585 } else
1586#endif /* CONFIG_NO_PBKDF2 */
1587 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1588 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1589 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1590 "Invalid PSK hex string");
1591 os_memset(pw_str, 0, sizeof(pw_str));
1592 ext_password_free(pw);
1593 return -1;
1594 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001595 wpa_hexdump_key(MSG_MSGDUMP,
1596 "PSK (from external PSK)",
1597 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001598 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1599 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001600 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001601 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001602 } else {
1603 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1604 "PSK available");
1605 os_memset(pw_str, 0, sizeof(pw_str));
1606 ext_password_free(pw);
1607 return -1;
1608 }
1609
1610 os_memset(pw_str, 0, sizeof(pw_str));
1611 ext_password_free(pw);
1612 }
1613#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001614
1615 if (!psk_set) {
1616 wpa_msg(wpa_s, MSG_INFO,
1617 "No PSK available for association");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001618 wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE");
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001619 return -1;
1620 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001621#ifdef CONFIG_OWE
1622 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1623 /* OWE Diffie-Hellman exchange in (Re)Association
1624 * Request/Response frames set the PMK, so do not override it
1625 * here. */
1626#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001627 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001628 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1629
1630 return 0;
1631}
1632
1633
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001634static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1635{
1636 *pos = 0x00;
1637
1638 switch (idx) {
1639 case 0: /* Bits 0-7 */
1640 break;
1641 case 1: /* Bits 8-15 */
1642 break;
1643 case 2: /* Bits 16-23 */
1644#ifdef CONFIG_WNM
1645 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1646 *pos |= 0x08; /* Bit 19 - BSS Transition */
1647#endif /* CONFIG_WNM */
1648 break;
1649 case 3: /* Bits 24-31 */
1650#ifdef CONFIG_WNM
1651 *pos |= 0x02; /* Bit 25 - SSID List */
1652#endif /* CONFIG_WNM */
1653#ifdef CONFIG_INTERWORKING
1654 if (wpa_s->conf->interworking)
1655 *pos |= 0x80; /* Bit 31 - Interworking */
1656#endif /* CONFIG_INTERWORKING */
1657 break;
1658 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001659#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001660 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1661 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001662#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001663 break;
1664 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001665#ifdef CONFIG_HS20
1666 if (wpa_s->conf->hs20)
1667 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1668#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001669#ifdef CONFIG_MBO
1670 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1671#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001672 break;
1673 case 6: /* Bits 48-55 */
1674 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001675 case 7: /* Bits 56-63 */
1676 break;
1677 case 8: /* Bits 64-71 */
1678 if (wpa_s->conf->ftm_responder)
1679 *pos |= 0x40; /* Bit 70 - FTM responder */
1680 if (wpa_s->conf->ftm_initiator)
1681 *pos |= 0x80; /* Bit 71 - FTM initiator */
1682 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001683 case 9: /* Bits 72-79 */
1684#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001685 if (!wpa_s->disable_fils)
1686 *pos |= 0x01;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001687#endif /* CONFIG_FILS */
1688 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001689 }
1690}
1691
1692
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001693int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001694{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001695 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001696 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001697
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001698 if (len < wpa_s->extended_capa_len)
1699 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001700 if (buflen < (size_t) len + 2) {
1701 wpa_printf(MSG_INFO,
1702 "Not enough room for building extended capabilities element");
1703 return -1;
1704 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001705
1706 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001707 *pos++ = len;
1708 for (i = 0; i < len; i++, pos++) {
1709 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001710
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001711 if (i < wpa_s->extended_capa_len) {
1712 *pos &= ~wpa_s->extended_capa_mask[i];
1713 *pos |= wpa_s->extended_capa[i];
1714 }
1715 }
1716
1717 while (len > 0 && buf[1 + len] == 0) {
1718 len--;
1719 buf[1] = len;
1720 }
1721 if (len == 0)
1722 return 0;
1723
1724 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001725}
1726
1727
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001728static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1729 struct wpa_bss *test_bss)
1730{
1731 struct wpa_bss *bss;
1732
1733 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1734 if (bss == test_bss)
1735 return 1;
1736 }
1737
1738 return 0;
1739}
1740
1741
1742static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1743 struct wpa_ssid *test_ssid)
1744{
1745 struct wpa_ssid *ssid;
1746
1747 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1748 if (ssid == test_ssid)
1749 return 1;
1750 }
1751
1752 return 0;
1753}
1754
1755
1756int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1757 struct wpa_ssid *test_ssid)
1758{
1759 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1760 return 0;
1761
1762 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1763}
1764
1765
1766void wpas_connect_work_free(struct wpa_connect_work *cwork)
1767{
1768 if (cwork == NULL)
1769 return;
1770 os_free(cwork);
1771}
1772
1773
1774void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1775{
1776 struct wpa_connect_work *cwork;
1777 struct wpa_radio_work *work = wpa_s->connect_work;
1778
1779 if (!work)
1780 return;
1781
1782 wpa_s->connect_work = NULL;
1783 cwork = work->ctx;
1784 work->ctx = NULL;
1785 wpas_connect_work_free(cwork);
1786 radio_work_done(work);
1787}
1788
1789
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001790int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1791{
1792 struct os_reltime now;
1793 u8 addr[ETH_ALEN];
1794
1795 os_get_reltime(&now);
1796 if (wpa_s->last_mac_addr_style == style &&
1797 wpa_s->last_mac_addr_change.sec != 0 &&
1798 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1799 wpa_s->conf->rand_addr_lifetime)) {
1800 wpa_msg(wpa_s, MSG_DEBUG,
1801 "Previously selected random MAC address has not yet expired");
1802 return 0;
1803 }
1804
1805 switch (style) {
1806 case 1:
1807 if (random_mac_addr(addr) < 0)
1808 return -1;
1809 break;
1810 case 2:
1811 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1812 if (random_mac_addr_keep_oui(addr) < 0)
1813 return -1;
1814 break;
1815 default:
1816 return -1;
1817 }
1818
1819 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1820 wpa_msg(wpa_s, MSG_INFO,
1821 "Failed to set random MAC address");
1822 return -1;
1823 }
1824
1825 os_get_reltime(&wpa_s->last_mac_addr_change);
1826 wpa_s->mac_addr_changed = 1;
1827 wpa_s->last_mac_addr_style = style;
1828
1829 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1830 wpa_msg(wpa_s, MSG_INFO,
1831 "Could not update MAC address information");
1832 return -1;
1833 }
1834
1835 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1836 MAC2STR(addr));
1837
1838 return 0;
1839}
1840
1841
1842int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1843{
1844 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1845 !wpa_s->conf->preassoc_mac_addr)
1846 return 0;
1847
1848 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1849}
1850
1851
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001852static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1853
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001854/**
1855 * wpa_supplicant_associate - Request association
1856 * @wpa_s: Pointer to wpa_supplicant data
1857 * @bss: Scan results for the selected BSS, or %NULL if not available
1858 * @ssid: Configuration data for the selected network
1859 *
1860 * This function is used to request %wpa_supplicant to associate with a BSS.
1861 */
1862void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1863 struct wpa_bss *bss, struct wpa_ssid *ssid)
1864{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001865 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001866 int rand_style;
1867
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001868 wpa_s->own_disconnect_req = 0;
1869
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001870 /*
1871 * If we are starting a new connection, any previously pending EAPOL
1872 * RX cannot be valid anymore.
1873 */
1874 wpabuf_free(wpa_s->pending_eapol_rx);
1875 wpa_s->pending_eapol_rx = NULL;
1876
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001877 if (ssid->mac_addr == -1)
1878 rand_style = wpa_s->conf->mac_addr;
1879 else
1880 rand_style = ssid->mac_addr;
1881
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001882 wmm_ac_clear_saved_tspecs(wpa_s);
1883 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001884 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001885#ifdef CONFIG_TESTING_OPTIONS
1886 wpa_s->testing_resend_assoc = 0;
1887#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001888
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001889 if (wpa_s->last_ssid == ssid) {
1890 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001891 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001892 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1893 wmm_ac_save_tspecs(wpa_s);
1894 wpa_s->reassoc_same_bss = 1;
1895 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001896 }
1897
1898 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001899 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1900 return;
1901 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001902 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001903 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1904 wpa_msg(wpa_s, MSG_INFO,
1905 "Could not restore permanent MAC address");
1906 return;
1907 }
1908 wpa_s->mac_addr_changed = 0;
1909 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1910 wpa_msg(wpa_s, MSG_INFO,
1911 "Could not update MAC address information");
1912 return;
1913 }
1914 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1915 }
1916 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001917
1918#ifdef CONFIG_IBSS_RSN
1919 ibss_rsn_deinit(wpa_s->ibss_rsn);
1920 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001921#else /* CONFIG_IBSS_RSN */
1922 if (ssid->mode == WPAS_MODE_IBSS &&
1923 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1924 wpa_msg(wpa_s, MSG_INFO,
1925 "IBSS RSN not supported in the build");
1926 return;
1927 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001928#endif /* CONFIG_IBSS_RSN */
1929
1930 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1931 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1932#ifdef CONFIG_AP
1933 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1934 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1935 "mode");
1936 return;
1937 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001938 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1939 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001940 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1941 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001942 return;
1943 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001944 wpa_s->current_bss = bss;
1945#else /* CONFIG_AP */
1946 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1947 "the build");
1948#endif /* CONFIG_AP */
1949 return;
1950 }
1951
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001952 if (ssid->mode == WPAS_MODE_MESH) {
1953#ifdef CONFIG_MESH
1954 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1955 wpa_msg(wpa_s, MSG_INFO,
1956 "Driver does not support mesh mode");
1957 return;
1958 }
1959 if (bss)
1960 ssid->frequency = bss->freq;
1961 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1962 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1963 return;
1964 }
1965 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001966 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1967 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1968 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001969 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001970#else /* CONFIG_MESH */
1971 wpa_msg(wpa_s, MSG_ERROR,
1972 "mesh mode support not included in the build");
1973#endif /* CONFIG_MESH */
1974 return;
1975 }
1976
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001977 /*
1978 * Set WPA state machine configuration to match the selected network now
1979 * so that the information is available before wpas_start_assoc_cb()
1980 * gets called. This is needed at least for RSN pre-authentication where
1981 * candidate APs are added to a list based on scan result processing
1982 * before completion of the first association.
1983 */
1984 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
1985
1986#ifdef CONFIG_DPP
1987 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
1988 return;
1989#endif /* CONFIG_DPP */
1990
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001991#ifdef CONFIG_TDLS
1992 if (bss)
1993 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1994 bss->ie_len);
1995#endif /* CONFIG_TDLS */
1996
1997 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1998 ssid->mode == IEEE80211_MODE_INFRA) {
1999 sme_authenticate(wpa_s, bss, ssid);
2000 return;
2001 }
2002
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002003 if (wpa_s->connect_work) {
2004 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
2005 return;
2006 }
2007
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002008 if (radio_work_pending(wpa_s, "connect")) {
2009 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
2010 return;
2011 }
2012
Dmitry Shmidt29333592017-01-09 12:27:11 -08002013#ifdef CONFIG_SME
2014 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
2015 /* Clear possibly set auth_alg, if any, from last attempt. */
2016 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
2017 }
2018#endif /* CONFIG_SME */
2019
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002020 wpas_abort_ongoing_scan(wpa_s);
2021
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002022 cwork = os_zalloc(sizeof(*cwork));
2023 if (cwork == NULL)
2024 return;
2025
2026 cwork->bss = bss;
2027 cwork->ssid = ssid;
2028
2029 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
2030 wpas_start_assoc_cb, cwork) < 0) {
2031 os_free(cwork);
2032 }
2033}
2034
2035
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002036static int bss_is_ibss(struct wpa_bss *bss)
2037{
2038 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
2039 IEEE80211_CAP_IBSS;
2040}
2041
2042
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002043static int drv_supports_vht(struct wpa_supplicant *wpa_s,
2044 const struct wpa_ssid *ssid)
2045{
2046 enum hostapd_hw_mode hw_mode;
2047 struct hostapd_hw_modes *mode = NULL;
2048 u8 channel;
2049 int i;
2050
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002051 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
2052 if (hw_mode == NUM_HOSTAPD_MODES)
2053 return 0;
2054 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2055 if (wpa_s->hw.modes[i].mode == hw_mode) {
2056 mode = &wpa_s->hw.modes[i];
2057 break;
2058 }
2059 }
2060
2061 if (!mode)
2062 return 0;
2063
2064 return mode->vht_capab != 0;
2065}
2066
2067
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002068void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
2069 const struct wpa_ssid *ssid,
2070 struct hostapd_freq_params *freq)
2071{
2072 enum hostapd_hw_mode hw_mode;
2073 struct hostapd_hw_modes *mode = NULL;
2074 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
2075 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002076 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002077 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2078 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002079 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002080 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002081 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002082 int chwidth, seg0, seg1;
2083 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002084
2085 freq->freq = ssid->frequency;
2086
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002087 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2088 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2089
2090 if (ssid->mode != WPAS_MODE_IBSS)
2091 break;
2092
2093 /* Don't adjust control freq in case of fixed_freq */
2094 if (ssid->fixed_freq)
2095 break;
2096
2097 if (!bss_is_ibss(bss))
2098 continue;
2099
2100 if (ssid->ssid_len == bss->ssid_len &&
2101 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2102 wpa_printf(MSG_DEBUG,
2103 "IBSS already found in scan results, adjust control freq: %d",
2104 bss->freq);
2105 freq->freq = bss->freq;
2106 obss_scan = 0;
2107 break;
2108 }
2109 }
2110
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002111 /* For IBSS check HT_IBSS flag */
2112 if (ssid->mode == WPAS_MODE_IBSS &&
2113 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2114 return;
2115
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002116 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2117 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2118 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2119 wpa_printf(MSG_DEBUG,
2120 "IBSS: WEP/TKIP detected, do not try to enable HT");
2121 return;
2122 }
2123
2124 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002125 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2126 if (wpa_s->hw.modes[i].mode == hw_mode) {
2127 mode = &wpa_s->hw.modes[i];
2128 break;
2129 }
2130 }
2131
2132 if (!mode)
2133 return;
2134
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002135#ifdef CONFIG_HT_OVERRIDES
2136 if (ssid->disable_ht) {
2137 freq->ht_enabled = 0;
2138 return;
2139 }
2140#endif /* CONFIG_HT_OVERRIDES */
2141
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002142 freq->ht_enabled = ht_supported(mode);
2143 if (!freq->ht_enabled)
2144 return;
2145
2146 /* Setup higher BW only for 5 GHz */
2147 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2148 return;
2149
2150 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2151 pri_chan = &mode->channels[chan_idx];
2152 if (pri_chan->chan == channel)
2153 break;
2154 pri_chan = NULL;
2155 }
2156 if (!pri_chan)
2157 return;
2158
2159 /* Check primary channel flags */
2160 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2161 return;
2162
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002163#ifdef CONFIG_HT_OVERRIDES
2164 if (ssid->disable_ht40)
2165 return;
2166#endif /* CONFIG_HT_OVERRIDES */
2167
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002168 /* Check/setup HT40+/HT40- */
2169 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2170 if (ht40plus[j] == channel) {
2171 ht40 = 1;
2172 break;
2173 }
2174 }
2175
2176 /* Find secondary channel */
2177 for (i = 0; i < mode->num_channels; i++) {
2178 sec_chan = &mode->channels[i];
2179 if (sec_chan->chan == channel + ht40 * 4)
2180 break;
2181 sec_chan = NULL;
2182 }
2183 if (!sec_chan)
2184 return;
2185
2186 /* Check secondary channel flags */
2187 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2188 return;
2189
2190 freq->channel = pri_chan->chan;
2191
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002192 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002193 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2194 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002195 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002196 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2197 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002198 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002199 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002200
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002201 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002202 struct wpa_scan_results *scan_res;
2203
2204 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2205 if (scan_res == NULL) {
2206 /* Back to HT20 */
2207 freq->sec_channel_offset = 0;
2208 return;
2209 }
2210
2211 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2212 sec_chan->chan);
2213 switch (res) {
2214 case 0:
2215 /* Back to HT20 */
2216 freq->sec_channel_offset = 0;
2217 break;
2218 case 1:
2219 /* Configuration allowed */
2220 break;
2221 case 2:
2222 /* Switch pri/sec channels */
2223 freq->freq = hw_get_freq(mode, sec_chan->chan);
2224 freq->sec_channel_offset = -freq->sec_channel_offset;
2225 freq->channel = sec_chan->chan;
2226 break;
2227 default:
2228 freq->sec_channel_offset = 0;
2229 break;
2230 }
2231
2232 wpa_scan_results_free(scan_res);
2233 }
2234
2235 wpa_printf(MSG_DEBUG,
2236 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2237 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002238
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002239 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002240 return;
2241
2242 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002243 if (ssid->mode == WPAS_MODE_IBSS &&
2244 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002245 return;
2246
2247 vht_freq = *freq;
2248
Paul Stewart092955c2017-02-06 09:13:09 -08002249#ifdef CONFIG_VHT_OVERRIDES
2250 if (ssid->disable_vht) {
2251 freq->vht_enabled = 0;
2252 return;
2253 }
2254#endif /* CONFIG_VHT_OVERRIDES */
2255
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002256 vht_freq.vht_enabled = vht_supported(mode);
2257 if (!vht_freq.vht_enabled)
2258 return;
2259
2260 /* setup center_freq1, bandwidth */
2261 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2262 if (freq->channel >= vht80[j] &&
2263 freq->channel < vht80[j] + 16)
2264 break;
2265 }
2266
2267 if (j == ARRAY_SIZE(vht80))
2268 return;
2269
2270 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2271 struct hostapd_channel_data *chan;
2272
2273 chan = hw_get_channel_chan(mode, i, NULL);
2274 if (!chan)
2275 return;
2276
2277 /* Back to HT configuration if channel not usable */
2278 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2279 return;
2280 }
2281
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002282 chwidth = VHT_CHANWIDTH_80MHZ;
2283 seg0 = vht80[j] + 6;
2284 seg1 = 0;
2285
2286 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2287 /* setup center_freq2, bandwidth */
2288 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2289 /* Only accept 80 MHz segments separated by a gap */
2290 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2291 continue;
2292 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2293 struct hostapd_channel_data *chan;
2294
2295 chan = hw_get_channel_chan(mode, i, NULL);
2296 if (!chan)
2297 continue;
2298
2299 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2300 HOSTAPD_CHAN_NO_IR |
2301 HOSTAPD_CHAN_RADAR))
2302 continue;
2303
2304 /* Found a suitable second segment for 80+80 */
2305 chwidth = VHT_CHANWIDTH_80P80MHZ;
2306 vht_caps |=
2307 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2308 seg1 = vht80[k] + 6;
2309 }
2310
2311 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2312 break;
2313 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002314 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2315 if (freq->freq == 5180) {
2316 chwidth = VHT_CHANWIDTH_160MHZ;
2317 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2318 seg0 = 50;
2319 } else if (freq->freq == 5520) {
2320 chwidth = VHT_CHANWIDTH_160MHZ;
2321 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2322 seg0 = 114;
2323 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002324 }
2325
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002326 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2327 freq->channel, freq->ht_enabled,
2328 vht_freq.vht_enabled,
2329 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002330 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002331 return;
2332
2333 *freq = vht_freq;
2334
2335 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2336 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002337}
2338
2339
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002340#ifdef CONFIG_FILS
2341static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2342 size_t ie_buf_len)
2343{
2344 struct fils_hlp_req *req;
2345 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2346 const u8 *pos;
2347 u8 *buf = ie_buf;
2348
2349 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2350 list) {
2351 rem_len = ie_buf_len - ie_len;
2352 pos = wpabuf_head(req->pkt);
2353 hdr_len = 1 + 2 * ETH_ALEN + 6;
2354 hlp_len = wpabuf_len(req->pkt);
2355
2356 if (rem_len < 2 + hdr_len + hlp_len) {
2357 wpa_printf(MSG_ERROR,
2358 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2359 (unsigned long) rem_len,
2360 (unsigned long) (2 + hdr_len + hlp_len));
2361 break;
2362 }
2363
2364 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2365 /* Element ID */
2366 *buf++ = WLAN_EID_EXTENSION;
2367 /* Length */
2368 *buf++ = len;
2369 /* Element ID Extension */
2370 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2371 /* Destination MAC address */
2372 os_memcpy(buf, req->dst, ETH_ALEN);
2373 buf += ETH_ALEN;
2374 /* Source MAC address */
2375 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2376 buf += ETH_ALEN;
2377 /* LLC/SNAP Header */
2378 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2379 buf += 6;
2380 /* HLP Packet */
2381 os_memcpy(buf, pos, len - hdr_len);
2382 buf += len - hdr_len;
2383 pos += len - hdr_len;
2384
2385 hlp_len -= len - hdr_len;
2386 ie_len += 2 + len;
2387 rem_len -= 2 + len;
2388
2389 while (hlp_len) {
2390 len = (hlp_len > 255) ? 255 : hlp_len;
2391 if (rem_len < 2 + len)
2392 break;
2393 *buf++ = WLAN_EID_FRAGMENT;
2394 *buf++ = len;
2395 os_memcpy(buf, pos, len);
2396 buf += len;
2397 pos += len;
2398
2399 hlp_len -= len;
2400 ie_len += 2 + len;
2401 rem_len -= 2 + len;
2402 }
2403 }
2404
2405 return ie_len;
2406}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002407
2408
2409int wpa_is_fils_supported(struct wpa_supplicant *wpa_s)
2410{
2411 return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2412 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) ||
2413 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2414 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)));
2415}
2416
2417
2418int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s)
2419{
2420#ifdef CONFIG_FILS_SK_PFS
2421 return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
2422 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS);
2423#else /* CONFIG_FILS_SK_PFS */
2424 return 0;
2425#endif /* CONFIG_FILS_SK_PFS */
2426}
2427
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002428#endif /* CONFIG_FILS */
2429
2430
2431static u8 * wpas_populate_assoc_ies(
2432 struct wpa_supplicant *wpa_s,
2433 struct wpa_bss *bss, struct wpa_ssid *ssid,
2434 struct wpa_driver_associate_params *params,
2435 enum wpa_drv_update_connect_params_mask *mask)
2436{
2437 u8 *wpa_ie;
2438 size_t max_wpa_ie_len = 500;
2439 size_t wpa_ie_len;
2440 int algs = WPA_AUTH_ALG_OPEN;
2441#ifdef CONFIG_FILS
2442 const u8 *realm, *username, *rrk;
2443 size_t realm_len, username_len, rrk_len;
2444 u16 next_seq_num;
2445 struct fils_hlp_req *req;
2446
2447 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2448 list) {
2449 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2450 2 + 2 * wpabuf_len(req->pkt) / 255;
2451 }
2452#endif /* CONFIG_FILS */
2453
2454 wpa_ie = os_malloc(max_wpa_ie_len);
2455 if (!wpa_ie) {
2456 wpa_printf(MSG_ERROR,
2457 "Failed to allocate connect IE buffer for %lu bytes",
2458 (unsigned long) max_wpa_ie_len);
2459 return NULL;
2460 }
2461
2462 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2463 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2464 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2465 int try_opportunistic;
2466 const u8 *cache_id = NULL;
2467
2468 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2469 wpa_s->conf->okc :
2470 ssid->proactive_key_caching) &&
2471 (ssid->proto & WPA_PROTO_RSN);
2472#ifdef CONFIG_FILS
2473 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2474 cache_id = wpa_bss_get_fils_cache_id(bss);
2475#endif /* CONFIG_FILS */
2476 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2477 ssid, try_opportunistic,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002478 cache_id, 0) == 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002479 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
2480 wpa_ie_len = max_wpa_ie_len;
2481 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2482 wpa_ie, &wpa_ie_len)) {
2483 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2484 "key management and encryption suites");
2485 os_free(wpa_ie);
2486 return NULL;
2487 }
2488 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2489 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2490 /*
2491 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2492 * use non-WPA since the scan results did not indicate that the
2493 * AP is using WPA or WPA2.
2494 */
2495 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2496 wpa_ie_len = 0;
2497 wpa_s->wpa_proto = 0;
2498 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2499 wpa_ie_len = max_wpa_ie_len;
2500 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2501 wpa_ie, &wpa_ie_len)) {
2502 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2503 "key management and encryption suites (no "
2504 "scan results)");
2505 os_free(wpa_ie);
2506 return NULL;
2507 }
2508#ifdef CONFIG_WPS
2509 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2510 struct wpabuf *wps_ie;
2511 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2512 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2513 wpa_ie_len = wpabuf_len(wps_ie);
2514 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2515 } else
2516 wpa_ie_len = 0;
2517 wpabuf_free(wps_ie);
2518 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2519 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2520 params->wps = WPS_MODE_PRIVACY;
2521 else
2522 params->wps = WPS_MODE_OPEN;
2523 wpa_s->wpa_proto = 0;
2524#endif /* CONFIG_WPS */
2525 } else {
2526 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2527 wpa_ie_len = 0;
2528 wpa_s->wpa_proto = 0;
2529 }
2530
2531#ifdef IEEE8021X_EAPOL
2532 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2533 if (ssid->leap) {
2534 if (ssid->non_leap == 0)
2535 algs = WPA_AUTH_ALG_LEAP;
2536 else
2537 algs |= WPA_AUTH_ALG_LEAP;
2538 }
2539 }
2540
2541#ifdef CONFIG_FILS
2542 /* Clear FILS association */
2543 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2544
2545 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2546 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2547 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2548 &username_len, &realm, &realm_len,
2549 &next_seq_num, &rrk, &rrk_len) == 0) {
2550 algs = WPA_AUTH_ALG_FILS;
2551 params->fils_erp_username = username;
2552 params->fils_erp_username_len = username_len;
2553 params->fils_erp_realm = realm;
2554 params->fils_erp_realm_len = realm_len;
2555 params->fils_erp_next_seq_num = next_seq_num;
2556 params->fils_erp_rrk = rrk;
2557 params->fils_erp_rrk_len = rrk_len;
2558
2559 if (mask)
2560 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2561 }
2562#endif /* CONFIG_FILS */
2563#endif /* IEEE8021X_EAPOL */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002564#ifdef CONFIG_SAE
2565 if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
2566 algs = WPA_AUTH_ALG_SAE;
2567#endif /* CONFIG_SAE */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002568
2569 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2570 if (ssid->auth_alg) {
2571 algs = ssid->auth_alg;
2572 wpa_dbg(wpa_s, MSG_DEBUG,
2573 "Overriding auth_alg selection: 0x%x", algs);
2574 }
2575
2576#ifdef CONFIG_P2P
2577 if (wpa_s->global->p2p) {
2578 u8 *pos;
2579 size_t len;
2580 int res;
2581 pos = wpa_ie + wpa_ie_len;
2582 len = max_wpa_ie_len - wpa_ie_len;
2583 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2584 ssid->p2p_group);
2585 if (res >= 0)
2586 wpa_ie_len += res;
2587 }
2588
2589 wpa_s->cross_connect_disallowed = 0;
2590 if (bss) {
2591 struct wpabuf *p2p;
2592 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2593 if (p2p) {
2594 wpa_s->cross_connect_disallowed =
2595 p2p_get_cross_connect_disallowed(p2p);
2596 wpabuf_free(p2p);
2597 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2598 "connection",
2599 wpa_s->cross_connect_disallowed ?
2600 "disallows" : "allows");
2601 }
2602 }
2603
2604 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2605#endif /* CONFIG_P2P */
2606
2607 if (bss) {
2608 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
2609 wpa_ie + wpa_ie_len,
2610 max_wpa_ie_len -
2611 wpa_ie_len);
2612 }
2613
2614 /*
2615 * Workaround: Add Extended Capabilities element only if the AP
2616 * included this element in Beacon/Probe Response frames. Some older
2617 * APs seem to have interoperability issues if this element is
2618 * included, so while the standard may require us to include the
2619 * element in all cases, it is justifiable to skip it to avoid
2620 * interoperability issues.
2621 */
2622 if (ssid->p2p_group)
2623 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2624 else
2625 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2626
2627 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2628 u8 ext_capab[18];
2629 int ext_capab_len;
2630 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2631 sizeof(ext_capab));
2632 if (ext_capab_len > 0 &&
2633 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2634 u8 *pos = wpa_ie;
2635 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2636 pos += 2 + pos[1];
2637 os_memmove(pos + ext_capab_len, pos,
2638 wpa_ie_len - (pos - wpa_ie));
2639 wpa_ie_len += ext_capab_len;
2640 os_memcpy(pos, ext_capab, ext_capab_len);
2641 }
2642 }
2643
2644#ifdef CONFIG_HS20
2645 if (is_hs20_network(wpa_s, ssid, bss)) {
2646 struct wpabuf *hs20;
2647
Roshan Pius3a1667e2018-07-03 15:17:14 -07002648 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002649 if (hs20) {
2650 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2651 size_t len;
2652
2653 wpas_hs20_add_indication(hs20, pps_mo_id);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002654 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002655 len = max_wpa_ie_len - wpa_ie_len;
2656 if (wpabuf_len(hs20) <= len) {
2657 os_memcpy(wpa_ie + wpa_ie_len,
2658 wpabuf_head(hs20), wpabuf_len(hs20));
2659 wpa_ie_len += wpabuf_len(hs20);
2660 }
2661 wpabuf_free(hs20);
2662
2663 hs20_configure_frame_filters(wpa_s);
2664 }
2665 }
2666#endif /* CONFIG_HS20 */
2667
2668 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2669 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2670 size_t len;
2671
2672 len = max_wpa_ie_len - wpa_ie_len;
2673 if (wpabuf_len(buf) <= len) {
2674 os_memcpy(wpa_ie + wpa_ie_len,
2675 wpabuf_head(buf), wpabuf_len(buf));
2676 wpa_ie_len += wpabuf_len(buf);
2677 }
2678 }
2679
2680#ifdef CONFIG_FST
2681 if (wpa_s->fst_ies) {
2682 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2683
2684 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
2685 os_memcpy(wpa_ie + wpa_ie_len,
2686 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2687 wpa_ie_len += fst_ies_len;
2688 }
2689 }
2690#endif /* CONFIG_FST */
2691
2692#ifdef CONFIG_MBO
2693 if (bss && wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
2694 int len;
2695
2696 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2697 max_wpa_ie_len - wpa_ie_len);
2698 if (len >= 0)
2699 wpa_ie_len += len;
2700 }
2701#endif /* CONFIG_MBO */
2702
2703#ifdef CONFIG_FILS
2704 if (algs == WPA_AUTH_ALG_FILS) {
2705 size_t len;
2706
2707 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
2708 max_wpa_ie_len - wpa_ie_len);
2709 wpa_ie_len += len;
2710 }
2711#endif /* CONFIG_FILS */
2712
2713#ifdef CONFIG_OWE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002714#ifdef CONFIG_TESTING_OPTIONS
2715 if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
2716 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2717 } else
2718#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002719 if (algs == WPA_AUTH_ALG_OPEN &&
2720 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
2721 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002722 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002723
Roshan Pius3a1667e2018-07-03 15:17:14 -07002724 if (ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002725 group = ssid->owe_group;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002726 } else {
2727 if (wpa_s->last_owe_group == 19)
2728 group = 20;
2729 else if (wpa_s->last_owe_group == 20)
2730 group = 21;
2731 else
2732 group = OWE_DH_GROUP;
2733 }
2734 wpa_s->last_owe_group = group;
2735 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002736 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2737 if (owe_ie &&
2738 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
2739 os_memcpy(wpa_ie + wpa_ie_len,
2740 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2741 wpa_ie_len += wpabuf_len(owe_ie);
2742 wpabuf_free(owe_ie);
2743 }
2744 }
2745#endif /* CONFIG_OWE */
2746
Roshan Pius3a1667e2018-07-03 15:17:14 -07002747#ifdef CONFIG_IEEE80211R
2748 /*
2749 * Add MDIE under these conditions: the network profile allows FT,
2750 * the AP supports FT, and the mobility domain ID matches.
2751 */
2752 if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) {
2753 const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2754
2755 if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
2756 size_t len = 0;
2757 const u8 *md = mdie + 2;
2758 const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa);
2759
2760 if (os_memcmp(md, wpa_md,
2761 MOBILITY_DOMAIN_ID_LEN) == 0) {
2762 /* Add mobility domain IE */
2763 len = wpa_ft_add_mdie(
2764 wpa_s->wpa, wpa_ie + wpa_ie_len,
2765 max_wpa_ie_len - wpa_ie_len, mdie);
2766 wpa_ie_len += len;
2767 }
2768#ifdef CONFIG_SME
2769 if (len > 0 && wpa_s->sme.ft_used &&
2770 wpa_sm_has_ptk(wpa_s->wpa)) {
2771 wpa_dbg(wpa_s, MSG_DEBUG,
2772 "SME: Trying to use FT over-the-air");
2773 algs |= WPA_AUTH_ALG_FT;
2774 }
2775#endif /* CONFIG_SME */
2776 }
2777 }
2778#endif /* CONFIG_IEEE80211R */
2779
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002780 params->wpa_ie = wpa_ie;
2781 params->wpa_ie_len = wpa_ie_len;
2782 params->auth_alg = algs;
2783 if (mask)
2784 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
2785
2786 return wpa_ie;
2787}
2788
2789
2790#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
2791static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
2792{
2793 struct wpa_driver_associate_params params;
2794 enum wpa_drv_update_connect_params_mask mask = 0;
2795 u8 *wpa_ie;
2796
2797 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
2798 return; /* nothing to do */
2799
2800 os_memset(&params, 0, sizeof(params));
2801 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
2802 wpa_s->current_ssid, &params, &mask);
2803 if (!wpa_ie)
2804 return;
2805
2806 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
2807 os_free(wpa_ie);
2808 return;
2809 }
2810
2811 wpa_s->auth_alg = params.auth_alg;
2812 wpa_drv_update_connect_params(wpa_s, &params, mask);
2813 os_free(wpa_ie);
2814}
2815#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
2816
2817
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002818static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2819{
2820 struct wpa_connect_work *cwork = work->ctx;
2821 struct wpa_bss *bss = cwork->bss;
2822 struct wpa_ssid *ssid = cwork->ssid;
2823 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002824 u8 *wpa_ie;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002825 int use_crypt, ret, i, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002826 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002827 struct wpa_driver_associate_params params;
2828 int wep_keys_set = 0;
2829 int assoc_failed = 0;
2830 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002831 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002832#ifdef CONFIG_HT_OVERRIDES
2833 struct ieee80211_ht_capabilities htcaps;
2834 struct ieee80211_ht_capabilities htcaps_mask;
2835#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002836#ifdef CONFIG_VHT_OVERRIDES
2837 struct ieee80211_vht_capabilities vhtcaps;
2838 struct ieee80211_vht_capabilities vhtcaps_mask;
2839#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002840
2841 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002842 if (work->started) {
2843 wpa_s->connect_work = NULL;
2844
2845 /* cancel possible auth. timeout */
2846 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2847 NULL);
2848 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002849 wpas_connect_work_free(cwork);
2850 return;
2851 }
2852
2853 wpa_s->connect_work = work;
2854
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002855 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2856 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002857 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2858 wpas_connect_work_done(wpa_s);
2859 return;
2860 }
2861
Dmitry Shmidte4663042016-04-04 10:07:49 -07002862 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002863 os_memset(&params, 0, sizeof(params));
2864 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002865 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002866 if (bss &&
2867 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002868#ifdef CONFIG_IEEE80211R
2869 const u8 *ie, *md = NULL;
2870#endif /* CONFIG_IEEE80211R */
2871 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2872 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2873 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2874 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2875 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2876 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2877 if (bssid_changed)
2878 wpas_notify_bssid_changed(wpa_s);
2879#ifdef CONFIG_IEEE80211R
2880 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2881 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2882 md = ie + 2;
2883 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2884 if (md) {
2885 /* Prepare for the next transition */
2886 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2887 }
2888#endif /* CONFIG_IEEE80211R */
2889#ifdef CONFIG_WPS
2890 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2891 wpa_s->conf->ap_scan == 2 &&
2892 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2893 /* Use ap_scan==1 style network selection to find the network
2894 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002895 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002896 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002897 wpa_s->reassociate = 1;
2898 wpa_supplicant_req_scan(wpa_s, 0, 0);
2899 return;
2900#endif /* CONFIG_WPS */
2901 } else {
2902 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2903 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002904 if (bss)
2905 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2906 else
2907 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002909 if (!wpa_s->pno)
2910 wpa_supplicant_cancel_sched_scan(wpa_s);
2911
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002912 wpa_supplicant_cancel_scan(wpa_s);
2913
2914 /* Starting new association, so clear the possibly used WPA IE from the
2915 * previous association. */
2916 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2917
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002918 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
2919 if (!wpa_ie) {
2920 wpas_connect_work_done(wpa_s);
2921 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002922 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002923
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2925 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002926 cipher_pairwise = wpa_s->pairwise_cipher;
2927 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002928 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002929 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2930 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2931 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2932 use_crypt = 0;
2933 if (wpa_set_wep_keys(wpa_s, ssid)) {
2934 use_crypt = 1;
2935 wep_keys_set = 1;
2936 }
2937 }
2938 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2939 use_crypt = 0;
2940
2941#ifdef IEEE8021X_EAPOL
2942 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2943 if ((ssid->eapol_flags &
2944 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2945 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2946 !wep_keys_set) {
2947 use_crypt = 0;
2948 } else {
2949 /* Assume that dynamic WEP-104 keys will be used and
2950 * set cipher suites in order for drivers to expect
2951 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002952 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002953 }
2954 }
2955#endif /* IEEE8021X_EAPOL */
2956
2957 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2958 /* Set the key before (and later after) association */
2959 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2960 }
2961
2962 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2963 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964 params.ssid = bss->ssid;
2965 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002966 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2967 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002968 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2969 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002970 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002971 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002972 ssid->bssid_set,
2973 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002974 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002975 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002976 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002977 params.bssid_hint = bss->bssid;
2978 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002979 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002981 if (ssid->bssid_hint_set)
2982 params.bssid_hint = ssid->bssid_hint;
2983
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002984 params.ssid = ssid->ssid;
2985 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002986 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002987 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002988
2989 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2990 wpa_s->conf->ap_scan == 2) {
2991 params.bssid = ssid->bssid;
2992 params.fixed_bssid = 1;
2993 }
2994
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002995 /* Initial frequency for IBSS/mesh */
2996 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002997 ssid->frequency > 0 && params.freq.freq == 0)
2998 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002999
3000 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003001 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003002 if (ssid->beacon_int)
3003 params.beacon_int = ssid->beacon_int;
3004 else
3005 params.beacon_int = wpa_s->conf->beacon_int;
3006 }
3007
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003008 params.pairwise_suite = cipher_pairwise;
3009 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003010 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003011 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003012 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003013 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003014 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003015 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003016 for (i = 0; i < NUM_WEP_KEYS; i++) {
3017 if (ssid->wep_key_len[i])
3018 params.wep_key[i] = ssid->wep_key[i];
3019 params.wep_key_len[i] = ssid->wep_key_len[i];
3020 }
3021 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
3022
3023 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003024 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3025 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003026 params.passphrase = ssid->passphrase;
3027 if (ssid->psk_set)
3028 params.psk = ssid->psk;
3029 }
3030
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003031 if (wpa_s->conf->key_mgmt_offload) {
3032 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
3033 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003034 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
3035 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003036 params.req_key_mgmt_offload =
3037 ssid->proactive_key_caching < 0 ?
3038 wpa_s->conf->okc : ssid->proactive_key_caching;
3039 else
3040 params.req_key_mgmt_offload = 1;
3041
3042 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
3043 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
3044 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
3045 ssid->psk_set)
3046 params.psk = ssid->psk;
3047 }
3048
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003049 params.drop_unencrypted = use_crypt;
3050
3051#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003052 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003053 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003054 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3055 struct wpa_ie_data ie;
3056 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
3057 ie.capabilities &
3058 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
3059 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
3060 "MFP: require MFP");
3061 params.mgmt_frame_protection =
3062 MGMT_FRAME_PROTECTION_REQUIRED;
3063 }
3064 }
3065#endif /* CONFIG_IEEE80211W */
3066
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003067 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003068
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003069 if (wpa_s->p2pdev->set_sta_uapsd)
3070 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003071 else
3072 params.uapsd = -1;
3073
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003074#ifdef CONFIG_HT_OVERRIDES
3075 os_memset(&htcaps, 0, sizeof(htcaps));
3076 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
3077 params.htcaps = (u8 *) &htcaps;
3078 params.htcaps_mask = (u8 *) &htcaps_mask;
3079 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
3080#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003081#ifdef CONFIG_VHT_OVERRIDES
3082 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
3083 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
3084 params.vhtcaps = &vhtcaps;
3085 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003086 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003087#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003088
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003089#ifdef CONFIG_P2P
3090 /*
3091 * If multi-channel concurrency is not supported, check for any
3092 * frequency conflict. In case of any frequency conflict, remove the
3093 * least prioritized connection.
3094 */
3095 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003096 int freq, num;
3097 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003098 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07003099 wpa_printf(MSG_DEBUG,
3100 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003101 freq, params.freq.freq);
3102 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003103 wpa_s, params.freq.freq, ssid) < 0) {
3104 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003105 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003106 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003107 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003108 }
3109 }
3110#endif /* CONFIG_P2P */
3111
Dmitry Shmidte4663042016-04-04 10:07:49 -07003112 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
3113 wpa_s->current_ssid)
3114 params.prev_bssid = prev_bssid;
3115
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003116 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003117 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003118 if (ret < 0) {
3119 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
3120 "failed");
3121 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
3122 /*
3123 * The driver is known to mean what is saying, so we
3124 * can stop right here; the association will not
3125 * succeed.
3126 */
3127 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003128 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003129 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
3130 return;
3131 }
3132 /* try to continue anyway; new association will be tried again
3133 * after timeout */
3134 assoc_failed = 1;
3135 }
3136
3137 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
3138 /* Set the key after the association just in case association
3139 * cleared the previously configured key. */
3140 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
3141 /* No need to timeout authentication since there is no key
3142 * management. */
3143 wpa_supplicant_cancel_auth_timeout(wpa_s);
3144 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
3145#ifdef CONFIG_IBSS_RSN
3146 } else if (ssid->mode == WPAS_MODE_IBSS &&
3147 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
3148 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
3149 /*
3150 * RSN IBSS authentication is per-STA and we can disable the
3151 * per-BSSID authentication.
3152 */
3153 wpa_supplicant_cancel_auth_timeout(wpa_s);
3154#endif /* CONFIG_IBSS_RSN */
3155 } else {
3156 /* Timeout for IEEE 802.11 authentication and association */
3157 int timeout = 60;
3158
3159 if (assoc_failed) {
3160 /* give IBSS a bit more time */
3161 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3162 } else if (wpa_s->conf->ap_scan == 1) {
3163 /* give IBSS a bit more time */
3164 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3165 }
3166 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3167 }
3168
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003169 if (wep_keys_set &&
3170 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003171 /* Set static WEP keys again */
3172 wpa_set_wep_keys(wpa_s, ssid);
3173 }
3174
3175 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3176 /*
3177 * Do not allow EAP session resumption between different
3178 * network configurations.
3179 */
3180 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3181 }
3182 old_ssid = wpa_s->current_ssid;
3183 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003184
3185 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003186 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003187#ifdef CONFIG_HS20
3188 hs20_configure_frame_filters(wpa_s);
3189#endif /* CONFIG_HS20 */
3190 }
3191
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003192 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3193 wpa_supplicant_initiate_eapol(wpa_s);
3194 if (old_ssid != wpa_s->current_ssid)
3195 wpas_notify_network_changed(wpa_s);
3196}
3197
3198
3199static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3200 const u8 *addr)
3201{
3202 struct wpa_ssid *old_ssid;
3203
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003204 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003205 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003206 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003207 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003208 wpa_sm_set_config(wpa_s->wpa, NULL);
3209 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3210 if (old_ssid != wpa_s->current_ssid)
3211 wpas_notify_network_changed(wpa_s);
3212 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3213}
3214
3215
3216/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003217 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3218 * @wpa_s: Pointer to wpa_supplicant data
3219 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3220 *
3221 * This function is used to request %wpa_supplicant to deauthenticate from the
3222 * current AP.
3223 */
3224void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
3225 int reason_code)
3226{
3227 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003228 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003229 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003230
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003231 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
3232 " pending_bssid=" MACSTR " reason=%d state=%s",
3233 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
3234 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
3235
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003236 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3237 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3238 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003239 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003240 else if (!is_zero_ether_addr(wpa_s->bssid))
3241 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003242 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3243 /*
3244 * When using driver-based BSS selection, we may not know the
3245 * BSSID with which we are currently trying to associate. We
3246 * need to notify the driver of this disconnection even in such
3247 * a case, so use the all zeros address here.
3248 */
3249 addr = wpa_s->bssid;
3250 zero_addr = 1;
3251 }
3252
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003253#ifdef CONFIG_TDLS
3254 wpa_tdls_teardown_peers(wpa_s->wpa);
3255#endif /* CONFIG_TDLS */
3256
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003257#ifdef CONFIG_MESH
3258 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003259 struct mesh_conf *mconf;
3260
3261 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003262 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3263 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003264 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3265 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003266 wpa_supplicant_leave_mesh(wpa_s);
3267 }
3268#endif /* CONFIG_MESH */
3269
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003270 if (addr) {
3271 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003272 os_memset(&event, 0, sizeof(event));
3273 event.deauth_info.reason_code = (u16) reason_code;
3274 event.deauth_info.locally_generated = 1;
3275 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003276 if (zero_addr)
3277 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003278 }
3279
3280 wpa_supplicant_clear_connection(wpa_s, addr);
3281}
3282
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003283static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3284 struct wpa_ssid *ssid)
3285{
3286 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3287 return;
3288
3289 ssid->disabled = 0;
3290 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3291 wpas_notify_network_enabled_changed(wpa_s, ssid);
3292
3293 /*
3294 * Try to reassociate since there is no current configuration and a new
3295 * network was made available.
3296 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003297 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003298 wpa_s->reassociate = 1;
3299}
3300
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003301
Roshan Pius950bec92016-07-19 09:49:24 -07003302/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003303 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003304 * @wpa_s: wpa_supplicant structure for a network interface
3305 * Returns: The new network configuration or %NULL if operation failed
3306 *
3307 * This function performs the following operations:
3308 * 1. Adds a new network.
3309 * 2. Send network addition notification.
3310 * 3. Marks the network disabled.
3311 * 4. Set network default parameters.
3312 */
3313struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3314{
3315 struct wpa_ssid *ssid;
3316
3317 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003318 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003319 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003320 wpas_notify_network_added(wpa_s, ssid);
3321 ssid->disabled = 1;
3322 wpa_config_set_network_defaults(ssid);
3323
3324 return ssid;
3325}
3326
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003327
Roshan Pius950bec92016-07-19 09:49:24 -07003328/**
3329 * wpa_supplicant_remove_network - Remove a configured network based on id
3330 * @wpa_s: wpa_supplicant structure for a network interface
3331 * @id: Unique network id to search for
3332 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3333 * could not be removed
3334 *
3335 * This function performs the following operations:
3336 * 1. Removes the network.
3337 * 2. Send network removal notification.
3338 * 3. Update internal state machines.
3339 * 4. Stop any running sched scans.
3340 */
3341int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
3342{
3343 struct wpa_ssid *ssid;
3344 int was_disabled;
3345
3346 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003347 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003348 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003349 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07003350
3351 if (wpa_s->last_ssid == ssid)
3352 wpa_s->last_ssid = NULL;
3353
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003354 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07003355#ifdef CONFIG_SME
3356 wpa_s->sme.prev_bssid_set = 0;
3357#endif /* CONFIG_SME */
3358 /*
3359 * Invalidate the EAP session cache if the current or
3360 * previously used network is removed.
3361 */
3362 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3363 }
3364
3365 if (ssid == wpa_s->current_ssid) {
3366 wpa_sm_set_config(wpa_s->wpa, NULL);
3367 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3368
3369 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3370 wpa_s->own_disconnect_req = 1;
3371 wpa_supplicant_deauthenticate(wpa_s,
3372 WLAN_REASON_DEAUTH_LEAVING);
3373 }
3374
3375 was_disabled = ssid->disabled;
3376
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003377 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07003378 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07003379
3380 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003381 wpa_printf(MSG_DEBUG,
3382 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07003383 wpa_supplicant_cancel_sched_scan(wpa_s);
3384 wpa_supplicant_req_scan(wpa_s, 0, 0);
3385 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003386
Roshan Pius950bec92016-07-19 09:49:24 -07003387 return 0;
3388}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003389
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003390
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003391/**
3392 * wpa_supplicant_enable_network - Mark a configured network as enabled
3393 * @wpa_s: wpa_supplicant structure for a network interface
3394 * @ssid: wpa_ssid structure for a configured network or %NULL
3395 *
3396 * Enables the specified network or all networks if no network specified.
3397 */
3398void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
3399 struct wpa_ssid *ssid)
3400{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003402 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3403 wpa_supplicant_enable_one_network(wpa_s, ssid);
3404 } else
3405 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003406
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003407 if (wpa_s->reassociate && !wpa_s->disconnected &&
3408 (!wpa_s->current_ssid ||
3409 wpa_s->wpa_state == WPA_DISCONNECTED ||
3410 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003411 if (wpa_s->sched_scanning) {
3412 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
3413 "new network to scan filters");
3414 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003415 }
3416
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003417 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3418 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003419 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003420 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003421 }
3422}
3423
3424
3425/**
3426 * wpa_supplicant_disable_network - Mark a configured network as disabled
3427 * @wpa_s: wpa_supplicant structure for a network interface
3428 * @ssid: wpa_ssid structure for a configured network or %NULL
3429 *
3430 * Disables the specified network or all networks if no network specified.
3431 */
3432void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
3433 struct wpa_ssid *ssid)
3434{
3435 struct wpa_ssid *other_ssid;
3436 int was_disabled;
3437
3438 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003439 if (wpa_s->sched_scanning)
3440 wpa_supplicant_cancel_sched_scan(wpa_s);
3441
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003442 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3443 other_ssid = other_ssid->next) {
3444 was_disabled = other_ssid->disabled;
3445 if (was_disabled == 2)
3446 continue; /* do not change persistent P2P group
3447 * data */
3448
3449 other_ssid->disabled = 1;
3450
3451 if (was_disabled != other_ssid->disabled)
3452 wpas_notify_network_enabled_changed(
3453 wpa_s, other_ssid);
3454 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003455 if (wpa_s->current_ssid) {
3456 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3457 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003458 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003459 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003460 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003461 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003462 if (ssid == wpa_s->current_ssid) {
3463 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3464 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003465 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003467 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468
3469 was_disabled = ssid->disabled;
3470
3471 ssid->disabled = 1;
3472
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003473 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003474 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003475 if (wpa_s->sched_scanning) {
3476 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3477 "to remove network from filters");
3478 wpa_supplicant_cancel_sched_scan(wpa_s);
3479 wpa_supplicant_req_scan(wpa_s, 0, 0);
3480 }
3481 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003482 }
3483}
3484
3485
3486/**
3487 * wpa_supplicant_select_network - Attempt association with a network
3488 * @wpa_s: wpa_supplicant structure for a network interface
3489 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3490 */
3491void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3492 struct wpa_ssid *ssid)
3493{
3494
3495 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003496 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003497
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003498 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003499 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3500 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003501 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003502 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003503 disconnected = 1;
3504 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003505
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003506 if (ssid)
3507 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003509 /*
3510 * Mark all other networks disabled or mark all networks enabled if no
3511 * network specified.
3512 */
3513 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3514 other_ssid = other_ssid->next) {
3515 int was_disabled = other_ssid->disabled;
3516 if (was_disabled == 2)
3517 continue; /* do not change persistent P2P group data */
3518
3519 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003520 if (was_disabled && !other_ssid->disabled)
3521 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003522
3523 if (was_disabled != other_ssid->disabled)
3524 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3525 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003526
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003527 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3528 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003529 /* We are already associated with the selected network */
3530 wpa_printf(MSG_DEBUG, "Already associated with the "
3531 "selected network - do nothing");
3532 return;
3533 }
3534
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003535 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003536 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003537 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003538 wpa_s->connect_without_scan =
3539 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003540
3541 /*
3542 * Don't optimize next scan freqs since a new ESS has been
3543 * selected.
3544 */
3545 os_free(wpa_s->next_scan_freqs);
3546 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003547 } else {
3548 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003549 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003550
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003551 wpa_s->disconnected = 0;
3552 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003553 wpa_s->last_owe_group = 0;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003554
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003555 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003556 wpa_supplicant_fast_associate(wpa_s) != 1) {
3557 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003558 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003559 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003560 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003561
3562 if (ssid)
3563 wpas_notify_network_selected(wpa_s, ssid);
3564}
3565
3566
3567/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003568 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3569 * @wpa_s: wpa_supplicant structure for a network interface
3570 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3571 * @pkcs11_module_path: PKCS #11 module path or NULL
3572 * Returns: 0 on success; -1 on failure
3573 *
3574 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3575 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3576 * module path fails the paths will be reset to the default value (NULL).
3577 */
3578int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3579 const char *pkcs11_engine_path,
3580 const char *pkcs11_module_path)
3581{
3582 char *pkcs11_engine_path_copy = NULL;
3583 char *pkcs11_module_path_copy = NULL;
3584
3585 if (pkcs11_engine_path != NULL) {
3586 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3587 if (pkcs11_engine_path_copy == NULL)
3588 return -1;
3589 }
3590 if (pkcs11_module_path != NULL) {
3591 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003592 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003593 os_free(pkcs11_engine_path_copy);
3594 return -1;
3595 }
3596 }
3597
3598 os_free(wpa_s->conf->pkcs11_engine_path);
3599 os_free(wpa_s->conf->pkcs11_module_path);
3600 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3601 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3602
3603 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3604 eapol_sm_deinit(wpa_s->eapol);
3605 wpa_s->eapol = NULL;
3606 if (wpa_supplicant_init_eapol(wpa_s)) {
3607 /* Error -> Reset paths to the default value (NULL) once. */
3608 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3609 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3610 NULL);
3611
3612 return -1;
3613 }
3614 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3615
3616 return 0;
3617}
3618
3619
3620/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003621 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3622 * @wpa_s: wpa_supplicant structure for a network interface
3623 * @ap_scan: AP scan mode
3624 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3625 *
3626 */
3627int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3628{
3629
3630 int old_ap_scan;
3631
3632 if (ap_scan < 0 || ap_scan > 2)
3633 return -1;
3634
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003635 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3636 wpa_printf(MSG_INFO,
3637 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3638 }
3639
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003640#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003641 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3642 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3643 wpa_s->wpa_state < WPA_COMPLETED) {
3644 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3645 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003646 return 0;
3647 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003648#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003649
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003650 old_ap_scan = wpa_s->conf->ap_scan;
3651 wpa_s->conf->ap_scan = ap_scan;
3652
3653 if (old_ap_scan != wpa_s->conf->ap_scan)
3654 wpas_notify_ap_scan_changed(wpa_s);
3655
3656 return 0;
3657}
3658
3659
3660/**
3661 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3662 * @wpa_s: wpa_supplicant structure for a network interface
3663 * @expire_age: Expiration age in seconds
3664 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3665 *
3666 */
3667int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3668 unsigned int bss_expire_age)
3669{
3670 if (bss_expire_age < 10) {
3671 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3672 bss_expire_age);
3673 return -1;
3674 }
3675 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3676 bss_expire_age);
3677 wpa_s->conf->bss_expiration_age = bss_expire_age;
3678
3679 return 0;
3680}
3681
3682
3683/**
3684 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3685 * @wpa_s: wpa_supplicant structure for a network interface
3686 * @expire_count: number of scans after which an unseen BSS is reclaimed
3687 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3688 *
3689 */
3690int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3691 unsigned int bss_expire_count)
3692{
3693 if (bss_expire_count < 1) {
3694 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3695 bss_expire_count);
3696 return -1;
3697 }
3698 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3699 bss_expire_count);
3700 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3701
3702 return 0;
3703}
3704
3705
3706/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003707 * wpa_supplicant_set_scan_interval - Set scan interval
3708 * @wpa_s: wpa_supplicant structure for a network interface
3709 * @scan_interval: scan interval in seconds
3710 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3711 *
3712 */
3713int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3714 int scan_interval)
3715{
3716 if (scan_interval < 0) {
3717 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3718 scan_interval);
3719 return -1;
3720 }
3721 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3722 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003723 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003724
3725 return 0;
3726}
3727
3728
3729/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003730 * wpa_supplicant_set_debug_params - Set global debug params
3731 * @global: wpa_global structure
3732 * @debug_level: debug level
3733 * @debug_timestamp: determines if show timestamp in debug data
3734 * @debug_show_keys: determines if show keys in debug data
3735 * Returns: 0 if succeed or -1 if debug_level has wrong value
3736 */
3737int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3738 int debug_timestamp, int debug_show_keys)
3739{
3740
3741 int old_level, old_timestamp, old_show_keys;
3742
3743 /* check for allowed debuglevels */
3744 if (debug_level != MSG_EXCESSIVE &&
3745 debug_level != MSG_MSGDUMP &&
3746 debug_level != MSG_DEBUG &&
3747 debug_level != MSG_INFO &&
3748 debug_level != MSG_WARNING &&
3749 debug_level != MSG_ERROR)
3750 return -1;
3751
3752 old_level = wpa_debug_level;
3753 old_timestamp = wpa_debug_timestamp;
3754 old_show_keys = wpa_debug_show_keys;
3755
3756 wpa_debug_level = debug_level;
3757 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3758 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3759
3760 if (wpa_debug_level != old_level)
3761 wpas_notify_debug_level_changed(global);
3762 if (wpa_debug_timestamp != old_timestamp)
3763 wpas_notify_debug_timestamp_changed(global);
3764 if (wpa_debug_show_keys != old_show_keys)
3765 wpas_notify_debug_show_keys_changed(global);
3766
3767 return 0;
3768}
3769
3770
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003771#ifdef CONFIG_OWE
3772static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
3773 const u8 *entry_ssid, size_t entry_ssid_len)
3774{
3775 const u8 *owe, *pos, *end;
3776 u8 ssid_len;
3777 struct wpa_bss *bss;
3778
3779 /* Check network profile SSID aganst the SSID in the
3780 * OWE Transition Mode element. */
3781
3782 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
3783 if (!bss)
3784 return 0;
3785
3786 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3787 if (!owe)
3788 return 0;
3789
3790 pos = owe + 6;
3791 end = owe + 2 + owe[1];
3792
3793 if (end - pos < ETH_ALEN + 1)
3794 return 0;
3795 pos += ETH_ALEN;
3796 ssid_len = *pos++;
3797 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
3798 return 0;
3799
3800 return entry_ssid_len == ssid_len &&
3801 os_memcmp(pos, entry_ssid, ssid_len) == 0;
3802}
3803#endif /* CONFIG_OWE */
3804
3805
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003806/**
3807 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3808 * @wpa_s: Pointer to wpa_supplicant data
3809 * Returns: A pointer to the current network structure or %NULL on failure
3810 */
3811struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3812{
3813 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003814 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003815 int res;
3816 size_t ssid_len;
3817 u8 bssid[ETH_ALEN];
3818 int wired;
3819
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003820 res = wpa_drv_get_ssid(wpa_s, ssid);
3821 if (res < 0) {
3822 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3823 "driver");
3824 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003826 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003827
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003828 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003829 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3830 "driver");
3831 return NULL;
3832 }
3833
3834 wired = wpa_s->conf->ap_scan == 0 &&
3835 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3836
3837 entry = wpa_s->conf->ssid;
3838 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003839 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003840 ((ssid_len == entry->ssid_len &&
3841 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3842 (!entry->bssid_set ||
3843 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3844 return entry;
3845#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003846 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003847 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3848 (entry->ssid == NULL || entry->ssid_len == 0) &&
3849 (!entry->bssid_set ||
3850 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3851 return entry;
3852#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003853
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003854#ifdef CONFIG_OWE
3855 if (!wpas_network_disabled(wpa_s, entry) &&
3856 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
3857 entry->ssid_len) &&
3858 (!entry->bssid_set ||
3859 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3860 return entry;
3861#endif /* CONFIG_OWE */
3862
Dmitry Shmidt04949592012-07-19 12:16:46 -07003863 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003864 entry->ssid_len == 0 &&
3865 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3866 return entry;
3867
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003868 entry = entry->next;
3869 }
3870
3871 return NULL;
3872}
3873
3874
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003875static int select_driver(struct wpa_supplicant *wpa_s, int i)
3876{
3877 struct wpa_global *global = wpa_s->global;
3878
3879 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003880 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003881 if (global->drv_priv[i] == NULL) {
3882 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3883 "'%s'", wpa_drivers[i]->name);
3884 return -1;
3885 }
3886 }
3887
3888 wpa_s->driver = wpa_drivers[i];
3889 wpa_s->global_drv_priv = global->drv_priv[i];
3890
3891 return 0;
3892}
3893
3894
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003895static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3896 const char *name)
3897{
3898 int i;
3899 size_t len;
3900 const char *pos, *driver = name;
3901
3902 if (wpa_s == NULL)
3903 return -1;
3904
3905 if (wpa_drivers[0] == NULL) {
3906 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3907 "wpa_supplicant");
3908 return -1;
3909 }
3910
3911 if (name == NULL) {
3912 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003913 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003914 }
3915
3916 do {
3917 pos = os_strchr(driver, ',');
3918 if (pos)
3919 len = pos - driver;
3920 else
3921 len = os_strlen(driver);
3922
3923 for (i = 0; wpa_drivers[i]; i++) {
3924 if (os_strlen(wpa_drivers[i]->name) == len &&
3925 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003926 0) {
3927 /* First driver that succeeds wins */
3928 if (select_driver(wpa_s, i) == 0)
3929 return 0;
3930 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003931 }
3932
3933 driver = pos + 1;
3934 } while (pos);
3935
3936 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3937 return -1;
3938}
3939
3940
3941/**
3942 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3943 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3944 * with struct wpa_driver_ops::init()
3945 * @src_addr: Source address of the EAPOL frame
3946 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3947 * @len: Length of the EAPOL data
3948 *
3949 * This function is called for each received EAPOL frame. Most driver
3950 * interfaces rely on more generic OS mechanism for receiving frames through
3951 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3952 * take care of received EAPOL frames and deliver them to the core supplicant
3953 * code by calling this function.
3954 */
3955void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3956 const u8 *buf, size_t len)
3957{
3958 struct wpa_supplicant *wpa_s = ctx;
3959
3960 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3961 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3962
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003963#ifdef CONFIG_TESTING_OPTIONS
3964 if (wpa_s->ignore_auth_resp) {
3965 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3966 return;
3967 }
3968#endif /* CONFIG_TESTING_OPTIONS */
3969
Jouni Malinena05074c2012-12-21 21:35:35 +02003970 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3971 (wpa_s->last_eapol_matches_bssid &&
3972#ifdef CONFIG_AP
3973 !wpa_s->ap_iface &&
3974#endif /* CONFIG_AP */
3975 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003976 /*
3977 * There is possible race condition between receiving the
3978 * association event and the EAPOL frame since they are coming
3979 * through different paths from the driver. In order to avoid
3980 * issues in trying to process the EAPOL frame before receiving
3981 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003982 * the association event is received. This may also be needed in
3983 * driver-based roaming case, so also use src_addr != BSSID as a
3984 * trigger if we have previously confirmed that the
3985 * Authenticator uses BSSID as the src_addr (which is not the
3986 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003987 */
3988 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003989 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3990 wpa_supplicant_state_txt(wpa_s->wpa_state),
3991 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003992 wpabuf_free(wpa_s->pending_eapol_rx);
3993 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3994 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003995 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003996 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3997 ETH_ALEN);
3998 }
3999 return;
4000 }
4001
Jouni Malinena05074c2012-12-21 21:35:35 +02004002 wpa_s->last_eapol_matches_bssid =
4003 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
4004
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004005#ifdef CONFIG_AP
4006 if (wpa_s->ap_iface) {
4007 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
4008 return;
4009 }
4010#endif /* CONFIG_AP */
4011
4012 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
4013 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
4014 "no key management is configured");
4015 return;
4016 }
4017
4018 if (wpa_s->eapol_received == 0 &&
4019 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
4020 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
4021 wpa_s->wpa_state != WPA_COMPLETED) &&
4022 (wpa_s->current_ssid == NULL ||
4023 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
4024 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004025 int timeout = 10;
4026
4027 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
4028 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
4029 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
4030 /* Use longer timeout for IEEE 802.1X/EAP */
4031 timeout = 70;
4032 }
4033
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004034#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004035 if (wpa_s->current_ssid && wpa_s->current_bss &&
4036 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
4037 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
4038 /*
4039 * Use shorter timeout if going through WPS AP iteration
4040 * for PIN config method with an AP that does not
4041 * advertise Selected Registrar.
4042 */
4043 struct wpabuf *wps_ie;
4044
4045 wps_ie = wpa_bss_get_vendor_ie_multi(
4046 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
4047 if (wps_ie &&
4048 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
4049 timeout = 10;
4050 wpabuf_free(wps_ie);
4051 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07004052#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004053
4054 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004055 }
4056 wpa_s->eapol_received++;
4057
4058 if (wpa_s->countermeasures) {
4059 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
4060 "EAPOL packet");
4061 return;
4062 }
4063
4064#ifdef CONFIG_IBSS_RSN
4065 if (wpa_s->current_ssid &&
4066 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
4067 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
4068 return;
4069 }
4070#endif /* CONFIG_IBSS_RSN */
4071
4072 /* Source address of the incoming EAPOL frame could be compared to the
4073 * current BSSID. However, it is possible that a centralized
4074 * Authenticator could be using another MAC address than the BSSID of
4075 * an AP, so just allow any address to be used for now. The replies are
4076 * still sent to the current BSSID (if available), though. */
4077
4078 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
4079 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004080 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
4081 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004082 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
4083 return;
4084 wpa_drv_poll(wpa_s);
4085 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
4086 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
4087 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
4088 /*
4089 * Set portValid = TRUE here since we are going to skip 4-way
4090 * handshake processing which would normally set portValid. We
4091 * need this to allow the EAPOL state machines to be completed
4092 * without going through EAPOL-Key handshake.
4093 */
4094 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
4095 }
4096}
4097
4098
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004099int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004100{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004101 if ((!wpa_s->p2p_mgmt ||
4102 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4103 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004104 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004105 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
4106 wpa_drv_get_mac_addr(wpa_s),
4107 ETH_P_EAPOL,
4108 wpa_supplicant_rx_eapol, wpa_s, 0);
4109 if (wpa_s->l2 == NULL)
4110 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004111
4112 if (l2_packet_set_packet_filter(wpa_s->l2,
4113 L2_PACKET_FILTER_PKTTYPE))
4114 wpa_dbg(wpa_s, MSG_DEBUG,
4115 "Failed to attach pkt_type filter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116 } else {
4117 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
4118 if (addr)
4119 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
4120 }
4121
4122 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
4123 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
4124 return -1;
4125 }
4126
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004127 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4128
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004129 return 0;
4130}
4131
4132
Dmitry Shmidt04949592012-07-19 12:16:46 -07004133static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
4134 const u8 *buf, size_t len)
4135{
4136 struct wpa_supplicant *wpa_s = ctx;
4137 const struct l2_ethhdr *eth;
4138
4139 if (len < sizeof(*eth))
4140 return;
4141 eth = (const struct l2_ethhdr *) buf;
4142
4143 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
4144 !(eth->h_dest[0] & 0x01)) {
4145 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4146 " (bridge - not for this interface - ignore)",
4147 MAC2STR(src_addr), MAC2STR(eth->h_dest));
4148 return;
4149 }
4150
4151 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
4152 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
4153 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
4154 len - sizeof(*eth));
4155}
4156
4157
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004158/**
4159 * wpa_supplicant_driver_init - Initialize driver interface parameters
4160 * @wpa_s: Pointer to wpa_supplicant data
4161 * Returns: 0 on success, -1 on failure
4162 *
4163 * This function is called to initialize driver interface parameters.
4164 * wpa_drv_init() must have been called before this function to initialize the
4165 * driver interface.
4166 */
4167int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4168{
4169 static int interface_count = 0;
4170
4171 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4172 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004173
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004174 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4175 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004176 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004177 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004179 if (wpa_s->bridge_ifname[0]) {
4180 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4181 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004182 wpa_s->l2_br = l2_packet_init_bridge(
4183 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4184 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004185 if (wpa_s->l2_br == NULL) {
4186 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4187 "connection for the bridge interface '%s'",
4188 wpa_s->bridge_ifname);
4189 return -1;
4190 }
4191 }
4192
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004193 if (wpa_s->conf->ap_scan == 2 &&
4194 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4195 wpa_printf(MSG_INFO,
4196 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4197 }
4198
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004199 wpa_clear_keys(wpa_s, NULL);
4200
4201 /* Make sure that TKIP countermeasures are not left enabled (could
4202 * happen if wpa_supplicant is killed during countermeasures. */
4203 wpa_drv_set_countermeasures(wpa_s, 0);
4204
4205 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4206 wpa_drv_flush_pmkid(wpa_s);
4207
4208 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004209 wpa_s->prev_scan_wildcard = 0;
4210
Dmitry Shmidt04949592012-07-19 12:16:46 -07004211 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004212 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4213 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4214 interface_count = 0;
4215 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004216#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004217 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004218 wpa_supplicant_delayed_sched_scan(wpa_s,
4219 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004220 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004221 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004222 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004223#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004224 interface_count++;
4225 } else
4226 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4227
4228 return 0;
4229}
4230
4231
4232static int wpa_supplicant_daemon(const char *pid_file)
4233{
4234 wpa_printf(MSG_DEBUG, "Daemonize..");
4235 return os_daemonize(pid_file);
4236}
4237
4238
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004239static struct wpa_supplicant *
4240wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004241{
4242 struct wpa_supplicant *wpa_s;
4243
4244 wpa_s = os_zalloc(sizeof(*wpa_s));
4245 if (wpa_s == NULL)
4246 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004247 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004248 wpa_s->scan_interval = 5;
4249 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004250 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004251 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004252 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004253
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004254 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004255 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004257 return wpa_s;
4258}
4259
4260
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004261#ifdef CONFIG_HT_OVERRIDES
4262
4263static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4264 struct ieee80211_ht_capabilities *htcaps,
4265 struct ieee80211_ht_capabilities *htcaps_mask,
4266 const char *ht_mcs)
4267{
4268 /* parse ht_mcs into hex array */
4269 int i;
4270 const char *tmp = ht_mcs;
4271 char *end = NULL;
4272
4273 /* If ht_mcs is null, do not set anything */
4274 if (!ht_mcs)
4275 return 0;
4276
4277 /* This is what we are setting in the kernel */
4278 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4279
4280 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4281
4282 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004283 long v;
4284
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004285 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004286 v = strtol(tmp, &end, 16);
4287
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004288 if (errno == 0) {
4289 wpa_msg(wpa_s, MSG_DEBUG,
4290 "htcap value[%i]: %ld end: %p tmp: %p",
4291 i, v, end, tmp);
4292 if (end == tmp)
4293 break;
4294
4295 htcaps->supported_mcs_set[i] = v;
4296 tmp = end;
4297 } else {
4298 wpa_msg(wpa_s, MSG_ERROR,
4299 "Failed to parse ht-mcs: %s, error: %s\n",
4300 ht_mcs, strerror(errno));
4301 return -1;
4302 }
4303 }
4304
4305 /*
4306 * If we were able to parse any values, then set mask for the MCS set.
4307 */
4308 if (i) {
4309 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4310 IEEE80211_HT_MCS_MASK_LEN - 1);
4311 /* skip the 3 reserved bits */
4312 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4313 0x1f;
4314 }
4315
4316 return 0;
4317}
4318
4319
4320static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4321 struct ieee80211_ht_capabilities *htcaps,
4322 struct ieee80211_ht_capabilities *htcaps_mask,
4323 int disabled)
4324{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004325 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004326
4327 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
4328
4329 if (disabled == -1)
4330 return 0;
4331
4332 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
4333 htcaps_mask->ht_capabilities_info |= msk;
4334 if (disabled)
4335 htcaps->ht_capabilities_info &= msk;
4336 else
4337 htcaps->ht_capabilities_info |= msk;
4338
4339 return 0;
4340}
4341
4342
4343static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
4344 struct ieee80211_ht_capabilities *htcaps,
4345 struct ieee80211_ht_capabilities *htcaps_mask,
4346 int factor)
4347{
4348 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
4349
4350 if (factor == -1)
4351 return 0;
4352
4353 if (factor < 0 || factor > 3) {
4354 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
4355 "Must be 0-3 or -1", factor);
4356 return -EINVAL;
4357 }
4358
4359 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
4360 htcaps->a_mpdu_params &= ~0x3;
4361 htcaps->a_mpdu_params |= factor & 0x3;
4362
4363 return 0;
4364}
4365
4366
4367static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
4368 struct ieee80211_ht_capabilities *htcaps,
4369 struct ieee80211_ht_capabilities *htcaps_mask,
4370 int density)
4371{
4372 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
4373
4374 if (density == -1)
4375 return 0;
4376
4377 if (density < 0 || density > 7) {
4378 wpa_msg(wpa_s, MSG_ERROR,
4379 "ampdu_density: %d out of range. Must be 0-7 or -1.",
4380 density);
4381 return -EINVAL;
4382 }
4383
4384 htcaps_mask->a_mpdu_params |= 0x1C;
4385 htcaps->a_mpdu_params &= ~(0x1C);
4386 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
4387
4388 return 0;
4389}
4390
4391
4392static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
4393 struct ieee80211_ht_capabilities *htcaps,
4394 struct ieee80211_ht_capabilities *htcaps_mask,
4395 int disabled)
4396{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004397 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
4398
Paul Stewart092955c2017-02-06 09:13:09 -08004399 set_disable_ht40(htcaps, disabled);
4400 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004401
4402 return 0;
4403}
4404
4405
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004406static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
4407 struct ieee80211_ht_capabilities *htcaps,
4408 struct ieee80211_ht_capabilities *htcaps_mask,
4409 int disabled)
4410{
4411 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004412 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
4413 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004414
4415 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
4416
4417 if (disabled)
4418 htcaps->ht_capabilities_info &= ~msk;
4419 else
4420 htcaps->ht_capabilities_info |= msk;
4421
4422 htcaps_mask->ht_capabilities_info |= msk;
4423
4424 return 0;
4425}
4426
4427
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004428static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
4429 struct ieee80211_ht_capabilities *htcaps,
4430 struct ieee80211_ht_capabilities *htcaps_mask,
4431 int disabled)
4432{
4433 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004434 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004435
4436 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
4437
4438 if (disabled)
4439 htcaps->ht_capabilities_info &= ~msk;
4440 else
4441 htcaps->ht_capabilities_info |= msk;
4442
4443 htcaps_mask->ht_capabilities_info |= msk;
4444
4445 return 0;
4446}
4447
4448
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004449void wpa_supplicant_apply_ht_overrides(
4450 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4451 struct wpa_driver_associate_params *params)
4452{
4453 struct ieee80211_ht_capabilities *htcaps;
4454 struct ieee80211_ht_capabilities *htcaps_mask;
4455
4456 if (!ssid)
4457 return;
4458
4459 params->disable_ht = ssid->disable_ht;
4460 if (!params->htcaps || !params->htcaps_mask)
4461 return;
4462
4463 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
4464 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
4465 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
4466 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
4467 ssid->disable_max_amsdu);
4468 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
4469 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
4470 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004471 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004472 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004473
4474 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004475 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004476 htcaps->ht_capabilities_info |= bit;
4477 htcaps_mask->ht_capabilities_info |= bit;
4478 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004479}
4480
4481#endif /* CONFIG_HT_OVERRIDES */
4482
4483
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004484#ifdef CONFIG_VHT_OVERRIDES
4485void wpa_supplicant_apply_vht_overrides(
4486 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4487 struct wpa_driver_associate_params *params)
4488{
4489 struct ieee80211_vht_capabilities *vhtcaps;
4490 struct ieee80211_vht_capabilities *vhtcaps_mask;
4491
4492 if (!ssid)
4493 return;
4494
4495 params->disable_vht = ssid->disable_vht;
4496
4497 vhtcaps = (void *) params->vhtcaps;
4498 vhtcaps_mask = (void *) params->vhtcaps_mask;
4499
4500 if (!vhtcaps || !vhtcaps_mask)
4501 return;
4502
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004503 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
4504 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004505
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004506#ifdef CONFIG_HT_OVERRIDES
4507 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004508 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
4509 int max_ampdu;
4510
4511 max_ampdu = (ssid->vht_capa &
4512 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4513 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004514
4515 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4516 wpa_set_ampdu_factor(wpa_s,
4517 (void *) params->htcaps,
4518 (void *) params->htcaps_mask,
4519 max_ampdu);
4520 }
4521#endif /* CONFIG_HT_OVERRIDES */
4522
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004523#define OVERRIDE_MCS(i) \
4524 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4525 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004526 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004527 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004528 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4529 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004530 } \
4531 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4532 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004533 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004534 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004535 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4536 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004537 }
4538
4539 OVERRIDE_MCS(1);
4540 OVERRIDE_MCS(2);
4541 OVERRIDE_MCS(3);
4542 OVERRIDE_MCS(4);
4543 OVERRIDE_MCS(5);
4544 OVERRIDE_MCS(6);
4545 OVERRIDE_MCS(7);
4546 OVERRIDE_MCS(8);
4547}
4548#endif /* CONFIG_VHT_OVERRIDES */
4549
4550
Dmitry Shmidt04949592012-07-19 12:16:46 -07004551static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4552{
4553#ifdef PCSC_FUNCS
4554 size_t len;
4555
4556 if (!wpa_s->conf->pcsc_reader)
4557 return 0;
4558
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004559 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004560 if (!wpa_s->scard)
4561 return 1;
4562
4563 if (wpa_s->conf->pcsc_pin &&
4564 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4565 scard_deinit(wpa_s->scard);
4566 wpa_s->scard = NULL;
4567 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4568 return -1;
4569 }
4570
4571 len = sizeof(wpa_s->imsi) - 1;
4572 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4573 scard_deinit(wpa_s->scard);
4574 wpa_s->scard = NULL;
4575 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4576 return -1;
4577 }
4578 wpa_s->imsi[len] = '\0';
4579
4580 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4581
4582 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4583 wpa_s->imsi, wpa_s->mnc_len);
4584
4585 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4586 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4587#endif /* PCSC_FUNCS */
4588
4589 return 0;
4590}
4591
4592
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004593int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4594{
4595 char *val, *pos;
4596
4597 ext_password_deinit(wpa_s->ext_pw);
4598 wpa_s->ext_pw = NULL;
4599 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4600
4601 if (!wpa_s->conf->ext_password_backend)
4602 return 0;
4603
4604 val = os_strdup(wpa_s->conf->ext_password_backend);
4605 if (val == NULL)
4606 return -1;
4607 pos = os_strchr(val, ':');
4608 if (pos)
4609 *pos++ = '\0';
4610
4611 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4612
4613 wpa_s->ext_pw = ext_password_init(val, pos);
4614 os_free(val);
4615 if (wpa_s->ext_pw == NULL) {
4616 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4617 return -1;
4618 }
4619 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4620
4621 return 0;
4622}
4623
4624
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004625#ifdef CONFIG_FST
4626
4627static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4628{
4629 struct wpa_supplicant *wpa_s = ctx;
4630
4631 return (is_zero_ether_addr(wpa_s->bssid) ||
4632 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4633}
4634
4635
4636static void wpas_fst_get_channel_info_cb(void *ctx,
4637 enum hostapd_hw_mode *hw_mode,
4638 u8 *channel)
4639{
4640 struct wpa_supplicant *wpa_s = ctx;
4641
4642 if (wpa_s->current_bss) {
4643 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4644 channel);
4645 } else if (wpa_s->hw.num_modes) {
4646 *hw_mode = wpa_s->hw.modes[0].mode;
4647 } else {
4648 WPA_ASSERT(0);
4649 *hw_mode = 0;
4650 }
4651}
4652
4653
4654static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4655{
4656 struct wpa_supplicant *wpa_s = ctx;
4657
4658 *modes = wpa_s->hw.modes;
4659 return wpa_s->hw.num_modes;
4660}
4661
4662
4663static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4664{
4665 struct wpa_supplicant *wpa_s = ctx;
4666
4667 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4668 wpa_s->fst_ies = fst_ies;
4669}
4670
4671
4672static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4673{
4674 struct wpa_supplicant *wpa_s = ctx;
4675
Paul Stewart092955c2017-02-06 09:13:09 -08004676 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
4677 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
4678 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
4679 return -1;
4680 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004681 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08004682 wpa_s->own_addr, wpa_s->bssid,
4683 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004684 0);
4685}
4686
4687
4688static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4689{
4690 struct wpa_supplicant *wpa_s = ctx;
4691
4692 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4693 return wpa_s->received_mb_ies;
4694}
4695
4696
4697static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4698 const u8 *buf, size_t size)
4699{
4700 struct wpa_supplicant *wpa_s = ctx;
4701 struct mb_ies_info info;
4702
4703 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4704
4705 if (!mb_ies_info_by_ies(&info, buf, size)) {
4706 wpabuf_free(wpa_s->received_mb_ies);
4707 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4708 }
4709}
4710
4711
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004712static const u8 * wpas_fst_get_peer_first(void *ctx,
4713 struct fst_get_peer_ctx **get_ctx,
4714 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004715{
4716 struct wpa_supplicant *wpa_s = ctx;
4717
4718 *get_ctx = NULL;
4719 if (!is_zero_ether_addr(wpa_s->bssid))
4720 return (wpa_s->received_mb_ies || !mb_only) ?
4721 wpa_s->bssid : NULL;
4722 return NULL;
4723}
4724
4725
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004726static const u8 * wpas_fst_get_peer_next(void *ctx,
4727 struct fst_get_peer_ctx **get_ctx,
4728 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004729{
4730 return NULL;
4731}
4732
4733void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4734 struct fst_wpa_obj *iface_obj)
4735{
4736 iface_obj->ctx = wpa_s;
4737 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4738 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4739 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4740 iface_obj->set_ies = wpas_fst_set_ies_cb;
4741 iface_obj->send_action = wpas_fst_send_action_cb;
4742 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4743 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4744 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4745 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4746}
4747#endif /* CONFIG_FST */
4748
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004749static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004750 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004751{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004752 struct wowlan_triggers *triggers;
4753 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004754
4755 if (!wpa_s->conf->wowlan_triggers)
4756 return 0;
4757
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004758 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4759 if (triggers) {
4760 ret = wpa_drv_wowlan(wpa_s, triggers);
4761 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004762 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004763 return ret;
4764}
4765
4766
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004767enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004768{
4769 if (freq < 3000)
4770 return BAND_2_4_GHZ;
4771 if (freq > 50000)
4772 return BAND_60_GHZ;
4773 return BAND_5_GHZ;
4774}
4775
4776
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004777unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004778{
4779 int i;
4780 unsigned int band = 0;
4781
4782 if (freqs) {
4783 /* freqs are specified for the radio work */
4784 for (i = 0; freqs[i]; i++)
4785 band |= wpas_freq_to_band(freqs[i]);
4786 } else {
4787 /*
4788 * freqs are not specified, implies all
4789 * the supported freqs by HW
4790 */
4791 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4792 if (wpa_s->hw.modes[i].num_channels != 0) {
4793 if (wpa_s->hw.modes[i].mode ==
4794 HOSTAPD_MODE_IEEE80211B ||
4795 wpa_s->hw.modes[i].mode ==
4796 HOSTAPD_MODE_IEEE80211G)
4797 band |= BAND_2_4_GHZ;
4798 else if (wpa_s->hw.modes[i].mode ==
4799 HOSTAPD_MODE_IEEE80211A)
4800 band |= BAND_5_GHZ;
4801 else if (wpa_s->hw.modes[i].mode ==
4802 HOSTAPD_MODE_IEEE80211AD)
4803 band |= BAND_60_GHZ;
4804 else if (wpa_s->hw.modes[i].mode ==
4805 HOSTAPD_MODE_IEEE80211ANY)
4806 band = BAND_2_4_GHZ | BAND_5_GHZ |
4807 BAND_60_GHZ;
4808 }
4809 }
4810 }
4811
4812 return band;
4813}
4814
4815
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004816static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4817 const char *rn)
4818{
4819 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4820 struct wpa_radio *radio;
4821
4822 while (rn && iface) {
4823 radio = iface->radio;
4824 if (radio && os_strcmp(rn, radio->name) == 0) {
4825 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4826 wpa_s->ifname, rn);
4827 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4828 return radio;
4829 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004830
4831 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004832 }
4833
4834 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4835 wpa_s->ifname, rn ? rn : "N/A");
4836 radio = os_zalloc(sizeof(*radio));
4837 if (radio == NULL)
4838 return NULL;
4839
4840 if (rn)
4841 os_strlcpy(radio->name, rn, sizeof(radio->name));
4842 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004843 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004844 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4845
4846 return radio;
4847}
4848
4849
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004850static void radio_work_free(struct wpa_radio_work *work)
4851{
4852 if (work->wpa_s->scan_work == work) {
4853 /* This should not really happen. */
4854 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4855 work->type, work, work->started);
4856 work->wpa_s->scan_work = NULL;
4857 }
4858
4859#ifdef CONFIG_P2P
4860 if (work->wpa_s->p2p_scan_work == work) {
4861 /* This should not really happen. */
4862 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4863 work->type, work, work->started);
4864 work->wpa_s->p2p_scan_work = NULL;
4865 }
4866#endif /* CONFIG_P2P */
4867
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004868 if (work->started) {
4869 work->wpa_s->radio->num_active_works--;
4870 wpa_dbg(work->wpa_s, MSG_DEBUG,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004871 "radio_work_free('%s'@%p): num_active_works --> %u",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004872 work->type, work,
4873 work->wpa_s->radio->num_active_works);
4874 }
4875
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004876 dl_list_del(&work->list);
4877 os_free(work);
4878}
4879
4880
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004881static int radio_work_is_connect(struct wpa_radio_work *work)
4882{
4883 return os_strcmp(work->type, "sme-connect") == 0 ||
4884 os_strcmp(work->type, "connect") == 0;
4885}
4886
4887
4888static int radio_work_is_scan(struct wpa_radio_work *work)
4889{
4890 return os_strcmp(work->type, "scan") == 0 ||
4891 os_strcmp(work->type, "p2p-scan") == 0;
4892}
4893
4894
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004895static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4896{
4897 struct wpa_radio_work *active_work = NULL;
4898 struct wpa_radio_work *tmp;
4899
4900 /* Get the active work to know the type and band. */
4901 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4902 if (tmp->started) {
4903 active_work = tmp;
4904 break;
4905 }
4906 }
4907
4908 if (!active_work) {
4909 /* No active work, start one */
4910 radio->num_active_works = 0;
4911 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4912 list) {
4913 if (os_strcmp(tmp->type, "scan") == 0 &&
4914 radio->external_scan_running &&
4915 (((struct wpa_driver_scan_params *)
4916 tmp->ctx)->only_new_results ||
4917 tmp->wpa_s->clear_driver_scan_cache))
4918 continue;
4919 return tmp;
4920 }
4921 return NULL;
4922 }
4923
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004924 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004925 /*
4926 * If the active work is either connect or sme-connect,
4927 * do not parallelize them with other radio works.
4928 */
4929 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4930 "Do not parallelize radio work with %s",
4931 active_work->type);
4932 return NULL;
4933 }
4934
4935 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4936 if (tmp->started)
4937 continue;
4938
4939 /*
4940 * If connect or sme-connect are enqueued, parallelize only
4941 * those operations ahead of them in the queue.
4942 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004943 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004944 break;
4945
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004946 /* Serialize parallel scan and p2p_scan operations on the same
4947 * interface since the driver_nl80211 mechanism for tracking
4948 * scan cookies does not yet have support for this. */
4949 if (active_work->wpa_s == tmp->wpa_s &&
4950 radio_work_is_scan(active_work) &&
4951 radio_work_is_scan(tmp)) {
4952 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4953 "Do not start work '%s' when another work '%s' is already scheduled",
4954 tmp->type, active_work->type);
4955 continue;
4956 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004957 /*
4958 * Check that the radio works are distinct and
4959 * on different bands.
4960 */
4961 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4962 (active_work->bands != tmp->bands)) {
4963 /*
4964 * If a scan has to be scheduled through nl80211 scan
4965 * interface and if an external scan is already running,
4966 * do not schedule the scan since it is likely to get
4967 * rejected by kernel.
4968 */
4969 if (os_strcmp(tmp->type, "scan") == 0 &&
4970 radio->external_scan_running &&
4971 (((struct wpa_driver_scan_params *)
4972 tmp->ctx)->only_new_results ||
4973 tmp->wpa_s->clear_driver_scan_cache))
4974 continue;
4975
4976 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4977 "active_work:%s new_work:%s",
4978 active_work->type, tmp->type);
4979 return tmp;
4980 }
4981 }
4982
4983 /* Did not find a radio work to schedule in parallel. */
4984 return NULL;
4985}
4986
4987
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004988static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4989{
4990 struct wpa_radio *radio = eloop_ctx;
4991 struct wpa_radio_work *work;
4992 struct os_reltime now, diff;
4993 struct wpa_supplicant *wpa_s;
4994
4995 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004996 if (work == NULL) {
4997 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004998 return;
4999 }
5000
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005001 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
5002 radio_list);
5003
5004 if (!(wpa_s &&
5005 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
5006 if (work->started)
5007 return; /* already started and still in progress */
5008
5009 if (wpa_s && wpa_s->radio->external_scan_running) {
5010 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
5011 return;
5012 }
5013 } else {
5014 work = NULL;
5015 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
5016 /* get the work to schedule next */
5017 work = radio_work_get_next_work(radio);
5018 }
5019 if (!work)
5020 return;
5021 }
5022
5023 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005024 os_get_reltime(&now);
5025 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005026 wpa_dbg(wpa_s, MSG_DEBUG,
5027 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005028 work->type, work, diff.sec, diff.usec);
5029 work->started = 1;
5030 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005031 radio->num_active_works++;
5032
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005033 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005034
5035 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
5036 radio->num_active_works < MAX_ACTIVE_WORKS)
5037 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005038}
5039
5040
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005041/*
5042 * This function removes both started and pending radio works running on
5043 * the provided interface's radio.
5044 * Prior to the removal of the radio work, its callback (cb) is called with
5045 * deinit set to be 1. Each work's callback is responsible for clearing its
5046 * internal data and restoring to a correct state.
5047 * @wpa_s: wpa_supplicant data
5048 * @type: type of works to be removed
5049 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
5050 * this interface's works.
5051 */
5052void radio_remove_works(struct wpa_supplicant *wpa_s,
5053 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005054{
5055 struct wpa_radio_work *work, *tmp;
5056 struct wpa_radio *radio = wpa_s->radio;
5057
5058 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
5059 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005060 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005061 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005062
5063 /* skip other ifaces' works */
5064 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005065 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005066
5067 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
5068 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005069 work->cb(work, 1);
5070 radio_work_free(work);
5071 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08005072
5073 /* in case we removed the started work */
5074 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005075}
5076
5077
Roshan Pius3a1667e2018-07-03 15:17:14 -07005078void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx)
5079{
5080 struct wpa_radio_work *work;
5081 struct wpa_radio *radio = wpa_s->radio;
5082
5083 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5084 if (work->ctx != ctx)
5085 continue;
5086 wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s",
5087 work->type, work, work->started ? " (started)" : "");
5088 radio_work_free(work);
5089 break;
5090 }
5091}
5092
5093
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005094static void radio_remove_interface(struct wpa_supplicant *wpa_s)
5095{
5096 struct wpa_radio *radio = wpa_s->radio;
5097
5098 if (!radio)
5099 return;
5100
5101 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
5102 wpa_s->ifname, radio->name);
5103 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005104 radio_remove_works(wpa_s, NULL, 0);
5105 wpa_s->radio = NULL;
5106 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005107 return; /* Interfaces remain for this radio */
5108
5109 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005110 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005111 os_free(radio);
5112}
5113
5114
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005115void radio_work_check_next(struct wpa_supplicant *wpa_s)
5116{
5117 struct wpa_radio *radio = wpa_s->radio;
5118
5119 if (dl_list_empty(&radio->work))
5120 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005121 if (wpa_s->ext_work_in_progress) {
5122 wpa_printf(MSG_DEBUG,
5123 "External radio work in progress - delay start of pending item");
5124 return;
5125 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005126 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
5127 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
5128}
5129
5130
5131/**
5132 * radio_add_work - Add a radio work item
5133 * @wpa_s: Pointer to wpa_supplicant data
5134 * @freq: Frequency of the offchannel operation in MHz or 0
5135 * @type: Unique identifier for each type of work
5136 * @next: Force as the next work to be executed
5137 * @cb: Callback function for indicating when radio is available
5138 * @ctx: Context pointer for the work (work->ctx in cb())
5139 * Returns: 0 on success, -1 on failure
5140 *
5141 * This function is used to request time for an operation that requires
5142 * exclusive radio control. Once the radio is available, the registered callback
5143 * function will be called. radio_work_done() must be called once the exclusive
5144 * radio operation has been completed, so that the radio is freed for other
5145 * operations. The special case of deinit=1 is used to free the context data
5146 * during interface removal. That does not allow the callback function to start
5147 * the radio operation, i.e., it must free any resources allocated for the radio
5148 * work and return.
5149 *
5150 * The @freq parameter can be used to indicate a single channel on which the
5151 * offchannel operation will occur. This may allow multiple radio work
5152 * operations to be performed in parallel if they apply for the same channel.
5153 * Setting this to 0 indicates that the work item may use multiple channels or
5154 * requires exclusive control of the radio.
5155 */
5156int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
5157 const char *type, int next,
5158 void (*cb)(struct wpa_radio_work *work, int deinit),
5159 void *ctx)
5160{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005161 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005162 struct wpa_radio_work *work;
5163 int was_empty;
5164
5165 work = os_zalloc(sizeof(*work));
5166 if (work == NULL)
5167 return -1;
5168 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
5169 os_get_reltime(&work->time);
5170 work->freq = freq;
5171 work->type = type;
5172 work->wpa_s = wpa_s;
5173 work->cb = cb;
5174 work->ctx = ctx;
5175
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005176 if (freq)
5177 work->bands = wpas_freq_to_band(freq);
5178 else if (os_strcmp(type, "scan") == 0 ||
5179 os_strcmp(type, "p2p-scan") == 0)
5180 work->bands = wpas_get_bands(wpa_s,
5181 ((struct wpa_driver_scan_params *)
5182 ctx)->freqs);
5183 else
5184 work->bands = wpas_get_bands(wpa_s, NULL);
5185
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005186 was_empty = dl_list_empty(&wpa_s->radio->work);
5187 if (next)
5188 dl_list_add(&wpa_s->radio->work, &work->list);
5189 else
5190 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5191 if (was_empty) {
5192 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5193 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005194 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5195 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5196 wpa_dbg(wpa_s, MSG_DEBUG,
5197 "Try to schedule a radio work (num_active_works=%u)",
5198 radio->num_active_works);
5199 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005200 }
5201
5202 return 0;
5203}
5204
5205
5206/**
5207 * radio_work_done - Indicate that a radio work item has been completed
5208 * @work: Completed work
5209 *
5210 * This function is called once the callback function registered with
5211 * radio_add_work() has completed its work.
5212 */
5213void radio_work_done(struct wpa_radio_work *work)
5214{
5215 struct wpa_supplicant *wpa_s = work->wpa_s;
5216 struct os_reltime now, diff;
5217 unsigned int started = work->started;
5218
5219 os_get_reltime(&now);
5220 os_reltime_sub(&now, &work->time, &diff);
5221 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5222 work->type, work, started ? "done" : "canceled",
5223 diff.sec, diff.usec);
5224 radio_work_free(work);
5225 if (started)
5226 radio_work_check_next(wpa_s);
5227}
5228
5229
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005230struct wpa_radio_work *
5231radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005232{
5233 struct wpa_radio_work *work;
5234 struct wpa_radio *radio = wpa_s->radio;
5235
5236 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5237 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005238 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005239 }
5240
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005241 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005242}
5243
5244
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005245static int wpas_init_driver(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005246 const struct wpa_interface *iface)
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005247{
5248 const char *ifname, *driver, *rn;
5249
5250 driver = iface->driver;
5251next_driver:
5252 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
5253 return -1;
5254
5255 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
5256 if (wpa_s->drv_priv == NULL) {
5257 const char *pos;
5258 pos = driver ? os_strchr(driver, ',') : NULL;
5259 if (pos) {
5260 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
5261 "driver interface - try next driver wrapper");
5262 driver = pos + 1;
5263 goto next_driver;
5264 }
5265 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
5266 "interface");
5267 return -1;
5268 }
5269 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
5270 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
5271 "driver_param '%s'", wpa_s->conf->driver_param);
5272 return -1;
5273 }
5274
5275 ifname = wpa_drv_get_ifname(wpa_s);
5276 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
5277 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
5278 "interface name with '%s'", ifname);
5279 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
5280 }
5281
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005282 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005283 if (rn && rn[0] == '\0')
5284 rn = NULL;
5285
5286 wpa_s->radio = radio_add_interface(wpa_s, rn);
5287 if (wpa_s->radio == NULL)
5288 return -1;
5289
5290 return 0;
5291}
5292
5293
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005294#ifdef CONFIG_GAS_SERVER
5295
5296static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
5297 unsigned int freq, const u8 *dst,
5298 const u8 *src, const u8 *bssid,
5299 const u8 *data, size_t data_len,
5300 enum offchannel_send_action_result result)
5301{
5302 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
5303 " result=%s",
5304 freq, MAC2STR(dst),
5305 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
5306 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
5307 "FAILED"));
5308 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
5309 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
5310}
5311
5312
5313static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
5314 struct wpabuf *buf, unsigned int wait_time)
5315{
5316 struct wpa_supplicant *wpa_s = ctx;
5317 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
5318
5319 if (wait_time > wpa_s->max_remain_on_chan)
5320 wait_time = wpa_s->max_remain_on_chan;
5321
5322 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
5323 wpabuf_head(buf), wpabuf_len(buf),
5324 wait_time, wpas_gas_server_tx_status, 0);
5325}
5326
5327#endif /* CONFIG_GAS_SERVER */
5328
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005329static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
Roshan Pius3a1667e2018-07-03 15:17:14 -07005330 const struct wpa_interface *iface)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005331{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005332 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005333 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005334 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005335
5336 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
5337 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
5338 iface->confname ? iface->confname : "N/A",
5339 iface->driver ? iface->driver : "default",
5340 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
5341 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
5342
5343 if (iface->confname) {
5344#ifdef CONFIG_BACKEND_FILE
5345 wpa_s->confname = os_rel2abs_path(iface->confname);
5346 if (wpa_s->confname == NULL) {
5347 wpa_printf(MSG_ERROR, "Failed to get absolute path "
5348 "for configuration file '%s'.",
5349 iface->confname);
5350 return -1;
5351 }
5352 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
5353 iface->confname, wpa_s->confname);
5354#else /* CONFIG_BACKEND_FILE */
5355 wpa_s->confname = os_strdup(iface->confname);
5356#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005357 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005358 if (wpa_s->conf == NULL) {
5359 wpa_printf(MSG_ERROR, "Failed to read or parse "
5360 "configuration '%s'.", wpa_s->confname);
5361 return -1;
5362 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005363 wpa_s->confanother = os_rel2abs_path(iface->confanother);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005364 if (wpa_s->confanother &&
5365 !wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
5366 wpa_printf(MSG_ERROR,
5367 "Failed to read or parse configuration '%s'.",
5368 wpa_s->confanother);
5369 return -1;
5370 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005371
5372 /*
5373 * Override ctrl_interface and driver_param if set on command
5374 * line.
5375 */
5376 if (iface->ctrl_interface) {
5377 os_free(wpa_s->conf->ctrl_interface);
5378 wpa_s->conf->ctrl_interface =
5379 os_strdup(iface->ctrl_interface);
5380 }
5381
5382 if (iface->driver_param) {
5383 os_free(wpa_s->conf->driver_param);
5384 wpa_s->conf->driver_param =
5385 os_strdup(iface->driver_param);
5386 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005387
5388 if (iface->p2p_mgmt && !iface->ctrl_interface) {
5389 os_free(wpa_s->conf->ctrl_interface);
5390 wpa_s->conf->ctrl_interface = NULL;
5391 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005392 } else
5393 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
5394 iface->driver_param);
5395
5396 if (wpa_s->conf == NULL) {
5397 wpa_printf(MSG_ERROR, "\nNo configuration found.");
5398 return -1;
5399 }
5400
5401 if (iface->ifname == NULL) {
5402 wpa_printf(MSG_ERROR, "\nInterface name is required.");
5403 return -1;
5404 }
5405 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
5406 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
5407 iface->ifname);
5408 return -1;
5409 }
5410 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
5411
5412 if (iface->bridge_ifname) {
5413 if (os_strlen(iface->bridge_ifname) >=
5414 sizeof(wpa_s->bridge_ifname)) {
5415 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
5416 "name '%s'.", iface->bridge_ifname);
5417 return -1;
5418 }
5419 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
5420 sizeof(wpa_s->bridge_ifname));
5421 }
5422
5423 /* RSNA Supplicant Key Management - INITIALIZE */
5424 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
5425 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
5426
5427 /* Initialize driver interface and register driver event handler before
5428 * L2 receive handler so that association events are processed before
5429 * EAPOL-Key packets if both become available for the same select()
5430 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005431 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005432 return -1;
5433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005434 if (wpa_supplicant_init_wpa(wpa_s) < 0)
5435 return -1;
5436
5437 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
5438 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
5439 NULL);
5440 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
5441
5442 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
5443 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
5444 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
5445 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5446 "dot11RSNAConfigPMKLifetime");
5447 return -1;
5448 }
5449
5450 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
5451 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
5452 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
5453 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5454 "dot11RSNAConfigPMKReauthThreshold");
5455 return -1;
5456 }
5457
5458 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
5459 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
5460 wpa_s->conf->dot11RSNAConfigSATimeout)) {
5461 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5462 "dot11RSNAConfigSATimeout");
5463 return -1;
5464 }
5465
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005466 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
5467 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005468 &wpa_s->hw.flags,
5469 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005470 if (wpa_s->hw.modes) {
5471 u16 i;
5472
5473 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5474 if (wpa_s->hw.modes[i].vht_capab) {
5475 wpa_s->hw_capab = CAPAB_VHT;
5476 break;
5477 }
5478
5479 if (wpa_s->hw.modes[i].ht_capab &
5480 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
5481 wpa_s->hw_capab = CAPAB_HT40;
5482 else if (wpa_s->hw.modes[i].ht_capab &&
5483 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
5484 wpa_s->hw_capab = CAPAB_HT;
5485 }
5486 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005487
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005488 capa_res = wpa_drv_get_capa(wpa_s, &capa);
5489 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005490 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005491 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005492 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005493 wpa_s->drv_smps_modes = capa.smps_modes;
5494 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005495 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005496 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005497 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005498 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
5499 wpa_s->max_sched_scan_plan_interval =
5500 capa.max_sched_scan_plan_interval;
5501 wpa_s->max_sched_scan_plan_iterations =
5502 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005503 wpa_s->sched_scan_supported = capa.sched_scan_supported;
5504 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005505 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
5506 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005507 wpa_s->extended_capa = capa.extended_capa;
5508 wpa_s->extended_capa_mask = capa.extended_capa_mask;
5509 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005510 wpa_s->num_multichan_concurrent =
5511 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005512 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
5513
5514 if (capa.mac_addr_rand_scan_supported)
5515 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
5516 if (wpa_s->sched_scan_supported &&
5517 capa.mac_addr_rand_sched_scan_supported)
5518 wpa_s->mac_addr_rand_supported |=
5519 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005520 }
5521 if (wpa_s->max_remain_on_chan == 0)
5522 wpa_s->max_remain_on_chan = 1000;
5523
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005524 /*
5525 * Only take p2p_mgmt parameters when P2P Device is supported.
5526 * Doing it here as it determines whether l2_packet_init() will be done
5527 * during wpa_supplicant_driver_init().
5528 */
5529 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
5530 wpa_s->p2p_mgmt = iface->p2p_mgmt;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005531
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005532 if (wpa_s->num_multichan_concurrent == 0)
5533 wpa_s->num_multichan_concurrent = 1;
5534
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005535 if (wpa_supplicant_driver_init(wpa_s) < 0)
5536 return -1;
5537
5538#ifdef CONFIG_TDLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07005539 if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005540 return -1;
5541#endif /* CONFIG_TDLS */
5542
5543 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
5544 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
5545 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
5546 return -1;
5547 }
5548
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005549#ifdef CONFIG_FST
5550 if (wpa_s->conf->fst_group_id) {
5551 struct fst_iface_cfg cfg;
5552 struct fst_wpa_obj iface_obj;
5553
5554 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
5555 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
5556 sizeof(cfg.group_id));
5557 cfg.priority = wpa_s->conf->fst_priority;
5558 cfg.llt = wpa_s->conf->fst_llt;
5559
5560 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
5561 &iface_obj, &cfg);
5562 if (!wpa_s->fst) {
5563 wpa_msg(wpa_s, MSG_ERROR,
5564 "FST: Cannot attach iface %s to group %s",
5565 wpa_s->ifname, cfg.group_id);
5566 return -1;
5567 }
5568 }
5569#endif /* CONFIG_FST */
5570
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005571 if (wpas_wps_init(wpa_s))
5572 return -1;
5573
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005574#ifdef CONFIG_GAS_SERVER
5575 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
5576 if (!wpa_s->gas_server) {
5577 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
5578 return -1;
5579 }
5580#endif /* CONFIG_GAS_SERVER */
5581
5582#ifdef CONFIG_DPP
5583 if (wpas_dpp_init(wpa_s) < 0)
5584 return -1;
5585#endif /* CONFIG_DPP */
5586
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005587 if (wpa_supplicant_init_eapol(wpa_s) < 0)
5588 return -1;
5589 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5590
5591 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
5592 if (wpa_s->ctrl_iface == NULL) {
5593 wpa_printf(MSG_ERROR,
5594 "Failed to initialize control interface '%s'.\n"
5595 "You may have another wpa_supplicant process "
5596 "already running or the file was\n"
5597 "left by an unclean termination of wpa_supplicant "
5598 "in which case you will need\n"
5599 "to manually remove this file before starting "
5600 "wpa_supplicant again.\n",
5601 wpa_s->conf->ctrl_interface);
5602 return -1;
5603 }
5604
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005605 wpa_s->gas = gas_query_init(wpa_s);
5606 if (wpa_s->gas == NULL) {
5607 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5608 return -1;
5609 }
5610
Roshan Pius3a1667e2018-07-03 15:17:14 -07005611 if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
5612 wpa_s->p2p_mgmt) &&
5613 wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005614 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5615 return -1;
5616 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005617
5618 if (wpa_bss_init(wpa_s) < 0)
5619 return -1;
5620
Paul Stewart092955c2017-02-06 09:13:09 -08005621#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5622#ifdef CONFIG_MESH
5623 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
5624#endif /* CONFIG_MESH */
5625#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5626
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005627 /*
5628 * Set Wake-on-WLAN triggers, if configured.
5629 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5630 * have effect anyway when the interface is down).
5631 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005632 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005633 return -1;
5634
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005635#ifdef CONFIG_EAP_PROXY
5636{
5637 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005638 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
5639 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005640 if (wpa_s->mnc_len > 0) {
5641 wpa_s->imsi[len] = '\0';
5642 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5643 wpa_s->imsi, wpa_s->mnc_len);
5644 } else {
5645 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5646 }
5647}
5648#endif /* CONFIG_EAP_PROXY */
5649
Dmitry Shmidt04949592012-07-19 12:16:46 -07005650 if (pcsc_reader_init(wpa_s) < 0)
5651 return -1;
5652
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005653 if (wpas_init_ext_pw(wpa_s) < 0)
5654 return -1;
5655
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005656 wpas_rrm_reset(wpa_s);
5657
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005658 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5659
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005660#ifdef CONFIG_HS20
5661 hs20_init(wpa_s);
5662#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005663#ifdef CONFIG_MBO
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005664 if (wpa_s->conf->oce) {
5665 if ((wpa_s->conf->oce & OCE_STA) &&
5666 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
5667 wpa_s->enable_oce = OCE_STA;
5668 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
5669 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
5670 /* TODO: Need to add STA-CFON support */
5671 wpa_printf(MSG_ERROR,
5672 "OCE STA-CFON feature is not yet supported");
5673 }
5674 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005675 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5676#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005677
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005678 wpa_supplicant_set_default_scan_ies(wpa_s);
5679
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005680 return 0;
5681}
5682
5683
5684static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005685 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005686{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005687 struct wpa_global *global = wpa_s->global;
5688 struct wpa_supplicant *iface, *prev;
5689
5690 if (wpa_s == wpa_s->parent)
5691 wpas_p2p_group_remove(wpa_s, "*");
5692
5693 iface = global->ifaces;
5694 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005695 if (iface->p2pdev == wpa_s)
5696 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005697 if (iface == wpa_s || iface->parent != wpa_s) {
5698 iface = iface->next;
5699 continue;
5700 }
5701 wpa_printf(MSG_DEBUG,
5702 "Remove remaining child interface %s from parent %s",
5703 iface->ifname, wpa_s->ifname);
5704 prev = iface;
5705 iface = iface->next;
5706 wpa_supplicant_remove_iface(global, prev, terminate);
5707 }
5708
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005709 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005710 if (wpa_s->drv_priv) {
5711 wpa_supplicant_deauthenticate(wpa_s,
5712 WLAN_REASON_DEAUTH_LEAVING);
5713
5714 wpa_drv_set_countermeasures(wpa_s, 0);
5715 wpa_clear_keys(wpa_s, NULL);
5716 }
5717
5718 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005719 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005720
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005721 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005722 radio_remove_interface(wpa_s);
5723
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005724#ifdef CONFIG_FST
5725 if (wpa_s->fst) {
5726 fst_detach(wpa_s->fst);
5727 wpa_s->fst = NULL;
5728 }
5729 if (wpa_s->received_mb_ies) {
5730 wpabuf_free(wpa_s->received_mb_ies);
5731 wpa_s->received_mb_ies = NULL;
5732 }
5733#endif /* CONFIG_FST */
5734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005735 if (wpa_s->drv_priv)
5736 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005737
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005738 if (notify)
5739 wpas_notify_iface_removed(wpa_s);
5740
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005741 if (terminate)
5742 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005743
5744 if (wpa_s->ctrl_iface) {
5745 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5746 wpa_s->ctrl_iface = NULL;
5747 }
5748
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005749#ifdef CONFIG_MESH
5750 if (wpa_s->ifmsh) {
5751 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5752 wpa_s->ifmsh = NULL;
5753 }
5754#endif /* CONFIG_MESH */
5755
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005756 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005757 wpa_config_free(wpa_s->conf);
5758 wpa_s->conf = NULL;
5759 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005760
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005761 os_free(wpa_s->ssids_from_scan_req);
5762
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005763 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005764}
5765
5766
Dmitry Shmidte4663042016-04-04 10:07:49 -07005767#ifdef CONFIG_MATCH_IFACE
5768
5769/**
5770 * wpa_supplicant_match_iface - Match an interface description to a name
5771 * @global: Pointer to global data from wpa_supplicant_init()
5772 * @ifname: Name of the interface to match
5773 * Returns: Pointer to the created interface description or %NULL on failure
5774 */
5775struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5776 const char *ifname)
5777{
5778 int i;
5779 struct wpa_interface *iface, *miface;
5780
5781 for (i = 0; i < global->params.match_iface_count; i++) {
5782 miface = &global->params.match_ifaces[i];
5783 if (!miface->ifname ||
5784 fnmatch(miface->ifname, ifname, 0) == 0) {
5785 iface = os_zalloc(sizeof(*iface));
5786 if (!iface)
5787 return NULL;
5788 *iface = *miface;
5789 iface->ifname = ifname;
5790 return iface;
5791 }
5792 }
5793
5794 return NULL;
5795}
5796
5797
5798/**
5799 * wpa_supplicant_match_existing - Match existing interfaces
5800 * @global: Pointer to global data from wpa_supplicant_init()
5801 * Returns: 0 on success, -1 on failure
5802 */
5803static int wpa_supplicant_match_existing(struct wpa_global *global)
5804{
5805 struct if_nameindex *ifi, *ifp;
5806 struct wpa_supplicant *wpa_s;
5807 struct wpa_interface *iface;
5808
5809 ifp = if_nameindex();
5810 if (!ifp) {
5811 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5812 return -1;
5813 }
5814
5815 for (ifi = ifp; ifi->if_name; ifi++) {
5816 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5817 if (wpa_s)
5818 continue;
5819 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5820 if (iface) {
5821 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5822 os_free(iface);
5823 if (wpa_s)
5824 wpa_s->matched = 1;
5825 }
5826 }
5827
5828 if_freenameindex(ifp);
5829 return 0;
5830}
5831
5832#endif /* CONFIG_MATCH_IFACE */
5833
5834
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005835/**
5836 * wpa_supplicant_add_iface - Add a new network interface
5837 * @global: Pointer to global data from wpa_supplicant_init()
5838 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005839 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005840 * Returns: Pointer to the created interface or %NULL on failure
5841 *
5842 * This function is used to add new network interfaces for %wpa_supplicant.
5843 * This can be called before wpa_supplicant_run() to add interfaces before the
5844 * main event loop has been started. In addition, new interfaces can be added
5845 * dynamically while %wpa_supplicant is already running. This could happen,
5846 * e.g., when a hotplug network adapter is inserted.
5847 */
5848struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005849 struct wpa_interface *iface,
5850 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005851{
5852 struct wpa_supplicant *wpa_s;
5853 struct wpa_interface t_iface;
5854 struct wpa_ssid *ssid;
5855
5856 if (global == NULL || iface == NULL)
5857 return NULL;
5858
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005859 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005860 if (wpa_s == NULL)
5861 return NULL;
5862
5863 wpa_s->global = global;
5864
5865 t_iface = *iface;
5866 if (global->params.override_driver) {
5867 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5868 "('%s' -> '%s')",
5869 iface->driver, global->params.override_driver);
5870 t_iface.driver = global->params.override_driver;
5871 }
5872 if (global->params.override_ctrl_interface) {
5873 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5874 "ctrl_interface ('%s' -> '%s')",
5875 iface->ctrl_interface,
5876 global->params.override_ctrl_interface);
5877 t_iface.ctrl_interface =
5878 global->params.override_ctrl_interface;
5879 }
5880 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5881 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5882 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005883 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005884 return NULL;
5885 }
5886
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005887 /* Notify the control interfaces about new iface */
5888 if (wpas_notify_iface_added(wpa_s)) {
5889 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5890 return NULL;
5891 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005892
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005893 /* Notify the control interfaces about new networks for non p2p mgmt
5894 * ifaces. */
5895 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005896 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5897 wpas_notify_network_added(wpa_s, ssid);
5898 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005899
5900 wpa_s->next = global->ifaces;
5901 global->ifaces = wpa_s;
5902
5903 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005904 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005905
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005906#ifdef CONFIG_P2P
5907 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005908 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005909 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005910 wpas_p2p_add_p2pdev_interface(
5911 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005912 wpa_printf(MSG_INFO,
5913 "P2P: Failed to enable P2P Device interface");
5914 /* Try to continue without. P2P will be disabled. */
5915 }
5916#endif /* CONFIG_P2P */
5917
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005918 return wpa_s;
5919}
5920
5921
5922/**
5923 * wpa_supplicant_remove_iface - Remove a network interface
5924 * @global: Pointer to global data from wpa_supplicant_init()
5925 * @wpa_s: Pointer to the network interface to be removed
5926 * Returns: 0 if interface was removed, -1 if interface was not found
5927 *
5928 * This function can be used to dynamically remove network interfaces from
5929 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5930 * addition, this function is used to remove all remaining interfaces when
5931 * %wpa_supplicant is terminated.
5932 */
5933int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005934 struct wpa_supplicant *wpa_s,
5935 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005936{
5937 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005938#ifdef CONFIG_MESH
5939 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5940 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005941 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005942#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005943
5944 /* Remove interface from the global list of interfaces */
5945 prev = global->ifaces;
5946 if (prev == wpa_s) {
5947 global->ifaces = wpa_s->next;
5948 } else {
5949 while (prev && prev->next != wpa_s)
5950 prev = prev->next;
5951 if (prev == NULL)
5952 return -1;
5953 prev->next = wpa_s->next;
5954 }
5955
5956 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5957
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005958#ifdef CONFIG_MESH
5959 if (mesh_if_created) {
5960 ifname = os_strdup(wpa_s->ifname);
5961 if (ifname == NULL) {
5962 wpa_dbg(wpa_s, MSG_ERROR,
5963 "mesh: Failed to malloc ifname");
5964 return -1;
5965 }
5966 }
5967#endif /* CONFIG_MESH */
5968
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005969 if (global->p2p_group_formation == wpa_s)
5970 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005971 if (global->p2p_invite_group == wpa_s)
5972 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005973 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005974
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005975#ifdef CONFIG_MESH
5976 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005977 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005978 os_free(ifname);
5979 }
5980#endif /* CONFIG_MESH */
5981
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005982 return 0;
5983}
5984
5985
5986/**
5987 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5988 * @wpa_s: Pointer to the network interface
5989 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5990 */
5991const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5992{
5993 const char *eapol_method;
5994
5995 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5996 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5997 return "NO-EAP";
5998 }
5999
6000 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
6001 if (eapol_method == NULL)
6002 return "UNKNOWN-EAP";
6003
6004 return eapol_method;
6005}
6006
6007
6008/**
6009 * wpa_supplicant_get_iface - Get a new network interface
6010 * @global: Pointer to global data from wpa_supplicant_init()
6011 * @ifname: Interface name
6012 * Returns: Pointer to the interface or %NULL if not found
6013 */
6014struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
6015 const char *ifname)
6016{
6017 struct wpa_supplicant *wpa_s;
6018
6019 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6020 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6021 return wpa_s;
6022 }
6023 return NULL;
6024}
6025
6026
6027#ifndef CONFIG_NO_WPA_MSG
6028static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
6029{
6030 struct wpa_supplicant *wpa_s = ctx;
6031 if (wpa_s == NULL)
6032 return NULL;
6033 return wpa_s->ifname;
6034}
6035#endif /* CONFIG_NO_WPA_MSG */
6036
6037
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006038#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
6039#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
6040#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
6041
6042/* Periodic cleanup tasks */
6043static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
6044{
6045 struct wpa_global *global = eloop_ctx;
6046 struct wpa_supplicant *wpa_s;
6047
6048 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6049 wpas_periodic, global, NULL);
6050
6051#ifdef CONFIG_P2P
6052 if (global->p2p)
6053 p2p_expire_peers(global->p2p);
6054#endif /* CONFIG_P2P */
6055
6056 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6057 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
6058#ifdef CONFIG_AP
6059 ap_periodic(wpa_s);
6060#endif /* CONFIG_AP */
6061 }
6062}
6063
6064
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006065/**
6066 * wpa_supplicant_init - Initialize %wpa_supplicant
6067 * @params: Parameters for %wpa_supplicant
6068 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
6069 *
6070 * This function is used to initialize %wpa_supplicant. After successful
6071 * initialization, the returned data pointer can be used to add and remove
6072 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
6073 */
6074struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
6075{
6076 struct wpa_global *global;
6077 int ret, i;
6078
6079 if (params == NULL)
6080 return NULL;
6081
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006082#ifdef CONFIG_DRIVER_NDIS
6083 {
6084 void driver_ndis_init_ops(void);
6085 driver_ndis_init_ops();
6086 }
6087#endif /* CONFIG_DRIVER_NDIS */
6088
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006089#ifndef CONFIG_NO_WPA_MSG
6090 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
6091#endif /* CONFIG_NO_WPA_MSG */
6092
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006093 if (params->wpa_debug_file_path)
6094 wpa_debug_open_file(params->wpa_debug_file_path);
6095 else
6096 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006097 if (params->wpa_debug_syslog)
6098 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006099 if (params->wpa_debug_tracing) {
6100 ret = wpa_debug_open_linux_tracing();
6101 if (ret) {
6102 wpa_printf(MSG_ERROR,
6103 "Failed to enable trace logging");
6104 return NULL;
6105 }
6106 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006107
6108 ret = eap_register_methods();
6109 if (ret) {
6110 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
6111 if (ret == -2)
6112 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
6113 "the same EAP type.");
6114 return NULL;
6115 }
6116
6117 global = os_zalloc(sizeof(*global));
6118 if (global == NULL)
6119 return NULL;
6120 dl_list_init(&global->p2p_srv_bonjour);
6121 dl_list_init(&global->p2p_srv_upnp);
6122 global->params.daemonize = params->daemonize;
6123 global->params.wait_for_monitor = params->wait_for_monitor;
6124 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
6125 if (params->pid_file)
6126 global->params.pid_file = os_strdup(params->pid_file);
6127 if (params->ctrl_interface)
6128 global->params.ctrl_interface =
6129 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006130 if (params->ctrl_interface_group)
6131 global->params.ctrl_interface_group =
6132 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006133 if (params->override_driver)
6134 global->params.override_driver =
6135 os_strdup(params->override_driver);
6136 if (params->override_ctrl_interface)
6137 global->params.override_ctrl_interface =
6138 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006139#ifdef CONFIG_MATCH_IFACE
6140 global->params.match_iface_count = params->match_iface_count;
6141 if (params->match_iface_count) {
6142 global->params.match_ifaces =
6143 os_calloc(params->match_iface_count,
6144 sizeof(struct wpa_interface));
6145 os_memcpy(global->params.match_ifaces,
6146 params->match_ifaces,
6147 params->match_iface_count *
6148 sizeof(struct wpa_interface));
6149 }
6150#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006151#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006152 if (params->conf_p2p_dev)
6153 global->params.conf_p2p_dev =
6154 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006155#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006156 wpa_debug_level = global->params.wpa_debug_level =
6157 params->wpa_debug_level;
6158 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
6159 params->wpa_debug_show_keys;
6160 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
6161 params->wpa_debug_timestamp;
6162
6163 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
6164
6165 if (eloop_init()) {
6166 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
6167 wpa_supplicant_deinit(global);
6168 return NULL;
6169 }
6170
Jouni Malinen75ecf522011-06-27 15:19:46 -07006171 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006172
6173 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
6174 if (global->ctrl_iface == NULL) {
6175 wpa_supplicant_deinit(global);
6176 return NULL;
6177 }
6178
6179 if (wpas_notify_supplicant_initialized(global)) {
6180 wpa_supplicant_deinit(global);
6181 return NULL;
6182 }
6183
6184 for (i = 0; wpa_drivers[i]; i++)
6185 global->drv_count++;
6186 if (global->drv_count == 0) {
6187 wpa_printf(MSG_ERROR, "No drivers enabled");
6188 wpa_supplicant_deinit(global);
6189 return NULL;
6190 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006191 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006192 if (global->drv_priv == NULL) {
6193 wpa_supplicant_deinit(global);
6194 return NULL;
6195 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006196
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006197#ifdef CONFIG_WIFI_DISPLAY
6198 if (wifi_display_init(global) < 0) {
6199 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6200 wpa_supplicant_deinit(global);
6201 return NULL;
6202 }
6203#endif /* CONFIG_WIFI_DISPLAY */
6204
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006205 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6206 wpas_periodic, global, NULL);
6207
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006208 return global;
6209}
6210
6211
6212/**
6213 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6214 * @global: Pointer to global data from wpa_supplicant_init()
6215 * Returns: 0 after successful event loop run, -1 on failure
6216 *
6217 * This function starts the main event loop and continues running as long as
6218 * there are any remaining events. In most cases, this function is running as
6219 * long as the %wpa_supplicant process in still in use.
6220 */
6221int wpa_supplicant_run(struct wpa_global *global)
6222{
6223 struct wpa_supplicant *wpa_s;
6224
6225 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006226 (wpa_supplicant_daemon(global->params.pid_file) ||
6227 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006228 return -1;
6229
Dmitry Shmidte4663042016-04-04 10:07:49 -07006230#ifdef CONFIG_MATCH_IFACE
6231 if (wpa_supplicant_match_existing(global))
6232 return -1;
6233#endif
6234
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006235 if (global->params.wait_for_monitor) {
6236 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08006237 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006238 wpa_supplicant_ctrl_iface_wait(
6239 wpa_s->ctrl_iface);
6240 }
6241
6242 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
6243 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
6244
6245 eloop_run();
6246
6247 return 0;
6248}
6249
6250
6251/**
6252 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
6253 * @global: Pointer to global data from wpa_supplicant_init()
6254 *
6255 * This function is called to deinitialize %wpa_supplicant and to free all
6256 * allocated resources. Remaining network interfaces will also be removed.
6257 */
6258void wpa_supplicant_deinit(struct wpa_global *global)
6259{
6260 int i;
6261
6262 if (global == NULL)
6263 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006264
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006265 eloop_cancel_timeout(wpas_periodic, global, NULL);
6266
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006267#ifdef CONFIG_WIFI_DISPLAY
6268 wifi_display_deinit(global);
6269#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006270
6271 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006272 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006273
6274 if (global->ctrl_iface)
6275 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
6276
6277 wpas_notify_supplicant_deinitialized(global);
6278
6279 eap_peer_unregister_methods();
6280#ifdef CONFIG_AP
6281 eap_server_unregister_methods();
6282#endif /* CONFIG_AP */
6283
6284 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
6285 if (!global->drv_priv[i])
6286 continue;
6287 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
6288 }
6289 os_free(global->drv_priv);
6290
6291 random_deinit();
6292
6293 eloop_destroy();
6294
6295 if (global->params.pid_file) {
6296 os_daemonize_terminate(global->params.pid_file);
6297 os_free(global->params.pid_file);
6298 }
6299 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006300 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006301 os_free(global->params.override_driver);
6302 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006303#ifdef CONFIG_MATCH_IFACE
6304 os_free(global->params.match_ifaces);
6305#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006306#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006307 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006308#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006309
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07006310 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006311 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006312 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006314 os_free(global);
6315 wpa_debug_close_syslog();
6316 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006317 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006318}
6319
6320
6321void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
6322{
6323 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
6324 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
6325 char country[3];
6326 country[0] = wpa_s->conf->country[0];
6327 country[1] = wpa_s->conf->country[1];
6328 country[2] = '\0';
6329 if (wpa_drv_set_country(wpa_s, country) < 0) {
6330 wpa_printf(MSG_ERROR, "Failed to set country code "
6331 "'%s'", country);
6332 }
6333 }
6334
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006335 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
6336 wpas_init_ext_pw(wpa_s);
6337
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006338 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
6339 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6340
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006341 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
6342 struct wpa_driver_capa capa;
6343 int res = wpa_drv_get_capa(wpa_s, &capa);
6344
6345 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
6346 wpa_printf(MSG_ERROR,
6347 "Failed to update wowlan_triggers to '%s'",
6348 wpa_s->conf->wowlan_triggers);
6349 }
6350
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006351#ifdef CONFIG_WPS
6352 wpas_wps_update_config(wpa_s);
6353#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006354 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006355 wpa_s->conf->changed_parameters = 0;
6356}
6357
6358
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006359void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006360{
6361 int i;
6362
6363 for (i = 0; i < *num_freqs; i++) {
6364 if (freqs[i] == freq)
6365 return;
6366 }
6367
6368 freqs[*num_freqs] = freq;
6369 (*num_freqs)++;
6370}
6371
6372
6373static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
6374{
6375 struct wpa_bss *bss, *cbss;
6376 const int max_freqs = 10;
6377 int *freqs;
6378 int num_freqs = 0;
6379
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006380 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006381 if (freqs == NULL)
6382 return NULL;
6383
6384 cbss = wpa_s->current_bss;
6385
6386 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
6387 if (bss == cbss)
6388 continue;
6389 if (bss->ssid_len == cbss->ssid_len &&
6390 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
6391 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
6392 add_freq(freqs, &num_freqs, bss->freq);
6393 if (num_freqs == max_freqs)
6394 break;
6395 }
6396 }
6397
6398 if (num_freqs == 0) {
6399 os_free(freqs);
6400 freqs = NULL;
6401 }
6402
6403 return freqs;
6404}
6405
6406
6407void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6408{
6409 int timeout;
6410 int count;
6411 int *freqs = NULL;
6412
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006413 wpas_connect_work_done(wpa_s);
6414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006415 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006416 * Remove possible authentication timeout since the connection failed.
6417 */
6418 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
6419
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006420 /*
6421 * There is no point in blacklisting the AP if this event is
6422 * generated based on local request to disconnect.
6423 */
6424 if (wpa_s->own_disconnect_req) {
6425 wpa_s->own_disconnect_req = 0;
6426 wpa_dbg(wpa_s, MSG_DEBUG,
6427 "Ignore connection failure due to local request to disconnect");
6428 return;
6429 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006430 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006431 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6432 "indication since interface has been put into "
6433 "disconnected state");
6434 return;
6435 }
6436
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006437 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006438 * Add the failed BSSID into the blacklist and speed up next scan
6439 * attempt if there could be other APs that could accept association.
6440 * The current blacklist count indicates how many times we have tried
6441 * connecting to this AP and multiple attempts mean that other APs are
6442 * either not available or has already been tried, so that we can start
6443 * increasing the delay here to avoid constant scanning.
6444 */
6445 count = wpa_blacklist_add(wpa_s, bssid);
6446 if (count == 1 && wpa_s->current_bss) {
6447 /*
6448 * This BSS was not in the blacklist before. If there is
6449 * another BSS available for the same ESS, we should try that
6450 * next. Otherwise, we may as well try this one once more
6451 * before allowing other, likely worse, ESSes to be considered.
6452 */
6453 freqs = get_bss_freqs_in_ess(wpa_s);
6454 if (freqs) {
6455 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
6456 "has been seen; try it next");
6457 wpa_blacklist_add(wpa_s, bssid);
6458 /*
6459 * On the next scan, go through only the known channels
6460 * used in this ESS based on previous scans to speed up
6461 * common load balancing use case.
6462 */
6463 os_free(wpa_s->next_scan_freqs);
6464 wpa_s->next_scan_freqs = freqs;
6465 }
6466 }
6467
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006468 /*
6469 * Add previous failure count in case the temporary blacklist was
6470 * cleared due to no other BSSes being available.
6471 */
6472 count += wpa_s->extra_blacklist_count;
6473
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006474 if (count > 3 && wpa_s->current_ssid) {
6475 wpa_printf(MSG_DEBUG, "Continuous association failures - "
6476 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006477 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006478 }
6479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006480 switch (count) {
6481 case 1:
6482 timeout = 100;
6483 break;
6484 case 2:
6485 timeout = 500;
6486 break;
6487 case 3:
6488 timeout = 1000;
6489 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006490 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006491 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006492 break;
6493 default:
6494 timeout = 10000;
6495 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006496 }
6497
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006498 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
6499 "ms", count, timeout);
6500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006501 /*
6502 * TODO: if more than one possible AP is available in scan results,
6503 * could try the other ones before requesting a new scan.
6504 */
6505 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
6506 1000 * (timeout % 1000));
6507}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006508
6509
6510int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
6511{
6512 return wpa_s->conf->ap_scan == 2 ||
6513 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
6514}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006515
Dmitry Shmidt04949592012-07-19 12:16:46 -07006516
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006517#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006518int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6519 struct wpa_ssid *ssid,
6520 const char *field,
6521 const char *value)
6522{
6523#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006524 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006525
6526 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
6527 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
6528 (const u8 *) value, os_strlen(value));
6529
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006530 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07006531 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006532#else /* IEEE8021X_EAPOL */
6533 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6534 return -1;
6535#endif /* IEEE8021X_EAPOL */
6536}
6537
6538int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6539 struct wpa_ssid *ssid,
6540 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07006541 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006542{
6543#ifdef IEEE8021X_EAPOL
6544 struct eap_peer_config *eap = &ssid->eap;
Ecco Park00a7b212018-01-26 13:44:44 -08006545 char *identity, *imsi_identity;
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006546
6547 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07006548 case WPA_CTRL_REQ_EAP_IDENTITY:
6549 os_free(eap->identity);
Ecco Park00a7b212018-01-26 13:44:44 -08006550 os_free(eap->imsi_identity);
6551 if (value == NULL)
6552 return -1;
6553 identity = os_strchr(value, ':');
6554 if (identity == NULL) {
6555 /* plain identity */
6556 eap->identity = (u8 *)os_strdup(value);
6557 eap->identity_len = os_strlen(value);
6558 } else {
6559 /* have both plain identity and encrypted identity */
6560 imsi_identity = value;
6561 *identity++ = '\0';
6562 /* plain identity */
6563 eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
6564 eap->imsi_identity_len = strlen(imsi_identity);
6565 /* encrypted identity */
6566 eap->identity = (u8 *)dup_binstr(identity,
6567 value_len - strlen(imsi_identity) - 1);
6568 eap->identity_len = value_len - strlen(imsi_identity) - 1;
6569 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006570 eap->pending_req_identity = 0;
6571 if (ssid == wpa_s->current_ssid)
6572 wpa_s->reassociate = 1;
6573 break;
6574 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006575 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006576 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006577 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006578 eap->pending_req_password = 0;
6579 if (ssid == wpa_s->current_ssid)
6580 wpa_s->reassociate = 1;
6581 break;
6582 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006583 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006584 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006585 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006586 eap->pending_req_new_password = 0;
6587 if (ssid == wpa_s->current_ssid)
6588 wpa_s->reassociate = 1;
6589 break;
6590 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006591 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006592 eap->pin = os_strdup(value);
6593 eap->pending_req_pin = 0;
6594 if (ssid == wpa_s->current_ssid)
6595 wpa_s->reassociate = 1;
6596 break;
6597 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006598 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006599 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006600 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006601 os_free(eap->pending_req_otp);
6602 eap->pending_req_otp = NULL;
6603 eap->pending_req_otp_len = 0;
6604 break;
6605 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006606 str_clear_free(eap->private_key_passwd);
6607 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006608 eap->pending_req_passphrase = 0;
6609 if (ssid == wpa_s->current_ssid)
6610 wpa_s->reassociate = 1;
6611 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006612 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006613 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07006614 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006615 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006616 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006617 case WPA_CTRL_REQ_PSK_PASSPHRASE:
6618 if (wpa_config_set(ssid, "psk", value, 0) < 0)
6619 return -1;
6620 ssid->mem_only_psk = 1;
6621 if (ssid->passphrase)
6622 wpa_config_update_psk(ssid);
6623 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
6624 wpa_supplicant_req_scan(wpa_s, 0, 0);
6625 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006626 case WPA_CTRL_REQ_EXT_CERT_CHECK:
6627 if (eap->pending_ext_cert_check != PENDING_CHECK)
6628 return -1;
6629 if (os_strcmp(value, "good") == 0)
6630 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
6631 else if (os_strcmp(value, "bad") == 0)
6632 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
6633 else
6634 return -1;
6635 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006636 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006637 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006638 return -1;
6639 }
6640
6641 return 0;
6642#else /* IEEE8021X_EAPOL */
6643 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6644 return -1;
6645#endif /* IEEE8021X_EAPOL */
6646}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006647#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006648
6649
6650int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6651{
6652 int i;
6653 unsigned int drv_enc;
6654
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006655 if (wpa_s->p2p_mgmt)
6656 return 1; /* no normal network profiles on p2p_mgmt interface */
6657
Dmitry Shmidt04949592012-07-19 12:16:46 -07006658 if (ssid == NULL)
6659 return 1;
6660
6661 if (ssid->disabled)
6662 return 1;
6663
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006664 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006665 drv_enc = wpa_s->drv_enc;
6666 else
6667 drv_enc = (unsigned int) -1;
6668
6669 for (i = 0; i < NUM_WEP_KEYS; i++) {
6670 size_t len = ssid->wep_key_len[i];
6671 if (len == 0)
6672 continue;
6673 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
6674 continue;
6675 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
6676 continue;
6677 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
6678 continue;
6679 return 1; /* invalid WEP key */
6680 }
6681
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006682 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006683 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006684 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006685 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006686 return 1;
6687
Dmitry Shmidt04949592012-07-19 12:16:46 -07006688 return 0;
6689}
6690
6691
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006692int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6693{
6694#ifdef CONFIG_IEEE80211W
6695 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6696 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6697 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6698 /*
6699 * Driver does not support BIP -- ignore pmf=1 default
6700 * since the connection with PMF would fail and the
6701 * configuration does not require PMF to be enabled.
6702 */
6703 return NO_MGMT_FRAME_PROTECTION;
6704 }
6705
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006706 if (ssid &&
6707 (ssid->key_mgmt &
6708 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6709 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6710 /*
6711 * Do not use the default PMF value for non-RSN networks
6712 * since PMF is available only with RSN and pmf=2
6713 * configuration would otherwise prevent connections to
6714 * all open networks.
6715 */
6716 return NO_MGMT_FRAME_PROTECTION;
6717 }
6718
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006719 return wpa_s->conf->pmf;
6720 }
6721
6722 return ssid->ieee80211w;
6723#else /* CONFIG_IEEE80211W */
6724 return NO_MGMT_FRAME_PROTECTION;
6725#endif /* CONFIG_IEEE80211W */
6726}
6727
6728
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006729int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006730{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006731 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006732 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006733 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006734 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006735 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006736}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006737
6738
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006739void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006740{
6741 struct wpa_ssid *ssid = wpa_s->current_ssid;
6742 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006743 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006744
6745 if (ssid == NULL) {
6746 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6747 "SSID block");
6748 return;
6749 }
6750
6751 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6752 return;
6753
6754 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006755
6756#ifdef CONFIG_P2P
6757 if (ssid->p2p_group &&
6758 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6759 /*
6760 * Skip the wait time since there is a short timeout on the
6761 * connection to a P2P group.
6762 */
6763 return;
6764 }
6765#endif /* CONFIG_P2P */
6766
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006767 if (ssid->auth_failures > 50)
6768 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006769 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006770 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006771 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006772 dur = 90;
6773 else if (ssid->auth_failures > 3)
6774 dur = 60;
6775 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006776 dur = 30;
6777 else if (ssid->auth_failures > 1)
6778 dur = 20;
6779 else
6780 dur = 10;
6781
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006782 if (ssid->auth_failures > 1 &&
6783 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6784 dur += os_random() % (ssid->auth_failures * 10);
6785
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006786 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006787 if (now.sec + dur <= ssid->disabled_until.sec)
6788 return;
6789
6790 ssid->disabled_until.sec = now.sec + dur;
6791
6792 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006793 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006794 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006795 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006796}
6797
6798
6799void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6800 struct wpa_ssid *ssid, int clear_failures)
6801{
6802 if (ssid == NULL)
6803 return;
6804
6805 if (ssid->disabled_until.sec) {
6806 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6807 "id=%d ssid=\"%s\"",
6808 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6809 }
6810 ssid->disabled_until.sec = 0;
6811 ssid->disabled_until.usec = 0;
6812 if (clear_failures)
6813 ssid->auth_failures = 0;
6814}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006815
6816
6817int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6818{
6819 size_t i;
6820
6821 if (wpa_s->disallow_aps_bssid == NULL)
6822 return 0;
6823
6824 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6825 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6826 bssid, ETH_ALEN) == 0)
6827 return 1;
6828 }
6829
6830 return 0;
6831}
6832
6833
6834int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6835 size_t ssid_len)
6836{
6837 size_t i;
6838
6839 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6840 return 0;
6841
6842 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6843 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6844 if (ssid_len == s->ssid_len &&
6845 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6846 return 1;
6847 }
6848
6849 return 0;
6850}
6851
6852
6853/**
6854 * wpas_request_connection - Request a new connection
6855 * @wpa_s: Pointer to the network interface
6856 *
6857 * This function is used to request a new connection to be found. It will mark
6858 * the interface to allow reassociation and request a new scan to find a
6859 * suitable network to connect to.
6860 */
6861void wpas_request_connection(struct wpa_supplicant *wpa_s)
6862{
6863 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006864 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006865 wpa_supplicant_reinit_autoscan(wpa_s);
6866 wpa_s->extra_blacklist_count = 0;
6867 wpa_s->disconnected = 0;
6868 wpa_s->reassociate = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006869 wpa_s->last_owe_group = 0;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006870
6871 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6872 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006873 else
6874 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006875}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006876
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006877
Roshan Pius02242d72016-08-09 15:31:48 -07006878/**
6879 * wpas_request_disconnection - Request disconnection
6880 * @wpa_s: Pointer to the network interface
6881 *
6882 * This function is used to request disconnection from the currently connected
6883 * network. This will stop any ongoing scans and initiate deauthentication.
6884 */
6885void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6886{
6887#ifdef CONFIG_SME
6888 wpa_s->sme.prev_bssid_set = 0;
6889#endif /* CONFIG_SME */
6890 wpa_s->reassociate = 0;
6891 wpa_s->disconnected = 1;
6892 wpa_supplicant_cancel_sched_scan(wpa_s);
6893 wpa_supplicant_cancel_scan(wpa_s);
6894 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6895 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6896}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006897
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006898
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006899void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6900 struct wpa_used_freq_data *freqs_data,
6901 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006902{
6903 unsigned int i;
6904
6905 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6906 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006907 for (i = 0; i < len; i++) {
6908 struct wpa_used_freq_data *cur = &freqs_data[i];
6909 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6910 i, cur->freq, cur->flags);
6911 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006912}
6913
6914
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006915/*
6916 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006917 * are using the same radio as the current interface, and in addition, get
6918 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006919 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006920int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6921 struct wpa_used_freq_data *freqs_data,
6922 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006923{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006924 struct wpa_supplicant *ifs;
6925 u8 bssid[ETH_ALEN];
6926 int freq;
6927 unsigned int idx = 0, i;
6928
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006929 wpa_dbg(wpa_s, MSG_DEBUG,
6930 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006931 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006932
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006933 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6934 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006935 if (idx == len)
6936 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006937
6938 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6939 continue;
6940
6941 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006942 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6943 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006944 freq = ifs->current_ssid->frequency;
6945 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6946 freq = ifs->assoc_freq;
6947 else
6948 continue;
6949
6950 /* Hold only distinct freqs */
6951 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006952 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006953 break;
6954
6955 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006956 freqs_data[idx++].freq = freq;
6957
6958 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006959 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006960 WPA_FREQ_USED_BY_P2P_CLIENT :
6961 WPA_FREQ_USED_BY_INFRA_STATION;
6962 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006963 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006964
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006965 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006966 return idx;
6967}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006968
6969
6970/*
6971 * Find the operating frequencies of any of the virtual interfaces that
6972 * are using the same radio as the current interface.
6973 */
6974int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6975 int *freq_array, unsigned int len)
6976{
6977 struct wpa_used_freq_data *freqs_data;
6978 int num, i;
6979
6980 os_memset(freq_array, 0, sizeof(int) * len);
6981
6982 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6983 if (!freqs_data)
6984 return -1;
6985
6986 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6987 for (i = 0; i < num; i++)
6988 freq_array[i] = freqs_data[i].freq;
6989
6990 os_free(freqs_data);
6991
6992 return num;
6993}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006994
6995
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006996struct wpa_supplicant *
6997wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6998{
6999 switch (frame) {
7000#ifdef CONFIG_P2P
7001 case VENDOR_ELEM_PROBE_REQ_P2P:
7002 case VENDOR_ELEM_PROBE_RESP_P2P:
7003 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
7004 case VENDOR_ELEM_BEACON_P2P_GO:
7005 case VENDOR_ELEM_P2P_PD_REQ:
7006 case VENDOR_ELEM_P2P_PD_RESP:
7007 case VENDOR_ELEM_P2P_GO_NEG_REQ:
7008 case VENDOR_ELEM_P2P_GO_NEG_RESP:
7009 case VENDOR_ELEM_P2P_GO_NEG_CONF:
7010 case VENDOR_ELEM_P2P_INV_REQ:
7011 case VENDOR_ELEM_P2P_INV_RESP:
7012 case VENDOR_ELEM_P2P_ASSOC_REQ:
7013 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007014 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08007015#endif /* CONFIG_P2P */
7016 default:
7017 return wpa_s;
7018 }
7019}
7020
7021
7022void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
7023{
7024 unsigned int i;
7025 char buf[30];
7026
7027 wpa_printf(MSG_DEBUG, "Update vendor elements");
7028
7029 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
7030 if (wpa_s->vendor_elem[i]) {
7031 int res;
7032
7033 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
7034 if (!os_snprintf_error(sizeof(buf), res)) {
7035 wpa_hexdump_buf(MSG_DEBUG, buf,
7036 wpa_s->vendor_elem[i]);
7037 }
7038 }
7039 }
7040
7041#ifdef CONFIG_P2P
7042 if (wpa_s->parent == wpa_s &&
7043 wpa_s->global->p2p &&
7044 !wpa_s->global->p2p_disabled)
7045 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
7046#endif /* CONFIG_P2P */
7047}
7048
7049
7050int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
7051 const u8 *elem, size_t len)
7052{
7053 u8 *ie, *end;
7054
7055 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
7056 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
7057
7058 for (; ie + 1 < end; ie += 2 + ie[1]) {
7059 if (ie + len > end)
7060 break;
7061 if (os_memcmp(ie, elem, len) != 0)
7062 continue;
7063
7064 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
7065 wpabuf_free(wpa_s->vendor_elem[frame]);
7066 wpa_s->vendor_elem[frame] = NULL;
7067 } else {
7068 os_memmove(ie, ie + len, end - (ie + len));
7069 wpa_s->vendor_elem[frame]->used -= len;
7070 }
7071 wpas_vendor_elem_update(wpa_s);
7072 return 0;
7073 }
7074
7075 return -1;
7076}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007077
7078
7079struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
7080 u16 num_modes, enum hostapd_hw_mode mode)
7081{
7082 u16 i;
7083
7084 for (i = 0; i < num_modes; i++) {
7085 if (modes[i].mode == mode)
7086 return &modes[i];
7087 }
7088
7089 return NULL;
7090}
7091
7092
7093static struct
7094wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
7095 const u8 *bssid)
7096{
7097 struct wpa_bss_tmp_disallowed *bss;
7098
7099 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
7100 struct wpa_bss_tmp_disallowed, list) {
7101 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
7102 return bss;
7103 }
7104
7105 return NULL;
7106}
7107
7108
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007109static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
7110{
7111 struct wpa_bss_tmp_disallowed *tmp;
7112 unsigned int num_bssid = 0;
7113 u8 *bssids;
7114 int ret;
7115
7116 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
7117 if (!bssids)
7118 return -1;
7119 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7120 struct wpa_bss_tmp_disallowed, list) {
7121 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
7122 ETH_ALEN);
7123 num_bssid++;
7124 }
7125 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
7126 os_free(bssids);
7127 return ret;
7128}
7129
7130
7131static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
7132{
7133 struct wpa_supplicant *wpa_s = eloop_ctx;
7134 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
7135
7136 /* Make sure the bss is not already freed */
7137 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
7138 struct wpa_bss_tmp_disallowed, list) {
7139 if (bss == tmp) {
7140 dl_list_del(&tmp->list);
7141 os_free(tmp);
7142 wpa_set_driver_tmp_disallow_list(wpa_s);
7143 break;
7144 }
7145 }
7146}
7147
7148
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007149void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
7150 unsigned int sec)
7151{
7152 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007153
7154 bss = wpas_get_disallowed_bss(wpa_s, bssid);
7155 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007156 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
7157 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7158 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007159 return;
7160 }
7161
7162 bss = os_malloc(sizeof(*bss));
7163 if (!bss) {
7164 wpa_printf(MSG_DEBUG,
7165 "Failed to allocate memory for temp disallow BSS");
7166 return;
7167 }
7168
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007169 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7170 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007171 wpa_set_driver_tmp_disallow_list(wpa_s);
7172 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
7173 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007174}
7175
7176
7177int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7178{
7179 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007180
7181 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7182 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007183 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
7184 bss = tmp;
7185 break;
7186 }
7187 }
7188 if (!bss)
7189 return 0;
7190
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007191 return 1;
7192}