blob: 498967b9798fced189c4e453d73fb6ca216af3c1 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidt29333592017-01-09 12:27:11 -08003 * Copyright (c) 2003-2017, 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);
247 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
248}
249
250
251/**
252 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
253 * @wpa_s: Pointer to wpa_supplicant data
254 *
255 * This function is used to cancel authentication timeout scheduled with
256 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
257 * been completed.
258 */
259void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
260{
261 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
262 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
263 wpa_blacklist_del(wpa_s, wpa_s->bssid);
264}
265
266
267/**
268 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
269 * @wpa_s: Pointer to wpa_supplicant data
270 *
271 * This function is used to configure EAPOL state machine based on the selected
272 * authentication mode.
273 */
274void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
275{
276#ifdef IEEE8021X_EAPOL
277 struct eapol_config eapol_conf;
278 struct wpa_ssid *ssid = wpa_s->current_ssid;
279
280#ifdef CONFIG_IBSS_RSN
281 if (ssid->mode == WPAS_MODE_IBSS &&
282 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
283 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
284 /*
285 * RSN IBSS authentication is per-STA and we can disable the
286 * per-BSSID EAPOL authentication.
287 */
288 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
289 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
290 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
291 return;
292 }
293#endif /* CONFIG_IBSS_RSN */
294
295 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
296 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
297
298 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
299 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
300 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
301 else
302 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
303
304 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
305 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
306 eapol_conf.accept_802_1x_keys = 1;
307 eapol_conf.required_keys = 0;
308 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
309 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
310 }
311 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
312 eapol_conf.required_keys |=
313 EAPOL_REQUIRE_KEY_BROADCAST;
314 }
315
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700316 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700317 eapol_conf.required_keys = 0;
318 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700319 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700320 eapol_conf.workaround = ssid->eap_workaround;
321 eapol_conf.eap_disabled =
322 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
323 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
324 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700325 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800326
327#ifdef CONFIG_WPS
328 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
329 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
330 if (wpa_s->current_bss) {
331 struct wpabuf *ie;
332 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
333 WPS_IE_VENDOR_TYPE);
334 if (ie) {
335 if (wps_is_20(ie))
336 eapol_conf.wps |=
337 EAPOL_PEER_IS_WPS20_AP;
338 wpabuf_free(ie);
339 }
340 }
341 }
342#endif /* CONFIG_WPS */
343
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700344 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700345
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800346#ifdef CONFIG_MACSEC
347 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
348 ieee802_1x_create_preshared_mka(wpa_s, ssid);
349 else
350 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
351#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800352#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700353}
354
355
356/**
357 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
358 * @wpa_s: Pointer to wpa_supplicant data
359 * @ssid: Configuration data for the network
360 *
361 * This function is used to configure WPA state machine and related parameters
362 * to a mode where WPA is not enabled. This is called as part of the
363 * authentication configuration when the selected network does not use WPA.
364 */
365void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
366 struct wpa_ssid *ssid)
367{
368 int i;
369
370 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
371 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
372 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
373 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
374 else
375 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
376 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
377 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
378 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
379 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
380 wpa_s->group_cipher = WPA_CIPHER_NONE;
381 wpa_s->mgmt_group_cipher = 0;
382
383 for (i = 0; i < NUM_WEP_KEYS; i++) {
384 if (ssid->wep_key_len[i] > 5) {
385 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
386 wpa_s->group_cipher = WPA_CIPHER_WEP104;
387 break;
388 } else if (ssid->wep_key_len[i] > 0) {
389 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
390 wpa_s->group_cipher = WPA_CIPHER_WEP40;
391 break;
392 }
393 }
394
395 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
396 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
397 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
398 wpa_s->pairwise_cipher);
399 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
400#ifdef CONFIG_IEEE80211W
401 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
402 wpa_s->mgmt_group_cipher);
403#endif /* CONFIG_IEEE80211W */
404
405 pmksa_cache_clear_current(wpa_s->wpa);
406}
407
408
Dmitry Shmidt04949592012-07-19 12:16:46 -0700409void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800410{
411 int i;
412 if (wpa_s->hw.modes == NULL)
413 return;
414
415 for (i = 0; i < wpa_s->hw.num_modes; i++) {
416 os_free(wpa_s->hw.modes[i].channels);
417 os_free(wpa_s->hw.modes[i].rates);
418 }
419
420 os_free(wpa_s->hw.modes);
421 wpa_s->hw.modes = NULL;
422}
423
424
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800425static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
426{
427 struct wpa_bss_tmp_disallowed *bss, *prev;
428
429 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
430 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700431 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800432 dl_list_del(&bss->list);
433 os_free(bss);
434 }
435}
436
437
Paul Stewart092955c2017-02-06 09:13:09 -0800438void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
439{
440 struct fils_hlp_req *req;
441
442 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
443 list)) != NULL) {
444 dl_list_del(&req->list);
445 wpabuf_free(req->pkt);
446 os_free(req);
447 }
448}
449
450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
452{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700453 int i;
454
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700455 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700456 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457 scard_deinit(wpa_s->scard);
458 wpa_s->scard = NULL;
459 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
460 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
461 l2_packet_deinit(wpa_s->l2);
462 wpa_s->l2 = NULL;
463 if (wpa_s->l2_br) {
464 l2_packet_deinit(wpa_s->l2_br);
465 wpa_s->l2_br = NULL;
466 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800467#ifdef CONFIG_TESTING_OPTIONS
468 l2_packet_deinit(wpa_s->l2_test);
469 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800470 os_free(wpa_s->get_pref_freq_list_override);
471 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700472 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
473 wpa_s->last_assoc_req_wpa_ie = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800474#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700475
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700476 if (wpa_s->conf != NULL) {
477 struct wpa_ssid *ssid;
478 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
479 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700480 }
481
482 os_free(wpa_s->confname);
483 wpa_s->confname = NULL;
484
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700485 os_free(wpa_s->confanother);
486 wpa_s->confanother = NULL;
487
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700488 wpa_sm_set_eapol(wpa_s->wpa, NULL);
489 eapol_sm_deinit(wpa_s->eapol);
490 wpa_s->eapol = NULL;
491
492 rsn_preauth_deinit(wpa_s->wpa);
493
494#ifdef CONFIG_TDLS
495 wpa_tdls_deinit(wpa_s->wpa);
496#endif /* CONFIG_TDLS */
497
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800498 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700499 pmksa_candidate_free(wpa_s->wpa);
500 wpa_sm_deinit(wpa_s->wpa);
501 wpa_s->wpa = NULL;
502 wpa_blacklist_clear(wpa_s);
503
504 wpa_bss_deinit(wpa_s);
505
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700506 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700507 wpa_supplicant_cancel_scan(wpa_s);
508 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800509 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
510#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
511 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
512 wpa_s, NULL);
513#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700514
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700515 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
516
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700517 wpas_wps_deinit(wpa_s);
518
519 wpabuf_free(wpa_s->pending_eapol_rx);
520 wpa_s->pending_eapol_rx = NULL;
521
522#ifdef CONFIG_IBSS_RSN
523 ibss_rsn_deinit(wpa_s->ibss_rsn);
524 wpa_s->ibss_rsn = NULL;
525#endif /* CONFIG_IBSS_RSN */
526
527 sme_deinit(wpa_s);
528
529#ifdef CONFIG_AP
530 wpa_supplicant_ap_deinit(wpa_s);
531#endif /* CONFIG_AP */
532
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700533 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700534
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800535#ifdef CONFIG_OFFCHANNEL
536 offchannel_deinit(wpa_s);
537#endif /* CONFIG_OFFCHANNEL */
538
539 wpa_supplicant_cancel_sched_scan(wpa_s);
540
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700541 os_free(wpa_s->next_scan_freqs);
542 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800543
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800544 os_free(wpa_s->manual_scan_freqs);
545 wpa_s->manual_scan_freqs = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700546 os_free(wpa_s->select_network_scan_freqs);
547 wpa_s->select_network_scan_freqs = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800548
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700549 os_free(wpa_s->manual_sched_scan_freqs);
550 wpa_s->manual_sched_scan_freqs = NULL;
551
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800552 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
553
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700554 /*
555 * Need to remove any pending gas-query radio work before the
556 * gas_query_deinit() call because gas_query::work has not yet been set
557 * for works that have not been started. gas_query_free() will be unable
558 * to cancel such pending radio works and once the pending gas-query
559 * radio work eventually gets removed, the deinit notification call to
560 * gas_query_start_cb() would result in dereferencing freed memory.
561 */
562 if (wpa_s->radio)
563 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800564 gas_query_deinit(wpa_s->gas);
565 wpa_s->gas = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700566 gas_server_deinit(wpa_s->gas_server);
567 wpa_s->gas_server = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800568
569 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700570
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700571 ieee802_1x_dealloc_kay_sm(wpa_s);
572
Dmitry Shmidt04949592012-07-19 12:16:46 -0700573 os_free(wpa_s->bssid_filter);
574 wpa_s->bssid_filter = NULL;
575
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800576 os_free(wpa_s->disallow_aps_bssid);
577 wpa_s->disallow_aps_bssid = NULL;
578 os_free(wpa_s->disallow_aps_ssid);
579 wpa_s->disallow_aps_ssid = NULL;
580
Dmitry Shmidt04949592012-07-19 12:16:46 -0700581 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700582#ifdef CONFIG_WNM
583 wnm_deallocate_memory(wpa_s);
584#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700585
586 ext_password_deinit(wpa_s->ext_pw);
587 wpa_s->ext_pw = NULL;
588
589 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800590 wpa_s->last_gas_resp = NULL;
591 wpabuf_free(wpa_s->prev_gas_resp);
592 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700593
594 os_free(wpa_s->last_scan_res);
595 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800596
597#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700598 if (wpa_s->drv_priv)
599 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700600 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800601#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700602
603 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
604 wpabuf_free(wpa_s->vendor_elem[i]);
605 wpa_s->vendor_elem[i] = NULL;
606 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800607
608 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800609
610 wpa_s->sched_scan_plans_num = 0;
611 os_free(wpa_s->sched_scan_plans);
612 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800613
614#ifdef CONFIG_MBO
615 wpa_s->non_pref_chan_num = 0;
616 os_free(wpa_s->non_pref_chan);
617 wpa_s->non_pref_chan = NULL;
618#endif /* CONFIG_MBO */
619
620 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700621
622 wpabuf_free(wpa_s->lci);
623 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800624 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800625
626#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
627#ifdef CONFIG_MESH
628 {
629 struct external_pmksa_cache *entry;
630
631 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
632 struct external_pmksa_cache,
633 list)) != NULL) {
634 dl_list_del(&entry->list);
635 os_free(entry->pmksa_cache);
636 os_free(entry);
637 }
638 }
639#endif /* CONFIG_MESH */
640#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
641
642 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800643
644 wpabuf_free(wpa_s->ric_ies);
645 wpa_s->ric_ies = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700646
647#ifdef CONFIG_DPP
648 wpas_dpp_deinit(wpa_s);
649#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700650}
651
652
653/**
654 * wpa_clear_keys - Clear keys configured for the driver
655 * @wpa_s: Pointer to wpa_supplicant data
656 * @addr: Previously used BSSID or %NULL if not available
657 *
658 * This function clears the encryption keys that has been previously configured
659 * for the driver.
660 */
661void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
662{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800663 int i, max;
664
665#ifdef CONFIG_IEEE80211W
666 max = 6;
667#else /* CONFIG_IEEE80211W */
668 max = 4;
669#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700670
671 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800672 for (i = 0; i < max; i++) {
673 if (wpa_s->keys_cleared & BIT(i))
674 continue;
675 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
676 NULL, 0);
677 }
678 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
679 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700680 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
681 0);
682 /* MLME-SETPROTECTION.request(None) */
683 wpa_drv_mlme_setprotection(
684 wpa_s, addr,
685 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
686 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
687 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800688 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689}
690
691
692/**
693 * wpa_supplicant_state_txt - Get the connection state name as a text string
694 * @state: State (wpa_state; WPA_*)
695 * Returns: The state name as a printable text string
696 */
697const char * wpa_supplicant_state_txt(enum wpa_states state)
698{
699 switch (state) {
700 case WPA_DISCONNECTED:
701 return "DISCONNECTED";
702 case WPA_INACTIVE:
703 return "INACTIVE";
704 case WPA_INTERFACE_DISABLED:
705 return "INTERFACE_DISABLED";
706 case WPA_SCANNING:
707 return "SCANNING";
708 case WPA_AUTHENTICATING:
709 return "AUTHENTICATING";
710 case WPA_ASSOCIATING:
711 return "ASSOCIATING";
712 case WPA_ASSOCIATED:
713 return "ASSOCIATED";
714 case WPA_4WAY_HANDSHAKE:
715 return "4WAY_HANDSHAKE";
716 case WPA_GROUP_HANDSHAKE:
717 return "GROUP_HANDSHAKE";
718 case WPA_COMPLETED:
719 return "COMPLETED";
720 default:
721 return "UNKNOWN";
722 }
723}
724
725
726#ifdef CONFIG_BGSCAN
727
728static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
729{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800730 const char *name;
731
732 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
733 name = wpa_s->current_ssid->bgscan;
734 else
735 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800736 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800737 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800738 if (wpas_driver_bss_selection(wpa_s))
739 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
741 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800742#ifdef CONFIG_P2P
743 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
744 return;
745#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746
747 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800748 if (wpa_s->current_ssid) {
749 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700750 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
751 "bgscan");
752 /*
753 * Live without bgscan; it is only used as a roaming
754 * optimization, so the initial connection is not
755 * affected.
756 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700757 } else {
758 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700759 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700760 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
761 0);
762 if (scan_res) {
763 bgscan_notify_scan(wpa_s, scan_res);
764 wpa_scan_results_free(scan_res);
765 }
766 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700767 } else
768 wpa_s->bgscan_ssid = NULL;
769}
770
771
772static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
773{
774 if (wpa_s->bgscan_ssid != NULL) {
775 bgscan_deinit(wpa_s);
776 wpa_s->bgscan_ssid = NULL;
777 }
778}
779
780#endif /* CONFIG_BGSCAN */
781
782
Dmitry Shmidt04949592012-07-19 12:16:46 -0700783static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
784{
785 if (autoscan_init(wpa_s, 0))
786 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
787}
788
789
790static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
791{
792 autoscan_deinit(wpa_s);
793}
794
795
796void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
797{
798 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
799 wpa_s->wpa_state == WPA_SCANNING) {
800 autoscan_deinit(wpa_s);
801 wpa_supplicant_start_autoscan(wpa_s);
802 }
803}
804
805
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700806/**
807 * wpa_supplicant_set_state - Set current connection state
808 * @wpa_s: Pointer to wpa_supplicant data
809 * @state: The new connection state
810 *
811 * This function is called whenever the connection state changes, e.g.,
812 * association is completed for WPA/WPA2 4-Way Handshake is started.
813 */
814void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
815 enum wpa_states state)
816{
817 enum wpa_states old_state = wpa_s->wpa_state;
818
819 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
820 wpa_supplicant_state_txt(wpa_s->wpa_state),
821 wpa_supplicant_state_txt(state));
822
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800823 if (state == WPA_INTERFACE_DISABLED) {
824 /* Assure normal scan when interface is restored */
825 wpa_s->normal_scans = 0;
826 }
827
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700828 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800829 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700830 /* Reinitialize normal_scan counter */
831 wpa_s->normal_scans = 0;
832 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800833
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700834#ifdef CONFIG_P2P
835 /*
836 * P2PS client has to reply to Probe Request frames received on the
837 * group operating channel. Enable Probe Request frame reporting for
838 * P2P connected client in case p2p_cli_probe configuration property is
839 * set to 1.
840 */
841 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
842 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
843 wpa_s->current_ssid->p2p_group) {
844 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
845 wpa_dbg(wpa_s, MSG_DEBUG,
846 "P2P: Enable CLI Probe Request RX reporting");
847 wpa_s->p2p_cli_probe =
848 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
849 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
850 wpa_dbg(wpa_s, MSG_DEBUG,
851 "P2P: Disable CLI Probe Request RX reporting");
852 wpa_s->p2p_cli_probe = 0;
853 wpa_drv_probe_req_report(wpa_s, 0);
854 }
855 }
856#endif /* CONFIG_P2P */
857
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700858 if (state != WPA_SCANNING)
859 wpa_supplicant_notify_scanning(wpa_s, 0);
860
861 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700862 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700863 int fils_hlp_sent = 0;
864
865#ifdef CONFIG_SME
866 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
867 wpa_auth_alg_fils(wpa_s->sme.auth_alg))
868 fils_hlp_sent = 1;
869#endif /* CONFIG_SME */
870 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
871 wpa_auth_alg_fils(wpa_s->auth_alg))
872 fils_hlp_sent = 1;
873
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700874#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700875 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700876 MACSTR " completed [id=%d id_str=%s%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800877 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700878 ssid ? ssid->id : -1,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700879 ssid && ssid->id_str ? ssid->id_str : "",
880 fils_hlp_sent ? " FILS_HLP_SENT" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700881#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700882 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700883 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800884 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700886 wpa_drv_set_operstate(wpa_s, 1);
887#ifndef IEEE8021X_EAPOL
888 wpa_drv_set_supp_port(wpa_s, 1);
889#endif /* IEEE8021X_EAPOL */
890 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700891 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700893
894 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700895
896#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
897 if (!fils_hlp_sent && ssid && ssid->eap.erp)
898 wpas_update_fils_connect_params(wpa_s);
899#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700900 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
901 state == WPA_ASSOCIATED) {
902 wpa_s->new_connection = 1;
903 wpa_drv_set_operstate(wpa_s, 0);
904#ifndef IEEE8021X_EAPOL
905 wpa_drv_set_supp_port(wpa_s, 0);
906#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700907 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700908 }
909 wpa_s->wpa_state = state;
910
911#ifdef CONFIG_BGSCAN
912 if (state == WPA_COMPLETED)
913 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800914 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700915 wpa_supplicant_stop_bgscan(wpa_s);
916#endif /* CONFIG_BGSCAN */
917
Dmitry Shmidt04949592012-07-19 12:16:46 -0700918 if (state == WPA_AUTHENTICATING)
919 wpa_supplicant_stop_autoscan(wpa_s);
920
921 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
922 wpa_supplicant_start_autoscan(wpa_s);
923
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800924 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
925 wmm_ac_notify_disassoc(wpa_s);
926
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700927 if (wpa_s->wpa_state != old_state) {
928 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
929
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700930 /*
931 * Notify the P2P Device interface about a state change in one
932 * of the interfaces.
933 */
934 wpas_p2p_indicate_state_change(wpa_s);
935
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700936 if (wpa_s->wpa_state == WPA_COMPLETED ||
937 old_state == WPA_COMPLETED)
938 wpas_notify_auth_changed(wpa_s);
939 }
940}
941
942
943void wpa_supplicant_terminate_proc(struct wpa_global *global)
944{
945 int pending = 0;
946#ifdef CONFIG_WPS
947 struct wpa_supplicant *wpa_s = global->ifaces;
948 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800949 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700950 if (wpas_wps_terminate_pending(wpa_s) == 1)
951 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700952#ifdef CONFIG_P2P
953 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
954 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
955 wpas_p2p_disconnect(wpa_s);
956#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800957 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700958 }
959#endif /* CONFIG_WPS */
960 if (pending)
961 return;
962 eloop_terminate();
963}
964
965
966static void wpa_supplicant_terminate(int sig, void *signal_ctx)
967{
968 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700969 wpa_supplicant_terminate_proc(global);
970}
971
972
973void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
974{
975 enum wpa_states old_state = wpa_s->wpa_state;
976
977 wpa_s->pairwise_cipher = 0;
978 wpa_s->group_cipher = 0;
979 wpa_s->mgmt_group_cipher = 0;
980 wpa_s->key_mgmt = 0;
981 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700982 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700983
984 if (wpa_s->wpa_state != old_state)
985 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
986}
987
988
989/**
990 * wpa_supplicant_reload_configuration - Reload configuration data
991 * @wpa_s: Pointer to wpa_supplicant data
992 * Returns: 0 on success or -1 if configuration parsing failed
993 *
994 * This function can be used to request that the configuration data is reloaded
995 * (e.g., after configuration file change). This function is reloading
996 * configuration only for one interface, so this may need to be called multiple
997 * times if %wpa_supplicant is controlling multiple interfaces and all
998 * interfaces need reconfiguration.
999 */
1000int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
1001{
1002 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003 int reconf_ctrl;
1004 int old_ap_scan;
1005
1006 if (wpa_s->confname == NULL)
1007 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001008 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009 if (conf == NULL) {
1010 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
1011 "file '%s' - exiting", wpa_s->confname);
1012 return -1;
1013 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001014 wpa_config_read(wpa_s->confanother, conf);
1015
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 conf->changed_parameters = (unsigned int) -1;
1017
1018 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
1019 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
1020 os_strcmp(conf->ctrl_interface,
1021 wpa_s->conf->ctrl_interface) != 0);
1022
1023 if (reconf_ctrl && wpa_s->ctrl_iface) {
1024 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
1025 wpa_s->ctrl_iface = NULL;
1026 }
1027
1028 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001029 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07001030 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
1031 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001032 wpa_supplicant_deauthenticate(wpa_s,
1033 WLAN_REASON_DEAUTH_LEAVING);
1034 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001035
1036 /*
1037 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001038 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001040 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
1041 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE ||
1042 wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001043 /*
1044 * Clear forced success to clear EAP state for next
1045 * authentication.
1046 */
1047 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1048 }
1049 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1050 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001051 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001052 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1053 rsn_preauth_deinit(wpa_s->wpa);
1054
1055 old_ap_scan = wpa_s->conf->ap_scan;
1056 wpa_config_free(wpa_s->conf);
1057 wpa_s->conf = conf;
1058 if (old_ap_scan != wpa_s->conf->ap_scan)
1059 wpas_notify_ap_scan_changed(wpa_s);
1060
1061 if (reconf_ctrl)
1062 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1063
1064 wpa_supplicant_update_config(wpa_s);
1065
1066 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001067 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001068 wpa_s->reassociate = 1;
1069 wpa_supplicant_req_scan(wpa_s, 0, 0);
1070 }
1071 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1072 return 0;
1073}
1074
1075
1076static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1077{
1078 struct wpa_global *global = signal_ctx;
1079 struct wpa_supplicant *wpa_s;
1080 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1081 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1082 sig);
1083 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1084 wpa_supplicant_terminate_proc(global);
1085 }
1086 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001087
1088 if (wpa_debug_reopen_file() < 0) {
1089 /* Ignore errors since we cannot really do much to fix this */
1090 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1091 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001092}
1093
1094
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001095static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1096 struct wpa_ssid *ssid,
1097 struct wpa_ie_data *ie)
1098{
1099 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1100 if (ret) {
1101 if (ret == -2) {
1102 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1103 "from association info");
1104 }
1105 return -1;
1106 }
1107
1108 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1109 "cipher suites");
1110 if (!(ie->group_cipher & ssid->group_cipher)) {
1111 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1112 "cipher 0x%x (mask 0x%x) - reject",
1113 ie->group_cipher, ssid->group_cipher);
1114 return -1;
1115 }
1116 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1117 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1118 "cipher 0x%x (mask 0x%x) - reject",
1119 ie->pairwise_cipher, ssid->pairwise_cipher);
1120 return -1;
1121 }
1122 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1123 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1124 "management 0x%x (mask 0x%x) - reject",
1125 ie->key_mgmt, ssid->key_mgmt);
1126 return -1;
1127 }
1128
1129#ifdef CONFIG_IEEE80211W
1130 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001131 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1133 "that does not support management frame protection - "
1134 "reject");
1135 return -1;
1136 }
1137#endif /* CONFIG_IEEE80211W */
1138
1139 return 0;
1140}
1141
1142
1143/**
1144 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1145 * @wpa_s: Pointer to wpa_supplicant data
1146 * @bss: Scan results for the selected BSS, or %NULL if not available
1147 * @ssid: Configuration data for the selected network
1148 * @wpa_ie: Buffer for the WPA/RSN IE
1149 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1150 * used buffer length in case the functions returns success.
1151 * Returns: 0 on success or -1 on failure
1152 *
1153 * This function is used to configure authentication and encryption parameters
1154 * based on the network configuration and scan result for the selected BSS (if
1155 * available).
1156 */
1157int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1158 struct wpa_bss *bss, struct wpa_ssid *ssid,
1159 u8 *wpa_ie, size_t *wpa_ie_len)
1160{
1161 struct wpa_ie_data ie;
1162 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001163 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001164
1165 if (bss) {
1166 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1167 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001168 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001169 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001170 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001171
1172 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1173 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1174 (ie.group_cipher & ssid->group_cipher) &&
1175 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1176 (ie.key_mgmt & ssid->key_mgmt)) {
1177 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1178 proto = WPA_PROTO_RSN;
1179 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001180 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001181 (ie.group_cipher & ssid->group_cipher) &&
1182 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1183 (ie.key_mgmt & ssid->key_mgmt)) {
1184 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1185 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001186#ifdef CONFIG_HS20
1187 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1188 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1189 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001190 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001191 ie.group_cipher = WPA_CIPHER_CCMP;
1192 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1193 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1194 proto = WPA_PROTO_OSEN;
1195#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001196 } else if (bss) {
1197 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001198 wpa_dbg(wpa_s, MSG_DEBUG,
1199 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1200 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1201 ssid->key_mgmt);
1202 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1203 MAC2STR(bss->bssid),
1204 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1205 bss_wpa ? " WPA" : "",
1206 bss_rsn ? " RSN" : "",
1207 bss_osen ? " OSEN" : "");
1208 if (bss_rsn) {
1209 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1210 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1211 wpa_dbg(wpa_s, MSG_DEBUG,
1212 "Could not parse RSN element");
1213 } else {
1214 wpa_dbg(wpa_s, MSG_DEBUG,
1215 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1216 ie.pairwise_cipher, ie.group_cipher,
1217 ie.key_mgmt);
1218 }
1219 }
1220 if (bss_wpa) {
1221 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1222 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1223 wpa_dbg(wpa_s, MSG_DEBUG,
1224 "Could not parse WPA element");
1225 } else {
1226 wpa_dbg(wpa_s, MSG_DEBUG,
1227 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1228 ie.pairwise_cipher, ie.group_cipher,
1229 ie.key_mgmt);
1230 }
1231 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001232 return -1;
1233 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001234 if (ssid->proto & WPA_PROTO_OSEN)
1235 proto = WPA_PROTO_OSEN;
1236 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001237 proto = WPA_PROTO_RSN;
1238 else
1239 proto = WPA_PROTO_WPA;
1240 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1241 os_memset(&ie, 0, sizeof(ie));
1242 ie.group_cipher = ssid->group_cipher;
1243 ie.pairwise_cipher = ssid->pairwise_cipher;
1244 ie.key_mgmt = ssid->key_mgmt;
1245#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001246 ie.mgmt_group_cipher = 0;
1247 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
1248 if (ssid->group_mgmt_cipher &
1249 WPA_CIPHER_BIP_GMAC_256)
1250 ie.mgmt_group_cipher =
1251 WPA_CIPHER_BIP_GMAC_256;
1252 else if (ssid->group_mgmt_cipher &
1253 WPA_CIPHER_BIP_CMAC_256)
1254 ie.mgmt_group_cipher =
1255 WPA_CIPHER_BIP_CMAC_256;
1256 else if (ssid->group_mgmt_cipher &
1257 WPA_CIPHER_BIP_GMAC_128)
1258 ie.mgmt_group_cipher =
1259 WPA_CIPHER_BIP_GMAC_128;
1260 else
1261 ie.mgmt_group_cipher =
1262 WPA_CIPHER_AES_128_CMAC;
1263 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001264#endif /* CONFIG_IEEE80211W */
1265 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1266 "based on configuration");
1267 } else
1268 proto = ie.proto;
1269 }
1270
1271 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1272 "pairwise %d key_mgmt %d proto %d",
1273 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1274#ifdef CONFIG_IEEE80211W
1275 if (ssid->ieee80211w) {
1276 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1277 ie.mgmt_group_cipher);
1278 }
1279#endif /* CONFIG_IEEE80211W */
1280
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001281 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001282 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1283 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001284 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001285
1286 if (bss || !wpa_s->ap_ies_from_associnfo) {
1287 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1288 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1289 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1290 bss_rsn ? 2 + bss_rsn[1] : 0))
1291 return -1;
1292 }
1293
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001294#ifdef CONFIG_NO_WPA
1295 wpa_s->group_cipher = WPA_CIPHER_NONE;
1296 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1297#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001299 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1300 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001301 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1302 "cipher");
1303 return -1;
1304 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001305 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1306 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307
1308 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001309 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1310 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001311 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1312 "cipher");
1313 return -1;
1314 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001315 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1316 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001317#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001318
1319 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001320#ifdef CONFIG_SAE
1321 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1322 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1323#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001324 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001325#ifdef CONFIG_SUITEB192
1326 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1327 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1328 wpa_dbg(wpa_s, MSG_DEBUG,
1329 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1330#endif /* CONFIG_SUITEB192 */
1331#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001332 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1333 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1334 wpa_dbg(wpa_s, MSG_DEBUG,
1335 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001336#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001337#ifdef CONFIG_FILS
1338#ifdef CONFIG_IEEE80211R
1339 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1340 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1341 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1342 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1343 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1344 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1345#endif /* CONFIG_IEEE80211R */
1346 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1347 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1348 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1349 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1350 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1351 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1352#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001353#ifdef CONFIG_IEEE80211R
1354 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1355 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1356 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1357 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1358 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1359 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1360#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001361#ifdef CONFIG_SAE
1362 } else if (sel & WPA_KEY_MGMT_SAE) {
1363 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1364 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1365 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1366 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1367 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1368#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001369#ifdef CONFIG_IEEE80211W
1370 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1371 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1372 wpa_dbg(wpa_s, MSG_DEBUG,
1373 "WPA: using KEY_MGMT 802.1X with SHA256");
1374 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1375 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1376 wpa_dbg(wpa_s, MSG_DEBUG,
1377 "WPA: using KEY_MGMT PSK with SHA256");
1378#endif /* CONFIG_IEEE80211W */
1379 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1380 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1381 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1382 } else if (sel & WPA_KEY_MGMT_PSK) {
1383 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1384 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1385 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1386 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1387 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001388#ifdef CONFIG_HS20
1389 } else if (sel & WPA_KEY_MGMT_OSEN) {
1390 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1391 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1392#endif /* CONFIG_HS20 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001393#ifdef CONFIG_OWE
1394 } else if (sel & WPA_KEY_MGMT_OWE) {
1395 wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
1396 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
1397#endif /* CONFIG_OWE */
1398#ifdef CONFIG_DPP
1399 } else if (sel & WPA_KEY_MGMT_DPP) {
1400 wpa_s->key_mgmt = WPA_KEY_MGMT_DPP;
1401 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP");
1402#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001403 } else {
1404 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1405 "authenticated key management type");
1406 return -1;
1407 }
1408
1409 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1410 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1411 wpa_s->pairwise_cipher);
1412 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1413
1414#ifdef CONFIG_IEEE80211W
1415 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001416 if (ssid->group_mgmt_cipher)
1417 sel &= ssid->group_mgmt_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001418 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001419 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1420 sel = 0;
1421 if (sel & WPA_CIPHER_AES_128_CMAC) {
1422 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1423 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1424 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001425 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1426 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1427 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1428 "BIP-GMAC-128");
1429 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1430 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1431 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1432 "BIP-GMAC-256");
1433 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1434 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1435 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1436 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001437 } else {
1438 wpa_s->mgmt_group_cipher = 0;
1439 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1440 }
1441 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1442 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001443 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001444 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001445#endif /* CONFIG_IEEE80211W */
1446
1447 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1448 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1449 return -1;
1450 }
1451
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001452 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001453 int psk_set = 0;
1454
1455 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001456 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1457 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001458 psk_set = 1;
1459 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001460
1461 if (wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password)
1462 psk_set = 1;
1463
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001464#ifndef CONFIG_NO_PBKDF2
1465 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1466 ssid->passphrase) {
1467 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001468 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1469 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001470 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1471 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001472 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001473 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001474 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001475 }
1476#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001477#ifdef CONFIG_EXT_PASSWORD
1478 if (ssid->ext_psk) {
1479 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1480 ssid->ext_psk);
1481 char pw_str[64 + 1];
1482 u8 psk[PMK_LEN];
1483
1484 if (pw == NULL) {
1485 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1486 "found from external storage");
1487 return -1;
1488 }
1489
1490 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1491 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1492 "PSK length %d in external storage",
1493 (int) wpabuf_len(pw));
1494 ext_password_free(pw);
1495 return -1;
1496 }
1497
1498 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1499 pw_str[wpabuf_len(pw)] = '\0';
1500
1501#ifndef CONFIG_NO_PBKDF2
1502 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1503 {
1504 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1505 4096, psk, PMK_LEN);
1506 os_memset(pw_str, 0, sizeof(pw_str));
1507 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1508 "external passphrase)",
1509 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001510 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1511 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001512 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001513 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001514 } else
1515#endif /* CONFIG_NO_PBKDF2 */
1516 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1517 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1518 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1519 "Invalid PSK hex string");
1520 os_memset(pw_str, 0, sizeof(pw_str));
1521 ext_password_free(pw);
1522 return -1;
1523 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001524 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1525 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001526 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001527 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001528 } else {
1529 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1530 "PSK available");
1531 os_memset(pw_str, 0, sizeof(pw_str));
1532 ext_password_free(pw);
1533 return -1;
1534 }
1535
1536 os_memset(pw_str, 0, sizeof(pw_str));
1537 ext_password_free(pw);
1538 }
1539#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001540
1541 if (!psk_set) {
1542 wpa_msg(wpa_s, MSG_INFO,
1543 "No PSK available for association");
1544 return -1;
1545 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001546#ifdef CONFIG_OWE
1547 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1548 /* OWE Diffie-Hellman exchange in (Re)Association
1549 * Request/Response frames set the PMK, so do not override it
1550 * here. */
1551#endif /* CONFIG_OWE */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001552 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001553 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1554
1555 return 0;
1556}
1557
1558
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001559static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1560{
1561 *pos = 0x00;
1562
1563 switch (idx) {
1564 case 0: /* Bits 0-7 */
1565 break;
1566 case 1: /* Bits 8-15 */
1567 break;
1568 case 2: /* Bits 16-23 */
1569#ifdef CONFIG_WNM
1570 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1571 *pos |= 0x08; /* Bit 19 - BSS Transition */
1572#endif /* CONFIG_WNM */
1573 break;
1574 case 3: /* Bits 24-31 */
1575#ifdef CONFIG_WNM
1576 *pos |= 0x02; /* Bit 25 - SSID List */
1577#endif /* CONFIG_WNM */
1578#ifdef CONFIG_INTERWORKING
1579 if (wpa_s->conf->interworking)
1580 *pos |= 0x80; /* Bit 31 - Interworking */
1581#endif /* CONFIG_INTERWORKING */
1582 break;
1583 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001584#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001585 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1586 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001587#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001588 break;
1589 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001590#ifdef CONFIG_HS20
1591 if (wpa_s->conf->hs20)
1592 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1593#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001594#ifdef CONFIG_MBO
1595 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1596#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001597 break;
1598 case 6: /* Bits 48-55 */
1599 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001600 case 7: /* Bits 56-63 */
1601 break;
1602 case 8: /* Bits 64-71 */
1603 if (wpa_s->conf->ftm_responder)
1604 *pos |= 0x40; /* Bit 70 - FTM responder */
1605 if (wpa_s->conf->ftm_initiator)
1606 *pos |= 0x80; /* Bit 71 - FTM initiator */
1607 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001608 case 9: /* Bits 72-79 */
1609#ifdef CONFIG_FILS
1610 *pos |= 0x01;
1611#endif /* CONFIG_FILS */
1612 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001613 }
1614}
1615
1616
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001617int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001618{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001619 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001620 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001621
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001622 if (len < wpa_s->extended_capa_len)
1623 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001624 if (buflen < (size_t) len + 2) {
1625 wpa_printf(MSG_INFO,
1626 "Not enough room for building extended capabilities element");
1627 return -1;
1628 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001629
1630 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001631 *pos++ = len;
1632 for (i = 0; i < len; i++, pos++) {
1633 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001634
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001635 if (i < wpa_s->extended_capa_len) {
1636 *pos &= ~wpa_s->extended_capa_mask[i];
1637 *pos |= wpa_s->extended_capa[i];
1638 }
1639 }
1640
1641 while (len > 0 && buf[1 + len] == 0) {
1642 len--;
1643 buf[1] = len;
1644 }
1645 if (len == 0)
1646 return 0;
1647
1648 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001649}
1650
1651
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001652static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1653 struct wpa_bss *test_bss)
1654{
1655 struct wpa_bss *bss;
1656
1657 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1658 if (bss == test_bss)
1659 return 1;
1660 }
1661
1662 return 0;
1663}
1664
1665
1666static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1667 struct wpa_ssid *test_ssid)
1668{
1669 struct wpa_ssid *ssid;
1670
1671 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1672 if (ssid == test_ssid)
1673 return 1;
1674 }
1675
1676 return 0;
1677}
1678
1679
1680int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1681 struct wpa_ssid *test_ssid)
1682{
1683 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1684 return 0;
1685
1686 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1687}
1688
1689
1690void wpas_connect_work_free(struct wpa_connect_work *cwork)
1691{
1692 if (cwork == NULL)
1693 return;
1694 os_free(cwork);
1695}
1696
1697
1698void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1699{
1700 struct wpa_connect_work *cwork;
1701 struct wpa_radio_work *work = wpa_s->connect_work;
1702
1703 if (!work)
1704 return;
1705
1706 wpa_s->connect_work = NULL;
1707 cwork = work->ctx;
1708 work->ctx = NULL;
1709 wpas_connect_work_free(cwork);
1710 radio_work_done(work);
1711}
1712
1713
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001714int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1715{
1716 struct os_reltime now;
1717 u8 addr[ETH_ALEN];
1718
1719 os_get_reltime(&now);
1720 if (wpa_s->last_mac_addr_style == style &&
1721 wpa_s->last_mac_addr_change.sec != 0 &&
1722 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1723 wpa_s->conf->rand_addr_lifetime)) {
1724 wpa_msg(wpa_s, MSG_DEBUG,
1725 "Previously selected random MAC address has not yet expired");
1726 return 0;
1727 }
1728
1729 switch (style) {
1730 case 1:
1731 if (random_mac_addr(addr) < 0)
1732 return -1;
1733 break;
1734 case 2:
1735 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1736 if (random_mac_addr_keep_oui(addr) < 0)
1737 return -1;
1738 break;
1739 default:
1740 return -1;
1741 }
1742
1743 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1744 wpa_msg(wpa_s, MSG_INFO,
1745 "Failed to set random MAC address");
1746 return -1;
1747 }
1748
1749 os_get_reltime(&wpa_s->last_mac_addr_change);
1750 wpa_s->mac_addr_changed = 1;
1751 wpa_s->last_mac_addr_style = style;
1752
1753 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1754 wpa_msg(wpa_s, MSG_INFO,
1755 "Could not update MAC address information");
1756 return -1;
1757 }
1758
1759 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1760 MAC2STR(addr));
1761
1762 return 0;
1763}
1764
1765
1766int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1767{
1768 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1769 !wpa_s->conf->preassoc_mac_addr)
1770 return 0;
1771
1772 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1773}
1774
1775
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001776static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1777
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001778/**
1779 * wpa_supplicant_associate - Request association
1780 * @wpa_s: Pointer to wpa_supplicant data
1781 * @bss: Scan results for the selected BSS, or %NULL if not available
1782 * @ssid: Configuration data for the selected network
1783 *
1784 * This function is used to request %wpa_supplicant to associate with a BSS.
1785 */
1786void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1787 struct wpa_bss *bss, struct wpa_ssid *ssid)
1788{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001789 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001790 int rand_style;
1791
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001792 wpa_s->own_disconnect_req = 0;
1793
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001794 /*
1795 * If we are starting a new connection, any previously pending EAPOL
1796 * RX cannot be valid anymore.
1797 */
1798 wpabuf_free(wpa_s->pending_eapol_rx);
1799 wpa_s->pending_eapol_rx = NULL;
1800
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001801 if (ssid->mac_addr == -1)
1802 rand_style = wpa_s->conf->mac_addr;
1803 else
1804 rand_style = ssid->mac_addr;
1805
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001806 wmm_ac_clear_saved_tspecs(wpa_s);
1807 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001808 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001809#ifdef CONFIG_TESTING_OPTIONS
1810 wpa_s->testing_resend_assoc = 0;
1811#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001812
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001813 if (wpa_s->last_ssid == ssid) {
1814 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001815 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001816 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1817 wmm_ac_save_tspecs(wpa_s);
1818 wpa_s->reassoc_same_bss = 1;
1819 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001820 }
1821
1822 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001823 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1824 return;
1825 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001826 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001827 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1828 wpa_msg(wpa_s, MSG_INFO,
1829 "Could not restore permanent MAC address");
1830 return;
1831 }
1832 wpa_s->mac_addr_changed = 0;
1833 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1834 wpa_msg(wpa_s, MSG_INFO,
1835 "Could not update MAC address information");
1836 return;
1837 }
1838 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1839 }
1840 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001841
1842#ifdef CONFIG_IBSS_RSN
1843 ibss_rsn_deinit(wpa_s->ibss_rsn);
1844 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001845#else /* CONFIG_IBSS_RSN */
1846 if (ssid->mode == WPAS_MODE_IBSS &&
1847 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1848 wpa_msg(wpa_s, MSG_INFO,
1849 "IBSS RSN not supported in the build");
1850 return;
1851 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001852#endif /* CONFIG_IBSS_RSN */
1853
1854 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1855 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1856#ifdef CONFIG_AP
1857 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1858 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1859 "mode");
1860 return;
1861 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001862 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1863 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001864 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1865 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001866 return;
1867 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001868 wpa_s->current_bss = bss;
1869#else /* CONFIG_AP */
1870 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1871 "the build");
1872#endif /* CONFIG_AP */
1873 return;
1874 }
1875
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001876 if (ssid->mode == WPAS_MODE_MESH) {
1877#ifdef CONFIG_MESH
1878 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1879 wpa_msg(wpa_s, MSG_INFO,
1880 "Driver does not support mesh mode");
1881 return;
1882 }
1883 if (bss)
1884 ssid->frequency = bss->freq;
1885 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1886 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1887 return;
1888 }
1889 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001890 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1891 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1892 ssid->id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001893 wpas_notify_mesh_group_started(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001894#else /* CONFIG_MESH */
1895 wpa_msg(wpa_s, MSG_ERROR,
1896 "mesh mode support not included in the build");
1897#endif /* CONFIG_MESH */
1898 return;
1899 }
1900
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001901 /*
1902 * Set WPA state machine configuration to match the selected network now
1903 * so that the information is available before wpas_start_assoc_cb()
1904 * gets called. This is needed at least for RSN pre-authentication where
1905 * candidate APs are added to a list based on scan result processing
1906 * before completion of the first association.
1907 */
1908 wpa_supplicant_rsn_supp_set_config(wpa_s, ssid);
1909
1910#ifdef CONFIG_DPP
1911 if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0)
1912 return;
1913#endif /* CONFIG_DPP */
1914
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001915#ifdef CONFIG_TDLS
1916 if (bss)
1917 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1918 bss->ie_len);
1919#endif /* CONFIG_TDLS */
1920
1921 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1922 ssid->mode == IEEE80211_MODE_INFRA) {
1923 sme_authenticate(wpa_s, bss, ssid);
1924 return;
1925 }
1926
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001927 if (wpa_s->connect_work) {
1928 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1929 return;
1930 }
1931
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001932 if (radio_work_pending(wpa_s, "connect")) {
1933 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1934 return;
1935 }
1936
Dmitry Shmidt29333592017-01-09 12:27:11 -08001937#ifdef CONFIG_SME
1938 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
1939 /* Clear possibly set auth_alg, if any, from last attempt. */
1940 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
1941 }
1942#endif /* CONFIG_SME */
1943
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001944 wpas_abort_ongoing_scan(wpa_s);
1945
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001946 cwork = os_zalloc(sizeof(*cwork));
1947 if (cwork == NULL)
1948 return;
1949
1950 cwork->bss = bss;
1951 cwork->ssid = ssid;
1952
1953 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1954 wpas_start_assoc_cb, cwork) < 0) {
1955 os_free(cwork);
1956 }
1957}
1958
1959
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001960static int bss_is_ibss(struct wpa_bss *bss)
1961{
1962 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1963 IEEE80211_CAP_IBSS;
1964}
1965
1966
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001967static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1968 const struct wpa_ssid *ssid)
1969{
1970 enum hostapd_hw_mode hw_mode;
1971 struct hostapd_hw_modes *mode = NULL;
1972 u8 channel;
1973 int i;
1974
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001975 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1976 if (hw_mode == NUM_HOSTAPD_MODES)
1977 return 0;
1978 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1979 if (wpa_s->hw.modes[i].mode == hw_mode) {
1980 mode = &wpa_s->hw.modes[i];
1981 break;
1982 }
1983 }
1984
1985 if (!mode)
1986 return 0;
1987
1988 return mode->vht_capab != 0;
1989}
1990
1991
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001992void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1993 const struct wpa_ssid *ssid,
1994 struct hostapd_freq_params *freq)
1995{
1996 enum hostapd_hw_mode hw_mode;
1997 struct hostapd_hw_modes *mode = NULL;
1998 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1999 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002000 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002001 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
2002 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002003 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002004 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002005 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002006 int chwidth, seg0, seg1;
2007 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002008
2009 freq->freq = ssid->frequency;
2010
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002011 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
2012 struct wpa_bss *bss = wpa_s->last_scan_res[j];
2013
2014 if (ssid->mode != WPAS_MODE_IBSS)
2015 break;
2016
2017 /* Don't adjust control freq in case of fixed_freq */
2018 if (ssid->fixed_freq)
2019 break;
2020
2021 if (!bss_is_ibss(bss))
2022 continue;
2023
2024 if (ssid->ssid_len == bss->ssid_len &&
2025 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
2026 wpa_printf(MSG_DEBUG,
2027 "IBSS already found in scan results, adjust control freq: %d",
2028 bss->freq);
2029 freq->freq = bss->freq;
2030 obss_scan = 0;
2031 break;
2032 }
2033 }
2034
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002035 /* For IBSS check HT_IBSS flag */
2036 if (ssid->mode == WPAS_MODE_IBSS &&
2037 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
2038 return;
2039
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002040 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
2041 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
2042 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
2043 wpa_printf(MSG_DEBUG,
2044 "IBSS: WEP/TKIP detected, do not try to enable HT");
2045 return;
2046 }
2047
2048 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002049 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
2050 if (wpa_s->hw.modes[i].mode == hw_mode) {
2051 mode = &wpa_s->hw.modes[i];
2052 break;
2053 }
2054 }
2055
2056 if (!mode)
2057 return;
2058
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002059#ifdef CONFIG_HT_OVERRIDES
2060 if (ssid->disable_ht) {
2061 freq->ht_enabled = 0;
2062 return;
2063 }
2064#endif /* CONFIG_HT_OVERRIDES */
2065
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002066 freq->ht_enabled = ht_supported(mode);
2067 if (!freq->ht_enabled)
2068 return;
2069
2070 /* Setup higher BW only for 5 GHz */
2071 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
2072 return;
2073
2074 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
2075 pri_chan = &mode->channels[chan_idx];
2076 if (pri_chan->chan == channel)
2077 break;
2078 pri_chan = NULL;
2079 }
2080 if (!pri_chan)
2081 return;
2082
2083 /* Check primary channel flags */
2084 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2085 return;
2086
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002087#ifdef CONFIG_HT_OVERRIDES
2088 if (ssid->disable_ht40)
2089 return;
2090#endif /* CONFIG_HT_OVERRIDES */
2091
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002092 /* Check/setup HT40+/HT40- */
2093 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
2094 if (ht40plus[j] == channel) {
2095 ht40 = 1;
2096 break;
2097 }
2098 }
2099
2100 /* Find secondary channel */
2101 for (i = 0; i < mode->num_channels; i++) {
2102 sec_chan = &mode->channels[i];
2103 if (sec_chan->chan == channel + ht40 * 4)
2104 break;
2105 sec_chan = NULL;
2106 }
2107 if (!sec_chan)
2108 return;
2109
2110 /* Check secondary channel flags */
2111 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2112 return;
2113
2114 freq->channel = pri_chan->chan;
2115
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002116 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002117 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2118 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002119 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002120 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2121 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002122 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002123 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002124
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002125 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002126 struct wpa_scan_results *scan_res;
2127
2128 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2129 if (scan_res == NULL) {
2130 /* Back to HT20 */
2131 freq->sec_channel_offset = 0;
2132 return;
2133 }
2134
2135 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2136 sec_chan->chan);
2137 switch (res) {
2138 case 0:
2139 /* Back to HT20 */
2140 freq->sec_channel_offset = 0;
2141 break;
2142 case 1:
2143 /* Configuration allowed */
2144 break;
2145 case 2:
2146 /* Switch pri/sec channels */
2147 freq->freq = hw_get_freq(mode, sec_chan->chan);
2148 freq->sec_channel_offset = -freq->sec_channel_offset;
2149 freq->channel = sec_chan->chan;
2150 break;
2151 default:
2152 freq->sec_channel_offset = 0;
2153 break;
2154 }
2155
2156 wpa_scan_results_free(scan_res);
2157 }
2158
2159 wpa_printf(MSG_DEBUG,
2160 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2161 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002162
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002163 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002164 return;
2165
2166 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002167 if (ssid->mode == WPAS_MODE_IBSS &&
2168 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002169 return;
2170
2171 vht_freq = *freq;
2172
Paul Stewart092955c2017-02-06 09:13:09 -08002173#ifdef CONFIG_VHT_OVERRIDES
2174 if (ssid->disable_vht) {
2175 freq->vht_enabled = 0;
2176 return;
2177 }
2178#endif /* CONFIG_VHT_OVERRIDES */
2179
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002180 vht_freq.vht_enabled = vht_supported(mode);
2181 if (!vht_freq.vht_enabled)
2182 return;
2183
2184 /* setup center_freq1, bandwidth */
2185 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2186 if (freq->channel >= vht80[j] &&
2187 freq->channel < vht80[j] + 16)
2188 break;
2189 }
2190
2191 if (j == ARRAY_SIZE(vht80))
2192 return;
2193
2194 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2195 struct hostapd_channel_data *chan;
2196
2197 chan = hw_get_channel_chan(mode, i, NULL);
2198 if (!chan)
2199 return;
2200
2201 /* Back to HT configuration if channel not usable */
2202 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2203 return;
2204 }
2205
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002206 chwidth = VHT_CHANWIDTH_80MHZ;
2207 seg0 = vht80[j] + 6;
2208 seg1 = 0;
2209
2210 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2211 /* setup center_freq2, bandwidth */
2212 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2213 /* Only accept 80 MHz segments separated by a gap */
2214 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2215 continue;
2216 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2217 struct hostapd_channel_data *chan;
2218
2219 chan = hw_get_channel_chan(mode, i, NULL);
2220 if (!chan)
2221 continue;
2222
2223 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2224 HOSTAPD_CHAN_NO_IR |
2225 HOSTAPD_CHAN_RADAR))
2226 continue;
2227
2228 /* Found a suitable second segment for 80+80 */
2229 chwidth = VHT_CHANWIDTH_80P80MHZ;
2230 vht_caps |=
2231 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2232 seg1 = vht80[k] + 6;
2233 }
2234
2235 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2236 break;
2237 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002238 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2239 if (freq->freq == 5180) {
2240 chwidth = VHT_CHANWIDTH_160MHZ;
2241 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2242 seg0 = 50;
2243 } else if (freq->freq == 5520) {
2244 chwidth = VHT_CHANWIDTH_160MHZ;
2245 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2246 seg0 = 114;
2247 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002248 }
2249
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002250 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2251 freq->channel, freq->ht_enabled,
2252 vht_freq.vht_enabled,
2253 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002254 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002255 return;
2256
2257 *freq = vht_freq;
2258
2259 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2260 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002261}
2262
2263
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002264#ifdef CONFIG_FILS
2265static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
2266 size_t ie_buf_len)
2267{
2268 struct fils_hlp_req *req;
2269 size_t rem_len, hdr_len, hlp_len, len, ie_len = 0;
2270 const u8 *pos;
2271 u8 *buf = ie_buf;
2272
2273 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2274 list) {
2275 rem_len = ie_buf_len - ie_len;
2276 pos = wpabuf_head(req->pkt);
2277 hdr_len = 1 + 2 * ETH_ALEN + 6;
2278 hlp_len = wpabuf_len(req->pkt);
2279
2280 if (rem_len < 2 + hdr_len + hlp_len) {
2281 wpa_printf(MSG_ERROR,
2282 "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu",
2283 (unsigned long) rem_len,
2284 (unsigned long) (2 + hdr_len + hlp_len));
2285 break;
2286 }
2287
2288 len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len;
2289 /* Element ID */
2290 *buf++ = WLAN_EID_EXTENSION;
2291 /* Length */
2292 *buf++ = len;
2293 /* Element ID Extension */
2294 *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER;
2295 /* Destination MAC address */
2296 os_memcpy(buf, req->dst, ETH_ALEN);
2297 buf += ETH_ALEN;
2298 /* Source MAC address */
2299 os_memcpy(buf, wpa_s->own_addr, ETH_ALEN);
2300 buf += ETH_ALEN;
2301 /* LLC/SNAP Header */
2302 os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6);
2303 buf += 6;
2304 /* HLP Packet */
2305 os_memcpy(buf, pos, len - hdr_len);
2306 buf += len - hdr_len;
2307 pos += len - hdr_len;
2308
2309 hlp_len -= len - hdr_len;
2310 ie_len += 2 + len;
2311 rem_len -= 2 + len;
2312
2313 while (hlp_len) {
2314 len = (hlp_len > 255) ? 255 : hlp_len;
2315 if (rem_len < 2 + len)
2316 break;
2317 *buf++ = WLAN_EID_FRAGMENT;
2318 *buf++ = len;
2319 os_memcpy(buf, pos, len);
2320 buf += len;
2321 pos += len;
2322
2323 hlp_len -= len;
2324 ie_len += 2 + len;
2325 rem_len -= 2 + len;
2326 }
2327 }
2328
2329 return ie_len;
2330}
2331#endif /* CONFIG_FILS */
2332
2333
2334static u8 * wpas_populate_assoc_ies(
2335 struct wpa_supplicant *wpa_s,
2336 struct wpa_bss *bss, struct wpa_ssid *ssid,
2337 struct wpa_driver_associate_params *params,
2338 enum wpa_drv_update_connect_params_mask *mask)
2339{
2340 u8 *wpa_ie;
2341 size_t max_wpa_ie_len = 500;
2342 size_t wpa_ie_len;
2343 int algs = WPA_AUTH_ALG_OPEN;
2344#ifdef CONFIG_FILS
2345 const u8 *realm, *username, *rrk;
2346 size_t realm_len, username_len, rrk_len;
2347 u16 next_seq_num;
2348 struct fils_hlp_req *req;
2349
2350 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2351 list) {
2352 max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) +
2353 2 + 2 * wpabuf_len(req->pkt) / 255;
2354 }
2355#endif /* CONFIG_FILS */
2356
2357 wpa_ie = os_malloc(max_wpa_ie_len);
2358 if (!wpa_ie) {
2359 wpa_printf(MSG_ERROR,
2360 "Failed to allocate connect IE buffer for %lu bytes",
2361 (unsigned long) max_wpa_ie_len);
2362 return NULL;
2363 }
2364
2365 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2366 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
2367 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
2368 int try_opportunistic;
2369 const u8 *cache_id = NULL;
2370
2371 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2372 wpa_s->conf->okc :
2373 ssid->proactive_key_caching) &&
2374 (ssid->proto & WPA_PROTO_RSN);
2375#ifdef CONFIG_FILS
2376 if (wpa_key_mgmt_fils(ssid->key_mgmt))
2377 cache_id = wpa_bss_get_fils_cache_id(bss);
2378#endif /* CONFIG_FILS */
2379 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
2380 ssid, try_opportunistic,
2381 cache_id) == 0)
2382 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
2383 wpa_ie_len = max_wpa_ie_len;
2384 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2385 wpa_ie, &wpa_ie_len)) {
2386 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2387 "key management and encryption suites");
2388 os_free(wpa_ie);
2389 return NULL;
2390 }
2391 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2392 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2393 /*
2394 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2395 * use non-WPA since the scan results did not indicate that the
2396 * AP is using WPA or WPA2.
2397 */
2398 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2399 wpa_ie_len = 0;
2400 wpa_s->wpa_proto = 0;
2401 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
2402 wpa_ie_len = max_wpa_ie_len;
2403 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2404 wpa_ie, &wpa_ie_len)) {
2405 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2406 "key management and encryption suites (no "
2407 "scan results)");
2408 os_free(wpa_ie);
2409 return NULL;
2410 }
2411#ifdef CONFIG_WPS
2412 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2413 struct wpabuf *wps_ie;
2414 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2415 if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) {
2416 wpa_ie_len = wpabuf_len(wps_ie);
2417 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2418 } else
2419 wpa_ie_len = 0;
2420 wpabuf_free(wps_ie);
2421 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2422 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2423 params->wps = WPS_MODE_PRIVACY;
2424 else
2425 params->wps = WPS_MODE_OPEN;
2426 wpa_s->wpa_proto = 0;
2427#endif /* CONFIG_WPS */
2428 } else {
2429 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2430 wpa_ie_len = 0;
2431 wpa_s->wpa_proto = 0;
2432 }
2433
2434#ifdef IEEE8021X_EAPOL
2435 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2436 if (ssid->leap) {
2437 if (ssid->non_leap == 0)
2438 algs = WPA_AUTH_ALG_LEAP;
2439 else
2440 algs |= WPA_AUTH_ALG_LEAP;
2441 }
2442 }
2443
2444#ifdef CONFIG_FILS
2445 /* Clear FILS association */
2446 wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
2447
2448 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
2449 ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) &&
2450 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
2451 &username_len, &realm, &realm_len,
2452 &next_seq_num, &rrk, &rrk_len) == 0) {
2453 algs = WPA_AUTH_ALG_FILS;
2454 params->fils_erp_username = username;
2455 params->fils_erp_username_len = username_len;
2456 params->fils_erp_realm = realm;
2457 params->fils_erp_realm_len = realm_len;
2458 params->fils_erp_next_seq_num = next_seq_num;
2459 params->fils_erp_rrk = rrk;
2460 params->fils_erp_rrk_len = rrk_len;
2461
2462 if (mask)
2463 *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
2464 }
2465#endif /* CONFIG_FILS */
2466#endif /* IEEE8021X_EAPOL */
2467
2468 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2469 if (ssid->auth_alg) {
2470 algs = ssid->auth_alg;
2471 wpa_dbg(wpa_s, MSG_DEBUG,
2472 "Overriding auth_alg selection: 0x%x", algs);
2473 }
2474
2475#ifdef CONFIG_P2P
2476 if (wpa_s->global->p2p) {
2477 u8 *pos;
2478 size_t len;
2479 int res;
2480 pos = wpa_ie + wpa_ie_len;
2481 len = max_wpa_ie_len - wpa_ie_len;
2482 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2483 ssid->p2p_group);
2484 if (res >= 0)
2485 wpa_ie_len += res;
2486 }
2487
2488 wpa_s->cross_connect_disallowed = 0;
2489 if (bss) {
2490 struct wpabuf *p2p;
2491 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2492 if (p2p) {
2493 wpa_s->cross_connect_disallowed =
2494 p2p_get_cross_connect_disallowed(p2p);
2495 wpabuf_free(p2p);
2496 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2497 "connection",
2498 wpa_s->cross_connect_disallowed ?
2499 "disallows" : "allows");
2500 }
2501 }
2502
2503 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
2504#endif /* CONFIG_P2P */
2505
2506 if (bss) {
2507 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
2508 wpa_ie + wpa_ie_len,
2509 max_wpa_ie_len -
2510 wpa_ie_len);
2511 }
2512
2513 /*
2514 * Workaround: Add Extended Capabilities element only if the AP
2515 * included this element in Beacon/Probe Response frames. Some older
2516 * APs seem to have interoperability issues if this element is
2517 * included, so while the standard may require us to include the
2518 * element in all cases, it is justifiable to skip it to avoid
2519 * interoperability issues.
2520 */
2521 if (ssid->p2p_group)
2522 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2523 else
2524 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2525
2526 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
2527 u8 ext_capab[18];
2528 int ext_capab_len;
2529 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2530 sizeof(ext_capab));
2531 if (ext_capab_len > 0 &&
2532 wpa_ie_len + ext_capab_len <= max_wpa_ie_len) {
2533 u8 *pos = wpa_ie;
2534 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2535 pos += 2 + pos[1];
2536 os_memmove(pos + ext_capab_len, pos,
2537 wpa_ie_len - (pos - wpa_ie));
2538 wpa_ie_len += ext_capab_len;
2539 os_memcpy(pos, ext_capab, ext_capab_len);
2540 }
2541 }
2542
2543#ifdef CONFIG_HS20
2544 if (is_hs20_network(wpa_s, ssid, bss)) {
2545 struct wpabuf *hs20;
2546
2547 hs20 = wpabuf_alloc(20);
2548 if (hs20) {
2549 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2550 size_t len;
2551
2552 wpas_hs20_add_indication(hs20, pps_mo_id);
2553 len = max_wpa_ie_len - wpa_ie_len;
2554 if (wpabuf_len(hs20) <= len) {
2555 os_memcpy(wpa_ie + wpa_ie_len,
2556 wpabuf_head(hs20), wpabuf_len(hs20));
2557 wpa_ie_len += wpabuf_len(hs20);
2558 }
2559 wpabuf_free(hs20);
2560
2561 hs20_configure_frame_filters(wpa_s);
2562 }
2563 }
2564#endif /* CONFIG_HS20 */
2565
2566 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2567 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2568 size_t len;
2569
2570 len = max_wpa_ie_len - wpa_ie_len;
2571 if (wpabuf_len(buf) <= len) {
2572 os_memcpy(wpa_ie + wpa_ie_len,
2573 wpabuf_head(buf), wpabuf_len(buf));
2574 wpa_ie_len += wpabuf_len(buf);
2575 }
2576 }
2577
2578#ifdef CONFIG_FST
2579 if (wpa_s->fst_ies) {
2580 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2581
2582 if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) {
2583 os_memcpy(wpa_ie + wpa_ie_len,
2584 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2585 wpa_ie_len += fst_ies_len;
2586 }
2587 }
2588#endif /* CONFIG_FST */
2589
2590#ifdef CONFIG_MBO
2591 if (bss && wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
2592 int len;
2593
2594 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2595 max_wpa_ie_len - wpa_ie_len);
2596 if (len >= 0)
2597 wpa_ie_len += len;
2598 }
2599#endif /* CONFIG_MBO */
2600
2601#ifdef CONFIG_FILS
2602 if (algs == WPA_AUTH_ALG_FILS) {
2603 size_t len;
2604
2605 len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len,
2606 max_wpa_ie_len - wpa_ie_len);
2607 wpa_ie_len += len;
2608 }
2609#endif /* CONFIG_FILS */
2610
2611#ifdef CONFIG_OWE
2612 if (algs == WPA_AUTH_ALG_OPEN &&
2613 ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
2614 struct wpabuf *owe_ie;
2615 u16 group = OWE_DH_GROUP;
2616
2617 if (ssid->owe_group)
2618 group = ssid->owe_group;
2619 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2620 if (owe_ie &&
2621 wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
2622 os_memcpy(wpa_ie + wpa_ie_len,
2623 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2624 wpa_ie_len += wpabuf_len(owe_ie);
2625 wpabuf_free(owe_ie);
2626 }
2627 }
2628#endif /* CONFIG_OWE */
2629
2630 params->wpa_ie = wpa_ie;
2631 params->wpa_ie_len = wpa_ie_len;
2632 params->auth_alg = algs;
2633 if (mask)
2634 *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
2635
2636 return wpa_ie;
2637}
2638
2639
2640#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
2641static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
2642{
2643 struct wpa_driver_associate_params params;
2644 enum wpa_drv_update_connect_params_mask mask = 0;
2645 u8 *wpa_ie;
2646
2647 if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
2648 return; /* nothing to do */
2649
2650 os_memset(&params, 0, sizeof(params));
2651 wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
2652 wpa_s->current_ssid, &params, &mask);
2653 if (!wpa_ie)
2654 return;
2655
2656 if (params.auth_alg != WPA_AUTH_ALG_FILS) {
2657 os_free(wpa_ie);
2658 return;
2659 }
2660
2661 wpa_s->auth_alg = params.auth_alg;
2662 wpa_drv_update_connect_params(wpa_s, &params, mask);
2663 os_free(wpa_ie);
2664}
2665#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
2666
2667
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002668static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2669{
2670 struct wpa_connect_work *cwork = work->ctx;
2671 struct wpa_bss *bss = cwork->bss;
2672 struct wpa_ssid *ssid = cwork->ssid;
2673 struct wpa_supplicant *wpa_s = work->wpa_s;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002674 u8 *wpa_ie;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002675 int use_crypt, ret, i, bssid_changed;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002676 unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002677 struct wpa_driver_associate_params params;
2678 int wep_keys_set = 0;
2679 int assoc_failed = 0;
2680 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002681 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002682#ifdef CONFIG_HT_OVERRIDES
2683 struct ieee80211_ht_capabilities htcaps;
2684 struct ieee80211_ht_capabilities htcaps_mask;
2685#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002686#ifdef CONFIG_VHT_OVERRIDES
2687 struct ieee80211_vht_capabilities vhtcaps;
2688 struct ieee80211_vht_capabilities vhtcaps_mask;
2689#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002690
2691 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002692 if (work->started) {
2693 wpa_s->connect_work = NULL;
2694
2695 /* cancel possible auth. timeout */
2696 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2697 NULL);
2698 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002699 wpas_connect_work_free(cwork);
2700 return;
2701 }
2702
2703 wpa_s->connect_work = work;
2704
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002705 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2706 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002707 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2708 wpas_connect_work_done(wpa_s);
2709 return;
2710 }
2711
Dmitry Shmidte4663042016-04-04 10:07:49 -07002712 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 os_memset(&params, 0, sizeof(params));
2714 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002715 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002716 if (bss &&
2717 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002718#ifdef CONFIG_IEEE80211R
2719 const u8 *ie, *md = NULL;
2720#endif /* CONFIG_IEEE80211R */
2721 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2722 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2723 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2724 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2725 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2726 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2727 if (bssid_changed)
2728 wpas_notify_bssid_changed(wpa_s);
2729#ifdef CONFIG_IEEE80211R
2730 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2731 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2732 md = ie + 2;
2733 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2734 if (md) {
2735 /* Prepare for the next transition */
2736 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2737 }
2738#endif /* CONFIG_IEEE80211R */
2739#ifdef CONFIG_WPS
2740 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2741 wpa_s->conf->ap_scan == 2 &&
2742 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2743 /* Use ap_scan==1 style network selection to find the network
2744 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002745 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002746 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002747 wpa_s->reassociate = 1;
2748 wpa_supplicant_req_scan(wpa_s, 0, 0);
2749 return;
2750#endif /* CONFIG_WPS */
2751 } else {
2752 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2753 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002754 if (bss)
2755 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2756 else
2757 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002758 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002759 if (!wpa_s->pno)
2760 wpa_supplicant_cancel_sched_scan(wpa_s);
2761
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002762 wpa_supplicant_cancel_scan(wpa_s);
2763
2764 /* Starting new association, so clear the possibly used WPA IE from the
2765 * previous association. */
2766 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2767
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002768 wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
2769 if (!wpa_ie) {
2770 wpas_connect_work_done(wpa_s);
2771 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002773
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002774 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2775 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002776 cipher_pairwise = wpa_s->pairwise_cipher;
2777 cipher_group = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002778 cipher_group_mgmt = wpa_s->mgmt_group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002779 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2780 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2781 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2782 use_crypt = 0;
2783 if (wpa_set_wep_keys(wpa_s, ssid)) {
2784 use_crypt = 1;
2785 wep_keys_set = 1;
2786 }
2787 }
2788 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2789 use_crypt = 0;
2790
2791#ifdef IEEE8021X_EAPOL
2792 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2793 if ((ssid->eapol_flags &
2794 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2795 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2796 !wep_keys_set) {
2797 use_crypt = 0;
2798 } else {
2799 /* Assume that dynamic WEP-104 keys will be used and
2800 * set cipher suites in order for drivers to expect
2801 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002802 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 }
2804 }
2805#endif /* IEEE8021X_EAPOL */
2806
2807 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2808 /* Set the key before (and later after) association */
2809 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2810 }
2811
2812 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2813 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002814 params.ssid = bss->ssid;
2815 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002816 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2817 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002818 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2819 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002820 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002821 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002822 ssid->bssid_set,
2823 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002824 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002825 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002826 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002827 params.bssid_hint = bss->bssid;
2828 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002829 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002830 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002831 if (ssid->bssid_hint_set)
2832 params.bssid_hint = ssid->bssid_hint;
2833
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002834 params.ssid = ssid->ssid;
2835 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002836 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002837 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002838
2839 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2840 wpa_s->conf->ap_scan == 2) {
2841 params.bssid = ssid->bssid;
2842 params.fixed_bssid = 1;
2843 }
2844
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002845 /* Initial frequency for IBSS/mesh */
2846 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002847 ssid->frequency > 0 && params.freq.freq == 0)
2848 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002849
2850 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002851 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002852 if (ssid->beacon_int)
2853 params.beacon_int = ssid->beacon_int;
2854 else
2855 params.beacon_int = wpa_s->conf->beacon_int;
2856 }
2857
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002858 params.pairwise_suite = cipher_pairwise;
2859 params.group_suite = cipher_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002860 params.mgmt_group_suite = cipher_group_mgmt;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002861 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002862 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002863 wpa_s->auth_alg = params.auth_alg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002864 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002865 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002866 for (i = 0; i < NUM_WEP_KEYS; i++) {
2867 if (ssid->wep_key_len[i])
2868 params.wep_key[i] = ssid->wep_key[i];
2869 params.wep_key_len[i] = ssid->wep_key_len[i];
2870 }
2871 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2872
2873 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002874 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2875 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002876 params.passphrase = ssid->passphrase;
2877 if (ssid->psk_set)
2878 params.psk = ssid->psk;
2879 }
2880
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002881 if (wpa_s->conf->key_mgmt_offload) {
2882 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2883 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002884 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2885 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002886 params.req_key_mgmt_offload =
2887 ssid->proactive_key_caching < 0 ?
2888 wpa_s->conf->okc : ssid->proactive_key_caching;
2889 else
2890 params.req_key_mgmt_offload = 1;
2891
2892 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2893 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2894 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2895 ssid->psk_set)
2896 params.psk = ssid->psk;
2897 }
2898
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002899 params.drop_unencrypted = use_crypt;
2900
2901#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002902 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002903 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2905 struct wpa_ie_data ie;
2906 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2907 ie.capabilities &
2908 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2909 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2910 "MFP: require MFP");
2911 params.mgmt_frame_protection =
2912 MGMT_FRAME_PROTECTION_REQUIRED;
2913 }
2914 }
2915#endif /* CONFIG_IEEE80211W */
2916
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002917 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002918
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002919 if (wpa_s->p2pdev->set_sta_uapsd)
2920 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921 else
2922 params.uapsd = -1;
2923
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002924#ifdef CONFIG_HT_OVERRIDES
2925 os_memset(&htcaps, 0, sizeof(htcaps));
2926 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2927 params.htcaps = (u8 *) &htcaps;
2928 params.htcaps_mask = (u8 *) &htcaps_mask;
2929 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2930#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002931#ifdef CONFIG_VHT_OVERRIDES
2932 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2933 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2934 params.vhtcaps = &vhtcaps;
2935 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002936 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002937#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002938
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002939#ifdef CONFIG_P2P
2940 /*
2941 * If multi-channel concurrency is not supported, check for any
2942 * frequency conflict. In case of any frequency conflict, remove the
2943 * least prioritized connection.
2944 */
2945 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002946 int freq, num;
2947 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002948 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002949 wpa_printf(MSG_DEBUG,
2950 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002951 freq, params.freq.freq);
2952 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002953 wpa_s, params.freq.freq, ssid) < 0) {
2954 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002955 os_free(wpa_ie);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002956 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002957 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002958 }
2959 }
2960#endif /* CONFIG_P2P */
2961
Dmitry Shmidte4663042016-04-04 10:07:49 -07002962 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2963 wpa_s->current_ssid)
2964 params.prev_bssid = prev_bssid;
2965
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002966 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002967 os_free(wpa_ie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002968 if (ret < 0) {
2969 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2970 "failed");
2971 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2972 /*
2973 * The driver is known to mean what is saying, so we
2974 * can stop right here; the association will not
2975 * succeed.
2976 */
2977 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002978 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002979 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2980 return;
2981 }
2982 /* try to continue anyway; new association will be tried again
2983 * after timeout */
2984 assoc_failed = 1;
2985 }
2986
2987 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2988 /* Set the key after the association just in case association
2989 * cleared the previously configured key. */
2990 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2991 /* No need to timeout authentication since there is no key
2992 * management. */
2993 wpa_supplicant_cancel_auth_timeout(wpa_s);
2994 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2995#ifdef CONFIG_IBSS_RSN
2996 } else if (ssid->mode == WPAS_MODE_IBSS &&
2997 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2998 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2999 /*
3000 * RSN IBSS authentication is per-STA and we can disable the
3001 * per-BSSID authentication.
3002 */
3003 wpa_supplicant_cancel_auth_timeout(wpa_s);
3004#endif /* CONFIG_IBSS_RSN */
3005 } else {
3006 /* Timeout for IEEE 802.11 authentication and association */
3007 int timeout = 60;
3008
3009 if (assoc_failed) {
3010 /* give IBSS a bit more time */
3011 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
3012 } else if (wpa_s->conf->ap_scan == 1) {
3013 /* give IBSS a bit more time */
3014 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
3015 }
3016 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
3017 }
3018
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003019 if (wep_keys_set &&
3020 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003021 /* Set static WEP keys again */
3022 wpa_set_wep_keys(wpa_s, ssid);
3023 }
3024
3025 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
3026 /*
3027 * Do not allow EAP session resumption between different
3028 * network configurations.
3029 */
3030 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3031 }
3032 old_ssid = wpa_s->current_ssid;
3033 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003034
3035 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07003036 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003037#ifdef CONFIG_HS20
3038 hs20_configure_frame_filters(wpa_s);
3039#endif /* CONFIG_HS20 */
3040 }
3041
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003042 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
3043 wpa_supplicant_initiate_eapol(wpa_s);
3044 if (old_ssid != wpa_s->current_ssid)
3045 wpas_notify_network_changed(wpa_s);
3046}
3047
3048
3049static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
3050 const u8 *addr)
3051{
3052 struct wpa_ssid *old_ssid;
3053
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003054 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003055 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003056 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003057 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058 wpa_sm_set_config(wpa_s->wpa, NULL);
3059 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3060 if (old_ssid != wpa_s->current_ssid)
3061 wpas_notify_network_changed(wpa_s);
3062 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3063}
3064
3065
3066/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003067 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
3068 * @wpa_s: Pointer to wpa_supplicant data
3069 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
3070 *
3071 * This function is used to request %wpa_supplicant to deauthenticate from the
3072 * current AP.
3073 */
3074void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
3075 int reason_code)
3076{
3077 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003078 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003079 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003080
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003081 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
3082 " pending_bssid=" MACSTR " reason=%d state=%s",
3083 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
3084 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
3085
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003086 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
3087 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
3088 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003089 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003090 else if (!is_zero_ether_addr(wpa_s->bssid))
3091 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003092 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3093 /*
3094 * When using driver-based BSS selection, we may not know the
3095 * BSSID with which we are currently trying to associate. We
3096 * need to notify the driver of this disconnection even in such
3097 * a case, so use the all zeros address here.
3098 */
3099 addr = wpa_s->bssid;
3100 zero_addr = 1;
3101 }
3102
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003103#ifdef CONFIG_TDLS
3104 wpa_tdls_teardown_peers(wpa_s->wpa);
3105#endif /* CONFIG_TDLS */
3106
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003107#ifdef CONFIG_MESH
3108 if (wpa_s->ifmsh) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003109 struct mesh_conf *mconf;
3110
3111 mconf = wpa_s->ifmsh->mconf;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003112 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
3113 wpa_s->ifname);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003114 wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
3115 mconf->meshid_len, reason_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003116 wpa_supplicant_leave_mesh(wpa_s);
3117 }
3118#endif /* CONFIG_MESH */
3119
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003120 if (addr) {
3121 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003122 os_memset(&event, 0, sizeof(event));
3123 event.deauth_info.reason_code = (u16) reason_code;
3124 event.deauth_info.locally_generated = 1;
3125 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003126 if (zero_addr)
3127 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003128 }
3129
3130 wpa_supplicant_clear_connection(wpa_s, addr);
3131}
3132
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003133static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
3134 struct wpa_ssid *ssid)
3135{
3136 if (!ssid || !ssid->disabled || ssid->disabled == 2)
3137 return;
3138
3139 ssid->disabled = 0;
3140 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3141 wpas_notify_network_enabled_changed(wpa_s, ssid);
3142
3143 /*
3144 * Try to reassociate since there is no current configuration and a new
3145 * network was made available.
3146 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003147 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003148 wpa_s->reassociate = 1;
3149}
3150
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003151
Roshan Pius950bec92016-07-19 09:49:24 -07003152/**
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003153 * wpa_supplicant_add_network - Add a new network
Roshan Pius950bec92016-07-19 09:49:24 -07003154 * @wpa_s: wpa_supplicant structure for a network interface
3155 * Returns: The new network configuration or %NULL if operation failed
3156 *
3157 * This function performs the following operations:
3158 * 1. Adds a new network.
3159 * 2. Send network addition notification.
3160 * 3. Marks the network disabled.
3161 * 4. Set network default parameters.
3162 */
3163struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
3164{
3165 struct wpa_ssid *ssid;
3166
3167 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003168 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003169 return NULL;
Roshan Pius950bec92016-07-19 09:49:24 -07003170 wpas_notify_network_added(wpa_s, ssid);
3171 ssid->disabled = 1;
3172 wpa_config_set_network_defaults(ssid);
3173
3174 return ssid;
3175}
3176
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003177
Roshan Pius950bec92016-07-19 09:49:24 -07003178/**
3179 * wpa_supplicant_remove_network - Remove a configured network based on id
3180 * @wpa_s: wpa_supplicant structure for a network interface
3181 * @id: Unique network id to search for
3182 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
3183 * could not be removed
3184 *
3185 * This function performs the following operations:
3186 * 1. Removes the network.
3187 * 2. Send network removal notification.
3188 * 3. Update internal state machines.
3189 * 4. Stop any running sched scans.
3190 */
3191int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
3192{
3193 struct wpa_ssid *ssid;
3194 int was_disabled;
3195
3196 ssid = wpa_config_get_network(wpa_s->conf, id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003197 if (!ssid)
Roshan Pius950bec92016-07-19 09:49:24 -07003198 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003199 wpas_notify_network_removed(wpa_s, ssid);
Roshan Pius950bec92016-07-19 09:49:24 -07003200
3201 if (wpa_s->last_ssid == ssid)
3202 wpa_s->last_ssid = NULL;
3203
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003204 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
Roshan Pius950bec92016-07-19 09:49:24 -07003205#ifdef CONFIG_SME
3206 wpa_s->sme.prev_bssid_set = 0;
3207#endif /* CONFIG_SME */
3208 /*
3209 * Invalidate the EAP session cache if the current or
3210 * previously used network is removed.
3211 */
3212 eapol_sm_invalidate_cached_session(wpa_s->eapol);
3213 }
3214
3215 if (ssid == wpa_s->current_ssid) {
3216 wpa_sm_set_config(wpa_s->wpa, NULL);
3217 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
3218
3219 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3220 wpa_s->own_disconnect_req = 1;
3221 wpa_supplicant_deauthenticate(wpa_s,
3222 WLAN_REASON_DEAUTH_LEAVING);
3223 }
3224
3225 was_disabled = ssid->disabled;
3226
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003227 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
Roshan Pius950bec92016-07-19 09:49:24 -07003228 return -2;
Roshan Pius950bec92016-07-19 09:49:24 -07003229
3230 if (!was_disabled && wpa_s->sched_scanning) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003231 wpa_printf(MSG_DEBUG,
3232 "Stop ongoing sched_scan to remove network from filters");
Roshan Pius950bec92016-07-19 09:49:24 -07003233 wpa_supplicant_cancel_sched_scan(wpa_s);
3234 wpa_supplicant_req_scan(wpa_s, 0, 0);
3235 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003236
Roshan Pius950bec92016-07-19 09:49:24 -07003237 return 0;
3238}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003239
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003240
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003241/**
3242 * wpa_supplicant_enable_network - Mark a configured network as enabled
3243 * @wpa_s: wpa_supplicant structure for a network interface
3244 * @ssid: wpa_ssid structure for a configured network or %NULL
3245 *
3246 * Enables the specified network or all networks if no network specified.
3247 */
3248void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
3249 struct wpa_ssid *ssid)
3250{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003251 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003252 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3253 wpa_supplicant_enable_one_network(wpa_s, ssid);
3254 } else
3255 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003256
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003257 if (wpa_s->reassociate && !wpa_s->disconnected &&
3258 (!wpa_s->current_ssid ||
3259 wpa_s->wpa_state == WPA_DISCONNECTED ||
3260 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003261 if (wpa_s->sched_scanning) {
3262 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
3263 "new network to scan filters");
3264 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003265 }
3266
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003267 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3268 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003269 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003270 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003271 }
3272}
3273
3274
3275/**
3276 * wpa_supplicant_disable_network - Mark a configured network as disabled
3277 * @wpa_s: wpa_supplicant structure for a network interface
3278 * @ssid: wpa_ssid structure for a configured network or %NULL
3279 *
3280 * Disables the specified network or all networks if no network specified.
3281 */
3282void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
3283 struct wpa_ssid *ssid)
3284{
3285 struct wpa_ssid *other_ssid;
3286 int was_disabled;
3287
3288 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003289 if (wpa_s->sched_scanning)
3290 wpa_supplicant_cancel_sched_scan(wpa_s);
3291
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003292 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3293 other_ssid = other_ssid->next) {
3294 was_disabled = other_ssid->disabled;
3295 if (was_disabled == 2)
3296 continue; /* do not change persistent P2P group
3297 * data */
3298
3299 other_ssid->disabled = 1;
3300
3301 if (was_disabled != other_ssid->disabled)
3302 wpas_notify_network_enabled_changed(
3303 wpa_s, other_ssid);
3304 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003305 if (wpa_s->current_ssid) {
3306 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3307 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003308 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003309 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003310 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311 } else if (ssid->disabled != 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003312 if (ssid == wpa_s->current_ssid) {
3313 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3314 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003315 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003316 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003317 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003318
3319 was_disabled = ssid->disabled;
3320
3321 ssid->disabled = 1;
3322
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003323 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003324 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003325 if (wpa_s->sched_scanning) {
3326 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3327 "to remove network from filters");
3328 wpa_supplicant_cancel_sched_scan(wpa_s);
3329 wpa_supplicant_req_scan(wpa_s, 0, 0);
3330 }
3331 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003332 }
3333}
3334
3335
3336/**
3337 * wpa_supplicant_select_network - Attempt association with a network
3338 * @wpa_s: wpa_supplicant structure for a network interface
3339 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3340 */
3341void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3342 struct wpa_ssid *ssid)
3343{
3344
3345 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003346 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003347
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003348 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003349 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3350 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003351 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003352 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003353 disconnected = 1;
3354 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003355
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003356 if (ssid)
3357 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3358
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003359 /*
3360 * Mark all other networks disabled or mark all networks enabled if no
3361 * network specified.
3362 */
3363 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3364 other_ssid = other_ssid->next) {
3365 int was_disabled = other_ssid->disabled;
3366 if (was_disabled == 2)
3367 continue; /* do not change persistent P2P group data */
3368
3369 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003370 if (was_disabled && !other_ssid->disabled)
3371 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003372
3373 if (was_disabled != other_ssid->disabled)
3374 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3375 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003376
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003377 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3378 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003379 /* We are already associated with the selected network */
3380 wpa_printf(MSG_DEBUG, "Already associated with the "
3381 "selected network - do nothing");
3382 return;
3383 }
3384
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003385 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003386 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003387 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003388 wpa_s->connect_without_scan =
3389 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003390
3391 /*
3392 * Don't optimize next scan freqs since a new ESS has been
3393 * selected.
3394 */
3395 os_free(wpa_s->next_scan_freqs);
3396 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003397 } else {
3398 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003399 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003400
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401 wpa_s->disconnected = 0;
3402 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003403
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003404 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003405 wpa_supplicant_fast_associate(wpa_s) != 1) {
3406 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003407 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003408 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003409 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003410
3411 if (ssid)
3412 wpas_notify_network_selected(wpa_s, ssid);
3413}
3414
3415
3416/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003417 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3418 * @wpa_s: wpa_supplicant structure for a network interface
3419 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3420 * @pkcs11_module_path: PKCS #11 module path or NULL
3421 * Returns: 0 on success; -1 on failure
3422 *
3423 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3424 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3425 * module path fails the paths will be reset to the default value (NULL).
3426 */
3427int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3428 const char *pkcs11_engine_path,
3429 const char *pkcs11_module_path)
3430{
3431 char *pkcs11_engine_path_copy = NULL;
3432 char *pkcs11_module_path_copy = NULL;
3433
3434 if (pkcs11_engine_path != NULL) {
3435 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3436 if (pkcs11_engine_path_copy == NULL)
3437 return -1;
3438 }
3439 if (pkcs11_module_path != NULL) {
3440 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003441 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003442 os_free(pkcs11_engine_path_copy);
3443 return -1;
3444 }
3445 }
3446
3447 os_free(wpa_s->conf->pkcs11_engine_path);
3448 os_free(wpa_s->conf->pkcs11_module_path);
3449 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3450 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3451
3452 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3453 eapol_sm_deinit(wpa_s->eapol);
3454 wpa_s->eapol = NULL;
3455 if (wpa_supplicant_init_eapol(wpa_s)) {
3456 /* Error -> Reset paths to the default value (NULL) once. */
3457 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3458 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3459 NULL);
3460
3461 return -1;
3462 }
3463 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3464
3465 return 0;
3466}
3467
3468
3469/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003470 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3471 * @wpa_s: wpa_supplicant structure for a network interface
3472 * @ap_scan: AP scan mode
3473 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3474 *
3475 */
3476int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3477{
3478
3479 int old_ap_scan;
3480
3481 if (ap_scan < 0 || ap_scan > 2)
3482 return -1;
3483
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003484 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3485 wpa_printf(MSG_INFO,
3486 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3487 }
3488
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003489#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003490 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3491 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3492 wpa_s->wpa_state < WPA_COMPLETED) {
3493 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3494 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003495 return 0;
3496 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003497#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003498
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003499 old_ap_scan = wpa_s->conf->ap_scan;
3500 wpa_s->conf->ap_scan = ap_scan;
3501
3502 if (old_ap_scan != wpa_s->conf->ap_scan)
3503 wpas_notify_ap_scan_changed(wpa_s);
3504
3505 return 0;
3506}
3507
3508
3509/**
3510 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3511 * @wpa_s: wpa_supplicant structure for a network interface
3512 * @expire_age: Expiration age in seconds
3513 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3514 *
3515 */
3516int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3517 unsigned int bss_expire_age)
3518{
3519 if (bss_expire_age < 10) {
3520 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3521 bss_expire_age);
3522 return -1;
3523 }
3524 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3525 bss_expire_age);
3526 wpa_s->conf->bss_expiration_age = bss_expire_age;
3527
3528 return 0;
3529}
3530
3531
3532/**
3533 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3534 * @wpa_s: wpa_supplicant structure for a network interface
3535 * @expire_count: number of scans after which an unseen BSS is reclaimed
3536 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3537 *
3538 */
3539int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3540 unsigned int bss_expire_count)
3541{
3542 if (bss_expire_count < 1) {
3543 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3544 bss_expire_count);
3545 return -1;
3546 }
3547 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3548 bss_expire_count);
3549 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3550
3551 return 0;
3552}
3553
3554
3555/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003556 * wpa_supplicant_set_scan_interval - Set scan interval
3557 * @wpa_s: wpa_supplicant structure for a network interface
3558 * @scan_interval: scan interval in seconds
3559 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3560 *
3561 */
3562int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3563 int scan_interval)
3564{
3565 if (scan_interval < 0) {
3566 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3567 scan_interval);
3568 return -1;
3569 }
3570 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3571 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003572 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003573
3574 return 0;
3575}
3576
3577
3578/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003579 * wpa_supplicant_set_debug_params - Set global debug params
3580 * @global: wpa_global structure
3581 * @debug_level: debug level
3582 * @debug_timestamp: determines if show timestamp in debug data
3583 * @debug_show_keys: determines if show keys in debug data
3584 * Returns: 0 if succeed or -1 if debug_level has wrong value
3585 */
3586int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3587 int debug_timestamp, int debug_show_keys)
3588{
3589
3590 int old_level, old_timestamp, old_show_keys;
3591
3592 /* check for allowed debuglevels */
3593 if (debug_level != MSG_EXCESSIVE &&
3594 debug_level != MSG_MSGDUMP &&
3595 debug_level != MSG_DEBUG &&
3596 debug_level != MSG_INFO &&
3597 debug_level != MSG_WARNING &&
3598 debug_level != MSG_ERROR)
3599 return -1;
3600
3601 old_level = wpa_debug_level;
3602 old_timestamp = wpa_debug_timestamp;
3603 old_show_keys = wpa_debug_show_keys;
3604
3605 wpa_debug_level = debug_level;
3606 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3607 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3608
3609 if (wpa_debug_level != old_level)
3610 wpas_notify_debug_level_changed(global);
3611 if (wpa_debug_timestamp != old_timestamp)
3612 wpas_notify_debug_timestamp_changed(global);
3613 if (wpa_debug_show_keys != old_show_keys)
3614 wpas_notify_debug_show_keys_changed(global);
3615
3616 return 0;
3617}
3618
3619
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003620#ifdef CONFIG_OWE
3621static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid,
3622 const u8 *entry_ssid, size_t entry_ssid_len)
3623{
3624 const u8 *owe, *pos, *end;
3625 u8 ssid_len;
3626 struct wpa_bss *bss;
3627
3628 /* Check network profile SSID aganst the SSID in the
3629 * OWE Transition Mode element. */
3630
3631 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
3632 if (!bss)
3633 return 0;
3634
3635 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
3636 if (!owe)
3637 return 0;
3638
3639 pos = owe + 6;
3640 end = owe + 2 + owe[1];
3641
3642 if (end - pos < ETH_ALEN + 1)
3643 return 0;
3644 pos += ETH_ALEN;
3645 ssid_len = *pos++;
3646 if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN)
3647 return 0;
3648
3649 return entry_ssid_len == ssid_len &&
3650 os_memcmp(pos, entry_ssid, ssid_len) == 0;
3651}
3652#endif /* CONFIG_OWE */
3653
3654
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003655/**
3656 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3657 * @wpa_s: Pointer to wpa_supplicant data
3658 * Returns: A pointer to the current network structure or %NULL on failure
3659 */
3660struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3661{
3662 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003663 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003664 int res;
3665 size_t ssid_len;
3666 u8 bssid[ETH_ALEN];
3667 int wired;
3668
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003669 res = wpa_drv_get_ssid(wpa_s, ssid);
3670 if (res < 0) {
3671 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3672 "driver");
3673 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003674 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003675 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003676
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003677 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003678 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3679 "driver");
3680 return NULL;
3681 }
3682
3683 wired = wpa_s->conf->ap_scan == 0 &&
3684 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3685
3686 entry = wpa_s->conf->ssid;
3687 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003688 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003689 ((ssid_len == entry->ssid_len &&
3690 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3691 (!entry->bssid_set ||
3692 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3693 return entry;
3694#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003695 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003696 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3697 (entry->ssid == NULL || entry->ssid_len == 0) &&
3698 (!entry->bssid_set ||
3699 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3700 return entry;
3701#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003702
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003703#ifdef CONFIG_OWE
3704 if (!wpas_network_disabled(wpa_s, entry) &&
3705 owe_trans_ssid_match(wpa_s, bssid, entry->ssid,
3706 entry->ssid_len) &&
3707 (!entry->bssid_set ||
3708 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3709 return entry;
3710#endif /* CONFIG_OWE */
3711
Dmitry Shmidt04949592012-07-19 12:16:46 -07003712 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003713 entry->ssid_len == 0 &&
3714 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3715 return entry;
3716
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003717 entry = entry->next;
3718 }
3719
3720 return NULL;
3721}
3722
3723
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003724static int select_driver(struct wpa_supplicant *wpa_s, int i)
3725{
3726 struct wpa_global *global = wpa_s->global;
3727
3728 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003729 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003730 if (global->drv_priv[i] == NULL) {
3731 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3732 "'%s'", wpa_drivers[i]->name);
3733 return -1;
3734 }
3735 }
3736
3737 wpa_s->driver = wpa_drivers[i];
3738 wpa_s->global_drv_priv = global->drv_priv[i];
3739
3740 return 0;
3741}
3742
3743
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003744static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3745 const char *name)
3746{
3747 int i;
3748 size_t len;
3749 const char *pos, *driver = name;
3750
3751 if (wpa_s == NULL)
3752 return -1;
3753
3754 if (wpa_drivers[0] == NULL) {
3755 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3756 "wpa_supplicant");
3757 return -1;
3758 }
3759
3760 if (name == NULL) {
3761 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003762 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003763 }
3764
3765 do {
3766 pos = os_strchr(driver, ',');
3767 if (pos)
3768 len = pos - driver;
3769 else
3770 len = os_strlen(driver);
3771
3772 for (i = 0; wpa_drivers[i]; i++) {
3773 if (os_strlen(wpa_drivers[i]->name) == len &&
3774 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003775 0) {
3776 /* First driver that succeeds wins */
3777 if (select_driver(wpa_s, i) == 0)
3778 return 0;
3779 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003780 }
3781
3782 driver = pos + 1;
3783 } while (pos);
3784
3785 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3786 return -1;
3787}
3788
3789
3790/**
3791 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3792 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3793 * with struct wpa_driver_ops::init()
3794 * @src_addr: Source address of the EAPOL frame
3795 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3796 * @len: Length of the EAPOL data
3797 *
3798 * This function is called for each received EAPOL frame. Most driver
3799 * interfaces rely on more generic OS mechanism for receiving frames through
3800 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3801 * take care of received EAPOL frames and deliver them to the core supplicant
3802 * code by calling this function.
3803 */
3804void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3805 const u8 *buf, size_t len)
3806{
3807 struct wpa_supplicant *wpa_s = ctx;
3808
3809 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3810 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3811
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003812#ifdef CONFIG_TESTING_OPTIONS
3813 if (wpa_s->ignore_auth_resp) {
3814 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3815 return;
3816 }
3817#endif /* CONFIG_TESTING_OPTIONS */
3818
Jouni Malinena05074c2012-12-21 21:35:35 +02003819 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3820 (wpa_s->last_eapol_matches_bssid &&
3821#ifdef CONFIG_AP
3822 !wpa_s->ap_iface &&
3823#endif /* CONFIG_AP */
3824 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 /*
3826 * There is possible race condition between receiving the
3827 * association event and the EAPOL frame since they are coming
3828 * through different paths from the driver. In order to avoid
3829 * issues in trying to process the EAPOL frame before receiving
3830 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003831 * the association event is received. This may also be needed in
3832 * driver-based roaming case, so also use src_addr != BSSID as a
3833 * trigger if we have previously confirmed that the
3834 * Authenticator uses BSSID as the src_addr (which is not the
3835 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003836 */
3837 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003838 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3839 wpa_supplicant_state_txt(wpa_s->wpa_state),
3840 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003841 wpabuf_free(wpa_s->pending_eapol_rx);
3842 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3843 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003844 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003845 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3846 ETH_ALEN);
3847 }
3848 return;
3849 }
3850
Jouni Malinena05074c2012-12-21 21:35:35 +02003851 wpa_s->last_eapol_matches_bssid =
3852 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3853
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003854#ifdef CONFIG_AP
3855 if (wpa_s->ap_iface) {
3856 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3857 return;
3858 }
3859#endif /* CONFIG_AP */
3860
3861 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3862 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3863 "no key management is configured");
3864 return;
3865 }
3866
3867 if (wpa_s->eapol_received == 0 &&
3868 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3869 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3870 wpa_s->wpa_state != WPA_COMPLETED) &&
3871 (wpa_s->current_ssid == NULL ||
3872 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3873 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003874 int timeout = 10;
3875
3876 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3877 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3878 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3879 /* Use longer timeout for IEEE 802.1X/EAP */
3880 timeout = 70;
3881 }
3882
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003883#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003884 if (wpa_s->current_ssid && wpa_s->current_bss &&
3885 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3886 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3887 /*
3888 * Use shorter timeout if going through WPS AP iteration
3889 * for PIN config method with an AP that does not
3890 * advertise Selected Registrar.
3891 */
3892 struct wpabuf *wps_ie;
3893
3894 wps_ie = wpa_bss_get_vendor_ie_multi(
3895 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3896 if (wps_ie &&
3897 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3898 timeout = 10;
3899 wpabuf_free(wps_ie);
3900 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003901#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003902
3903 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003904 }
3905 wpa_s->eapol_received++;
3906
3907 if (wpa_s->countermeasures) {
3908 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3909 "EAPOL packet");
3910 return;
3911 }
3912
3913#ifdef CONFIG_IBSS_RSN
3914 if (wpa_s->current_ssid &&
3915 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3916 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3917 return;
3918 }
3919#endif /* CONFIG_IBSS_RSN */
3920
3921 /* Source address of the incoming EAPOL frame could be compared to the
3922 * current BSSID. However, it is possible that a centralized
3923 * Authenticator could be using another MAC address than the BSSID of
3924 * an AP, so just allow any address to be used for now. The replies are
3925 * still sent to the current BSSID (if available), though. */
3926
3927 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3928 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003929 wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
3930 wpa_s->key_mgmt != WPA_KEY_MGMT_DPP &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003931 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3932 return;
3933 wpa_drv_poll(wpa_s);
3934 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3935 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3936 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3937 /*
3938 * Set portValid = TRUE here since we are going to skip 4-way
3939 * handshake processing which would normally set portValid. We
3940 * need this to allow the EAPOL state machines to be completed
3941 * without going through EAPOL-Key handshake.
3942 */
3943 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3944 }
3945}
3946
3947
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003948int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003949{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003950 if ((!wpa_s->p2p_mgmt ||
3951 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3952 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003953 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003954 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3955 wpa_drv_get_mac_addr(wpa_s),
3956 ETH_P_EAPOL,
3957 wpa_supplicant_rx_eapol, wpa_s, 0);
3958 if (wpa_s->l2 == NULL)
3959 return -1;
3960 } else {
3961 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3962 if (addr)
3963 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3964 }
3965
3966 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3967 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3968 return -1;
3969 }
3970
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003971 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3972
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003973 return 0;
3974}
3975
3976
Dmitry Shmidt04949592012-07-19 12:16:46 -07003977static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3978 const u8 *buf, size_t len)
3979{
3980 struct wpa_supplicant *wpa_s = ctx;
3981 const struct l2_ethhdr *eth;
3982
3983 if (len < sizeof(*eth))
3984 return;
3985 eth = (const struct l2_ethhdr *) buf;
3986
3987 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3988 !(eth->h_dest[0] & 0x01)) {
3989 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3990 " (bridge - not for this interface - ignore)",
3991 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3992 return;
3993 }
3994
3995 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3996 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3997 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3998 len - sizeof(*eth));
3999}
4000
4001
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004002/**
4003 * wpa_supplicant_driver_init - Initialize driver interface parameters
4004 * @wpa_s: Pointer to wpa_supplicant data
4005 * Returns: 0 on success, -1 on failure
4006 *
4007 * This function is called to initialize driver interface parameters.
4008 * wpa_drv_init() must have been called before this function to initialize the
4009 * driver interface.
4010 */
4011int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
4012{
4013 static int interface_count = 0;
4014
4015 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
4016 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004017
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004018 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
4019 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004020 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004021 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
4022
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004023 if (wpa_s->bridge_ifname[0]) {
4024 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
4025 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004026 wpa_s->l2_br = l2_packet_init_bridge(
4027 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
4028 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004029 if (wpa_s->l2_br == NULL) {
4030 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
4031 "connection for the bridge interface '%s'",
4032 wpa_s->bridge_ifname);
4033 return -1;
4034 }
4035 }
4036
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004037 if (wpa_s->conf->ap_scan == 2 &&
4038 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
4039 wpa_printf(MSG_INFO,
4040 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
4041 }
4042
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004043 wpa_clear_keys(wpa_s, NULL);
4044
4045 /* Make sure that TKIP countermeasures are not left enabled (could
4046 * happen if wpa_supplicant is killed during countermeasures. */
4047 wpa_drv_set_countermeasures(wpa_s, 0);
4048
4049 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
4050 wpa_drv_flush_pmkid(wpa_s);
4051
4052 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004053 wpa_s->prev_scan_wildcard = 0;
4054
Dmitry Shmidt04949592012-07-19 12:16:46 -07004055 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08004056 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
4057 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
4058 interface_count = 0;
4059 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004060#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08004061 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07004062 wpa_supplicant_delayed_sched_scan(wpa_s,
4063 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004064 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07004065 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004066 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004067#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004068 interface_count++;
4069 } else
4070 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
4071
4072 return 0;
4073}
4074
4075
4076static int wpa_supplicant_daemon(const char *pid_file)
4077{
4078 wpa_printf(MSG_DEBUG, "Daemonize..");
4079 return os_daemonize(pid_file);
4080}
4081
4082
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004083static struct wpa_supplicant *
4084wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004085{
4086 struct wpa_supplicant *wpa_s;
4087
4088 wpa_s = os_zalloc(sizeof(*wpa_s));
4089 if (wpa_s == NULL)
4090 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004091 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004092 wpa_s->scan_interval = 5;
4093 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004094 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004095 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004096 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004097
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004098 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08004099 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004100
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004101 return wpa_s;
4102}
4103
4104
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004105#ifdef CONFIG_HT_OVERRIDES
4106
4107static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
4108 struct ieee80211_ht_capabilities *htcaps,
4109 struct ieee80211_ht_capabilities *htcaps_mask,
4110 const char *ht_mcs)
4111{
4112 /* parse ht_mcs into hex array */
4113 int i;
4114 const char *tmp = ht_mcs;
4115 char *end = NULL;
4116
4117 /* If ht_mcs is null, do not set anything */
4118 if (!ht_mcs)
4119 return 0;
4120
4121 /* This is what we are setting in the kernel */
4122 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
4123
4124 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
4125
4126 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08004127 long v;
4128
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004129 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08004130 v = strtol(tmp, &end, 16);
4131
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004132 if (errno == 0) {
4133 wpa_msg(wpa_s, MSG_DEBUG,
4134 "htcap value[%i]: %ld end: %p tmp: %p",
4135 i, v, end, tmp);
4136 if (end == tmp)
4137 break;
4138
4139 htcaps->supported_mcs_set[i] = v;
4140 tmp = end;
4141 } else {
4142 wpa_msg(wpa_s, MSG_ERROR,
4143 "Failed to parse ht-mcs: %s, error: %s\n",
4144 ht_mcs, strerror(errno));
4145 return -1;
4146 }
4147 }
4148
4149 /*
4150 * If we were able to parse any values, then set mask for the MCS set.
4151 */
4152 if (i) {
4153 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
4154 IEEE80211_HT_MCS_MASK_LEN - 1);
4155 /* skip the 3 reserved bits */
4156 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
4157 0x1f;
4158 }
4159
4160 return 0;
4161}
4162
4163
4164static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
4165 struct ieee80211_ht_capabilities *htcaps,
4166 struct ieee80211_ht_capabilities *htcaps_mask,
4167 int disabled)
4168{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004169 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004170
4171 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
4172
4173 if (disabled == -1)
4174 return 0;
4175
4176 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
4177 htcaps_mask->ht_capabilities_info |= msk;
4178 if (disabled)
4179 htcaps->ht_capabilities_info &= msk;
4180 else
4181 htcaps->ht_capabilities_info |= msk;
4182
4183 return 0;
4184}
4185
4186
4187static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
4188 struct ieee80211_ht_capabilities *htcaps,
4189 struct ieee80211_ht_capabilities *htcaps_mask,
4190 int factor)
4191{
4192 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
4193
4194 if (factor == -1)
4195 return 0;
4196
4197 if (factor < 0 || factor > 3) {
4198 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
4199 "Must be 0-3 or -1", factor);
4200 return -EINVAL;
4201 }
4202
4203 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
4204 htcaps->a_mpdu_params &= ~0x3;
4205 htcaps->a_mpdu_params |= factor & 0x3;
4206
4207 return 0;
4208}
4209
4210
4211static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
4212 struct ieee80211_ht_capabilities *htcaps,
4213 struct ieee80211_ht_capabilities *htcaps_mask,
4214 int density)
4215{
4216 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
4217
4218 if (density == -1)
4219 return 0;
4220
4221 if (density < 0 || density > 7) {
4222 wpa_msg(wpa_s, MSG_ERROR,
4223 "ampdu_density: %d out of range. Must be 0-7 or -1.",
4224 density);
4225 return -EINVAL;
4226 }
4227
4228 htcaps_mask->a_mpdu_params |= 0x1C;
4229 htcaps->a_mpdu_params &= ~(0x1C);
4230 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
4231
4232 return 0;
4233}
4234
4235
4236static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
4237 struct ieee80211_ht_capabilities *htcaps,
4238 struct ieee80211_ht_capabilities *htcaps_mask,
4239 int disabled)
4240{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004241 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
4242
Paul Stewart092955c2017-02-06 09:13:09 -08004243 set_disable_ht40(htcaps, disabled);
4244 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004245
4246 return 0;
4247}
4248
4249
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004250static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
4251 struct ieee80211_ht_capabilities *htcaps,
4252 struct ieee80211_ht_capabilities *htcaps_mask,
4253 int disabled)
4254{
4255 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004256 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
4257 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004258
4259 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
4260
4261 if (disabled)
4262 htcaps->ht_capabilities_info &= ~msk;
4263 else
4264 htcaps->ht_capabilities_info |= msk;
4265
4266 htcaps_mask->ht_capabilities_info |= msk;
4267
4268 return 0;
4269}
4270
4271
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004272static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
4273 struct ieee80211_ht_capabilities *htcaps,
4274 struct ieee80211_ht_capabilities *htcaps_mask,
4275 int disabled)
4276{
4277 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004278 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004279
4280 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
4281
4282 if (disabled)
4283 htcaps->ht_capabilities_info &= ~msk;
4284 else
4285 htcaps->ht_capabilities_info |= msk;
4286
4287 htcaps_mask->ht_capabilities_info |= msk;
4288
4289 return 0;
4290}
4291
4292
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004293void wpa_supplicant_apply_ht_overrides(
4294 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4295 struct wpa_driver_associate_params *params)
4296{
4297 struct ieee80211_ht_capabilities *htcaps;
4298 struct ieee80211_ht_capabilities *htcaps_mask;
4299
4300 if (!ssid)
4301 return;
4302
4303 params->disable_ht = ssid->disable_ht;
4304 if (!params->htcaps || !params->htcaps_mask)
4305 return;
4306
4307 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
4308 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
4309 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
4310 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
4311 ssid->disable_max_amsdu);
4312 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
4313 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
4314 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004315 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004316 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004317
4318 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004319 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004320 htcaps->ht_capabilities_info |= bit;
4321 htcaps_mask->ht_capabilities_info |= bit;
4322 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004323}
4324
4325#endif /* CONFIG_HT_OVERRIDES */
4326
4327
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004328#ifdef CONFIG_VHT_OVERRIDES
4329void wpa_supplicant_apply_vht_overrides(
4330 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4331 struct wpa_driver_associate_params *params)
4332{
4333 struct ieee80211_vht_capabilities *vhtcaps;
4334 struct ieee80211_vht_capabilities *vhtcaps_mask;
4335
4336 if (!ssid)
4337 return;
4338
4339 params->disable_vht = ssid->disable_vht;
4340
4341 vhtcaps = (void *) params->vhtcaps;
4342 vhtcaps_mask = (void *) params->vhtcaps_mask;
4343
4344 if (!vhtcaps || !vhtcaps_mask)
4345 return;
4346
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004347 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
4348 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004349
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004350#ifdef CONFIG_HT_OVERRIDES
4351 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004352 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
4353 int max_ampdu;
4354
4355 max_ampdu = (ssid->vht_capa &
4356 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4357 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004358
4359 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4360 wpa_set_ampdu_factor(wpa_s,
4361 (void *) params->htcaps,
4362 (void *) params->htcaps_mask,
4363 max_ampdu);
4364 }
4365#endif /* CONFIG_HT_OVERRIDES */
4366
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004367#define OVERRIDE_MCS(i) \
4368 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4369 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004370 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004371 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004372 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4373 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004374 } \
4375 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4376 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004377 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004378 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004379 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4380 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004381 }
4382
4383 OVERRIDE_MCS(1);
4384 OVERRIDE_MCS(2);
4385 OVERRIDE_MCS(3);
4386 OVERRIDE_MCS(4);
4387 OVERRIDE_MCS(5);
4388 OVERRIDE_MCS(6);
4389 OVERRIDE_MCS(7);
4390 OVERRIDE_MCS(8);
4391}
4392#endif /* CONFIG_VHT_OVERRIDES */
4393
4394
Dmitry Shmidt04949592012-07-19 12:16:46 -07004395static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4396{
4397#ifdef PCSC_FUNCS
4398 size_t len;
4399
4400 if (!wpa_s->conf->pcsc_reader)
4401 return 0;
4402
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004403 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004404 if (!wpa_s->scard)
4405 return 1;
4406
4407 if (wpa_s->conf->pcsc_pin &&
4408 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4409 scard_deinit(wpa_s->scard);
4410 wpa_s->scard = NULL;
4411 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4412 return -1;
4413 }
4414
4415 len = sizeof(wpa_s->imsi) - 1;
4416 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4417 scard_deinit(wpa_s->scard);
4418 wpa_s->scard = NULL;
4419 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4420 return -1;
4421 }
4422 wpa_s->imsi[len] = '\0';
4423
4424 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4425
4426 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4427 wpa_s->imsi, wpa_s->mnc_len);
4428
4429 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4430 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4431#endif /* PCSC_FUNCS */
4432
4433 return 0;
4434}
4435
4436
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004437int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4438{
4439 char *val, *pos;
4440
4441 ext_password_deinit(wpa_s->ext_pw);
4442 wpa_s->ext_pw = NULL;
4443 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4444
4445 if (!wpa_s->conf->ext_password_backend)
4446 return 0;
4447
4448 val = os_strdup(wpa_s->conf->ext_password_backend);
4449 if (val == NULL)
4450 return -1;
4451 pos = os_strchr(val, ':');
4452 if (pos)
4453 *pos++ = '\0';
4454
4455 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4456
4457 wpa_s->ext_pw = ext_password_init(val, pos);
4458 os_free(val);
4459 if (wpa_s->ext_pw == NULL) {
4460 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4461 return -1;
4462 }
4463 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4464
4465 return 0;
4466}
4467
4468
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004469#ifdef CONFIG_FST
4470
4471static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4472{
4473 struct wpa_supplicant *wpa_s = ctx;
4474
4475 return (is_zero_ether_addr(wpa_s->bssid) ||
4476 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4477}
4478
4479
4480static void wpas_fst_get_channel_info_cb(void *ctx,
4481 enum hostapd_hw_mode *hw_mode,
4482 u8 *channel)
4483{
4484 struct wpa_supplicant *wpa_s = ctx;
4485
4486 if (wpa_s->current_bss) {
4487 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4488 channel);
4489 } else if (wpa_s->hw.num_modes) {
4490 *hw_mode = wpa_s->hw.modes[0].mode;
4491 } else {
4492 WPA_ASSERT(0);
4493 *hw_mode = 0;
4494 }
4495}
4496
4497
4498static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4499{
4500 struct wpa_supplicant *wpa_s = ctx;
4501
4502 *modes = wpa_s->hw.modes;
4503 return wpa_s->hw.num_modes;
4504}
4505
4506
4507static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4508{
4509 struct wpa_supplicant *wpa_s = ctx;
4510
4511 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4512 wpa_s->fst_ies = fst_ies;
4513}
4514
4515
4516static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4517{
4518 struct wpa_supplicant *wpa_s = ctx;
4519
Paul Stewart092955c2017-02-06 09:13:09 -08004520 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
4521 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
4522 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
4523 return -1;
4524 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004525 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08004526 wpa_s->own_addr, wpa_s->bssid,
4527 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004528 0);
4529}
4530
4531
4532static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4533{
4534 struct wpa_supplicant *wpa_s = ctx;
4535
4536 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4537 return wpa_s->received_mb_ies;
4538}
4539
4540
4541static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4542 const u8 *buf, size_t size)
4543{
4544 struct wpa_supplicant *wpa_s = ctx;
4545 struct mb_ies_info info;
4546
4547 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4548
4549 if (!mb_ies_info_by_ies(&info, buf, size)) {
4550 wpabuf_free(wpa_s->received_mb_ies);
4551 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4552 }
4553}
4554
4555
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004556static const u8 * wpas_fst_get_peer_first(void *ctx,
4557 struct fst_get_peer_ctx **get_ctx,
4558 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004559{
4560 struct wpa_supplicant *wpa_s = ctx;
4561
4562 *get_ctx = NULL;
4563 if (!is_zero_ether_addr(wpa_s->bssid))
4564 return (wpa_s->received_mb_ies || !mb_only) ?
4565 wpa_s->bssid : NULL;
4566 return NULL;
4567}
4568
4569
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004570static const u8 * wpas_fst_get_peer_next(void *ctx,
4571 struct fst_get_peer_ctx **get_ctx,
4572 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004573{
4574 return NULL;
4575}
4576
4577void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4578 struct fst_wpa_obj *iface_obj)
4579{
4580 iface_obj->ctx = wpa_s;
4581 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4582 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4583 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4584 iface_obj->set_ies = wpas_fst_set_ies_cb;
4585 iface_obj->send_action = wpas_fst_send_action_cb;
4586 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4587 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4588 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4589 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4590}
4591#endif /* CONFIG_FST */
4592
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004593static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004594 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004595{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004596 struct wowlan_triggers *triggers;
4597 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004598
4599 if (!wpa_s->conf->wowlan_triggers)
4600 return 0;
4601
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004602 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4603 if (triggers) {
4604 ret = wpa_drv_wowlan(wpa_s, triggers);
4605 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004606 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004607 return ret;
4608}
4609
4610
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004611enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004612{
4613 if (freq < 3000)
4614 return BAND_2_4_GHZ;
4615 if (freq > 50000)
4616 return BAND_60_GHZ;
4617 return BAND_5_GHZ;
4618}
4619
4620
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004621unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004622{
4623 int i;
4624 unsigned int band = 0;
4625
4626 if (freqs) {
4627 /* freqs are specified for the radio work */
4628 for (i = 0; freqs[i]; i++)
4629 band |= wpas_freq_to_band(freqs[i]);
4630 } else {
4631 /*
4632 * freqs are not specified, implies all
4633 * the supported freqs by HW
4634 */
4635 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4636 if (wpa_s->hw.modes[i].num_channels != 0) {
4637 if (wpa_s->hw.modes[i].mode ==
4638 HOSTAPD_MODE_IEEE80211B ||
4639 wpa_s->hw.modes[i].mode ==
4640 HOSTAPD_MODE_IEEE80211G)
4641 band |= BAND_2_4_GHZ;
4642 else if (wpa_s->hw.modes[i].mode ==
4643 HOSTAPD_MODE_IEEE80211A)
4644 band |= BAND_5_GHZ;
4645 else if (wpa_s->hw.modes[i].mode ==
4646 HOSTAPD_MODE_IEEE80211AD)
4647 band |= BAND_60_GHZ;
4648 else if (wpa_s->hw.modes[i].mode ==
4649 HOSTAPD_MODE_IEEE80211ANY)
4650 band = BAND_2_4_GHZ | BAND_5_GHZ |
4651 BAND_60_GHZ;
4652 }
4653 }
4654 }
4655
4656 return band;
4657}
4658
4659
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004660static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4661 const char *rn)
4662{
4663 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4664 struct wpa_radio *radio;
4665
4666 while (rn && iface) {
4667 radio = iface->radio;
4668 if (radio && os_strcmp(rn, radio->name) == 0) {
4669 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4670 wpa_s->ifname, rn);
4671 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4672 return radio;
4673 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004674
4675 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004676 }
4677
4678 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4679 wpa_s->ifname, rn ? rn : "N/A");
4680 radio = os_zalloc(sizeof(*radio));
4681 if (radio == NULL)
4682 return NULL;
4683
4684 if (rn)
4685 os_strlcpy(radio->name, rn, sizeof(radio->name));
4686 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004687 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004688 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4689
4690 return radio;
4691}
4692
4693
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004694static void radio_work_free(struct wpa_radio_work *work)
4695{
4696 if (work->wpa_s->scan_work == work) {
4697 /* This should not really happen. */
4698 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4699 work->type, work, work->started);
4700 work->wpa_s->scan_work = NULL;
4701 }
4702
4703#ifdef CONFIG_P2P
4704 if (work->wpa_s->p2p_scan_work == work) {
4705 /* This should not really happen. */
4706 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4707 work->type, work, work->started);
4708 work->wpa_s->p2p_scan_work = NULL;
4709 }
4710#endif /* CONFIG_P2P */
4711
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004712 if (work->started) {
4713 work->wpa_s->radio->num_active_works--;
4714 wpa_dbg(work->wpa_s, MSG_DEBUG,
4715 "radio_work_free('%s'@%p: num_active_works --> %u",
4716 work->type, work,
4717 work->wpa_s->radio->num_active_works);
4718 }
4719
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004720 dl_list_del(&work->list);
4721 os_free(work);
4722}
4723
4724
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004725static int radio_work_is_connect(struct wpa_radio_work *work)
4726{
4727 return os_strcmp(work->type, "sme-connect") == 0 ||
4728 os_strcmp(work->type, "connect") == 0;
4729}
4730
4731
4732static int radio_work_is_scan(struct wpa_radio_work *work)
4733{
4734 return os_strcmp(work->type, "scan") == 0 ||
4735 os_strcmp(work->type, "p2p-scan") == 0;
4736}
4737
4738
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004739static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4740{
4741 struct wpa_radio_work *active_work = NULL;
4742 struct wpa_radio_work *tmp;
4743
4744 /* Get the active work to know the type and band. */
4745 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4746 if (tmp->started) {
4747 active_work = tmp;
4748 break;
4749 }
4750 }
4751
4752 if (!active_work) {
4753 /* No active work, start one */
4754 radio->num_active_works = 0;
4755 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4756 list) {
4757 if (os_strcmp(tmp->type, "scan") == 0 &&
4758 radio->external_scan_running &&
4759 (((struct wpa_driver_scan_params *)
4760 tmp->ctx)->only_new_results ||
4761 tmp->wpa_s->clear_driver_scan_cache))
4762 continue;
4763 return tmp;
4764 }
4765 return NULL;
4766 }
4767
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004768 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004769 /*
4770 * If the active work is either connect or sme-connect,
4771 * do not parallelize them with other radio works.
4772 */
4773 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4774 "Do not parallelize radio work with %s",
4775 active_work->type);
4776 return NULL;
4777 }
4778
4779 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4780 if (tmp->started)
4781 continue;
4782
4783 /*
4784 * If connect or sme-connect are enqueued, parallelize only
4785 * those operations ahead of them in the queue.
4786 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004787 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004788 break;
4789
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004790 /* Serialize parallel scan and p2p_scan operations on the same
4791 * interface since the driver_nl80211 mechanism for tracking
4792 * scan cookies does not yet have support for this. */
4793 if (active_work->wpa_s == tmp->wpa_s &&
4794 radio_work_is_scan(active_work) &&
4795 radio_work_is_scan(tmp)) {
4796 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4797 "Do not start work '%s' when another work '%s' is already scheduled",
4798 tmp->type, active_work->type);
4799 continue;
4800 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004801 /*
4802 * Check that the radio works are distinct and
4803 * on different bands.
4804 */
4805 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4806 (active_work->bands != tmp->bands)) {
4807 /*
4808 * If a scan has to be scheduled through nl80211 scan
4809 * interface and if an external scan is already running,
4810 * do not schedule the scan since it is likely to get
4811 * rejected by kernel.
4812 */
4813 if (os_strcmp(tmp->type, "scan") == 0 &&
4814 radio->external_scan_running &&
4815 (((struct wpa_driver_scan_params *)
4816 tmp->ctx)->only_new_results ||
4817 tmp->wpa_s->clear_driver_scan_cache))
4818 continue;
4819
4820 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4821 "active_work:%s new_work:%s",
4822 active_work->type, tmp->type);
4823 return tmp;
4824 }
4825 }
4826
4827 /* Did not find a radio work to schedule in parallel. */
4828 return NULL;
4829}
4830
4831
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004832static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4833{
4834 struct wpa_radio *radio = eloop_ctx;
4835 struct wpa_radio_work *work;
4836 struct os_reltime now, diff;
4837 struct wpa_supplicant *wpa_s;
4838
4839 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004840 if (work == NULL) {
4841 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004842 return;
4843 }
4844
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004845 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4846 radio_list);
4847
4848 if (!(wpa_s &&
4849 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4850 if (work->started)
4851 return; /* already started and still in progress */
4852
4853 if (wpa_s && wpa_s->radio->external_scan_running) {
4854 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4855 return;
4856 }
4857 } else {
4858 work = NULL;
4859 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4860 /* get the work to schedule next */
4861 work = radio_work_get_next_work(radio);
4862 }
4863 if (!work)
4864 return;
4865 }
4866
4867 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004868 os_get_reltime(&now);
4869 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004870 wpa_dbg(wpa_s, MSG_DEBUG,
4871 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004872 work->type, work, diff.sec, diff.usec);
4873 work->started = 1;
4874 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004875 radio->num_active_works++;
4876
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004877 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004878
4879 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4880 radio->num_active_works < MAX_ACTIVE_WORKS)
4881 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004882}
4883
4884
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004885/*
4886 * This function removes both started and pending radio works running on
4887 * the provided interface's radio.
4888 * Prior to the removal of the radio work, its callback (cb) is called with
4889 * deinit set to be 1. Each work's callback is responsible for clearing its
4890 * internal data and restoring to a correct state.
4891 * @wpa_s: wpa_supplicant data
4892 * @type: type of works to be removed
4893 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4894 * this interface's works.
4895 */
4896void radio_remove_works(struct wpa_supplicant *wpa_s,
4897 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004898{
4899 struct wpa_radio_work *work, *tmp;
4900 struct wpa_radio *radio = wpa_s->radio;
4901
4902 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4903 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004904 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004905 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004906
4907 /* skip other ifaces' works */
4908 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004909 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004910
4911 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4912 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004913 work->cb(work, 1);
4914 radio_work_free(work);
4915 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004916
4917 /* in case we removed the started work */
4918 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004919}
4920
4921
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004922static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4923{
4924 struct wpa_radio *radio = wpa_s->radio;
4925
4926 if (!radio)
4927 return;
4928
4929 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4930 wpa_s->ifname, radio->name);
4931 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004932 radio_remove_works(wpa_s, NULL, 0);
4933 wpa_s->radio = NULL;
4934 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004935 return; /* Interfaces remain for this radio */
4936
4937 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004938 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004939 os_free(radio);
4940}
4941
4942
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004943void radio_work_check_next(struct wpa_supplicant *wpa_s)
4944{
4945 struct wpa_radio *radio = wpa_s->radio;
4946
4947 if (dl_list_empty(&radio->work))
4948 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004949 if (wpa_s->ext_work_in_progress) {
4950 wpa_printf(MSG_DEBUG,
4951 "External radio work in progress - delay start of pending item");
4952 return;
4953 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004954 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4955 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4956}
4957
4958
4959/**
4960 * radio_add_work - Add a radio work item
4961 * @wpa_s: Pointer to wpa_supplicant data
4962 * @freq: Frequency of the offchannel operation in MHz or 0
4963 * @type: Unique identifier for each type of work
4964 * @next: Force as the next work to be executed
4965 * @cb: Callback function for indicating when radio is available
4966 * @ctx: Context pointer for the work (work->ctx in cb())
4967 * Returns: 0 on success, -1 on failure
4968 *
4969 * This function is used to request time for an operation that requires
4970 * exclusive radio control. Once the radio is available, the registered callback
4971 * function will be called. radio_work_done() must be called once the exclusive
4972 * radio operation has been completed, so that the radio is freed for other
4973 * operations. The special case of deinit=1 is used to free the context data
4974 * during interface removal. That does not allow the callback function to start
4975 * the radio operation, i.e., it must free any resources allocated for the radio
4976 * work and return.
4977 *
4978 * The @freq parameter can be used to indicate a single channel on which the
4979 * offchannel operation will occur. This may allow multiple radio work
4980 * operations to be performed in parallel if they apply for the same channel.
4981 * Setting this to 0 indicates that the work item may use multiple channels or
4982 * requires exclusive control of the radio.
4983 */
4984int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4985 const char *type, int next,
4986 void (*cb)(struct wpa_radio_work *work, int deinit),
4987 void *ctx)
4988{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004989 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004990 struct wpa_radio_work *work;
4991 int was_empty;
4992
4993 work = os_zalloc(sizeof(*work));
4994 if (work == NULL)
4995 return -1;
4996 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4997 os_get_reltime(&work->time);
4998 work->freq = freq;
4999 work->type = type;
5000 work->wpa_s = wpa_s;
5001 work->cb = cb;
5002 work->ctx = ctx;
5003
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005004 if (freq)
5005 work->bands = wpas_freq_to_band(freq);
5006 else if (os_strcmp(type, "scan") == 0 ||
5007 os_strcmp(type, "p2p-scan") == 0)
5008 work->bands = wpas_get_bands(wpa_s,
5009 ((struct wpa_driver_scan_params *)
5010 ctx)->freqs);
5011 else
5012 work->bands = wpas_get_bands(wpa_s, NULL);
5013
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005014 was_empty = dl_list_empty(&wpa_s->radio->work);
5015 if (next)
5016 dl_list_add(&wpa_s->radio->work, &work->list);
5017 else
5018 dl_list_add_tail(&wpa_s->radio->work, &work->list);
5019 if (was_empty) {
5020 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
5021 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005022 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
5023 && radio->num_active_works < MAX_ACTIVE_WORKS) {
5024 wpa_dbg(wpa_s, MSG_DEBUG,
5025 "Try to schedule a radio work (num_active_works=%u)",
5026 radio->num_active_works);
5027 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005028 }
5029
5030 return 0;
5031}
5032
5033
5034/**
5035 * radio_work_done - Indicate that a radio work item has been completed
5036 * @work: Completed work
5037 *
5038 * This function is called once the callback function registered with
5039 * radio_add_work() has completed its work.
5040 */
5041void radio_work_done(struct wpa_radio_work *work)
5042{
5043 struct wpa_supplicant *wpa_s = work->wpa_s;
5044 struct os_reltime now, diff;
5045 unsigned int started = work->started;
5046
5047 os_get_reltime(&now);
5048 os_reltime_sub(&now, &work->time, &diff);
5049 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
5050 work->type, work, started ? "done" : "canceled",
5051 diff.sec, diff.usec);
5052 radio_work_free(work);
5053 if (started)
5054 radio_work_check_next(wpa_s);
5055}
5056
5057
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005058struct wpa_radio_work *
5059radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005060{
5061 struct wpa_radio_work *work;
5062 struct wpa_radio *radio = wpa_s->radio;
5063
5064 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
5065 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005066 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005067 }
5068
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08005069 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005070}
5071
5072
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005073static int wpas_init_driver(struct wpa_supplicant *wpa_s,
5074 struct wpa_interface *iface)
5075{
5076 const char *ifname, *driver, *rn;
5077
5078 driver = iface->driver;
5079next_driver:
5080 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
5081 return -1;
5082
5083 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
5084 if (wpa_s->drv_priv == NULL) {
5085 const char *pos;
5086 pos = driver ? os_strchr(driver, ',') : NULL;
5087 if (pos) {
5088 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
5089 "driver interface - try next driver wrapper");
5090 driver = pos + 1;
5091 goto next_driver;
5092 }
5093 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
5094 "interface");
5095 return -1;
5096 }
5097 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
5098 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
5099 "driver_param '%s'", wpa_s->conf->driver_param);
5100 return -1;
5101 }
5102
5103 ifname = wpa_drv_get_ifname(wpa_s);
5104 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
5105 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
5106 "interface name with '%s'", ifname);
5107 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
5108 }
5109
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005110 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005111 if (rn && rn[0] == '\0')
5112 rn = NULL;
5113
5114 wpa_s->radio = radio_add_interface(wpa_s, rn);
5115 if (wpa_s->radio == NULL)
5116 return -1;
5117
5118 return 0;
5119}
5120
5121
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005122#ifdef CONFIG_GAS_SERVER
5123
5124static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s,
5125 unsigned int freq, const u8 *dst,
5126 const u8 *src, const u8 *bssid,
5127 const u8 *data, size_t data_len,
5128 enum offchannel_send_action_result result)
5129{
5130 wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR
5131 " result=%s",
5132 freq, MAC2STR(dst),
5133 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
5134 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
5135 "FAILED"));
5136 gas_server_tx_status(wpa_s->gas_server, dst, data, data_len,
5137 result == OFFCHANNEL_SEND_ACTION_SUCCESS);
5138}
5139
5140
5141static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da,
5142 struct wpabuf *buf, unsigned int wait_time)
5143{
5144 struct wpa_supplicant *wpa_s = ctx;
5145 const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
5146
5147 if (wait_time > wpa_s->max_remain_on_chan)
5148 wait_time = wpa_s->max_remain_on_chan;
5149
5150 offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast,
5151 wpabuf_head(buf), wpabuf_len(buf),
5152 wait_time, wpas_gas_server_tx_status, 0);
5153}
5154
5155#endif /* CONFIG_GAS_SERVER */
5156
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005157static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
5158 struct wpa_interface *iface)
5159{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005160 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005161 int capa_res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005162 u8 dfs_domain;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005163
5164 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
5165 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
5166 iface->confname ? iface->confname : "N/A",
5167 iface->driver ? iface->driver : "default",
5168 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
5169 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
5170
5171 if (iface->confname) {
5172#ifdef CONFIG_BACKEND_FILE
5173 wpa_s->confname = os_rel2abs_path(iface->confname);
5174 if (wpa_s->confname == NULL) {
5175 wpa_printf(MSG_ERROR, "Failed to get absolute path "
5176 "for configuration file '%s'.",
5177 iface->confname);
5178 return -1;
5179 }
5180 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
5181 iface->confname, wpa_s->confname);
5182#else /* CONFIG_BACKEND_FILE */
5183 wpa_s->confname = os_strdup(iface->confname);
5184#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005185 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005186 if (wpa_s->conf == NULL) {
5187 wpa_printf(MSG_ERROR, "Failed to read or parse "
5188 "configuration '%s'.", wpa_s->confname);
5189 return -1;
5190 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07005191 wpa_s->confanother = os_rel2abs_path(iface->confanother);
5192 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005193
5194 /*
5195 * Override ctrl_interface and driver_param if set on command
5196 * line.
5197 */
5198 if (iface->ctrl_interface) {
5199 os_free(wpa_s->conf->ctrl_interface);
5200 wpa_s->conf->ctrl_interface =
5201 os_strdup(iface->ctrl_interface);
5202 }
5203
5204 if (iface->driver_param) {
5205 os_free(wpa_s->conf->driver_param);
5206 wpa_s->conf->driver_param =
5207 os_strdup(iface->driver_param);
5208 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005209
5210 if (iface->p2p_mgmt && !iface->ctrl_interface) {
5211 os_free(wpa_s->conf->ctrl_interface);
5212 wpa_s->conf->ctrl_interface = NULL;
5213 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005214 } else
5215 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
5216 iface->driver_param);
5217
5218 if (wpa_s->conf == NULL) {
5219 wpa_printf(MSG_ERROR, "\nNo configuration found.");
5220 return -1;
5221 }
5222
5223 if (iface->ifname == NULL) {
5224 wpa_printf(MSG_ERROR, "\nInterface name is required.");
5225 return -1;
5226 }
5227 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
5228 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
5229 iface->ifname);
5230 return -1;
5231 }
5232 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
5233
5234 if (iface->bridge_ifname) {
5235 if (os_strlen(iface->bridge_ifname) >=
5236 sizeof(wpa_s->bridge_ifname)) {
5237 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
5238 "name '%s'.", iface->bridge_ifname);
5239 return -1;
5240 }
5241 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
5242 sizeof(wpa_s->bridge_ifname));
5243 }
5244
5245 /* RSNA Supplicant Key Management - INITIALIZE */
5246 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
5247 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
5248
5249 /* Initialize driver interface and register driver event handler before
5250 * L2 receive handler so that association events are processed before
5251 * EAPOL-Key packets if both become available for the same select()
5252 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005253 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005254 return -1;
5255
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005256 if (wpa_supplicant_init_wpa(wpa_s) < 0)
5257 return -1;
5258
5259 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
5260 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
5261 NULL);
5262 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
5263
5264 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
5265 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
5266 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
5267 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5268 "dot11RSNAConfigPMKLifetime");
5269 return -1;
5270 }
5271
5272 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
5273 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
5274 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
5275 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5276 "dot11RSNAConfigPMKReauthThreshold");
5277 return -1;
5278 }
5279
5280 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
5281 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
5282 wpa_s->conf->dot11RSNAConfigSATimeout)) {
5283 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
5284 "dot11RSNAConfigSATimeout");
5285 return -1;
5286 }
5287
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005288 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
5289 &wpa_s->hw.num_modes,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005290 &wpa_s->hw.flags,
5291 &dfs_domain);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005292 if (wpa_s->hw.modes) {
5293 u16 i;
5294
5295 for (i = 0; i < wpa_s->hw.num_modes; i++) {
5296 if (wpa_s->hw.modes[i].vht_capab) {
5297 wpa_s->hw_capab = CAPAB_VHT;
5298 break;
5299 }
5300
5301 if (wpa_s->hw.modes[i].ht_capab &
5302 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
5303 wpa_s->hw_capab = CAPAB_HT40;
5304 else if (wpa_s->hw.modes[i].ht_capab &&
5305 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
5306 wpa_s->hw_capab = CAPAB_HT;
5307 }
5308 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005309
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005310 capa_res = wpa_drv_get_capa(wpa_s, &capa);
5311 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005312 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005313 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005314 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005315 wpa_s->drv_smps_modes = capa.smps_modes;
5316 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005317 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005318 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005319 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005320 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
5321 wpa_s->max_sched_scan_plan_interval =
5322 capa.max_sched_scan_plan_interval;
5323 wpa_s->max_sched_scan_plan_iterations =
5324 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005325 wpa_s->sched_scan_supported = capa.sched_scan_supported;
5326 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005327 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
5328 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005329 wpa_s->extended_capa = capa.extended_capa;
5330 wpa_s->extended_capa_mask = capa.extended_capa_mask;
5331 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005332 wpa_s->num_multichan_concurrent =
5333 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005334 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
5335
5336 if (capa.mac_addr_rand_scan_supported)
5337 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
5338 if (wpa_s->sched_scan_supported &&
5339 capa.mac_addr_rand_sched_scan_supported)
5340 wpa_s->mac_addr_rand_supported |=
5341 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005342 }
5343 if (wpa_s->max_remain_on_chan == 0)
5344 wpa_s->max_remain_on_chan = 1000;
5345
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005346 /*
5347 * Only take p2p_mgmt parameters when P2P Device is supported.
5348 * Doing it here as it determines whether l2_packet_init() will be done
5349 * during wpa_supplicant_driver_init().
5350 */
5351 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
5352 wpa_s->p2p_mgmt = iface->p2p_mgmt;
5353 else
5354 iface->p2p_mgmt = 1;
5355
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005356 if (wpa_s->num_multichan_concurrent == 0)
5357 wpa_s->num_multichan_concurrent = 1;
5358
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005359 if (wpa_supplicant_driver_init(wpa_s) < 0)
5360 return -1;
5361
5362#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005363 if ((!iface->p2p_mgmt ||
5364 !(wpa_s->drv_flags &
5365 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
5366 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005367 return -1;
5368#endif /* CONFIG_TDLS */
5369
5370 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
5371 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
5372 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
5373 return -1;
5374 }
5375
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005376#ifdef CONFIG_FST
5377 if (wpa_s->conf->fst_group_id) {
5378 struct fst_iface_cfg cfg;
5379 struct fst_wpa_obj iface_obj;
5380
5381 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
5382 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
5383 sizeof(cfg.group_id));
5384 cfg.priority = wpa_s->conf->fst_priority;
5385 cfg.llt = wpa_s->conf->fst_llt;
5386
5387 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
5388 &iface_obj, &cfg);
5389 if (!wpa_s->fst) {
5390 wpa_msg(wpa_s, MSG_ERROR,
5391 "FST: Cannot attach iface %s to group %s",
5392 wpa_s->ifname, cfg.group_id);
5393 return -1;
5394 }
5395 }
5396#endif /* CONFIG_FST */
5397
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005398 if (wpas_wps_init(wpa_s))
5399 return -1;
5400
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005401#ifdef CONFIG_GAS_SERVER
5402 wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
5403 if (!wpa_s->gas_server) {
5404 wpa_printf(MSG_ERROR, "Failed to initialize GAS server");
5405 return -1;
5406 }
5407#endif /* CONFIG_GAS_SERVER */
5408
5409#ifdef CONFIG_DPP
5410 if (wpas_dpp_init(wpa_s) < 0)
5411 return -1;
5412#endif /* CONFIG_DPP */
5413
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005414 if (wpa_supplicant_init_eapol(wpa_s) < 0)
5415 return -1;
5416 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5417
5418 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
5419 if (wpa_s->ctrl_iface == NULL) {
5420 wpa_printf(MSG_ERROR,
5421 "Failed to initialize control interface '%s'.\n"
5422 "You may have another wpa_supplicant process "
5423 "already running or the file was\n"
5424 "left by an unclean termination of wpa_supplicant "
5425 "in which case you will need\n"
5426 "to manually remove this file before starting "
5427 "wpa_supplicant again.\n",
5428 wpa_s->conf->ctrl_interface);
5429 return -1;
5430 }
5431
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005432 wpa_s->gas = gas_query_init(wpa_s);
5433 if (wpa_s->gas == NULL) {
5434 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5435 return -1;
5436 }
5437
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005438 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005439 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5440 return -1;
5441 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005442
5443 if (wpa_bss_init(wpa_s) < 0)
5444 return -1;
5445
Paul Stewart092955c2017-02-06 09:13:09 -08005446#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5447#ifdef CONFIG_MESH
5448 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
5449#endif /* CONFIG_MESH */
5450#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5451
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005452 /*
5453 * Set Wake-on-WLAN triggers, if configured.
5454 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5455 * have effect anyway when the interface is down).
5456 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005457 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005458 return -1;
5459
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005460#ifdef CONFIG_EAP_PROXY
5461{
5462 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005463 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
5464 wpa_s->imsi, &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005465 if (wpa_s->mnc_len > 0) {
5466 wpa_s->imsi[len] = '\0';
5467 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5468 wpa_s->imsi, wpa_s->mnc_len);
5469 } else {
5470 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5471 }
5472}
5473#endif /* CONFIG_EAP_PROXY */
5474
Dmitry Shmidt04949592012-07-19 12:16:46 -07005475 if (pcsc_reader_init(wpa_s) < 0)
5476 return -1;
5477
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005478 if (wpas_init_ext_pw(wpa_s) < 0)
5479 return -1;
5480
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005481 wpas_rrm_reset(wpa_s);
5482
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005483 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5484
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005485#ifdef CONFIG_HS20
5486 hs20_init(wpa_s);
5487#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005488#ifdef CONFIG_MBO
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005489 if (wpa_s->conf->oce) {
5490 if ((wpa_s->conf->oce & OCE_STA) &&
5491 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))
5492 wpa_s->enable_oce = OCE_STA;
5493 if ((wpa_s->conf->oce & OCE_STA_CFON) &&
5494 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
5495 /* TODO: Need to add STA-CFON support */
5496 wpa_printf(MSG_ERROR,
5497 "OCE STA-CFON feature is not yet supported");
5498 }
5499 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005500 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5501#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005502
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005503 wpa_supplicant_set_default_scan_ies(wpa_s);
5504
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005505 return 0;
5506}
5507
5508
5509static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005510 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005511{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005512 struct wpa_global *global = wpa_s->global;
5513 struct wpa_supplicant *iface, *prev;
5514
5515 if (wpa_s == wpa_s->parent)
5516 wpas_p2p_group_remove(wpa_s, "*");
5517
5518 iface = global->ifaces;
5519 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005520 if (iface->p2pdev == wpa_s)
5521 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005522 if (iface == wpa_s || iface->parent != wpa_s) {
5523 iface = iface->next;
5524 continue;
5525 }
5526 wpa_printf(MSG_DEBUG,
5527 "Remove remaining child interface %s from parent %s",
5528 iface->ifname, wpa_s->ifname);
5529 prev = iface;
5530 iface = iface->next;
5531 wpa_supplicant_remove_iface(global, prev, terminate);
5532 }
5533
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005534 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005535 if (wpa_s->drv_priv) {
5536 wpa_supplicant_deauthenticate(wpa_s,
5537 WLAN_REASON_DEAUTH_LEAVING);
5538
5539 wpa_drv_set_countermeasures(wpa_s, 0);
5540 wpa_clear_keys(wpa_s, NULL);
5541 }
5542
5543 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005544 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005545
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005546 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005547 radio_remove_interface(wpa_s);
5548
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005549#ifdef CONFIG_FST
5550 if (wpa_s->fst) {
5551 fst_detach(wpa_s->fst);
5552 wpa_s->fst = NULL;
5553 }
5554 if (wpa_s->received_mb_ies) {
5555 wpabuf_free(wpa_s->received_mb_ies);
5556 wpa_s->received_mb_ies = NULL;
5557 }
5558#endif /* CONFIG_FST */
5559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005560 if (wpa_s->drv_priv)
5561 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005562
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005563 if (notify)
5564 wpas_notify_iface_removed(wpa_s);
5565
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005566 if (terminate)
5567 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005568
5569 if (wpa_s->ctrl_iface) {
5570 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5571 wpa_s->ctrl_iface = NULL;
5572 }
5573
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005574#ifdef CONFIG_MESH
5575 if (wpa_s->ifmsh) {
5576 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5577 wpa_s->ifmsh = NULL;
5578 }
5579#endif /* CONFIG_MESH */
5580
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005581 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005582 wpa_config_free(wpa_s->conf);
5583 wpa_s->conf = NULL;
5584 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005585
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005586 os_free(wpa_s->ssids_from_scan_req);
5587
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005588 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005589}
5590
5591
Dmitry Shmidte4663042016-04-04 10:07:49 -07005592#ifdef CONFIG_MATCH_IFACE
5593
5594/**
5595 * wpa_supplicant_match_iface - Match an interface description to a name
5596 * @global: Pointer to global data from wpa_supplicant_init()
5597 * @ifname: Name of the interface to match
5598 * Returns: Pointer to the created interface description or %NULL on failure
5599 */
5600struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5601 const char *ifname)
5602{
5603 int i;
5604 struct wpa_interface *iface, *miface;
5605
5606 for (i = 0; i < global->params.match_iface_count; i++) {
5607 miface = &global->params.match_ifaces[i];
5608 if (!miface->ifname ||
5609 fnmatch(miface->ifname, ifname, 0) == 0) {
5610 iface = os_zalloc(sizeof(*iface));
5611 if (!iface)
5612 return NULL;
5613 *iface = *miface;
5614 iface->ifname = ifname;
5615 return iface;
5616 }
5617 }
5618
5619 return NULL;
5620}
5621
5622
5623/**
5624 * wpa_supplicant_match_existing - Match existing interfaces
5625 * @global: Pointer to global data from wpa_supplicant_init()
5626 * Returns: 0 on success, -1 on failure
5627 */
5628static int wpa_supplicant_match_existing(struct wpa_global *global)
5629{
5630 struct if_nameindex *ifi, *ifp;
5631 struct wpa_supplicant *wpa_s;
5632 struct wpa_interface *iface;
5633
5634 ifp = if_nameindex();
5635 if (!ifp) {
5636 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5637 return -1;
5638 }
5639
5640 for (ifi = ifp; ifi->if_name; ifi++) {
5641 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5642 if (wpa_s)
5643 continue;
5644 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5645 if (iface) {
5646 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5647 os_free(iface);
5648 if (wpa_s)
5649 wpa_s->matched = 1;
5650 }
5651 }
5652
5653 if_freenameindex(ifp);
5654 return 0;
5655}
5656
5657#endif /* CONFIG_MATCH_IFACE */
5658
5659
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005660/**
5661 * wpa_supplicant_add_iface - Add a new network interface
5662 * @global: Pointer to global data from wpa_supplicant_init()
5663 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005664 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005665 * Returns: Pointer to the created interface or %NULL on failure
5666 *
5667 * This function is used to add new network interfaces for %wpa_supplicant.
5668 * This can be called before wpa_supplicant_run() to add interfaces before the
5669 * main event loop has been started. In addition, new interfaces can be added
5670 * dynamically while %wpa_supplicant is already running. This could happen,
5671 * e.g., when a hotplug network adapter is inserted.
5672 */
5673struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005674 struct wpa_interface *iface,
5675 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005676{
5677 struct wpa_supplicant *wpa_s;
5678 struct wpa_interface t_iface;
5679 struct wpa_ssid *ssid;
5680
5681 if (global == NULL || iface == NULL)
5682 return NULL;
5683
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005684 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005685 if (wpa_s == NULL)
5686 return NULL;
5687
5688 wpa_s->global = global;
5689
5690 t_iface = *iface;
5691 if (global->params.override_driver) {
5692 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5693 "('%s' -> '%s')",
5694 iface->driver, global->params.override_driver);
5695 t_iface.driver = global->params.override_driver;
5696 }
5697 if (global->params.override_ctrl_interface) {
5698 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5699 "ctrl_interface ('%s' -> '%s')",
5700 iface->ctrl_interface,
5701 global->params.override_ctrl_interface);
5702 t_iface.ctrl_interface =
5703 global->params.override_ctrl_interface;
5704 }
5705 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5706 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5707 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005708 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005709 return NULL;
5710 }
5711
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005712 /* Notify the control interfaces about new iface */
5713 if (wpas_notify_iface_added(wpa_s)) {
5714 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5715 return NULL;
5716 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005717
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005718 /* Notify the control interfaces about new networks for non p2p mgmt
5719 * ifaces. */
5720 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005721 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5722 wpas_notify_network_added(wpa_s, ssid);
5723 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005724
5725 wpa_s->next = global->ifaces;
5726 global->ifaces = wpa_s;
5727
5728 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005729 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005730
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005731#ifdef CONFIG_P2P
5732 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005733 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005734 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005735 wpas_p2p_add_p2pdev_interface(
5736 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005737 wpa_printf(MSG_INFO,
5738 "P2P: Failed to enable P2P Device interface");
5739 /* Try to continue without. P2P will be disabled. */
5740 }
5741#endif /* CONFIG_P2P */
5742
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005743 return wpa_s;
5744}
5745
5746
5747/**
5748 * wpa_supplicant_remove_iface - Remove a network interface
5749 * @global: Pointer to global data from wpa_supplicant_init()
5750 * @wpa_s: Pointer to the network interface to be removed
5751 * Returns: 0 if interface was removed, -1 if interface was not found
5752 *
5753 * This function can be used to dynamically remove network interfaces from
5754 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5755 * addition, this function is used to remove all remaining interfaces when
5756 * %wpa_supplicant is terminated.
5757 */
5758int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005759 struct wpa_supplicant *wpa_s,
5760 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005761{
5762 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005763#ifdef CONFIG_MESH
5764 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5765 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005766 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005767#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005768
5769 /* Remove interface from the global list of interfaces */
5770 prev = global->ifaces;
5771 if (prev == wpa_s) {
5772 global->ifaces = wpa_s->next;
5773 } else {
5774 while (prev && prev->next != wpa_s)
5775 prev = prev->next;
5776 if (prev == NULL)
5777 return -1;
5778 prev->next = wpa_s->next;
5779 }
5780
5781 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5782
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005783#ifdef CONFIG_MESH
5784 if (mesh_if_created) {
5785 ifname = os_strdup(wpa_s->ifname);
5786 if (ifname == NULL) {
5787 wpa_dbg(wpa_s, MSG_ERROR,
5788 "mesh: Failed to malloc ifname");
5789 return -1;
5790 }
5791 }
5792#endif /* CONFIG_MESH */
5793
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005794 if (global->p2p_group_formation == wpa_s)
5795 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005796 if (global->p2p_invite_group == wpa_s)
5797 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005798 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005799
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005800#ifdef CONFIG_MESH
5801 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005802 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005803 os_free(ifname);
5804 }
5805#endif /* CONFIG_MESH */
5806
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005807 return 0;
5808}
5809
5810
5811/**
5812 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5813 * @wpa_s: Pointer to the network interface
5814 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5815 */
5816const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5817{
5818 const char *eapol_method;
5819
5820 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5821 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5822 return "NO-EAP";
5823 }
5824
5825 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5826 if (eapol_method == NULL)
5827 return "UNKNOWN-EAP";
5828
5829 return eapol_method;
5830}
5831
5832
5833/**
5834 * wpa_supplicant_get_iface - Get a new network interface
5835 * @global: Pointer to global data from wpa_supplicant_init()
5836 * @ifname: Interface name
5837 * Returns: Pointer to the interface or %NULL if not found
5838 */
5839struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5840 const char *ifname)
5841{
5842 struct wpa_supplicant *wpa_s;
5843
5844 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5845 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5846 return wpa_s;
5847 }
5848 return NULL;
5849}
5850
5851
5852#ifndef CONFIG_NO_WPA_MSG
5853static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5854{
5855 struct wpa_supplicant *wpa_s = ctx;
5856 if (wpa_s == NULL)
5857 return NULL;
5858 return wpa_s->ifname;
5859}
5860#endif /* CONFIG_NO_WPA_MSG */
5861
5862
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005863#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5864#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5865#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5866
5867/* Periodic cleanup tasks */
5868static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5869{
5870 struct wpa_global *global = eloop_ctx;
5871 struct wpa_supplicant *wpa_s;
5872
5873 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5874 wpas_periodic, global, NULL);
5875
5876#ifdef CONFIG_P2P
5877 if (global->p2p)
5878 p2p_expire_peers(global->p2p);
5879#endif /* CONFIG_P2P */
5880
5881 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5882 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5883#ifdef CONFIG_AP
5884 ap_periodic(wpa_s);
5885#endif /* CONFIG_AP */
5886 }
5887}
5888
5889
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005890/**
5891 * wpa_supplicant_init - Initialize %wpa_supplicant
5892 * @params: Parameters for %wpa_supplicant
5893 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5894 *
5895 * This function is used to initialize %wpa_supplicant. After successful
5896 * initialization, the returned data pointer can be used to add and remove
5897 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5898 */
5899struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5900{
5901 struct wpa_global *global;
5902 int ret, i;
5903
5904 if (params == NULL)
5905 return NULL;
5906
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005907#ifdef CONFIG_DRIVER_NDIS
5908 {
5909 void driver_ndis_init_ops(void);
5910 driver_ndis_init_ops();
5911 }
5912#endif /* CONFIG_DRIVER_NDIS */
5913
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005914#ifndef CONFIG_NO_WPA_MSG
5915 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5916#endif /* CONFIG_NO_WPA_MSG */
5917
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005918 if (params->wpa_debug_file_path)
5919 wpa_debug_open_file(params->wpa_debug_file_path);
5920 else
5921 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005922 if (params->wpa_debug_syslog)
5923 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005924 if (params->wpa_debug_tracing) {
5925 ret = wpa_debug_open_linux_tracing();
5926 if (ret) {
5927 wpa_printf(MSG_ERROR,
5928 "Failed to enable trace logging");
5929 return NULL;
5930 }
5931 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005932
5933 ret = eap_register_methods();
5934 if (ret) {
5935 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5936 if (ret == -2)
5937 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5938 "the same EAP type.");
5939 return NULL;
5940 }
5941
5942 global = os_zalloc(sizeof(*global));
5943 if (global == NULL)
5944 return NULL;
5945 dl_list_init(&global->p2p_srv_bonjour);
5946 dl_list_init(&global->p2p_srv_upnp);
5947 global->params.daemonize = params->daemonize;
5948 global->params.wait_for_monitor = params->wait_for_monitor;
5949 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5950 if (params->pid_file)
5951 global->params.pid_file = os_strdup(params->pid_file);
5952 if (params->ctrl_interface)
5953 global->params.ctrl_interface =
5954 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005955 if (params->ctrl_interface_group)
5956 global->params.ctrl_interface_group =
5957 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005958 if (params->override_driver)
5959 global->params.override_driver =
5960 os_strdup(params->override_driver);
5961 if (params->override_ctrl_interface)
5962 global->params.override_ctrl_interface =
5963 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005964#ifdef CONFIG_MATCH_IFACE
5965 global->params.match_iface_count = params->match_iface_count;
5966 if (params->match_iface_count) {
5967 global->params.match_ifaces =
5968 os_calloc(params->match_iface_count,
5969 sizeof(struct wpa_interface));
5970 os_memcpy(global->params.match_ifaces,
5971 params->match_ifaces,
5972 params->match_iface_count *
5973 sizeof(struct wpa_interface));
5974 }
5975#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005976#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005977 if (params->conf_p2p_dev)
5978 global->params.conf_p2p_dev =
5979 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005980#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005981 wpa_debug_level = global->params.wpa_debug_level =
5982 params->wpa_debug_level;
5983 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5984 params->wpa_debug_show_keys;
5985 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5986 params->wpa_debug_timestamp;
5987
5988 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5989
5990 if (eloop_init()) {
5991 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5992 wpa_supplicant_deinit(global);
5993 return NULL;
5994 }
5995
Jouni Malinen75ecf522011-06-27 15:19:46 -07005996 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005997
5998 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5999 if (global->ctrl_iface == NULL) {
6000 wpa_supplicant_deinit(global);
6001 return NULL;
6002 }
6003
6004 if (wpas_notify_supplicant_initialized(global)) {
6005 wpa_supplicant_deinit(global);
6006 return NULL;
6007 }
6008
6009 for (i = 0; wpa_drivers[i]; i++)
6010 global->drv_count++;
6011 if (global->drv_count == 0) {
6012 wpa_printf(MSG_ERROR, "No drivers enabled");
6013 wpa_supplicant_deinit(global);
6014 return NULL;
6015 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006016 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006017 if (global->drv_priv == NULL) {
6018 wpa_supplicant_deinit(global);
6019 return NULL;
6020 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006021
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006022#ifdef CONFIG_WIFI_DISPLAY
6023 if (wifi_display_init(global) < 0) {
6024 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
6025 wpa_supplicant_deinit(global);
6026 return NULL;
6027 }
6028#endif /* CONFIG_WIFI_DISPLAY */
6029
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006030 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
6031 wpas_periodic, global, NULL);
6032
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006033 return global;
6034}
6035
6036
6037/**
6038 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
6039 * @global: Pointer to global data from wpa_supplicant_init()
6040 * Returns: 0 after successful event loop run, -1 on failure
6041 *
6042 * This function starts the main event loop and continues running as long as
6043 * there are any remaining events. In most cases, this function is running as
6044 * long as the %wpa_supplicant process in still in use.
6045 */
6046int wpa_supplicant_run(struct wpa_global *global)
6047{
6048 struct wpa_supplicant *wpa_s;
6049
6050 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08006051 (wpa_supplicant_daemon(global->params.pid_file) ||
6052 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006053 return -1;
6054
Dmitry Shmidte4663042016-04-04 10:07:49 -07006055#ifdef CONFIG_MATCH_IFACE
6056 if (wpa_supplicant_match_existing(global))
6057 return -1;
6058#endif
6059
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006060 if (global->params.wait_for_monitor) {
6061 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08006062 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006063 wpa_supplicant_ctrl_iface_wait(
6064 wpa_s->ctrl_iface);
6065 }
6066
6067 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
6068 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
6069
6070 eloop_run();
6071
6072 return 0;
6073}
6074
6075
6076/**
6077 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
6078 * @global: Pointer to global data from wpa_supplicant_init()
6079 *
6080 * This function is called to deinitialize %wpa_supplicant and to free all
6081 * allocated resources. Remaining network interfaces will also be removed.
6082 */
6083void wpa_supplicant_deinit(struct wpa_global *global)
6084{
6085 int i;
6086
6087 if (global == NULL)
6088 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006089
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006090 eloop_cancel_timeout(wpas_periodic, global, NULL);
6091
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006092#ifdef CONFIG_WIFI_DISPLAY
6093 wifi_display_deinit(global);
6094#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006095
6096 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07006097 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006098
6099 if (global->ctrl_iface)
6100 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
6101
6102 wpas_notify_supplicant_deinitialized(global);
6103
6104 eap_peer_unregister_methods();
6105#ifdef CONFIG_AP
6106 eap_server_unregister_methods();
6107#endif /* CONFIG_AP */
6108
6109 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
6110 if (!global->drv_priv[i])
6111 continue;
6112 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
6113 }
6114 os_free(global->drv_priv);
6115
6116 random_deinit();
6117
6118 eloop_destroy();
6119
6120 if (global->params.pid_file) {
6121 os_daemonize_terminate(global->params.pid_file);
6122 os_free(global->params.pid_file);
6123 }
6124 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006125 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006126 os_free(global->params.override_driver);
6127 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006128#ifdef CONFIG_MATCH_IFACE
6129 os_free(global->params.match_ifaces);
6130#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006131#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07006132 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006133#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006134
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07006135 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006136 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006137 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006138
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006139 os_free(global);
6140 wpa_debug_close_syslog();
6141 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07006142 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006143}
6144
6145
6146void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
6147{
6148 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
6149 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
6150 char country[3];
6151 country[0] = wpa_s->conf->country[0];
6152 country[1] = wpa_s->conf->country[1];
6153 country[2] = '\0';
6154 if (wpa_drv_set_country(wpa_s, country) < 0) {
6155 wpa_printf(MSG_ERROR, "Failed to set country code "
6156 "'%s'", country);
6157 }
6158 }
6159
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006160 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
6161 wpas_init_ext_pw(wpa_s);
6162
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006163 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
6164 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
6165
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006166 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) {
6167 struct wpa_driver_capa capa;
6168 int res = wpa_drv_get_capa(wpa_s, &capa);
6169
6170 if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
6171 wpa_printf(MSG_ERROR,
6172 "Failed to update wowlan_triggers to '%s'",
6173 wpa_s->conf->wowlan_triggers);
6174 }
6175
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006176#ifdef CONFIG_WPS
6177 wpas_wps_update_config(wpa_s);
6178#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006179 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006180 wpa_s->conf->changed_parameters = 0;
6181}
6182
6183
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006184void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006185{
6186 int i;
6187
6188 for (i = 0; i < *num_freqs; i++) {
6189 if (freqs[i] == freq)
6190 return;
6191 }
6192
6193 freqs[*num_freqs] = freq;
6194 (*num_freqs)++;
6195}
6196
6197
6198static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
6199{
6200 struct wpa_bss *bss, *cbss;
6201 const int max_freqs = 10;
6202 int *freqs;
6203 int num_freqs = 0;
6204
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006205 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006206 if (freqs == NULL)
6207 return NULL;
6208
6209 cbss = wpa_s->current_bss;
6210
6211 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
6212 if (bss == cbss)
6213 continue;
6214 if (bss->ssid_len == cbss->ssid_len &&
6215 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
6216 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
6217 add_freq(freqs, &num_freqs, bss->freq);
6218 if (num_freqs == max_freqs)
6219 break;
6220 }
6221 }
6222
6223 if (num_freqs == 0) {
6224 os_free(freqs);
6225 freqs = NULL;
6226 }
6227
6228 return freqs;
6229}
6230
6231
6232void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6233{
6234 int timeout;
6235 int count;
6236 int *freqs = NULL;
6237
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006238 wpas_connect_work_done(wpa_s);
6239
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006240 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006241 * Remove possible authentication timeout since the connection failed.
6242 */
6243 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
6244
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006245 /*
6246 * There is no point in blacklisting the AP if this event is
6247 * generated based on local request to disconnect.
6248 */
6249 if (wpa_s->own_disconnect_req) {
6250 wpa_s->own_disconnect_req = 0;
6251 wpa_dbg(wpa_s, MSG_DEBUG,
6252 "Ignore connection failure due to local request to disconnect");
6253 return;
6254 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006255 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006256 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
6257 "indication since interface has been put into "
6258 "disconnected state");
6259 return;
6260 }
6261
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006262 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006263 * Add the failed BSSID into the blacklist and speed up next scan
6264 * attempt if there could be other APs that could accept association.
6265 * The current blacklist count indicates how many times we have tried
6266 * connecting to this AP and multiple attempts mean that other APs are
6267 * either not available or has already been tried, so that we can start
6268 * increasing the delay here to avoid constant scanning.
6269 */
6270 count = wpa_blacklist_add(wpa_s, bssid);
6271 if (count == 1 && wpa_s->current_bss) {
6272 /*
6273 * This BSS was not in the blacklist before. If there is
6274 * another BSS available for the same ESS, we should try that
6275 * next. Otherwise, we may as well try this one once more
6276 * before allowing other, likely worse, ESSes to be considered.
6277 */
6278 freqs = get_bss_freqs_in_ess(wpa_s);
6279 if (freqs) {
6280 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
6281 "has been seen; try it next");
6282 wpa_blacklist_add(wpa_s, bssid);
6283 /*
6284 * On the next scan, go through only the known channels
6285 * used in this ESS based on previous scans to speed up
6286 * common load balancing use case.
6287 */
6288 os_free(wpa_s->next_scan_freqs);
6289 wpa_s->next_scan_freqs = freqs;
6290 }
6291 }
6292
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006293 /*
6294 * Add previous failure count in case the temporary blacklist was
6295 * cleared due to no other BSSes being available.
6296 */
6297 count += wpa_s->extra_blacklist_count;
6298
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006299 if (count > 3 && wpa_s->current_ssid) {
6300 wpa_printf(MSG_DEBUG, "Continuous association failures - "
6301 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006302 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006303 }
6304
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006305 switch (count) {
6306 case 1:
6307 timeout = 100;
6308 break;
6309 case 2:
6310 timeout = 500;
6311 break;
6312 case 3:
6313 timeout = 1000;
6314 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006315 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006316 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006317 break;
6318 default:
6319 timeout = 10000;
6320 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006321 }
6322
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006323 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
6324 "ms", count, timeout);
6325
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006326 /*
6327 * TODO: if more than one possible AP is available in scan results,
6328 * could try the other ones before requesting a new scan.
6329 */
6330 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
6331 1000 * (timeout % 1000));
6332}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006333
6334
6335int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
6336{
6337 return wpa_s->conf->ap_scan == 2 ||
6338 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
6339}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006340
Dmitry Shmidt04949592012-07-19 12:16:46 -07006341
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006342#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006343int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6344 struct wpa_ssid *ssid,
6345 const char *field,
6346 const char *value)
6347{
6348#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006349 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006350
6351 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
6352 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
6353 (const u8 *) value, os_strlen(value));
6354
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006355 rtype = wpa_supplicant_ctrl_req_from_string(field);
pkanwareb9203e2017-10-26 16:00:35 -07006356 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006357#else /* IEEE8021X_EAPOL */
6358 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6359 return -1;
6360#endif /* IEEE8021X_EAPOL */
6361}
6362
6363int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
6364 struct wpa_ssid *ssid,
6365 enum wpa_ctrl_req_type rtype,
pkanwareb9203e2017-10-26 16:00:35 -07006366 const char *value, int value_len)
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006367{
6368#ifdef IEEE8021X_EAPOL
6369 struct eap_peer_config *eap = &ssid->eap;
6370
6371 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07006372 case WPA_CTRL_REQ_EAP_IDENTITY:
6373 os_free(eap->identity);
pkanwareb9203e2017-10-26 16:00:35 -07006374 eap->identity = (u8 *) dup_binstr(value, value_len);
6375 eap->identity_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006376 eap->pending_req_identity = 0;
6377 if (ssid == wpa_s->current_ssid)
6378 wpa_s->reassociate = 1;
6379 break;
6380 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006381 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006382 eap->password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006383 eap->password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006384 eap->pending_req_password = 0;
6385 if (ssid == wpa_s->current_ssid)
6386 wpa_s->reassociate = 1;
6387 break;
6388 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006389 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006390 eap->new_password = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006391 eap->new_password_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006392 eap->pending_req_new_password = 0;
6393 if (ssid == wpa_s->current_ssid)
6394 wpa_s->reassociate = 1;
6395 break;
6396 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006397 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006398 eap->pin = os_strdup(value);
6399 eap->pending_req_pin = 0;
6400 if (ssid == wpa_s->current_ssid)
6401 wpa_s->reassociate = 1;
6402 break;
6403 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006404 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006405 eap->otp = (u8 *) os_strdup(value);
pkanwareb9203e2017-10-26 16:00:35 -07006406 eap->otp_len = value_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006407 os_free(eap->pending_req_otp);
6408 eap->pending_req_otp = NULL;
6409 eap->pending_req_otp_len = 0;
6410 break;
6411 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006412 str_clear_free(eap->private_key_passwd);
6413 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006414 eap->pending_req_passphrase = 0;
6415 if (ssid == wpa_s->current_ssid)
6416 wpa_s->reassociate = 1;
6417 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006418 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07006419 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07006420 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006421 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006422 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006423 case WPA_CTRL_REQ_PSK_PASSPHRASE:
6424 if (wpa_config_set(ssid, "psk", value, 0) < 0)
6425 return -1;
6426 ssid->mem_only_psk = 1;
6427 if (ssid->passphrase)
6428 wpa_config_update_psk(ssid);
6429 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
6430 wpa_supplicant_req_scan(wpa_s, 0, 0);
6431 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006432 case WPA_CTRL_REQ_EXT_CERT_CHECK:
6433 if (eap->pending_ext_cert_check != PENDING_CHECK)
6434 return -1;
6435 if (os_strcmp(value, "good") == 0)
6436 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
6437 else if (os_strcmp(value, "bad") == 0)
6438 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
6439 else
6440 return -1;
6441 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006442 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006443 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006444 return -1;
6445 }
6446
6447 return 0;
6448#else /* IEEE8021X_EAPOL */
6449 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6450 return -1;
6451#endif /* IEEE8021X_EAPOL */
6452}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006453#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006454
6455
6456int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6457{
6458 int i;
6459 unsigned int drv_enc;
6460
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006461 if (wpa_s->p2p_mgmt)
6462 return 1; /* no normal network profiles on p2p_mgmt interface */
6463
Dmitry Shmidt04949592012-07-19 12:16:46 -07006464 if (ssid == NULL)
6465 return 1;
6466
6467 if (ssid->disabled)
6468 return 1;
6469
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006470 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006471 drv_enc = wpa_s->drv_enc;
6472 else
6473 drv_enc = (unsigned int) -1;
6474
6475 for (i = 0; i < NUM_WEP_KEYS; i++) {
6476 size_t len = ssid->wep_key_len[i];
6477 if (len == 0)
6478 continue;
6479 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
6480 continue;
6481 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
6482 continue;
6483 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
6484 continue;
6485 return 1; /* invalid WEP key */
6486 }
6487
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006488 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006489 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006490 !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006491 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006492 return 1;
6493
Dmitry Shmidt04949592012-07-19 12:16:46 -07006494 return 0;
6495}
6496
6497
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006498int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6499{
6500#ifdef CONFIG_IEEE80211W
6501 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6502 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6503 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6504 /*
6505 * Driver does not support BIP -- ignore pmf=1 default
6506 * since the connection with PMF would fail and the
6507 * configuration does not require PMF to be enabled.
6508 */
6509 return NO_MGMT_FRAME_PROTECTION;
6510 }
6511
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006512 if (ssid &&
6513 (ssid->key_mgmt &
6514 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6515 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6516 /*
6517 * Do not use the default PMF value for non-RSN networks
6518 * since PMF is available only with RSN and pmf=2
6519 * configuration would otherwise prevent connections to
6520 * all open networks.
6521 */
6522 return NO_MGMT_FRAME_PROTECTION;
6523 }
6524
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006525 return wpa_s->conf->pmf;
6526 }
6527
6528 return ssid->ieee80211w;
6529#else /* CONFIG_IEEE80211W */
6530 return NO_MGMT_FRAME_PROTECTION;
6531#endif /* CONFIG_IEEE80211W */
6532}
6533
6534
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006535int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006536{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006537 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006538 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006539 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006540 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006541 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006542}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006543
6544
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006545void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006546{
6547 struct wpa_ssid *ssid = wpa_s->current_ssid;
6548 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006549 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006550
6551 if (ssid == NULL) {
6552 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6553 "SSID block");
6554 return;
6555 }
6556
6557 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6558 return;
6559
6560 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006561
6562#ifdef CONFIG_P2P
6563 if (ssid->p2p_group &&
6564 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6565 /*
6566 * Skip the wait time since there is a short timeout on the
6567 * connection to a P2P group.
6568 */
6569 return;
6570 }
6571#endif /* CONFIG_P2P */
6572
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006573 if (ssid->auth_failures > 50)
6574 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006575 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006576 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006577 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006578 dur = 90;
6579 else if (ssid->auth_failures > 3)
6580 dur = 60;
6581 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006582 dur = 30;
6583 else if (ssid->auth_failures > 1)
6584 dur = 20;
6585 else
6586 dur = 10;
6587
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006588 if (ssid->auth_failures > 1 &&
6589 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6590 dur += os_random() % (ssid->auth_failures * 10);
6591
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006592 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006593 if (now.sec + dur <= ssid->disabled_until.sec)
6594 return;
6595
6596 ssid->disabled_until.sec = now.sec + dur;
6597
6598 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006599 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006600 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006601 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006602}
6603
6604
6605void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6606 struct wpa_ssid *ssid, int clear_failures)
6607{
6608 if (ssid == NULL)
6609 return;
6610
6611 if (ssid->disabled_until.sec) {
6612 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6613 "id=%d ssid=\"%s\"",
6614 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6615 }
6616 ssid->disabled_until.sec = 0;
6617 ssid->disabled_until.usec = 0;
6618 if (clear_failures)
6619 ssid->auth_failures = 0;
6620}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006621
6622
6623int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6624{
6625 size_t i;
6626
6627 if (wpa_s->disallow_aps_bssid == NULL)
6628 return 0;
6629
6630 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6631 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6632 bssid, ETH_ALEN) == 0)
6633 return 1;
6634 }
6635
6636 return 0;
6637}
6638
6639
6640int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6641 size_t ssid_len)
6642{
6643 size_t i;
6644
6645 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6646 return 0;
6647
6648 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6649 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6650 if (ssid_len == s->ssid_len &&
6651 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6652 return 1;
6653 }
6654
6655 return 0;
6656}
6657
6658
6659/**
6660 * wpas_request_connection - Request a new connection
6661 * @wpa_s: Pointer to the network interface
6662 *
6663 * This function is used to request a new connection to be found. It will mark
6664 * the interface to allow reassociation and request a new scan to find a
6665 * suitable network to connect to.
6666 */
6667void wpas_request_connection(struct wpa_supplicant *wpa_s)
6668{
6669 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006670 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006671 wpa_supplicant_reinit_autoscan(wpa_s);
6672 wpa_s->extra_blacklist_count = 0;
6673 wpa_s->disconnected = 0;
6674 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006675
6676 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6677 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006678 else
6679 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006680}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006681
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006682
Roshan Pius02242d72016-08-09 15:31:48 -07006683/**
6684 * wpas_request_disconnection - Request disconnection
6685 * @wpa_s: Pointer to the network interface
6686 *
6687 * This function is used to request disconnection from the currently connected
6688 * network. This will stop any ongoing scans and initiate deauthentication.
6689 */
6690void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6691{
6692#ifdef CONFIG_SME
6693 wpa_s->sme.prev_bssid_set = 0;
6694#endif /* CONFIG_SME */
6695 wpa_s->reassociate = 0;
6696 wpa_s->disconnected = 1;
6697 wpa_supplicant_cancel_sched_scan(wpa_s);
6698 wpa_supplicant_cancel_scan(wpa_s);
6699 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6700 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6701}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006702
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006703
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006704void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6705 struct wpa_used_freq_data *freqs_data,
6706 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006707{
6708 unsigned int i;
6709
6710 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6711 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006712 for (i = 0; i < len; i++) {
6713 struct wpa_used_freq_data *cur = &freqs_data[i];
6714 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6715 i, cur->freq, cur->flags);
6716 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006717}
6718
6719
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006720/*
6721 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006722 * are using the same radio as the current interface, and in addition, get
6723 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006724 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006725int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6726 struct wpa_used_freq_data *freqs_data,
6727 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006728{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006729 struct wpa_supplicant *ifs;
6730 u8 bssid[ETH_ALEN];
6731 int freq;
6732 unsigned int idx = 0, i;
6733
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006734 wpa_dbg(wpa_s, MSG_DEBUG,
6735 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006736 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006737
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006738 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6739 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006740 if (idx == len)
6741 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006742
6743 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6744 continue;
6745
6746 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006747 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6748 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006749 freq = ifs->current_ssid->frequency;
6750 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6751 freq = ifs->assoc_freq;
6752 else
6753 continue;
6754
6755 /* Hold only distinct freqs */
6756 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006757 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006758 break;
6759
6760 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006761 freqs_data[idx++].freq = freq;
6762
6763 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006764 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006765 WPA_FREQ_USED_BY_P2P_CLIENT :
6766 WPA_FREQ_USED_BY_INFRA_STATION;
6767 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006768 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006769
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006770 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006771 return idx;
6772}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006773
6774
6775/*
6776 * Find the operating frequencies of any of the virtual interfaces that
6777 * are using the same radio as the current interface.
6778 */
6779int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6780 int *freq_array, unsigned int len)
6781{
6782 struct wpa_used_freq_data *freqs_data;
6783 int num, i;
6784
6785 os_memset(freq_array, 0, sizeof(int) * len);
6786
6787 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6788 if (!freqs_data)
6789 return -1;
6790
6791 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6792 for (i = 0; i < num; i++)
6793 freq_array[i] = freqs_data[i].freq;
6794
6795 os_free(freqs_data);
6796
6797 return num;
6798}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006799
6800
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006801struct wpa_supplicant *
6802wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6803{
6804 switch (frame) {
6805#ifdef CONFIG_P2P
6806 case VENDOR_ELEM_PROBE_REQ_P2P:
6807 case VENDOR_ELEM_PROBE_RESP_P2P:
6808 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6809 case VENDOR_ELEM_BEACON_P2P_GO:
6810 case VENDOR_ELEM_P2P_PD_REQ:
6811 case VENDOR_ELEM_P2P_PD_RESP:
6812 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6813 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6814 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6815 case VENDOR_ELEM_P2P_INV_REQ:
6816 case VENDOR_ELEM_P2P_INV_RESP:
6817 case VENDOR_ELEM_P2P_ASSOC_REQ:
6818 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006819 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006820#endif /* CONFIG_P2P */
6821 default:
6822 return wpa_s;
6823 }
6824}
6825
6826
6827void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6828{
6829 unsigned int i;
6830 char buf[30];
6831
6832 wpa_printf(MSG_DEBUG, "Update vendor elements");
6833
6834 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6835 if (wpa_s->vendor_elem[i]) {
6836 int res;
6837
6838 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6839 if (!os_snprintf_error(sizeof(buf), res)) {
6840 wpa_hexdump_buf(MSG_DEBUG, buf,
6841 wpa_s->vendor_elem[i]);
6842 }
6843 }
6844 }
6845
6846#ifdef CONFIG_P2P
6847 if (wpa_s->parent == wpa_s &&
6848 wpa_s->global->p2p &&
6849 !wpa_s->global->p2p_disabled)
6850 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6851#endif /* CONFIG_P2P */
6852}
6853
6854
6855int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6856 const u8 *elem, size_t len)
6857{
6858 u8 *ie, *end;
6859
6860 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6861 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6862
6863 for (; ie + 1 < end; ie += 2 + ie[1]) {
6864 if (ie + len > end)
6865 break;
6866 if (os_memcmp(ie, elem, len) != 0)
6867 continue;
6868
6869 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6870 wpabuf_free(wpa_s->vendor_elem[frame]);
6871 wpa_s->vendor_elem[frame] = NULL;
6872 } else {
6873 os_memmove(ie, ie + len, end - (ie + len));
6874 wpa_s->vendor_elem[frame]->used -= len;
6875 }
6876 wpas_vendor_elem_update(wpa_s);
6877 return 0;
6878 }
6879
6880 return -1;
6881}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006882
6883
6884struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6885 u16 num_modes, enum hostapd_hw_mode mode)
6886{
6887 u16 i;
6888
6889 for (i = 0; i < num_modes; i++) {
6890 if (modes[i].mode == mode)
6891 return &modes[i];
6892 }
6893
6894 return NULL;
6895}
6896
6897
6898static struct
6899wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6900 const u8 *bssid)
6901{
6902 struct wpa_bss_tmp_disallowed *bss;
6903
6904 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6905 struct wpa_bss_tmp_disallowed, list) {
6906 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6907 return bss;
6908 }
6909
6910 return NULL;
6911}
6912
6913
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006914static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
6915{
6916 struct wpa_bss_tmp_disallowed *tmp;
6917 unsigned int num_bssid = 0;
6918 u8 *bssids;
6919 int ret;
6920
6921 bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
6922 if (!bssids)
6923 return -1;
6924 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
6925 struct wpa_bss_tmp_disallowed, list) {
6926 os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
6927 ETH_ALEN);
6928 num_bssid++;
6929 }
6930 ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
6931 os_free(bssids);
6932 return ret;
6933}
6934
6935
6936static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
6937{
6938 struct wpa_supplicant *wpa_s = eloop_ctx;
6939 struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
6940
6941 /* Make sure the bss is not already freed */
6942 dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
6943 struct wpa_bss_tmp_disallowed, list) {
6944 if (bss == tmp) {
6945 dl_list_del(&tmp->list);
6946 os_free(tmp);
6947 wpa_set_driver_tmp_disallow_list(wpa_s);
6948 break;
6949 }
6950 }
6951}
6952
6953
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006954void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6955 unsigned int sec)
6956{
6957 struct wpa_bss_tmp_disallowed *bss;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006958
6959 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6960 if (bss) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006961 eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
6962 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
6963 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006964 return;
6965 }
6966
6967 bss = os_malloc(sizeof(*bss));
6968 if (!bss) {
6969 wpa_printf(MSG_DEBUG,
6970 "Failed to allocate memory for temp disallow BSS");
6971 return;
6972 }
6973
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006974 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6975 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006976 wpa_set_driver_tmp_disallow_list(wpa_s);
6977 eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
6978 wpa_s, bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006979}
6980
6981
6982int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6983{
6984 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006985
6986 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6987 struct wpa_bss_tmp_disallowed, list) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006988 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6989 bss = tmp;
6990 break;
6991 }
6992 }
6993 if (!bss)
6994 return 0;
6995
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006996 return 1;
6997}