blob: 9aaedb314d04a2533ee04b8cb48805050d574442 [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 Shmidt8d520ff2011-05-09 14:06:53 -070041#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080042#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043#include "blacklist.h"
44#include "wpas_glue.h"
45#include "wps_supplicant.h"
46#include "ibss_rsn.h"
47#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080048#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "ap.h"
50#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070051#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070052#include "notify.h"
53#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070054#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070055#include "bss.h"
56#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080057#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070058#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070059#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070060#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080061#include "mesh.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070062
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070063const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070064"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidt29333592017-01-09 12:27:11 -080065"Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070066
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070067const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080068"This software may be distributed under the terms of the BSD license.\n"
69"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070#ifdef EAP_TLS_OPENSSL
71"\nThis product includes software developed by the OpenSSL Project\n"
72"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
73#endif /* EAP_TLS_OPENSSL */
74;
75
76#ifndef CONFIG_NO_STDOUT_DEBUG
77/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070078const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080079"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070080const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080081"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082"\n"
83"Redistribution and use in source and binary forms, with or without\n"
84"modification, are permitted provided that the following conditions are\n"
85"met:\n"
86"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070087const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088"1. Redistributions of source code must retain the above copyright\n"
89" notice, this list of conditions and the following disclaimer.\n"
90"\n"
91"2. Redistributions in binary form must reproduce the above copyright\n"
92" notice, this list of conditions and the following disclaimer in the\n"
93" documentation and/or other materials provided with the distribution.\n"
94"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070095const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
97" names of its contributors may be used to endorse or promote products\n"
98" derived from this software without specific prior written permission.\n"
99"\n"
100"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
101"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
102"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
103"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700104const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
106"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
107"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
108"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
109"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
110"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
111"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
112"\n";
113#endif /* CONFIG_NO_STDOUT_DEBUG */
114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700115/* Configure default/group WEP keys for static WEP */
116int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
117{
118 int i, set = 0;
119
120 for (i = 0; i < NUM_WEP_KEYS; i++) {
121 if (ssid->wep_key_len[i] == 0)
122 continue;
123
124 set = 1;
125 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
126 i, i == ssid->wep_tx_keyidx, NULL, 0,
127 ssid->wep_key[i], ssid->wep_key_len[i]);
128 }
129
130 return set;
131}
132
133
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700134int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
135 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136{
137 u8 key[32];
138 size_t keylen;
139 enum wpa_alg alg;
140 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800141 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700142
143 /* IBSS/WPA-None uses only one key (Group) for both receiving and
144 * sending unicast and multicast packets. */
145
146 if (ssid->mode != WPAS_MODE_IBSS) {
147 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
148 "IBSS/ad-hoc) for WPA-None", ssid->mode);
149 return -1;
150 }
151
152 if (!ssid->psk_set) {
153 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
154 "WPA-None");
155 return -1;
156 }
157
158 switch (wpa_s->group_cipher) {
159 case WPA_CIPHER_CCMP:
160 os_memcpy(key, ssid->psk, 16);
161 keylen = 16;
162 alg = WPA_ALG_CCMP;
163 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700164 case WPA_CIPHER_GCMP:
165 os_memcpy(key, ssid->psk, 16);
166 keylen = 16;
167 alg = WPA_ALG_GCMP;
168 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700169 case WPA_CIPHER_TKIP:
170 /* WPA-None uses the same Michael MIC key for both TX and RX */
171 os_memcpy(key, ssid->psk, 16 + 8);
172 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
173 keylen = 32;
174 alg = WPA_ALG_TKIP;
175 break;
176 default:
177 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
178 "WPA-None", wpa_s->group_cipher);
179 return -1;
180 }
181
182 /* TODO: should actually remember the previously used seq#, both for TX
183 * and RX from each STA.. */
184
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800185 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
186 os_memset(key, 0, sizeof(key));
187 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700188}
189
190
191static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
192{
193 struct wpa_supplicant *wpa_s = eloop_ctx;
194 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700195 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
196 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
197 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700198 bssid = wpa_s->pending_bssid;
199 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
200 MAC2STR(bssid));
201 wpa_blacklist_add(wpa_s, bssid);
202 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800203 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700204 wpa_s->reassociate = 1;
Roshan Pius38e96762017-01-23 14:52:00 -0800205 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700206
207 /*
208 * If we timed out, the AP or the local radio may be busy.
209 * So, wait a second until scanning again.
210 */
211 wpa_supplicant_req_scan(wpa_s, 1, 0);
212}
213
214
215/**
216 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
217 * @wpa_s: Pointer to wpa_supplicant data
218 * @sec: Number of seconds after which to time out authentication
219 * @usec: Number of microseconds after which to time out authentication
220 *
221 * This function is used to schedule a timeout for the current authentication
222 * attempt.
223 */
224void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
225 int sec, int usec)
226{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700227 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
229 return;
230
231 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
232 "%d usec", sec, usec);
233 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
234 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
235}
236
237
238/**
239 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
240 * @wpa_s: Pointer to wpa_supplicant data
241 *
242 * This function is used to cancel authentication timeout scheduled with
243 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
244 * been completed.
245 */
246void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
247{
248 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
249 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
250 wpa_blacklist_del(wpa_s, wpa_s->bssid);
251}
252
253
254/**
255 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
256 * @wpa_s: Pointer to wpa_supplicant data
257 *
258 * This function is used to configure EAPOL state machine based on the selected
259 * authentication mode.
260 */
261void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
262{
263#ifdef IEEE8021X_EAPOL
264 struct eapol_config eapol_conf;
265 struct wpa_ssid *ssid = wpa_s->current_ssid;
266
267#ifdef CONFIG_IBSS_RSN
268 if (ssid->mode == WPAS_MODE_IBSS &&
269 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
270 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
271 /*
272 * RSN IBSS authentication is per-STA and we can disable the
273 * per-BSSID EAPOL authentication.
274 */
275 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
276 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
277 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
278 return;
279 }
280#endif /* CONFIG_IBSS_RSN */
281
282 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
283 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
284
285 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
286 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
287 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
288 else
289 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
290
291 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
292 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
293 eapol_conf.accept_802_1x_keys = 1;
294 eapol_conf.required_keys = 0;
295 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
296 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
297 }
298 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
299 eapol_conf.required_keys |=
300 EAPOL_REQUIRE_KEY_BROADCAST;
301 }
302
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700303 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700304 eapol_conf.required_keys = 0;
305 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700306 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700307 eapol_conf.workaround = ssid->eap_workaround;
308 eapol_conf.eap_disabled =
309 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
310 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
311 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700312 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800313
314#ifdef CONFIG_WPS
315 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
316 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
317 if (wpa_s->current_bss) {
318 struct wpabuf *ie;
319 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
320 WPS_IE_VENDOR_TYPE);
321 if (ie) {
322 if (wps_is_20(ie))
323 eapol_conf.wps |=
324 EAPOL_PEER_IS_WPS20_AP;
325 wpabuf_free(ie);
326 }
327 }
328 }
329#endif /* CONFIG_WPS */
330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700331 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700332
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800333#ifdef CONFIG_MACSEC
334 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
335 ieee802_1x_create_preshared_mka(wpa_s, ssid);
336 else
337 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
338#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800339#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700340}
341
342
343/**
344 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
345 * @wpa_s: Pointer to wpa_supplicant data
346 * @ssid: Configuration data for the network
347 *
348 * This function is used to configure WPA state machine and related parameters
349 * to a mode where WPA is not enabled. This is called as part of the
350 * authentication configuration when the selected network does not use WPA.
351 */
352void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
353 struct wpa_ssid *ssid)
354{
355 int i;
356
357 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
358 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
359 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
360 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
361 else
362 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
363 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
364 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
365 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
366 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
367 wpa_s->group_cipher = WPA_CIPHER_NONE;
368 wpa_s->mgmt_group_cipher = 0;
369
370 for (i = 0; i < NUM_WEP_KEYS; i++) {
371 if (ssid->wep_key_len[i] > 5) {
372 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
373 wpa_s->group_cipher = WPA_CIPHER_WEP104;
374 break;
375 } else if (ssid->wep_key_len[i] > 0) {
376 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
377 wpa_s->group_cipher = WPA_CIPHER_WEP40;
378 break;
379 }
380 }
381
382 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
383 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
384 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
385 wpa_s->pairwise_cipher);
386 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
387#ifdef CONFIG_IEEE80211W
388 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
389 wpa_s->mgmt_group_cipher);
390#endif /* CONFIG_IEEE80211W */
391
392 pmksa_cache_clear_current(wpa_s->wpa);
393}
394
395
Dmitry Shmidt04949592012-07-19 12:16:46 -0700396void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800397{
398 int i;
399 if (wpa_s->hw.modes == NULL)
400 return;
401
402 for (i = 0; i < wpa_s->hw.num_modes; i++) {
403 os_free(wpa_s->hw.modes[i].channels);
404 os_free(wpa_s->hw.modes[i].rates);
405 }
406
407 os_free(wpa_s->hw.modes);
408 wpa_s->hw.modes = NULL;
409}
410
411
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800412static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
413{
414 struct wpa_bss_tmp_disallowed *bss, *prev;
415
416 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
417 struct wpa_bss_tmp_disallowed, list) {
418 dl_list_del(&bss->list);
419 os_free(bss);
420 }
421}
422
423
Paul Stewart092955c2017-02-06 09:13:09 -0800424void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
425{
426 struct fils_hlp_req *req;
427
428 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
429 list)) != NULL) {
430 dl_list_del(&req->list);
431 wpabuf_free(req->pkt);
432 os_free(req);
433 }
434}
435
436
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700437static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
438{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700439 int i;
440
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700441 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700442 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 scard_deinit(wpa_s->scard);
444 wpa_s->scard = NULL;
445 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
446 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
447 l2_packet_deinit(wpa_s->l2);
448 wpa_s->l2 = NULL;
449 if (wpa_s->l2_br) {
450 l2_packet_deinit(wpa_s->l2_br);
451 wpa_s->l2_br = NULL;
452 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800453#ifdef CONFIG_TESTING_OPTIONS
454 l2_packet_deinit(wpa_s->l2_test);
455 wpa_s->l2_test = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800456 os_free(wpa_s->get_pref_freq_list_override);
457 wpa_s->get_pref_freq_list_override = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800458#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700459
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700460 if (wpa_s->conf != NULL) {
461 struct wpa_ssid *ssid;
462 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
463 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700464 }
465
466 os_free(wpa_s->confname);
467 wpa_s->confname = NULL;
468
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700469 os_free(wpa_s->confanother);
470 wpa_s->confanother = NULL;
471
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700472 wpa_sm_set_eapol(wpa_s->wpa, NULL);
473 eapol_sm_deinit(wpa_s->eapol);
474 wpa_s->eapol = NULL;
475
476 rsn_preauth_deinit(wpa_s->wpa);
477
478#ifdef CONFIG_TDLS
479 wpa_tdls_deinit(wpa_s->wpa);
480#endif /* CONFIG_TDLS */
481
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800482 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700483 pmksa_candidate_free(wpa_s->wpa);
484 wpa_sm_deinit(wpa_s->wpa);
485 wpa_s->wpa = NULL;
486 wpa_blacklist_clear(wpa_s);
487
488 wpa_bss_deinit(wpa_s);
489
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700490 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700491 wpa_supplicant_cancel_scan(wpa_s);
492 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800493 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
494#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
495 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
496 wpa_s, NULL);
497#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700498
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700499 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700501 wpas_wps_deinit(wpa_s);
502
503 wpabuf_free(wpa_s->pending_eapol_rx);
504 wpa_s->pending_eapol_rx = NULL;
505
506#ifdef CONFIG_IBSS_RSN
507 ibss_rsn_deinit(wpa_s->ibss_rsn);
508 wpa_s->ibss_rsn = NULL;
509#endif /* CONFIG_IBSS_RSN */
510
511 sme_deinit(wpa_s);
512
513#ifdef CONFIG_AP
514 wpa_supplicant_ap_deinit(wpa_s);
515#endif /* CONFIG_AP */
516
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700517 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700518
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800519#ifdef CONFIG_OFFCHANNEL
520 offchannel_deinit(wpa_s);
521#endif /* CONFIG_OFFCHANNEL */
522
523 wpa_supplicant_cancel_sched_scan(wpa_s);
524
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700525 os_free(wpa_s->next_scan_freqs);
526 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800527
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800528 os_free(wpa_s->manual_scan_freqs);
529 wpa_s->manual_scan_freqs = NULL;
530
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700531 os_free(wpa_s->manual_sched_scan_freqs);
532 wpa_s->manual_sched_scan_freqs = NULL;
533
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800534 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
535
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700536 /*
537 * Need to remove any pending gas-query radio work before the
538 * gas_query_deinit() call because gas_query::work has not yet been set
539 * for works that have not been started. gas_query_free() will be unable
540 * to cancel such pending radio works and once the pending gas-query
541 * radio work eventually gets removed, the deinit notification call to
542 * gas_query_start_cb() would result in dereferencing freed memory.
543 */
544 if (wpa_s->radio)
545 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800546 gas_query_deinit(wpa_s->gas);
547 wpa_s->gas = NULL;
548
549 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700550
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700551 ieee802_1x_dealloc_kay_sm(wpa_s);
552
Dmitry Shmidt04949592012-07-19 12:16:46 -0700553 os_free(wpa_s->bssid_filter);
554 wpa_s->bssid_filter = NULL;
555
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800556 os_free(wpa_s->disallow_aps_bssid);
557 wpa_s->disallow_aps_bssid = NULL;
558 os_free(wpa_s->disallow_aps_ssid);
559 wpa_s->disallow_aps_ssid = NULL;
560
Dmitry Shmidt04949592012-07-19 12:16:46 -0700561 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700562#ifdef CONFIG_WNM
563 wnm_deallocate_memory(wpa_s);
564#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700565
566 ext_password_deinit(wpa_s->ext_pw);
567 wpa_s->ext_pw = NULL;
568
569 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800570 wpa_s->last_gas_resp = NULL;
571 wpabuf_free(wpa_s->prev_gas_resp);
572 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700573
574 os_free(wpa_s->last_scan_res);
575 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800576
577#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700578 if (wpa_s->drv_priv)
579 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700580 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800581#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700582
583 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
584 wpabuf_free(wpa_s->vendor_elem[i]);
585 wpa_s->vendor_elem[i] = NULL;
586 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800587
588 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800589
590 wpa_s->sched_scan_plans_num = 0;
591 os_free(wpa_s->sched_scan_plans);
592 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800593
594#ifdef CONFIG_MBO
595 wpa_s->non_pref_chan_num = 0;
596 os_free(wpa_s->non_pref_chan);
597 wpa_s->non_pref_chan = NULL;
598#endif /* CONFIG_MBO */
599
600 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700601
602 wpabuf_free(wpa_s->lci);
603 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800604 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800605
606#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
607#ifdef CONFIG_MESH
608 {
609 struct external_pmksa_cache *entry;
610
611 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
612 struct external_pmksa_cache,
613 list)) != NULL) {
614 dl_list_del(&entry->list);
615 os_free(entry->pmksa_cache);
616 os_free(entry);
617 }
618 }
619#endif /* CONFIG_MESH */
620#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
621
622 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800623
624 wpabuf_free(wpa_s->ric_ies);
625 wpa_s->ric_ies = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700626}
627
628
629/**
630 * wpa_clear_keys - Clear keys configured for the driver
631 * @wpa_s: Pointer to wpa_supplicant data
632 * @addr: Previously used BSSID or %NULL if not available
633 *
634 * This function clears the encryption keys that has been previously configured
635 * for the driver.
636 */
637void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
638{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800639 int i, max;
640
641#ifdef CONFIG_IEEE80211W
642 max = 6;
643#else /* CONFIG_IEEE80211W */
644 max = 4;
645#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700646
647 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800648 for (i = 0; i < max; i++) {
649 if (wpa_s->keys_cleared & BIT(i))
650 continue;
651 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
652 NULL, 0);
653 }
654 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
655 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700656 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
657 0);
658 /* MLME-SETPROTECTION.request(None) */
659 wpa_drv_mlme_setprotection(
660 wpa_s, addr,
661 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
662 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
663 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800664 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700665}
666
667
668/**
669 * wpa_supplicant_state_txt - Get the connection state name as a text string
670 * @state: State (wpa_state; WPA_*)
671 * Returns: The state name as a printable text string
672 */
673const char * wpa_supplicant_state_txt(enum wpa_states state)
674{
675 switch (state) {
676 case WPA_DISCONNECTED:
677 return "DISCONNECTED";
678 case WPA_INACTIVE:
679 return "INACTIVE";
680 case WPA_INTERFACE_DISABLED:
681 return "INTERFACE_DISABLED";
682 case WPA_SCANNING:
683 return "SCANNING";
684 case WPA_AUTHENTICATING:
685 return "AUTHENTICATING";
686 case WPA_ASSOCIATING:
687 return "ASSOCIATING";
688 case WPA_ASSOCIATED:
689 return "ASSOCIATED";
690 case WPA_4WAY_HANDSHAKE:
691 return "4WAY_HANDSHAKE";
692 case WPA_GROUP_HANDSHAKE:
693 return "GROUP_HANDSHAKE";
694 case WPA_COMPLETED:
695 return "COMPLETED";
696 default:
697 return "UNKNOWN";
698 }
699}
700
701
702#ifdef CONFIG_BGSCAN
703
704static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
705{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800706 const char *name;
707
708 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
709 name = wpa_s->current_ssid->bgscan;
710 else
711 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800712 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800713 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800714 if (wpas_driver_bss_selection(wpa_s))
715 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
717 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800718#ifdef CONFIG_P2P
719 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
720 return;
721#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700722
723 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800724 if (wpa_s->current_ssid) {
725 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700726 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
727 "bgscan");
728 /*
729 * Live without bgscan; it is only used as a roaming
730 * optimization, so the initial connection is not
731 * affected.
732 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700733 } else {
734 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700735 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700736 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
737 0);
738 if (scan_res) {
739 bgscan_notify_scan(wpa_s, scan_res);
740 wpa_scan_results_free(scan_res);
741 }
742 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743 } else
744 wpa_s->bgscan_ssid = NULL;
745}
746
747
748static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
749{
750 if (wpa_s->bgscan_ssid != NULL) {
751 bgscan_deinit(wpa_s);
752 wpa_s->bgscan_ssid = NULL;
753 }
754}
755
756#endif /* CONFIG_BGSCAN */
757
758
Dmitry Shmidt04949592012-07-19 12:16:46 -0700759static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
760{
761 if (autoscan_init(wpa_s, 0))
762 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
763}
764
765
766static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
767{
768 autoscan_deinit(wpa_s);
769}
770
771
772void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
773{
774 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
775 wpa_s->wpa_state == WPA_SCANNING) {
776 autoscan_deinit(wpa_s);
777 wpa_supplicant_start_autoscan(wpa_s);
778 }
779}
780
781
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700782/**
783 * wpa_supplicant_set_state - Set current connection state
784 * @wpa_s: Pointer to wpa_supplicant data
785 * @state: The new connection state
786 *
787 * This function is called whenever the connection state changes, e.g.,
788 * association is completed for WPA/WPA2 4-Way Handshake is started.
789 */
790void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
791 enum wpa_states state)
792{
793 enum wpa_states old_state = wpa_s->wpa_state;
794
795 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
796 wpa_supplicant_state_txt(wpa_s->wpa_state),
797 wpa_supplicant_state_txt(state));
798
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800799 if (state == WPA_INTERFACE_DISABLED) {
800 /* Assure normal scan when interface is restored */
801 wpa_s->normal_scans = 0;
802 }
803
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700804 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800805 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700806 /* Reinitialize normal_scan counter */
807 wpa_s->normal_scans = 0;
808 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800809
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700810#ifdef CONFIG_P2P
811 /*
812 * P2PS client has to reply to Probe Request frames received on the
813 * group operating channel. Enable Probe Request frame reporting for
814 * P2P connected client in case p2p_cli_probe configuration property is
815 * set to 1.
816 */
817 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
818 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
819 wpa_s->current_ssid->p2p_group) {
820 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
821 wpa_dbg(wpa_s, MSG_DEBUG,
822 "P2P: Enable CLI Probe Request RX reporting");
823 wpa_s->p2p_cli_probe =
824 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
825 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
826 wpa_dbg(wpa_s, MSG_DEBUG,
827 "P2P: Disable CLI Probe Request RX reporting");
828 wpa_s->p2p_cli_probe = 0;
829 wpa_drv_probe_req_report(wpa_s, 0);
830 }
831 }
832#endif /* CONFIG_P2P */
833
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700834 if (state != WPA_SCANNING)
835 wpa_supplicant_notify_scanning(wpa_s, 0);
836
837 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700838 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700839#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700840 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800841 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800842 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700843 ssid ? ssid->id : -1,
844 ssid && ssid->id_str ? ssid->id_str : "");
845#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700846 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700847 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800848 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700850 wpa_drv_set_operstate(wpa_s, 1);
851#ifndef IEEE8021X_EAPOL
852 wpa_drv_set_supp_port(wpa_s, 1);
853#endif /* IEEE8021X_EAPOL */
854 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700855 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700856 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700857
858 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700859 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
860 state == WPA_ASSOCIATED) {
861 wpa_s->new_connection = 1;
862 wpa_drv_set_operstate(wpa_s, 0);
863#ifndef IEEE8021X_EAPOL
864 wpa_drv_set_supp_port(wpa_s, 0);
865#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700866 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700867 }
868 wpa_s->wpa_state = state;
869
870#ifdef CONFIG_BGSCAN
871 if (state == WPA_COMPLETED)
872 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800873 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700874 wpa_supplicant_stop_bgscan(wpa_s);
875#endif /* CONFIG_BGSCAN */
876
Dmitry Shmidt04949592012-07-19 12:16:46 -0700877 if (state == WPA_AUTHENTICATING)
878 wpa_supplicant_stop_autoscan(wpa_s);
879
880 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
881 wpa_supplicant_start_autoscan(wpa_s);
882
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800883 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
884 wmm_ac_notify_disassoc(wpa_s);
885
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700886 if (wpa_s->wpa_state != old_state) {
887 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
888
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700889 /*
890 * Notify the P2P Device interface about a state change in one
891 * of the interfaces.
892 */
893 wpas_p2p_indicate_state_change(wpa_s);
894
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700895 if (wpa_s->wpa_state == WPA_COMPLETED ||
896 old_state == WPA_COMPLETED)
897 wpas_notify_auth_changed(wpa_s);
898 }
899}
900
901
902void wpa_supplicant_terminate_proc(struct wpa_global *global)
903{
904 int pending = 0;
905#ifdef CONFIG_WPS
906 struct wpa_supplicant *wpa_s = global->ifaces;
907 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800908 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700909 if (wpas_wps_terminate_pending(wpa_s) == 1)
910 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700911#ifdef CONFIG_P2P
912 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
913 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
914 wpas_p2p_disconnect(wpa_s);
915#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800916 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700917 }
918#endif /* CONFIG_WPS */
919 if (pending)
920 return;
921 eloop_terminate();
922}
923
924
925static void wpa_supplicant_terminate(int sig, void *signal_ctx)
926{
927 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700928 wpa_supplicant_terminate_proc(global);
929}
930
931
932void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
933{
934 enum wpa_states old_state = wpa_s->wpa_state;
935
936 wpa_s->pairwise_cipher = 0;
937 wpa_s->group_cipher = 0;
938 wpa_s->mgmt_group_cipher = 0;
939 wpa_s->key_mgmt = 0;
940 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700941 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700942
943 if (wpa_s->wpa_state != old_state)
944 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
945}
946
947
948/**
949 * wpa_supplicant_reload_configuration - Reload configuration data
950 * @wpa_s: Pointer to wpa_supplicant data
951 * Returns: 0 on success or -1 if configuration parsing failed
952 *
953 * This function can be used to request that the configuration data is reloaded
954 * (e.g., after configuration file change). This function is reloading
955 * configuration only for one interface, so this may need to be called multiple
956 * times if %wpa_supplicant is controlling multiple interfaces and all
957 * interfaces need reconfiguration.
958 */
959int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
960{
961 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700962 int reconf_ctrl;
963 int old_ap_scan;
964
965 if (wpa_s->confname == NULL)
966 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700967 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700968 if (conf == NULL) {
969 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
970 "file '%s' - exiting", wpa_s->confname);
971 return -1;
972 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700973 wpa_config_read(wpa_s->confanother, conf);
974
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700975 conf->changed_parameters = (unsigned int) -1;
976
977 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
978 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
979 os_strcmp(conf->ctrl_interface,
980 wpa_s->conf->ctrl_interface) != 0);
981
982 if (reconf_ctrl && wpa_s->ctrl_iface) {
983 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
984 wpa_s->ctrl_iface = NULL;
985 }
986
987 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800988 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700989 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
990 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800991 wpa_supplicant_deauthenticate(wpa_s,
992 WLAN_REASON_DEAUTH_LEAVING);
993 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700994
995 /*
996 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800997 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700998 */
999 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
1000 /*
1001 * Clear forced success to clear EAP state for next
1002 * authentication.
1003 */
1004 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1005 }
1006 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1007 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001008 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1010 rsn_preauth_deinit(wpa_s->wpa);
1011
1012 old_ap_scan = wpa_s->conf->ap_scan;
1013 wpa_config_free(wpa_s->conf);
1014 wpa_s->conf = conf;
1015 if (old_ap_scan != wpa_s->conf->ap_scan)
1016 wpas_notify_ap_scan_changed(wpa_s);
1017
1018 if (reconf_ctrl)
1019 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1020
1021 wpa_supplicant_update_config(wpa_s);
1022
1023 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001024 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 wpa_s->reassociate = 1;
1026 wpa_supplicant_req_scan(wpa_s, 0, 0);
1027 }
1028 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1029 return 0;
1030}
1031
1032
1033static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1034{
1035 struct wpa_global *global = signal_ctx;
1036 struct wpa_supplicant *wpa_s;
1037 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1038 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1039 sig);
1040 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1041 wpa_supplicant_terminate_proc(global);
1042 }
1043 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001044
1045 if (wpa_debug_reopen_file() < 0) {
1046 /* Ignore errors since we cannot really do much to fix this */
1047 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1048 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001049}
1050
1051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001052static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1053 struct wpa_ssid *ssid,
1054 struct wpa_ie_data *ie)
1055{
1056 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1057 if (ret) {
1058 if (ret == -2) {
1059 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1060 "from association info");
1061 }
1062 return -1;
1063 }
1064
1065 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1066 "cipher suites");
1067 if (!(ie->group_cipher & ssid->group_cipher)) {
1068 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1069 "cipher 0x%x (mask 0x%x) - reject",
1070 ie->group_cipher, ssid->group_cipher);
1071 return -1;
1072 }
1073 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1074 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1075 "cipher 0x%x (mask 0x%x) - reject",
1076 ie->pairwise_cipher, ssid->pairwise_cipher);
1077 return -1;
1078 }
1079 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1080 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1081 "management 0x%x (mask 0x%x) - reject",
1082 ie->key_mgmt, ssid->key_mgmt);
1083 return -1;
1084 }
1085
1086#ifdef CONFIG_IEEE80211W
1087 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001088 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1090 "that does not support management frame protection - "
1091 "reject");
1092 return -1;
1093 }
1094#endif /* CONFIG_IEEE80211W */
1095
1096 return 0;
1097}
1098
1099
1100/**
1101 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1102 * @wpa_s: Pointer to wpa_supplicant data
1103 * @bss: Scan results for the selected BSS, or %NULL if not available
1104 * @ssid: Configuration data for the selected network
1105 * @wpa_ie: Buffer for the WPA/RSN IE
1106 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1107 * used buffer length in case the functions returns success.
1108 * Returns: 0 on success or -1 on failure
1109 *
1110 * This function is used to configure authentication and encryption parameters
1111 * based on the network configuration and scan result for the selected BSS (if
1112 * available).
1113 */
1114int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1115 struct wpa_bss *bss, struct wpa_ssid *ssid,
1116 u8 *wpa_ie, size_t *wpa_ie_len)
1117{
1118 struct wpa_ie_data ie;
1119 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001120 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121
1122 if (bss) {
1123 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1124 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001125 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001126 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001127 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128
1129 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1130 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1131 (ie.group_cipher & ssid->group_cipher) &&
1132 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1133 (ie.key_mgmt & ssid->key_mgmt)) {
1134 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1135 proto = WPA_PROTO_RSN;
1136 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001137 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 (ie.group_cipher & ssid->group_cipher) &&
1139 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1140 (ie.key_mgmt & ssid->key_mgmt)) {
1141 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1142 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001143#ifdef CONFIG_HS20
1144 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1145 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1146 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001147 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001148 ie.group_cipher = WPA_CIPHER_CCMP;
1149 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1150 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1151 proto = WPA_PROTO_OSEN;
1152#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001153 } else if (bss) {
1154 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001155 wpa_dbg(wpa_s, MSG_DEBUG,
1156 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1157 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1158 ssid->key_mgmt);
1159 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1160 MAC2STR(bss->bssid),
1161 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1162 bss_wpa ? " WPA" : "",
1163 bss_rsn ? " RSN" : "",
1164 bss_osen ? " OSEN" : "");
1165 if (bss_rsn) {
1166 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1167 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1168 wpa_dbg(wpa_s, MSG_DEBUG,
1169 "Could not parse RSN element");
1170 } else {
1171 wpa_dbg(wpa_s, MSG_DEBUG,
1172 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1173 ie.pairwise_cipher, ie.group_cipher,
1174 ie.key_mgmt);
1175 }
1176 }
1177 if (bss_wpa) {
1178 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1179 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1180 wpa_dbg(wpa_s, MSG_DEBUG,
1181 "Could not parse WPA element");
1182 } else {
1183 wpa_dbg(wpa_s, MSG_DEBUG,
1184 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1185 ie.pairwise_cipher, ie.group_cipher,
1186 ie.key_mgmt);
1187 }
1188 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001189 return -1;
1190 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001191 if (ssid->proto & WPA_PROTO_OSEN)
1192 proto = WPA_PROTO_OSEN;
1193 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194 proto = WPA_PROTO_RSN;
1195 else
1196 proto = WPA_PROTO_WPA;
1197 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1198 os_memset(&ie, 0, sizeof(ie));
1199 ie.group_cipher = ssid->group_cipher;
1200 ie.pairwise_cipher = ssid->pairwise_cipher;
1201 ie.key_mgmt = ssid->key_mgmt;
1202#ifdef CONFIG_IEEE80211W
1203 ie.mgmt_group_cipher =
1204 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1205 WPA_CIPHER_AES_128_CMAC : 0;
1206#endif /* CONFIG_IEEE80211W */
1207 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1208 "based on configuration");
1209 } else
1210 proto = ie.proto;
1211 }
1212
1213 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1214 "pairwise %d key_mgmt %d proto %d",
1215 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1216#ifdef CONFIG_IEEE80211W
1217 if (ssid->ieee80211w) {
1218 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1219 ie.mgmt_group_cipher);
1220 }
1221#endif /* CONFIG_IEEE80211W */
1222
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001223 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001224 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1225 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001226 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001227
1228 if (bss || !wpa_s->ap_ies_from_associnfo) {
1229 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1230 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1231 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1232 bss_rsn ? 2 + bss_rsn[1] : 0))
1233 return -1;
1234 }
1235
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001236#ifdef CONFIG_NO_WPA
1237 wpa_s->group_cipher = WPA_CIPHER_NONE;
1238 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1239#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001240 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001241 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1242 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001243 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1244 "cipher");
1245 return -1;
1246 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001247 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1248 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001249
1250 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001251 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1252 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001253 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1254 "cipher");
1255 return -1;
1256 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001257 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1258 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001259#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001260
1261 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001262#ifdef CONFIG_SAE
1263 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1264 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1265#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001266 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001267#ifdef CONFIG_SUITEB192
1268 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1269 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1270 wpa_dbg(wpa_s, MSG_DEBUG,
1271 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1272#endif /* CONFIG_SUITEB192 */
1273#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001274 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1275 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1276 wpa_dbg(wpa_s, MSG_DEBUG,
1277 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001278#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001279#ifdef CONFIG_FILS
1280#ifdef CONFIG_IEEE80211R
1281 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1282 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1283 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1284 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1285 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1286 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1287#endif /* CONFIG_IEEE80211R */
1288 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1289 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1290 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1291 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1292 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1293 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1294#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001295#ifdef CONFIG_IEEE80211R
1296 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1297 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1298 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1299 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1300 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1301 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1302#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001303#ifdef CONFIG_SAE
1304 } else if (sel & WPA_KEY_MGMT_SAE) {
1305 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1306 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1307 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1308 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1309 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1310#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001311#ifdef CONFIG_IEEE80211W
1312 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1313 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1314 wpa_dbg(wpa_s, MSG_DEBUG,
1315 "WPA: using KEY_MGMT 802.1X with SHA256");
1316 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1317 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1318 wpa_dbg(wpa_s, MSG_DEBUG,
1319 "WPA: using KEY_MGMT PSK with SHA256");
1320#endif /* CONFIG_IEEE80211W */
1321 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1322 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1323 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1324 } else if (sel & WPA_KEY_MGMT_PSK) {
1325 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1326 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1327 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1328 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1329 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001330#ifdef CONFIG_HS20
1331 } else if (sel & WPA_KEY_MGMT_OSEN) {
1332 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1333 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1334#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001335 } else {
1336 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1337 "authenticated key management type");
1338 return -1;
1339 }
1340
1341 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1342 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1343 wpa_s->pairwise_cipher);
1344 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1345
1346#ifdef CONFIG_IEEE80211W
1347 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001348 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001349 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1350 sel = 0;
1351 if (sel & WPA_CIPHER_AES_128_CMAC) {
1352 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1353 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1354 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001355 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1356 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1357 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1358 "BIP-GMAC-128");
1359 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1360 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1361 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1362 "BIP-GMAC-256");
1363 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1364 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1365 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1366 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001367 } else {
1368 wpa_s->mgmt_group_cipher = 0;
1369 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1370 }
1371 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1372 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001373 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001374 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001375#endif /* CONFIG_IEEE80211W */
1376
1377 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1378 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1379 return -1;
1380 }
1381
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001382 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001383 int psk_set = 0;
1384
1385 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001386 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1387 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001388 psk_set = 1;
1389 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001390#ifndef CONFIG_NO_PBKDF2
1391 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1392 ssid->passphrase) {
1393 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001394 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1395 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001396 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1397 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001398 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001399 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001400 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001401 }
1402#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001403#ifdef CONFIG_EXT_PASSWORD
1404 if (ssid->ext_psk) {
1405 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1406 ssid->ext_psk);
1407 char pw_str[64 + 1];
1408 u8 psk[PMK_LEN];
1409
1410 if (pw == NULL) {
1411 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1412 "found from external storage");
1413 return -1;
1414 }
1415
1416 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1417 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1418 "PSK length %d in external storage",
1419 (int) wpabuf_len(pw));
1420 ext_password_free(pw);
1421 return -1;
1422 }
1423
1424 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1425 pw_str[wpabuf_len(pw)] = '\0';
1426
1427#ifndef CONFIG_NO_PBKDF2
1428 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1429 {
1430 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1431 4096, psk, PMK_LEN);
1432 os_memset(pw_str, 0, sizeof(pw_str));
1433 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1434 "external passphrase)",
1435 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001436 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1437 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001438 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001439 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001440 } else
1441#endif /* CONFIG_NO_PBKDF2 */
1442 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1443 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1444 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1445 "Invalid PSK hex string");
1446 os_memset(pw_str, 0, sizeof(pw_str));
1447 ext_password_free(pw);
1448 return -1;
1449 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001450 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1451 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001452 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001453 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001454 } else {
1455 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1456 "PSK available");
1457 os_memset(pw_str, 0, sizeof(pw_str));
1458 ext_password_free(pw);
1459 return -1;
1460 }
1461
1462 os_memset(pw_str, 0, sizeof(pw_str));
1463 ext_password_free(pw);
1464 }
1465#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001466
1467 if (!psk_set) {
1468 wpa_msg(wpa_s, MSG_INFO,
1469 "No PSK available for association");
1470 return -1;
1471 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001472 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001473 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1474
1475 return 0;
1476}
1477
1478
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001479static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1480{
1481 *pos = 0x00;
1482
1483 switch (idx) {
1484 case 0: /* Bits 0-7 */
1485 break;
1486 case 1: /* Bits 8-15 */
1487 break;
1488 case 2: /* Bits 16-23 */
1489#ifdef CONFIG_WNM
1490 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1491 *pos |= 0x08; /* Bit 19 - BSS Transition */
1492#endif /* CONFIG_WNM */
1493 break;
1494 case 3: /* Bits 24-31 */
1495#ifdef CONFIG_WNM
1496 *pos |= 0x02; /* Bit 25 - SSID List */
1497#endif /* CONFIG_WNM */
1498#ifdef CONFIG_INTERWORKING
1499 if (wpa_s->conf->interworking)
1500 *pos |= 0x80; /* Bit 31 - Interworking */
1501#endif /* CONFIG_INTERWORKING */
1502 break;
1503 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001504#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001505 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1506 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001507#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001508 break;
1509 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001510#ifdef CONFIG_HS20
1511 if (wpa_s->conf->hs20)
1512 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1513#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001514#ifdef CONFIG_MBO
1515 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1516#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001517 break;
1518 case 6: /* Bits 48-55 */
1519 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001520 case 7: /* Bits 56-63 */
1521 break;
1522 case 8: /* Bits 64-71 */
1523 if (wpa_s->conf->ftm_responder)
1524 *pos |= 0x40; /* Bit 70 - FTM responder */
1525 if (wpa_s->conf->ftm_initiator)
1526 *pos |= 0x80; /* Bit 71 - FTM initiator */
1527 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001528 case 9: /* Bits 72-79 */
1529#ifdef CONFIG_FILS
1530 *pos |= 0x01;
1531#endif /* CONFIG_FILS */
1532 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001533 }
1534}
1535
1536
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001537int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001538{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001539 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001540 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001541
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001542 if (len < wpa_s->extended_capa_len)
1543 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001544 if (buflen < (size_t) len + 2) {
1545 wpa_printf(MSG_INFO,
1546 "Not enough room for building extended capabilities element");
1547 return -1;
1548 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001549
1550 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001551 *pos++ = len;
1552 for (i = 0; i < len; i++, pos++) {
1553 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001554
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001555 if (i < wpa_s->extended_capa_len) {
1556 *pos &= ~wpa_s->extended_capa_mask[i];
1557 *pos |= wpa_s->extended_capa[i];
1558 }
1559 }
1560
1561 while (len > 0 && buf[1 + len] == 0) {
1562 len--;
1563 buf[1] = len;
1564 }
1565 if (len == 0)
1566 return 0;
1567
1568 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001569}
1570
1571
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001572static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1573 struct wpa_bss *test_bss)
1574{
1575 struct wpa_bss *bss;
1576
1577 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1578 if (bss == test_bss)
1579 return 1;
1580 }
1581
1582 return 0;
1583}
1584
1585
1586static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1587 struct wpa_ssid *test_ssid)
1588{
1589 struct wpa_ssid *ssid;
1590
1591 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1592 if (ssid == test_ssid)
1593 return 1;
1594 }
1595
1596 return 0;
1597}
1598
1599
1600int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1601 struct wpa_ssid *test_ssid)
1602{
1603 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1604 return 0;
1605
1606 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1607}
1608
1609
1610void wpas_connect_work_free(struct wpa_connect_work *cwork)
1611{
1612 if (cwork == NULL)
1613 return;
1614 os_free(cwork);
1615}
1616
1617
1618void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1619{
1620 struct wpa_connect_work *cwork;
1621 struct wpa_radio_work *work = wpa_s->connect_work;
1622
1623 if (!work)
1624 return;
1625
1626 wpa_s->connect_work = NULL;
1627 cwork = work->ctx;
1628 work->ctx = NULL;
1629 wpas_connect_work_free(cwork);
1630 radio_work_done(work);
1631}
1632
1633
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001634int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1635{
1636 struct os_reltime now;
1637 u8 addr[ETH_ALEN];
1638
1639 os_get_reltime(&now);
1640 if (wpa_s->last_mac_addr_style == style &&
1641 wpa_s->last_mac_addr_change.sec != 0 &&
1642 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1643 wpa_s->conf->rand_addr_lifetime)) {
1644 wpa_msg(wpa_s, MSG_DEBUG,
1645 "Previously selected random MAC address has not yet expired");
1646 return 0;
1647 }
1648
1649 switch (style) {
1650 case 1:
1651 if (random_mac_addr(addr) < 0)
1652 return -1;
1653 break;
1654 case 2:
1655 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1656 if (random_mac_addr_keep_oui(addr) < 0)
1657 return -1;
1658 break;
1659 default:
1660 return -1;
1661 }
1662
1663 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1664 wpa_msg(wpa_s, MSG_INFO,
1665 "Failed to set random MAC address");
1666 return -1;
1667 }
1668
1669 os_get_reltime(&wpa_s->last_mac_addr_change);
1670 wpa_s->mac_addr_changed = 1;
1671 wpa_s->last_mac_addr_style = style;
1672
1673 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1674 wpa_msg(wpa_s, MSG_INFO,
1675 "Could not update MAC address information");
1676 return -1;
1677 }
1678
1679 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1680 MAC2STR(addr));
1681
1682 return 0;
1683}
1684
1685
1686int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1687{
1688 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1689 !wpa_s->conf->preassoc_mac_addr)
1690 return 0;
1691
1692 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1693}
1694
1695
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001696static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1697
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001698/**
1699 * wpa_supplicant_associate - Request association
1700 * @wpa_s: Pointer to wpa_supplicant data
1701 * @bss: Scan results for the selected BSS, or %NULL if not available
1702 * @ssid: Configuration data for the selected network
1703 *
1704 * This function is used to request %wpa_supplicant to associate with a BSS.
1705 */
1706void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1707 struct wpa_bss *bss, struct wpa_ssid *ssid)
1708{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001709 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001710 int rand_style;
1711
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001712 wpa_s->own_disconnect_req = 0;
1713
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001714 /*
1715 * If we are starting a new connection, any previously pending EAPOL
1716 * RX cannot be valid anymore.
1717 */
1718 wpabuf_free(wpa_s->pending_eapol_rx);
1719 wpa_s->pending_eapol_rx = NULL;
1720
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001721 if (ssid->mac_addr == -1)
1722 rand_style = wpa_s->conf->mac_addr;
1723 else
1724 rand_style = ssid->mac_addr;
1725
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001726 wmm_ac_clear_saved_tspecs(wpa_s);
1727 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001728 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001729
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001730 if (wpa_s->last_ssid == ssid) {
1731 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001732 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001733 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1734 wmm_ac_save_tspecs(wpa_s);
1735 wpa_s->reassoc_same_bss = 1;
1736 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001737 }
1738
1739 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001740 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1741 return;
1742 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001743 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001744 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1745 wpa_msg(wpa_s, MSG_INFO,
1746 "Could not restore permanent MAC address");
1747 return;
1748 }
1749 wpa_s->mac_addr_changed = 0;
1750 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1751 wpa_msg(wpa_s, MSG_INFO,
1752 "Could not update MAC address information");
1753 return;
1754 }
1755 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1756 }
1757 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001758
1759#ifdef CONFIG_IBSS_RSN
1760 ibss_rsn_deinit(wpa_s->ibss_rsn);
1761 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001762#else /* CONFIG_IBSS_RSN */
1763 if (ssid->mode == WPAS_MODE_IBSS &&
1764 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1765 wpa_msg(wpa_s, MSG_INFO,
1766 "IBSS RSN not supported in the build");
1767 return;
1768 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001769#endif /* CONFIG_IBSS_RSN */
1770
1771 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1772 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1773#ifdef CONFIG_AP
1774 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1775 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1776 "mode");
1777 return;
1778 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001779 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1780 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001781 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1782 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001783 return;
1784 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001785 wpa_s->current_bss = bss;
1786#else /* CONFIG_AP */
1787 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1788 "the build");
1789#endif /* CONFIG_AP */
1790 return;
1791 }
1792
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001793 if (ssid->mode == WPAS_MODE_MESH) {
1794#ifdef CONFIG_MESH
1795 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1796 wpa_msg(wpa_s, MSG_INFO,
1797 "Driver does not support mesh mode");
1798 return;
1799 }
1800 if (bss)
1801 ssid->frequency = bss->freq;
1802 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1803 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1804 return;
1805 }
1806 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001807 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1808 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1809 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001810#else /* CONFIG_MESH */
1811 wpa_msg(wpa_s, MSG_ERROR,
1812 "mesh mode support not included in the build");
1813#endif /* CONFIG_MESH */
1814 return;
1815 }
1816
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001817#ifdef CONFIG_TDLS
1818 if (bss)
1819 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1820 bss->ie_len);
1821#endif /* CONFIG_TDLS */
1822
1823 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1824 ssid->mode == IEEE80211_MODE_INFRA) {
1825 sme_authenticate(wpa_s, bss, ssid);
1826 return;
1827 }
1828
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001829 if (wpa_s->connect_work) {
1830 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1831 return;
1832 }
1833
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001834 if (radio_work_pending(wpa_s, "connect")) {
1835 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1836 return;
1837 }
1838
Dmitry Shmidt29333592017-01-09 12:27:11 -08001839#ifdef CONFIG_SME
1840 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
1841 /* Clear possibly set auth_alg, if any, from last attempt. */
1842 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
1843 }
1844#endif /* CONFIG_SME */
1845
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001846 wpas_abort_ongoing_scan(wpa_s);
1847
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001848 cwork = os_zalloc(sizeof(*cwork));
1849 if (cwork == NULL)
1850 return;
1851
1852 cwork->bss = bss;
1853 cwork->ssid = ssid;
1854
1855 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1856 wpas_start_assoc_cb, cwork) < 0) {
1857 os_free(cwork);
1858 }
1859}
1860
1861
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001862static int bss_is_ibss(struct wpa_bss *bss)
1863{
1864 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1865 IEEE80211_CAP_IBSS;
1866}
1867
1868
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001869static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1870 const struct wpa_ssid *ssid)
1871{
1872 enum hostapd_hw_mode hw_mode;
1873 struct hostapd_hw_modes *mode = NULL;
1874 u8 channel;
1875 int i;
1876
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001877 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1878 if (hw_mode == NUM_HOSTAPD_MODES)
1879 return 0;
1880 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1881 if (wpa_s->hw.modes[i].mode == hw_mode) {
1882 mode = &wpa_s->hw.modes[i];
1883 break;
1884 }
1885 }
1886
1887 if (!mode)
1888 return 0;
1889
1890 return mode->vht_capab != 0;
1891}
1892
1893
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001894void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1895 const struct wpa_ssid *ssid,
1896 struct hostapd_freq_params *freq)
1897{
1898 enum hostapd_hw_mode hw_mode;
1899 struct hostapd_hw_modes *mode = NULL;
1900 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1901 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001902 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001903 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1904 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001905 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001906 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001907 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001908 int chwidth, seg0, seg1;
1909 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001910
1911 freq->freq = ssid->frequency;
1912
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001913 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1914 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1915
1916 if (ssid->mode != WPAS_MODE_IBSS)
1917 break;
1918
1919 /* Don't adjust control freq in case of fixed_freq */
1920 if (ssid->fixed_freq)
1921 break;
1922
1923 if (!bss_is_ibss(bss))
1924 continue;
1925
1926 if (ssid->ssid_len == bss->ssid_len &&
1927 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1928 wpa_printf(MSG_DEBUG,
1929 "IBSS already found in scan results, adjust control freq: %d",
1930 bss->freq);
1931 freq->freq = bss->freq;
1932 obss_scan = 0;
1933 break;
1934 }
1935 }
1936
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001937 /* For IBSS check HT_IBSS flag */
1938 if (ssid->mode == WPAS_MODE_IBSS &&
1939 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1940 return;
1941
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001942 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1943 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1944 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1945 wpa_printf(MSG_DEBUG,
1946 "IBSS: WEP/TKIP detected, do not try to enable HT");
1947 return;
1948 }
1949
1950 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001951 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1952 if (wpa_s->hw.modes[i].mode == hw_mode) {
1953 mode = &wpa_s->hw.modes[i];
1954 break;
1955 }
1956 }
1957
1958 if (!mode)
1959 return;
1960
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001961#ifdef CONFIG_HT_OVERRIDES
1962 if (ssid->disable_ht) {
1963 freq->ht_enabled = 0;
1964 return;
1965 }
1966#endif /* CONFIG_HT_OVERRIDES */
1967
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001968 freq->ht_enabled = ht_supported(mode);
1969 if (!freq->ht_enabled)
1970 return;
1971
1972 /* Setup higher BW only for 5 GHz */
1973 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1974 return;
1975
1976 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1977 pri_chan = &mode->channels[chan_idx];
1978 if (pri_chan->chan == channel)
1979 break;
1980 pri_chan = NULL;
1981 }
1982 if (!pri_chan)
1983 return;
1984
1985 /* Check primary channel flags */
1986 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1987 return;
1988
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001989#ifdef CONFIG_HT_OVERRIDES
1990 if (ssid->disable_ht40)
1991 return;
1992#endif /* CONFIG_HT_OVERRIDES */
1993
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001994 /* Check/setup HT40+/HT40- */
1995 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1996 if (ht40plus[j] == channel) {
1997 ht40 = 1;
1998 break;
1999 }
2000 }
2001
2002 /* Find secondary channel */
2003 for (i = 0; i < mode->num_channels; i++) {
2004 sec_chan = &mode->channels[i];
2005 if (sec_chan->chan == channel + ht40 * 4)
2006 break;
2007 sec_chan = NULL;
2008 }
2009 if (!sec_chan)
2010 return;
2011
2012 /* Check secondary channel flags */
2013 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2014 return;
2015
2016 freq->channel = pri_chan->chan;
2017
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002018 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002019 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2020 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002021 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002022 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2023 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002024 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002025 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002026
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002027 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002028 struct wpa_scan_results *scan_res;
2029
2030 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2031 if (scan_res == NULL) {
2032 /* Back to HT20 */
2033 freq->sec_channel_offset = 0;
2034 return;
2035 }
2036
2037 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2038 sec_chan->chan);
2039 switch (res) {
2040 case 0:
2041 /* Back to HT20 */
2042 freq->sec_channel_offset = 0;
2043 break;
2044 case 1:
2045 /* Configuration allowed */
2046 break;
2047 case 2:
2048 /* Switch pri/sec channels */
2049 freq->freq = hw_get_freq(mode, sec_chan->chan);
2050 freq->sec_channel_offset = -freq->sec_channel_offset;
2051 freq->channel = sec_chan->chan;
2052 break;
2053 default:
2054 freq->sec_channel_offset = 0;
2055 break;
2056 }
2057
2058 wpa_scan_results_free(scan_res);
2059 }
2060
2061 wpa_printf(MSG_DEBUG,
2062 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2063 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002064
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002065 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002066 return;
2067
2068 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002069 if (ssid->mode == WPAS_MODE_IBSS &&
2070 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002071 return;
2072
2073 vht_freq = *freq;
2074
Paul Stewart092955c2017-02-06 09:13:09 -08002075#ifdef CONFIG_VHT_OVERRIDES
2076 if (ssid->disable_vht) {
2077 freq->vht_enabled = 0;
2078 return;
2079 }
2080#endif /* CONFIG_VHT_OVERRIDES */
2081
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002082 vht_freq.vht_enabled = vht_supported(mode);
2083 if (!vht_freq.vht_enabled)
2084 return;
2085
2086 /* setup center_freq1, bandwidth */
2087 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2088 if (freq->channel >= vht80[j] &&
2089 freq->channel < vht80[j] + 16)
2090 break;
2091 }
2092
2093 if (j == ARRAY_SIZE(vht80))
2094 return;
2095
2096 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2097 struct hostapd_channel_data *chan;
2098
2099 chan = hw_get_channel_chan(mode, i, NULL);
2100 if (!chan)
2101 return;
2102
2103 /* Back to HT configuration if channel not usable */
2104 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2105 return;
2106 }
2107
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002108 chwidth = VHT_CHANWIDTH_80MHZ;
2109 seg0 = vht80[j] + 6;
2110 seg1 = 0;
2111
2112 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2113 /* setup center_freq2, bandwidth */
2114 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2115 /* Only accept 80 MHz segments separated by a gap */
2116 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2117 continue;
2118 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2119 struct hostapd_channel_data *chan;
2120
2121 chan = hw_get_channel_chan(mode, i, NULL);
2122 if (!chan)
2123 continue;
2124
2125 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2126 HOSTAPD_CHAN_NO_IR |
2127 HOSTAPD_CHAN_RADAR))
2128 continue;
2129
2130 /* Found a suitable second segment for 80+80 */
2131 chwidth = VHT_CHANWIDTH_80P80MHZ;
2132 vht_caps |=
2133 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2134 seg1 = vht80[k] + 6;
2135 }
2136
2137 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2138 break;
2139 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002140 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2141 if (freq->freq == 5180) {
2142 chwidth = VHT_CHANWIDTH_160MHZ;
2143 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2144 seg0 = 50;
2145 } else if (freq->freq == 5520) {
2146 chwidth = VHT_CHANWIDTH_160MHZ;
2147 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2148 seg0 = 114;
2149 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002150 }
2151
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002152 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2153 freq->channel, freq->ht_enabled,
2154 vht_freq.vht_enabled,
2155 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002156 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002157 return;
2158
2159 *freq = vht_freq;
2160
2161 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2162 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002163}
2164
2165
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002166static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2167{
2168 struct wpa_connect_work *cwork = work->ctx;
2169 struct wpa_bss *bss = cwork->bss;
2170 struct wpa_ssid *ssid = cwork->ssid;
2171 struct wpa_supplicant *wpa_s = work->wpa_s;
2172 u8 wpa_ie[200];
2173 size_t wpa_ie_len;
2174 int use_crypt, ret, i, bssid_changed;
2175 int algs = WPA_AUTH_ALG_OPEN;
2176 unsigned int cipher_pairwise, cipher_group;
2177 struct wpa_driver_associate_params params;
2178 int wep_keys_set = 0;
2179 int assoc_failed = 0;
2180 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002181 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002182#ifdef CONFIG_HT_OVERRIDES
2183 struct ieee80211_ht_capabilities htcaps;
2184 struct ieee80211_ht_capabilities htcaps_mask;
2185#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002186#ifdef CONFIG_VHT_OVERRIDES
2187 struct ieee80211_vht_capabilities vhtcaps;
2188 struct ieee80211_vht_capabilities vhtcaps_mask;
2189#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002190
2191 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002192 if (work->started) {
2193 wpa_s->connect_work = NULL;
2194
2195 /* cancel possible auth. timeout */
2196 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2197 NULL);
2198 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002199 wpas_connect_work_free(cwork);
2200 return;
2201 }
2202
2203 wpa_s->connect_work = work;
2204
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002205 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2206 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002207 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2208 wpas_connect_work_done(wpa_s);
2209 return;
2210 }
2211
Dmitry Shmidte4663042016-04-04 10:07:49 -07002212 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002213 os_memset(&params, 0, sizeof(params));
2214 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002215 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002216 if (bss &&
2217 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002218#ifdef CONFIG_IEEE80211R
2219 const u8 *ie, *md = NULL;
2220#endif /* CONFIG_IEEE80211R */
2221 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2222 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2223 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2224 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2225 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2226 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2227 if (bssid_changed)
2228 wpas_notify_bssid_changed(wpa_s);
2229#ifdef CONFIG_IEEE80211R
2230 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2231 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2232 md = ie + 2;
2233 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2234 if (md) {
2235 /* Prepare for the next transition */
2236 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2237 }
2238#endif /* CONFIG_IEEE80211R */
2239#ifdef CONFIG_WPS
2240 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2241 wpa_s->conf->ap_scan == 2 &&
2242 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2243 /* Use ap_scan==1 style network selection to find the network
2244 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002245 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002246 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002247 wpa_s->reassociate = 1;
2248 wpa_supplicant_req_scan(wpa_s, 0, 0);
2249 return;
2250#endif /* CONFIG_WPS */
2251 } else {
2252 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2253 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002254 if (bss)
2255 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2256 else
2257 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002259 if (!wpa_s->pno)
2260 wpa_supplicant_cancel_sched_scan(wpa_s);
2261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002262 wpa_supplicant_cancel_scan(wpa_s);
2263
2264 /* Starting new association, so clear the possibly used WPA IE from the
2265 * previous association. */
2266 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2267
2268#ifdef IEEE8021X_EAPOL
2269 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2270 if (ssid->leap) {
2271 if (ssid->non_leap == 0)
2272 algs = WPA_AUTH_ALG_LEAP;
2273 else
2274 algs |= WPA_AUTH_ALG_LEAP;
2275 }
2276 }
2277#endif /* IEEE8021X_EAPOL */
2278 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2279 if (ssid->auth_alg) {
2280 algs = ssid->auth_alg;
2281 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2282 "0x%x", algs);
2283 }
2284
2285 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2286 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002287 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002288 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002289 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2290 wpa_s->conf->okc :
2291 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002292 (ssid->proto & WPA_PROTO_RSN);
2293 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002294 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002295 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296 wpa_ie_len = sizeof(wpa_ie);
2297 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2298 wpa_ie, &wpa_ie_len)) {
2299 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2300 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002301 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002302 return;
2303 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002304 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2305 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2306 /*
2307 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2308 * use non-WPA since the scan results did not indicate that the
2309 * AP is using WPA or WPA2.
2310 */
2311 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2312 wpa_ie_len = 0;
2313 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002314 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002315 wpa_ie_len = sizeof(wpa_ie);
2316 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2317 wpa_ie, &wpa_ie_len)) {
2318 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2319 "key management and encryption suites (no "
2320 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002321 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002322 return;
2323 }
2324#ifdef CONFIG_WPS
2325 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2326 struct wpabuf *wps_ie;
2327 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2328 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2329 wpa_ie_len = wpabuf_len(wps_ie);
2330 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2331 } else
2332 wpa_ie_len = 0;
2333 wpabuf_free(wps_ie);
2334 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2335 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2336 params.wps = WPS_MODE_PRIVACY;
2337 else
2338 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002339 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340#endif /* CONFIG_WPS */
2341 } else {
2342 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2343 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002344 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002345 }
2346
2347#ifdef CONFIG_P2P
2348 if (wpa_s->global->p2p) {
2349 u8 *pos;
2350 size_t len;
2351 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002352 pos = wpa_ie + wpa_ie_len;
2353 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002354 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2355 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002356 if (res >= 0)
2357 wpa_ie_len += res;
2358 }
2359
2360 wpa_s->cross_connect_disallowed = 0;
2361 if (bss) {
2362 struct wpabuf *p2p;
2363 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2364 if (p2p) {
2365 wpa_s->cross_connect_disallowed =
2366 p2p_get_cross_connect_disallowed(p2p);
2367 wpabuf_free(p2p);
2368 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2369 "connection",
2370 wpa_s->cross_connect_disallowed ?
2371 "disallows" : "allows");
2372 }
2373 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002374
2375 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376#endif /* CONFIG_P2P */
2377
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002378 if (bss) {
Dmitry Shmidt29333592017-01-09 12:27:11 -08002379 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
2380 wpa_ie + wpa_ie_len,
2381 sizeof(wpa_ie) -
2382 wpa_ie_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002383 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002384
Dmitry Shmidt56052862013-10-04 10:23:25 -07002385 /*
2386 * Workaround: Add Extended Capabilities element only if the AP
2387 * included this element in Beacon/Probe Response frames. Some older
2388 * APs seem to have interoperability issues if this element is
2389 * included, so while the standard may require us to include the
2390 * element in all cases, it is justifiable to skip it to avoid
2391 * interoperability issues.
2392 */
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002393 if (ssid->p2p_group)
2394 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2395 else
2396 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2397
Dmitry Shmidt56052862013-10-04 10:23:25 -07002398 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002399 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002400 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002401 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2402 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002403 if (ext_capab_len > 0) {
2404 u8 *pos = wpa_ie;
2405 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2406 pos += 2 + pos[1];
2407 os_memmove(pos + ext_capab_len, pos,
2408 wpa_ie_len - (pos - wpa_ie));
2409 wpa_ie_len += ext_capab_len;
2410 os_memcpy(pos, ext_capab, ext_capab_len);
2411 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002412 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002413
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002414#ifdef CONFIG_HS20
2415 if (is_hs20_network(wpa_s, ssid, bss)) {
2416 struct wpabuf *hs20;
2417
2418 hs20 = wpabuf_alloc(20);
2419 if (hs20) {
2420 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2421 size_t len;
2422
2423 wpas_hs20_add_indication(hs20, pps_mo_id);
2424 len = sizeof(wpa_ie) - wpa_ie_len;
2425 if (wpabuf_len(hs20) <= len) {
2426 os_memcpy(wpa_ie + wpa_ie_len,
2427 wpabuf_head(hs20), wpabuf_len(hs20));
2428 wpa_ie_len += wpabuf_len(hs20);
2429 }
2430 wpabuf_free(hs20);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002431
2432 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002433 }
2434 }
2435#endif /* CONFIG_HS20 */
2436
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002437 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2438 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2439 size_t len;
2440
2441 len = sizeof(wpa_ie) - wpa_ie_len;
2442 if (wpabuf_len(buf) <= len) {
2443 os_memcpy(wpa_ie + wpa_ie_len,
2444 wpabuf_head(buf), wpabuf_len(buf));
2445 wpa_ie_len += wpabuf_len(buf);
2446 }
2447 }
2448
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002449#ifdef CONFIG_FST
2450 if (wpa_s->fst_ies) {
2451 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2452
2453 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2454 os_memcpy(wpa_ie + wpa_ie_len,
2455 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2456 wpa_ie_len += fst_ies_len;
2457 }
2458 }
2459#endif /* CONFIG_FST */
2460
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002461#ifdef CONFIG_MBO
Dmitry Shmidt29333592017-01-09 12:27:11 -08002462 if (bss && wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002463 int len;
2464
2465 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2466 sizeof(wpa_ie) - wpa_ie_len);
2467 if (len >= 0)
2468 wpa_ie_len += len;
2469 }
2470#endif /* CONFIG_MBO */
2471
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002472 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2473 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002474 cipher_pairwise = wpa_s->pairwise_cipher;
2475 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2477 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2478 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2479 use_crypt = 0;
2480 if (wpa_set_wep_keys(wpa_s, ssid)) {
2481 use_crypt = 1;
2482 wep_keys_set = 1;
2483 }
2484 }
2485 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2486 use_crypt = 0;
2487
2488#ifdef IEEE8021X_EAPOL
2489 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2490 if ((ssid->eapol_flags &
2491 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2492 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2493 !wep_keys_set) {
2494 use_crypt = 0;
2495 } else {
2496 /* Assume that dynamic WEP-104 keys will be used and
2497 * set cipher suites in order for drivers to expect
2498 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002499 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002500 }
2501 }
2502#endif /* IEEE8021X_EAPOL */
2503
2504 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2505 /* Set the key before (and later after) association */
2506 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2507 }
2508
2509 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2510 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 params.ssid = bss->ssid;
2512 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002513 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2514 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002515 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2516 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002517 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002518 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002519 ssid->bssid_set,
2520 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002521 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002522 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002523 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002524 params.bssid_hint = bss->bssid;
2525 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002526 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 } else {
2528 params.ssid = ssid->ssid;
2529 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002530 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002532
2533 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2534 wpa_s->conf->ap_scan == 2) {
2535 params.bssid = ssid->bssid;
2536 params.fixed_bssid = 1;
2537 }
2538
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002539 /* Initial frequency for IBSS/mesh */
2540 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002541 ssid->frequency > 0 && params.freq.freq == 0)
2542 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002543
2544 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002545 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002546 if (ssid->beacon_int)
2547 params.beacon_int = ssid->beacon_int;
2548 else
2549 params.beacon_int = wpa_s->conf->beacon_int;
2550 }
2551
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 params.wpa_ie = wpa_ie;
2553 params.wpa_ie_len = wpa_ie_len;
2554 params.pairwise_suite = cipher_pairwise;
2555 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002556 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002557 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 params.auth_alg = algs;
2559 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002560 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 for (i = 0; i < NUM_WEP_KEYS; i++) {
2562 if (ssid->wep_key_len[i])
2563 params.wep_key[i] = ssid->wep_key[i];
2564 params.wep_key_len[i] = ssid->wep_key_len[i];
2565 }
2566 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2567
2568 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002569 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2570 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002571 params.passphrase = ssid->passphrase;
2572 if (ssid->psk_set)
2573 params.psk = ssid->psk;
2574 }
2575
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002576 if (wpa_s->conf->key_mgmt_offload) {
2577 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2578 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002579 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2580 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002581 params.req_key_mgmt_offload =
2582 ssid->proactive_key_caching < 0 ?
2583 wpa_s->conf->okc : ssid->proactive_key_caching;
2584 else
2585 params.req_key_mgmt_offload = 1;
2586
2587 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2588 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2589 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2590 ssid->psk_set)
2591 params.psk = ssid->psk;
2592 }
2593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002594 params.drop_unencrypted = use_crypt;
2595
2596#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002597 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002598 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2600 struct wpa_ie_data ie;
2601 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2602 ie.capabilities &
2603 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2604 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2605 "MFP: require MFP");
2606 params.mgmt_frame_protection =
2607 MGMT_FRAME_PROTECTION_REQUIRED;
2608 }
2609 }
2610#endif /* CONFIG_IEEE80211W */
2611
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002612 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002613
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002614 if (wpa_s->p2pdev->set_sta_uapsd)
2615 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616 else
2617 params.uapsd = -1;
2618
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002619#ifdef CONFIG_HT_OVERRIDES
2620 os_memset(&htcaps, 0, sizeof(htcaps));
2621 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2622 params.htcaps = (u8 *) &htcaps;
2623 params.htcaps_mask = (u8 *) &htcaps_mask;
2624 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2625#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002626#ifdef CONFIG_VHT_OVERRIDES
2627 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2628 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2629 params.vhtcaps = &vhtcaps;
2630 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002631 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002632#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002633
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002634#ifdef CONFIG_P2P
2635 /*
2636 * If multi-channel concurrency is not supported, check for any
2637 * frequency conflict. In case of any frequency conflict, remove the
2638 * least prioritized connection.
2639 */
2640 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002641 int freq, num;
2642 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002643 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002644 wpa_printf(MSG_DEBUG,
2645 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002646 freq, params.freq.freq);
2647 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002648 wpa_s, params.freq.freq, ssid) < 0) {
2649 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002650 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002651 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002652 }
2653 }
2654#endif /* CONFIG_P2P */
2655
Dmitry Shmidte4663042016-04-04 10:07:49 -07002656 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2657 wpa_s->current_ssid)
2658 params.prev_bssid = prev_bssid;
2659
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002660 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 if (ret < 0) {
2662 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2663 "failed");
2664 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2665 /*
2666 * The driver is known to mean what is saying, so we
2667 * can stop right here; the association will not
2668 * succeed.
2669 */
2670 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002671 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2673 return;
2674 }
2675 /* try to continue anyway; new association will be tried again
2676 * after timeout */
2677 assoc_failed = 1;
2678 }
2679
2680 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2681 /* Set the key after the association just in case association
2682 * cleared the previously configured key. */
2683 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2684 /* No need to timeout authentication since there is no key
2685 * management. */
2686 wpa_supplicant_cancel_auth_timeout(wpa_s);
2687 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2688#ifdef CONFIG_IBSS_RSN
2689 } else if (ssid->mode == WPAS_MODE_IBSS &&
2690 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2691 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2692 /*
2693 * RSN IBSS authentication is per-STA and we can disable the
2694 * per-BSSID authentication.
2695 */
2696 wpa_supplicant_cancel_auth_timeout(wpa_s);
2697#endif /* CONFIG_IBSS_RSN */
2698 } else {
2699 /* Timeout for IEEE 802.11 authentication and association */
2700 int timeout = 60;
2701
2702 if (assoc_failed) {
2703 /* give IBSS a bit more time */
2704 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2705 } else if (wpa_s->conf->ap_scan == 1) {
2706 /* give IBSS a bit more time */
2707 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2708 }
2709 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2710 }
2711
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002712 if (wep_keys_set &&
2713 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 /* Set static WEP keys again */
2715 wpa_set_wep_keys(wpa_s, ssid);
2716 }
2717
2718 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2719 /*
2720 * Do not allow EAP session resumption between different
2721 * network configurations.
2722 */
2723 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2724 }
2725 old_ssid = wpa_s->current_ssid;
2726 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002727
2728 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002729 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002730#ifdef CONFIG_HS20
2731 hs20_configure_frame_filters(wpa_s);
2732#endif /* CONFIG_HS20 */
2733 }
2734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2736 wpa_supplicant_initiate_eapol(wpa_s);
2737 if (old_ssid != wpa_s->current_ssid)
2738 wpas_notify_network_changed(wpa_s);
2739}
2740
2741
2742static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2743 const u8 *addr)
2744{
2745 struct wpa_ssid *old_ssid;
2746
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002747 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002749 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002751 wpa_sm_set_config(wpa_s->wpa, NULL);
2752 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2753 if (old_ssid != wpa_s->current_ssid)
2754 wpas_notify_network_changed(wpa_s);
2755 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2756}
2757
2758
2759/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002760 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2761 * @wpa_s: Pointer to wpa_supplicant data
2762 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2763 *
2764 * This function is used to request %wpa_supplicant to deauthenticate from the
2765 * current AP.
2766 */
2767void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2768 int reason_code)
2769{
2770 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002771 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002772 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002773
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002774 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2775 " pending_bssid=" MACSTR " reason=%d state=%s",
2776 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2777 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2778
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002779 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2780 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2781 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002782 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002783 else if (!is_zero_ether_addr(wpa_s->bssid))
2784 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002785 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2786 /*
2787 * When using driver-based BSS selection, we may not know the
2788 * BSSID with which we are currently trying to associate. We
2789 * need to notify the driver of this disconnection even in such
2790 * a case, so use the all zeros address here.
2791 */
2792 addr = wpa_s->bssid;
2793 zero_addr = 1;
2794 }
2795
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002796#ifdef CONFIG_TDLS
2797 wpa_tdls_teardown_peers(wpa_s->wpa);
2798#endif /* CONFIG_TDLS */
2799
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002800#ifdef CONFIG_MESH
2801 if (wpa_s->ifmsh) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002802 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2803 wpa_s->ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002804 wpa_supplicant_leave_mesh(wpa_s);
2805 }
2806#endif /* CONFIG_MESH */
2807
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002808 if (addr) {
2809 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002810 os_memset(&event, 0, sizeof(event));
2811 event.deauth_info.reason_code = (u16) reason_code;
2812 event.deauth_info.locally_generated = 1;
2813 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002814 if (zero_addr)
2815 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002816 }
2817
2818 wpa_supplicant_clear_connection(wpa_s, addr);
2819}
2820
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002821static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2822 struct wpa_ssid *ssid)
2823{
2824 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2825 return;
2826
2827 ssid->disabled = 0;
2828 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2829 wpas_notify_network_enabled_changed(wpa_s, ssid);
2830
2831 /*
2832 * Try to reassociate since there is no current configuration and a new
2833 * network was made available.
2834 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002835 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002836 wpa_s->reassociate = 1;
2837}
2838
Roshan Pius950bec92016-07-19 09:49:24 -07002839/**
2840 * wpa_supplicant_add_network - Add a new network.
2841 * @wpa_s: wpa_supplicant structure for a network interface
2842 * Returns: The new network configuration or %NULL if operation failed
2843 *
2844 * This function performs the following operations:
2845 * 1. Adds a new network.
2846 * 2. Send network addition notification.
2847 * 3. Marks the network disabled.
2848 * 4. Set network default parameters.
2849 */
2850struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2851{
2852 struct wpa_ssid *ssid;
2853
2854 ssid = wpa_config_add_network(wpa_s->conf);
2855 if (!ssid) {
2856 return NULL;
2857 }
2858 wpas_notify_network_added(wpa_s, ssid);
2859 ssid->disabled = 1;
2860 wpa_config_set_network_defaults(ssid);
2861
2862 return ssid;
2863}
2864
2865/**
2866 * wpa_supplicant_remove_network - Remove a configured network based on id
2867 * @wpa_s: wpa_supplicant structure for a network interface
2868 * @id: Unique network id to search for
2869 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2870 * could not be removed
2871 *
2872 * This function performs the following operations:
2873 * 1. Removes the network.
2874 * 2. Send network removal notification.
2875 * 3. Update internal state machines.
2876 * 4. Stop any running sched scans.
2877 */
2878int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2879{
2880 struct wpa_ssid *ssid;
2881 int was_disabled;
2882
2883 ssid = wpa_config_get_network(wpa_s->conf, id);
2884 if (ssid)
2885 wpas_notify_network_removed(wpa_s, ssid);
2886 if (ssid == NULL) {
2887 return -1;
2888 }
2889
2890 if (wpa_s->last_ssid == ssid)
2891 wpa_s->last_ssid = NULL;
2892
2893 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2894#ifdef CONFIG_SME
2895 wpa_s->sme.prev_bssid_set = 0;
2896#endif /* CONFIG_SME */
2897 /*
2898 * Invalidate the EAP session cache if the current or
2899 * previously used network is removed.
2900 */
2901 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2902 }
2903
2904 if (ssid == wpa_s->current_ssid) {
2905 wpa_sm_set_config(wpa_s->wpa, NULL);
2906 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2907
2908 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2909 wpa_s->own_disconnect_req = 1;
2910 wpa_supplicant_deauthenticate(wpa_s,
2911 WLAN_REASON_DEAUTH_LEAVING);
2912 }
2913
2914 was_disabled = ssid->disabled;
2915
2916 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2917 return -2;
2918 }
2919
2920 if (!was_disabled && wpa_s->sched_scanning) {
2921 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2922 "network from filters");
2923 wpa_supplicant_cancel_sched_scan(wpa_s);
2924 wpa_supplicant_req_scan(wpa_s, 0, 0);
2925 }
2926 return 0;
2927}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928
2929/**
2930 * wpa_supplicant_enable_network - Mark a configured network as enabled
2931 * @wpa_s: wpa_supplicant structure for a network interface
2932 * @ssid: wpa_ssid structure for a configured network or %NULL
2933 *
2934 * Enables the specified network or all networks if no network specified.
2935 */
2936void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2937 struct wpa_ssid *ssid)
2938{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002939 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002940 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2941 wpa_supplicant_enable_one_network(wpa_s, ssid);
2942 } else
2943 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002944
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002945 if (wpa_s->reassociate && !wpa_s->disconnected &&
2946 (!wpa_s->current_ssid ||
2947 wpa_s->wpa_state == WPA_DISCONNECTED ||
2948 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002949 if (wpa_s->sched_scanning) {
2950 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2951 "new network to scan filters");
2952 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002953 }
2954
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002955 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2956 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002957 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002958 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959 }
2960}
2961
2962
2963/**
2964 * wpa_supplicant_disable_network - Mark a configured network as disabled
2965 * @wpa_s: wpa_supplicant structure for a network interface
2966 * @ssid: wpa_ssid structure for a configured network or %NULL
2967 *
2968 * Disables the specified network or all networks if no network specified.
2969 */
2970void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2971 struct wpa_ssid *ssid)
2972{
2973 struct wpa_ssid *other_ssid;
2974 int was_disabled;
2975
2976 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002977 if (wpa_s->sched_scanning)
2978 wpa_supplicant_cancel_sched_scan(wpa_s);
2979
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2981 other_ssid = other_ssid->next) {
2982 was_disabled = other_ssid->disabled;
2983 if (was_disabled == 2)
2984 continue; /* do not change persistent P2P group
2985 * data */
2986
2987 other_ssid->disabled = 1;
2988
2989 if (was_disabled != other_ssid->disabled)
2990 wpas_notify_network_enabled_changed(
2991 wpa_s, other_ssid);
2992 }
2993 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002994 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2996 } else if (ssid->disabled != 2) {
2997 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002998 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002999 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3000
3001 was_disabled = ssid->disabled;
3002
3003 ssid->disabled = 1;
3004
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003005 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003006 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003007 if (wpa_s->sched_scanning) {
3008 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3009 "to remove network from filters");
3010 wpa_supplicant_cancel_sched_scan(wpa_s);
3011 wpa_supplicant_req_scan(wpa_s, 0, 0);
3012 }
3013 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003014 }
3015}
3016
3017
3018/**
3019 * wpa_supplicant_select_network - Attempt association with a network
3020 * @wpa_s: wpa_supplicant structure for a network interface
3021 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3022 */
3023void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3024 struct wpa_ssid *ssid)
3025{
3026
3027 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003028 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003029
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003030 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003031 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3032 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003033 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003034 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003035 disconnected = 1;
3036 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003037
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003038 if (ssid)
3039 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3040
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003041 /*
3042 * Mark all other networks disabled or mark all networks enabled if no
3043 * network specified.
3044 */
3045 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3046 other_ssid = other_ssid->next) {
3047 int was_disabled = other_ssid->disabled;
3048 if (was_disabled == 2)
3049 continue; /* do not change persistent P2P group data */
3050
3051 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003052 if (was_disabled && !other_ssid->disabled)
3053 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003054
3055 if (was_disabled != other_ssid->disabled)
3056 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3057 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003058
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003059 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3060 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003061 /* We are already associated with the selected network */
3062 wpa_printf(MSG_DEBUG, "Already associated with the "
3063 "selected network - do nothing");
3064 return;
3065 }
3066
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003067 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003068 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003069 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003070 wpa_s->connect_without_scan =
3071 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003072
3073 /*
3074 * Don't optimize next scan freqs since a new ESS has been
3075 * selected.
3076 */
3077 os_free(wpa_s->next_scan_freqs);
3078 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003079 } else {
3080 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003081 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003083 wpa_s->disconnected = 0;
3084 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003085
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003086 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003087 wpa_supplicant_fast_associate(wpa_s) != 1) {
3088 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003089 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003090 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003091 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003092
3093 if (ssid)
3094 wpas_notify_network_selected(wpa_s, ssid);
3095}
3096
3097
3098/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003099 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3100 * @wpa_s: wpa_supplicant structure for a network interface
3101 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3102 * @pkcs11_module_path: PKCS #11 module path or NULL
3103 * Returns: 0 on success; -1 on failure
3104 *
3105 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3106 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3107 * module path fails the paths will be reset to the default value (NULL).
3108 */
3109int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3110 const char *pkcs11_engine_path,
3111 const char *pkcs11_module_path)
3112{
3113 char *pkcs11_engine_path_copy = NULL;
3114 char *pkcs11_module_path_copy = NULL;
3115
3116 if (pkcs11_engine_path != NULL) {
3117 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3118 if (pkcs11_engine_path_copy == NULL)
3119 return -1;
3120 }
3121 if (pkcs11_module_path != NULL) {
3122 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003123 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003124 os_free(pkcs11_engine_path_copy);
3125 return -1;
3126 }
3127 }
3128
3129 os_free(wpa_s->conf->pkcs11_engine_path);
3130 os_free(wpa_s->conf->pkcs11_module_path);
3131 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3132 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3133
3134 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3135 eapol_sm_deinit(wpa_s->eapol);
3136 wpa_s->eapol = NULL;
3137 if (wpa_supplicant_init_eapol(wpa_s)) {
3138 /* Error -> Reset paths to the default value (NULL) once. */
3139 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3140 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3141 NULL);
3142
3143 return -1;
3144 }
3145 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3146
3147 return 0;
3148}
3149
3150
3151/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003152 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3153 * @wpa_s: wpa_supplicant structure for a network interface
3154 * @ap_scan: AP scan mode
3155 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3156 *
3157 */
3158int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3159{
3160
3161 int old_ap_scan;
3162
3163 if (ap_scan < 0 || ap_scan > 2)
3164 return -1;
3165
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003166 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3167 wpa_printf(MSG_INFO,
3168 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3169 }
3170
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003171#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003172 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3173 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3174 wpa_s->wpa_state < WPA_COMPLETED) {
3175 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3176 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003177 return 0;
3178 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003179#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003180
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003181 old_ap_scan = wpa_s->conf->ap_scan;
3182 wpa_s->conf->ap_scan = ap_scan;
3183
3184 if (old_ap_scan != wpa_s->conf->ap_scan)
3185 wpas_notify_ap_scan_changed(wpa_s);
3186
3187 return 0;
3188}
3189
3190
3191/**
3192 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3193 * @wpa_s: wpa_supplicant structure for a network interface
3194 * @expire_age: Expiration age in seconds
3195 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3196 *
3197 */
3198int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3199 unsigned int bss_expire_age)
3200{
3201 if (bss_expire_age < 10) {
3202 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3203 bss_expire_age);
3204 return -1;
3205 }
3206 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3207 bss_expire_age);
3208 wpa_s->conf->bss_expiration_age = bss_expire_age;
3209
3210 return 0;
3211}
3212
3213
3214/**
3215 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3216 * @wpa_s: wpa_supplicant structure for a network interface
3217 * @expire_count: number of scans after which an unseen BSS is reclaimed
3218 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3219 *
3220 */
3221int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3222 unsigned int bss_expire_count)
3223{
3224 if (bss_expire_count < 1) {
3225 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3226 bss_expire_count);
3227 return -1;
3228 }
3229 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3230 bss_expire_count);
3231 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3232
3233 return 0;
3234}
3235
3236
3237/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003238 * wpa_supplicant_set_scan_interval - Set scan interval
3239 * @wpa_s: wpa_supplicant structure for a network interface
3240 * @scan_interval: scan interval in seconds
3241 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3242 *
3243 */
3244int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3245 int scan_interval)
3246{
3247 if (scan_interval < 0) {
3248 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3249 scan_interval);
3250 return -1;
3251 }
3252 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3253 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003254 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003255
3256 return 0;
3257}
3258
3259
3260/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003261 * wpa_supplicant_set_debug_params - Set global debug params
3262 * @global: wpa_global structure
3263 * @debug_level: debug level
3264 * @debug_timestamp: determines if show timestamp in debug data
3265 * @debug_show_keys: determines if show keys in debug data
3266 * Returns: 0 if succeed or -1 if debug_level has wrong value
3267 */
3268int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3269 int debug_timestamp, int debug_show_keys)
3270{
3271
3272 int old_level, old_timestamp, old_show_keys;
3273
3274 /* check for allowed debuglevels */
3275 if (debug_level != MSG_EXCESSIVE &&
3276 debug_level != MSG_MSGDUMP &&
3277 debug_level != MSG_DEBUG &&
3278 debug_level != MSG_INFO &&
3279 debug_level != MSG_WARNING &&
3280 debug_level != MSG_ERROR)
3281 return -1;
3282
3283 old_level = wpa_debug_level;
3284 old_timestamp = wpa_debug_timestamp;
3285 old_show_keys = wpa_debug_show_keys;
3286
3287 wpa_debug_level = debug_level;
3288 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3289 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3290
3291 if (wpa_debug_level != old_level)
3292 wpas_notify_debug_level_changed(global);
3293 if (wpa_debug_timestamp != old_timestamp)
3294 wpas_notify_debug_timestamp_changed(global);
3295 if (wpa_debug_show_keys != old_show_keys)
3296 wpas_notify_debug_show_keys_changed(global);
3297
3298 return 0;
3299}
3300
3301
3302/**
3303 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3304 * @wpa_s: Pointer to wpa_supplicant data
3305 * Returns: A pointer to the current network structure or %NULL on failure
3306 */
3307struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3308{
3309 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003310 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311 int res;
3312 size_t ssid_len;
3313 u8 bssid[ETH_ALEN];
3314 int wired;
3315
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003316 res = wpa_drv_get_ssid(wpa_s, ssid);
3317 if (res < 0) {
3318 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3319 "driver");
3320 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003321 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003322 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003323
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003324 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003325 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3326 "driver");
3327 return NULL;
3328 }
3329
3330 wired = wpa_s->conf->ap_scan == 0 &&
3331 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3332
3333 entry = wpa_s->conf->ssid;
3334 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003335 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003336 ((ssid_len == entry->ssid_len &&
3337 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3338 (!entry->bssid_set ||
3339 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3340 return entry;
3341#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003342 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003343 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3344 (entry->ssid == NULL || entry->ssid_len == 0) &&
3345 (!entry->bssid_set ||
3346 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3347 return entry;
3348#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003349
Dmitry Shmidt04949592012-07-19 12:16:46 -07003350 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003351 entry->ssid_len == 0 &&
3352 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3353 return entry;
3354
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003355 entry = entry->next;
3356 }
3357
3358 return NULL;
3359}
3360
3361
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003362static int select_driver(struct wpa_supplicant *wpa_s, int i)
3363{
3364 struct wpa_global *global = wpa_s->global;
3365
3366 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003367 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003368 if (global->drv_priv[i] == NULL) {
3369 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3370 "'%s'", wpa_drivers[i]->name);
3371 return -1;
3372 }
3373 }
3374
3375 wpa_s->driver = wpa_drivers[i];
3376 wpa_s->global_drv_priv = global->drv_priv[i];
3377
3378 return 0;
3379}
3380
3381
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003382static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3383 const char *name)
3384{
3385 int i;
3386 size_t len;
3387 const char *pos, *driver = name;
3388
3389 if (wpa_s == NULL)
3390 return -1;
3391
3392 if (wpa_drivers[0] == NULL) {
3393 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3394 "wpa_supplicant");
3395 return -1;
3396 }
3397
3398 if (name == NULL) {
3399 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003400 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401 }
3402
3403 do {
3404 pos = os_strchr(driver, ',');
3405 if (pos)
3406 len = pos - driver;
3407 else
3408 len = os_strlen(driver);
3409
3410 for (i = 0; wpa_drivers[i]; i++) {
3411 if (os_strlen(wpa_drivers[i]->name) == len &&
3412 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003413 0) {
3414 /* First driver that succeeds wins */
3415 if (select_driver(wpa_s, i) == 0)
3416 return 0;
3417 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003418 }
3419
3420 driver = pos + 1;
3421 } while (pos);
3422
3423 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3424 return -1;
3425}
3426
3427
3428/**
3429 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3430 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3431 * with struct wpa_driver_ops::init()
3432 * @src_addr: Source address of the EAPOL frame
3433 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3434 * @len: Length of the EAPOL data
3435 *
3436 * This function is called for each received EAPOL frame. Most driver
3437 * interfaces rely on more generic OS mechanism for receiving frames through
3438 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3439 * take care of received EAPOL frames and deliver them to the core supplicant
3440 * code by calling this function.
3441 */
3442void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3443 const u8 *buf, size_t len)
3444{
3445 struct wpa_supplicant *wpa_s = ctx;
3446
3447 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3448 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3449
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003450#ifdef CONFIG_TESTING_OPTIONS
3451 if (wpa_s->ignore_auth_resp) {
3452 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3453 return;
3454 }
3455#endif /* CONFIG_TESTING_OPTIONS */
3456
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003457#ifdef CONFIG_PEERKEY
3458 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3459 wpa_s->current_ssid->peerkey &&
3460 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3461 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3462 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3463 return;
3464 }
3465#endif /* CONFIG_PEERKEY */
3466
Jouni Malinena05074c2012-12-21 21:35:35 +02003467 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3468 (wpa_s->last_eapol_matches_bssid &&
3469#ifdef CONFIG_AP
3470 !wpa_s->ap_iface &&
3471#endif /* CONFIG_AP */
3472 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003473 /*
3474 * There is possible race condition between receiving the
3475 * association event and the EAPOL frame since they are coming
3476 * through different paths from the driver. In order to avoid
3477 * issues in trying to process the EAPOL frame before receiving
3478 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003479 * the association event is received. This may also be needed in
3480 * driver-based roaming case, so also use src_addr != BSSID as a
3481 * trigger if we have previously confirmed that the
3482 * Authenticator uses BSSID as the src_addr (which is not the
3483 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003484 */
3485 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003486 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3487 wpa_supplicant_state_txt(wpa_s->wpa_state),
3488 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 wpabuf_free(wpa_s->pending_eapol_rx);
3490 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3491 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003492 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003493 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3494 ETH_ALEN);
3495 }
3496 return;
3497 }
3498
Jouni Malinena05074c2012-12-21 21:35:35 +02003499 wpa_s->last_eapol_matches_bssid =
3500 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3501
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003502#ifdef CONFIG_AP
3503 if (wpa_s->ap_iface) {
3504 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3505 return;
3506 }
3507#endif /* CONFIG_AP */
3508
3509 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3510 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3511 "no key management is configured");
3512 return;
3513 }
3514
3515 if (wpa_s->eapol_received == 0 &&
3516 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3517 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3518 wpa_s->wpa_state != WPA_COMPLETED) &&
3519 (wpa_s->current_ssid == NULL ||
3520 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3521 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003522 int timeout = 10;
3523
3524 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3525 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3526 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3527 /* Use longer timeout for IEEE 802.1X/EAP */
3528 timeout = 70;
3529 }
3530
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003531#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003532 if (wpa_s->current_ssid && wpa_s->current_bss &&
3533 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3534 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3535 /*
3536 * Use shorter timeout if going through WPS AP iteration
3537 * for PIN config method with an AP that does not
3538 * advertise Selected Registrar.
3539 */
3540 struct wpabuf *wps_ie;
3541
3542 wps_ie = wpa_bss_get_vendor_ie_multi(
3543 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3544 if (wps_ie &&
3545 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3546 timeout = 10;
3547 wpabuf_free(wps_ie);
3548 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003549#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003550
3551 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003552 }
3553 wpa_s->eapol_received++;
3554
3555 if (wpa_s->countermeasures) {
3556 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3557 "EAPOL packet");
3558 return;
3559 }
3560
3561#ifdef CONFIG_IBSS_RSN
3562 if (wpa_s->current_ssid &&
3563 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3564 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3565 return;
3566 }
3567#endif /* CONFIG_IBSS_RSN */
3568
3569 /* Source address of the incoming EAPOL frame could be compared to the
3570 * current BSSID. However, it is possible that a centralized
3571 * Authenticator could be using another MAC address than the BSSID of
3572 * an AP, so just allow any address to be used for now. The replies are
3573 * still sent to the current BSSID (if available), though. */
3574
3575 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3576 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3577 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3578 return;
3579 wpa_drv_poll(wpa_s);
3580 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3581 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3582 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3583 /*
3584 * Set portValid = TRUE here since we are going to skip 4-way
3585 * handshake processing which would normally set portValid. We
3586 * need this to allow the EAPOL state machines to be completed
3587 * without going through EAPOL-Key handshake.
3588 */
3589 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3590 }
3591}
3592
3593
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003594int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003595{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003596 if ((!wpa_s->p2p_mgmt ||
3597 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3598 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003599 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003600 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3601 wpa_drv_get_mac_addr(wpa_s),
3602 ETH_P_EAPOL,
3603 wpa_supplicant_rx_eapol, wpa_s, 0);
3604 if (wpa_s->l2 == NULL)
3605 return -1;
3606 } else {
3607 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3608 if (addr)
3609 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3610 }
3611
3612 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3613 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3614 return -1;
3615 }
3616
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003617 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3618
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003619 return 0;
3620}
3621
3622
Dmitry Shmidt04949592012-07-19 12:16:46 -07003623static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3624 const u8 *buf, size_t len)
3625{
3626 struct wpa_supplicant *wpa_s = ctx;
3627 const struct l2_ethhdr *eth;
3628
3629 if (len < sizeof(*eth))
3630 return;
3631 eth = (const struct l2_ethhdr *) buf;
3632
3633 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3634 !(eth->h_dest[0] & 0x01)) {
3635 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3636 " (bridge - not for this interface - ignore)",
3637 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3638 return;
3639 }
3640
3641 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3642 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3643 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3644 len - sizeof(*eth));
3645}
3646
3647
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003648/**
3649 * wpa_supplicant_driver_init - Initialize driver interface parameters
3650 * @wpa_s: Pointer to wpa_supplicant data
3651 * Returns: 0 on success, -1 on failure
3652 *
3653 * This function is called to initialize driver interface parameters.
3654 * wpa_drv_init() must have been called before this function to initialize the
3655 * driver interface.
3656 */
3657int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3658{
3659 static int interface_count = 0;
3660
3661 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3662 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003663
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003664 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3665 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003666 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003667 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3668
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669 if (wpa_s->bridge_ifname[0]) {
3670 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3671 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003672 wpa_s->l2_br = l2_packet_init_bridge(
3673 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3674 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675 if (wpa_s->l2_br == NULL) {
3676 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3677 "connection for the bridge interface '%s'",
3678 wpa_s->bridge_ifname);
3679 return -1;
3680 }
3681 }
3682
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003683 if (wpa_s->conf->ap_scan == 2 &&
3684 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3685 wpa_printf(MSG_INFO,
3686 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3687 }
3688
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003689 wpa_clear_keys(wpa_s, NULL);
3690
3691 /* Make sure that TKIP countermeasures are not left enabled (could
3692 * happen if wpa_supplicant is killed during countermeasures. */
3693 wpa_drv_set_countermeasures(wpa_s, 0);
3694
3695 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3696 wpa_drv_flush_pmkid(wpa_s);
3697
3698 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003699 wpa_s->prev_scan_wildcard = 0;
3700
Dmitry Shmidt04949592012-07-19 12:16:46 -07003701 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003702 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3703 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3704 interface_count = 0;
3705 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003706#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003707 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003708 wpa_supplicant_delayed_sched_scan(wpa_s,
3709 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003710 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003711 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003712 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003713#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003714 interface_count++;
3715 } else
3716 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3717
3718 return 0;
3719}
3720
3721
3722static int wpa_supplicant_daemon(const char *pid_file)
3723{
3724 wpa_printf(MSG_DEBUG, "Daemonize..");
3725 return os_daemonize(pid_file);
3726}
3727
3728
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003729static struct wpa_supplicant *
3730wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003731{
3732 struct wpa_supplicant *wpa_s;
3733
3734 wpa_s = os_zalloc(sizeof(*wpa_s));
3735 if (wpa_s == NULL)
3736 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003737 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003738 wpa_s->scan_interval = 5;
3739 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003740 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003741 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003742 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003744 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08003745 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747 return wpa_s;
3748}
3749
3750
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003751#ifdef CONFIG_HT_OVERRIDES
3752
3753static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3754 struct ieee80211_ht_capabilities *htcaps,
3755 struct ieee80211_ht_capabilities *htcaps_mask,
3756 const char *ht_mcs)
3757{
3758 /* parse ht_mcs into hex array */
3759 int i;
3760 const char *tmp = ht_mcs;
3761 char *end = NULL;
3762
3763 /* If ht_mcs is null, do not set anything */
3764 if (!ht_mcs)
3765 return 0;
3766
3767 /* This is what we are setting in the kernel */
3768 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3769
3770 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3771
3772 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08003773 long v;
3774
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003775 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08003776 v = strtol(tmp, &end, 16);
3777
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003778 if (errno == 0) {
3779 wpa_msg(wpa_s, MSG_DEBUG,
3780 "htcap value[%i]: %ld end: %p tmp: %p",
3781 i, v, end, tmp);
3782 if (end == tmp)
3783 break;
3784
3785 htcaps->supported_mcs_set[i] = v;
3786 tmp = end;
3787 } else {
3788 wpa_msg(wpa_s, MSG_ERROR,
3789 "Failed to parse ht-mcs: %s, error: %s\n",
3790 ht_mcs, strerror(errno));
3791 return -1;
3792 }
3793 }
3794
3795 /*
3796 * If we were able to parse any values, then set mask for the MCS set.
3797 */
3798 if (i) {
3799 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3800 IEEE80211_HT_MCS_MASK_LEN - 1);
3801 /* skip the 3 reserved bits */
3802 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3803 0x1f;
3804 }
3805
3806 return 0;
3807}
3808
3809
3810static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3811 struct ieee80211_ht_capabilities *htcaps,
3812 struct ieee80211_ht_capabilities *htcaps_mask,
3813 int disabled)
3814{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003815 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003816
3817 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3818
3819 if (disabled == -1)
3820 return 0;
3821
3822 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3823 htcaps_mask->ht_capabilities_info |= msk;
3824 if (disabled)
3825 htcaps->ht_capabilities_info &= msk;
3826 else
3827 htcaps->ht_capabilities_info |= msk;
3828
3829 return 0;
3830}
3831
3832
3833static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3834 struct ieee80211_ht_capabilities *htcaps,
3835 struct ieee80211_ht_capabilities *htcaps_mask,
3836 int factor)
3837{
3838 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3839
3840 if (factor == -1)
3841 return 0;
3842
3843 if (factor < 0 || factor > 3) {
3844 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3845 "Must be 0-3 or -1", factor);
3846 return -EINVAL;
3847 }
3848
3849 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3850 htcaps->a_mpdu_params &= ~0x3;
3851 htcaps->a_mpdu_params |= factor & 0x3;
3852
3853 return 0;
3854}
3855
3856
3857static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3858 struct ieee80211_ht_capabilities *htcaps,
3859 struct ieee80211_ht_capabilities *htcaps_mask,
3860 int density)
3861{
3862 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3863
3864 if (density == -1)
3865 return 0;
3866
3867 if (density < 0 || density > 7) {
3868 wpa_msg(wpa_s, MSG_ERROR,
3869 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3870 density);
3871 return -EINVAL;
3872 }
3873
3874 htcaps_mask->a_mpdu_params |= 0x1C;
3875 htcaps->a_mpdu_params &= ~(0x1C);
3876 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3877
3878 return 0;
3879}
3880
3881
3882static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3883 struct ieee80211_ht_capabilities *htcaps,
3884 struct ieee80211_ht_capabilities *htcaps_mask,
3885 int disabled)
3886{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003887 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3888
Paul Stewart092955c2017-02-06 09:13:09 -08003889 set_disable_ht40(htcaps, disabled);
3890 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003891
3892 return 0;
3893}
3894
3895
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003896static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3897 struct ieee80211_ht_capabilities *htcaps,
3898 struct ieee80211_ht_capabilities *htcaps_mask,
3899 int disabled)
3900{
3901 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003902 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3903 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003904
3905 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3906
3907 if (disabled)
3908 htcaps->ht_capabilities_info &= ~msk;
3909 else
3910 htcaps->ht_capabilities_info |= msk;
3911
3912 htcaps_mask->ht_capabilities_info |= msk;
3913
3914 return 0;
3915}
3916
3917
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003918static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3919 struct ieee80211_ht_capabilities *htcaps,
3920 struct ieee80211_ht_capabilities *htcaps_mask,
3921 int disabled)
3922{
3923 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003924 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003925
3926 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3927
3928 if (disabled)
3929 htcaps->ht_capabilities_info &= ~msk;
3930 else
3931 htcaps->ht_capabilities_info |= msk;
3932
3933 htcaps_mask->ht_capabilities_info |= msk;
3934
3935 return 0;
3936}
3937
3938
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003939void wpa_supplicant_apply_ht_overrides(
3940 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3941 struct wpa_driver_associate_params *params)
3942{
3943 struct ieee80211_ht_capabilities *htcaps;
3944 struct ieee80211_ht_capabilities *htcaps_mask;
3945
3946 if (!ssid)
3947 return;
3948
3949 params->disable_ht = ssid->disable_ht;
3950 if (!params->htcaps || !params->htcaps_mask)
3951 return;
3952
3953 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3954 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3955 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3956 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3957 ssid->disable_max_amsdu);
3958 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3959 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3960 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003961 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003962 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003963
3964 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003965 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003966 htcaps->ht_capabilities_info |= bit;
3967 htcaps_mask->ht_capabilities_info |= bit;
3968 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003969}
3970
3971#endif /* CONFIG_HT_OVERRIDES */
3972
3973
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003974#ifdef CONFIG_VHT_OVERRIDES
3975void wpa_supplicant_apply_vht_overrides(
3976 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3977 struct wpa_driver_associate_params *params)
3978{
3979 struct ieee80211_vht_capabilities *vhtcaps;
3980 struct ieee80211_vht_capabilities *vhtcaps_mask;
3981
3982 if (!ssid)
3983 return;
3984
3985 params->disable_vht = ssid->disable_vht;
3986
3987 vhtcaps = (void *) params->vhtcaps;
3988 vhtcaps_mask = (void *) params->vhtcaps_mask;
3989
3990 if (!vhtcaps || !vhtcaps_mask)
3991 return;
3992
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003993 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
3994 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003995
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003996#ifdef CONFIG_HT_OVERRIDES
3997 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003998 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3999 int max_ampdu;
4000
4001 max_ampdu = (ssid->vht_capa &
4002 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4003 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004004
4005 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4006 wpa_set_ampdu_factor(wpa_s,
4007 (void *) params->htcaps,
4008 (void *) params->htcaps_mask,
4009 max_ampdu);
4010 }
4011#endif /* CONFIG_HT_OVERRIDES */
4012
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004013#define OVERRIDE_MCS(i) \
4014 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4015 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004016 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004017 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004018 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4019 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004020 } \
4021 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4022 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004023 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004024 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004025 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4026 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004027 }
4028
4029 OVERRIDE_MCS(1);
4030 OVERRIDE_MCS(2);
4031 OVERRIDE_MCS(3);
4032 OVERRIDE_MCS(4);
4033 OVERRIDE_MCS(5);
4034 OVERRIDE_MCS(6);
4035 OVERRIDE_MCS(7);
4036 OVERRIDE_MCS(8);
4037}
4038#endif /* CONFIG_VHT_OVERRIDES */
4039
4040
Dmitry Shmidt04949592012-07-19 12:16:46 -07004041static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4042{
4043#ifdef PCSC_FUNCS
4044 size_t len;
4045
4046 if (!wpa_s->conf->pcsc_reader)
4047 return 0;
4048
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004049 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004050 if (!wpa_s->scard)
4051 return 1;
4052
4053 if (wpa_s->conf->pcsc_pin &&
4054 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4055 scard_deinit(wpa_s->scard);
4056 wpa_s->scard = NULL;
4057 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4058 return -1;
4059 }
4060
4061 len = sizeof(wpa_s->imsi) - 1;
4062 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4063 scard_deinit(wpa_s->scard);
4064 wpa_s->scard = NULL;
4065 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4066 return -1;
4067 }
4068 wpa_s->imsi[len] = '\0';
4069
4070 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4071
4072 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4073 wpa_s->imsi, wpa_s->mnc_len);
4074
4075 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4076 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4077#endif /* PCSC_FUNCS */
4078
4079 return 0;
4080}
4081
4082
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004083int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4084{
4085 char *val, *pos;
4086
4087 ext_password_deinit(wpa_s->ext_pw);
4088 wpa_s->ext_pw = NULL;
4089 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4090
4091 if (!wpa_s->conf->ext_password_backend)
4092 return 0;
4093
4094 val = os_strdup(wpa_s->conf->ext_password_backend);
4095 if (val == NULL)
4096 return -1;
4097 pos = os_strchr(val, ':');
4098 if (pos)
4099 *pos++ = '\0';
4100
4101 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4102
4103 wpa_s->ext_pw = ext_password_init(val, pos);
4104 os_free(val);
4105 if (wpa_s->ext_pw == NULL) {
4106 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4107 return -1;
4108 }
4109 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4110
4111 return 0;
4112}
4113
4114
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004115#ifdef CONFIG_FST
4116
4117static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4118{
4119 struct wpa_supplicant *wpa_s = ctx;
4120
4121 return (is_zero_ether_addr(wpa_s->bssid) ||
4122 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4123}
4124
4125
4126static void wpas_fst_get_channel_info_cb(void *ctx,
4127 enum hostapd_hw_mode *hw_mode,
4128 u8 *channel)
4129{
4130 struct wpa_supplicant *wpa_s = ctx;
4131
4132 if (wpa_s->current_bss) {
4133 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4134 channel);
4135 } else if (wpa_s->hw.num_modes) {
4136 *hw_mode = wpa_s->hw.modes[0].mode;
4137 } else {
4138 WPA_ASSERT(0);
4139 *hw_mode = 0;
4140 }
4141}
4142
4143
4144static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4145{
4146 struct wpa_supplicant *wpa_s = ctx;
4147
4148 *modes = wpa_s->hw.modes;
4149 return wpa_s->hw.num_modes;
4150}
4151
4152
4153static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4154{
4155 struct wpa_supplicant *wpa_s = ctx;
4156
4157 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4158 wpa_s->fst_ies = fst_ies;
4159}
4160
4161
4162static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4163{
4164 struct wpa_supplicant *wpa_s = ctx;
4165
Paul Stewart092955c2017-02-06 09:13:09 -08004166 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
4167 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
4168 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
4169 return -1;
4170 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004171 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08004172 wpa_s->own_addr, wpa_s->bssid,
4173 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004174 0);
4175}
4176
4177
4178static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4179{
4180 struct wpa_supplicant *wpa_s = ctx;
4181
4182 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4183 return wpa_s->received_mb_ies;
4184}
4185
4186
4187static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4188 const u8 *buf, size_t size)
4189{
4190 struct wpa_supplicant *wpa_s = ctx;
4191 struct mb_ies_info info;
4192
4193 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4194
4195 if (!mb_ies_info_by_ies(&info, buf, size)) {
4196 wpabuf_free(wpa_s->received_mb_ies);
4197 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4198 }
4199}
4200
4201
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004202static const u8 * wpas_fst_get_peer_first(void *ctx,
4203 struct fst_get_peer_ctx **get_ctx,
4204 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004205{
4206 struct wpa_supplicant *wpa_s = ctx;
4207
4208 *get_ctx = NULL;
4209 if (!is_zero_ether_addr(wpa_s->bssid))
4210 return (wpa_s->received_mb_ies || !mb_only) ?
4211 wpa_s->bssid : NULL;
4212 return NULL;
4213}
4214
4215
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004216static const u8 * wpas_fst_get_peer_next(void *ctx,
4217 struct fst_get_peer_ctx **get_ctx,
4218 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004219{
4220 return NULL;
4221}
4222
4223void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4224 struct fst_wpa_obj *iface_obj)
4225{
4226 iface_obj->ctx = wpa_s;
4227 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4228 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4229 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4230 iface_obj->set_ies = wpas_fst_set_ies_cb;
4231 iface_obj->send_action = wpas_fst_send_action_cb;
4232 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4233 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4234 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4235 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4236}
4237#endif /* CONFIG_FST */
4238
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004239static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004240 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004241{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004242 struct wowlan_triggers *triggers;
4243 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004244
4245 if (!wpa_s->conf->wowlan_triggers)
4246 return 0;
4247
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004248 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4249 if (triggers) {
4250 ret = wpa_drv_wowlan(wpa_s, triggers);
4251 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004252 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004253 return ret;
4254}
4255
4256
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004257enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004258{
4259 if (freq < 3000)
4260 return BAND_2_4_GHZ;
4261 if (freq > 50000)
4262 return BAND_60_GHZ;
4263 return BAND_5_GHZ;
4264}
4265
4266
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004267unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004268{
4269 int i;
4270 unsigned int band = 0;
4271
4272 if (freqs) {
4273 /* freqs are specified for the radio work */
4274 for (i = 0; freqs[i]; i++)
4275 band |= wpas_freq_to_band(freqs[i]);
4276 } else {
4277 /*
4278 * freqs are not specified, implies all
4279 * the supported freqs by HW
4280 */
4281 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4282 if (wpa_s->hw.modes[i].num_channels != 0) {
4283 if (wpa_s->hw.modes[i].mode ==
4284 HOSTAPD_MODE_IEEE80211B ||
4285 wpa_s->hw.modes[i].mode ==
4286 HOSTAPD_MODE_IEEE80211G)
4287 band |= BAND_2_4_GHZ;
4288 else if (wpa_s->hw.modes[i].mode ==
4289 HOSTAPD_MODE_IEEE80211A)
4290 band |= BAND_5_GHZ;
4291 else if (wpa_s->hw.modes[i].mode ==
4292 HOSTAPD_MODE_IEEE80211AD)
4293 band |= BAND_60_GHZ;
4294 else if (wpa_s->hw.modes[i].mode ==
4295 HOSTAPD_MODE_IEEE80211ANY)
4296 band = BAND_2_4_GHZ | BAND_5_GHZ |
4297 BAND_60_GHZ;
4298 }
4299 }
4300 }
4301
4302 return band;
4303}
4304
4305
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004306static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4307 const char *rn)
4308{
4309 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4310 struct wpa_radio *radio;
4311
4312 while (rn && iface) {
4313 radio = iface->radio;
4314 if (radio && os_strcmp(rn, radio->name) == 0) {
4315 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4316 wpa_s->ifname, rn);
4317 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4318 return radio;
4319 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004320
4321 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004322 }
4323
4324 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4325 wpa_s->ifname, rn ? rn : "N/A");
4326 radio = os_zalloc(sizeof(*radio));
4327 if (radio == NULL)
4328 return NULL;
4329
4330 if (rn)
4331 os_strlcpy(radio->name, rn, sizeof(radio->name));
4332 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004333 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004334 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4335
4336 return radio;
4337}
4338
4339
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004340static void radio_work_free(struct wpa_radio_work *work)
4341{
4342 if (work->wpa_s->scan_work == work) {
4343 /* This should not really happen. */
4344 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4345 work->type, work, work->started);
4346 work->wpa_s->scan_work = NULL;
4347 }
4348
4349#ifdef CONFIG_P2P
4350 if (work->wpa_s->p2p_scan_work == work) {
4351 /* This should not really happen. */
4352 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4353 work->type, work, work->started);
4354 work->wpa_s->p2p_scan_work = NULL;
4355 }
4356#endif /* CONFIG_P2P */
4357
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004358 if (work->started) {
4359 work->wpa_s->radio->num_active_works--;
4360 wpa_dbg(work->wpa_s, MSG_DEBUG,
4361 "radio_work_free('%s'@%p: num_active_works --> %u",
4362 work->type, work,
4363 work->wpa_s->radio->num_active_works);
4364 }
4365
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004366 dl_list_del(&work->list);
4367 os_free(work);
4368}
4369
4370
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004371static int radio_work_is_connect(struct wpa_radio_work *work)
4372{
4373 return os_strcmp(work->type, "sme-connect") == 0 ||
4374 os_strcmp(work->type, "connect") == 0;
4375}
4376
4377
4378static int radio_work_is_scan(struct wpa_radio_work *work)
4379{
4380 return os_strcmp(work->type, "scan") == 0 ||
4381 os_strcmp(work->type, "p2p-scan") == 0;
4382}
4383
4384
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004385static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4386{
4387 struct wpa_radio_work *active_work = NULL;
4388 struct wpa_radio_work *tmp;
4389
4390 /* Get the active work to know the type and band. */
4391 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4392 if (tmp->started) {
4393 active_work = tmp;
4394 break;
4395 }
4396 }
4397
4398 if (!active_work) {
4399 /* No active work, start one */
4400 radio->num_active_works = 0;
4401 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4402 list) {
4403 if (os_strcmp(tmp->type, "scan") == 0 &&
4404 radio->external_scan_running &&
4405 (((struct wpa_driver_scan_params *)
4406 tmp->ctx)->only_new_results ||
4407 tmp->wpa_s->clear_driver_scan_cache))
4408 continue;
4409 return tmp;
4410 }
4411 return NULL;
4412 }
4413
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004414 if (radio_work_is_connect(active_work)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004415 /*
4416 * If the active work is either connect or sme-connect,
4417 * do not parallelize them with other radio works.
4418 */
4419 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4420 "Do not parallelize radio work with %s",
4421 active_work->type);
4422 return NULL;
4423 }
4424
4425 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4426 if (tmp->started)
4427 continue;
4428
4429 /*
4430 * If connect or sme-connect are enqueued, parallelize only
4431 * those operations ahead of them in the queue.
4432 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004433 if (radio_work_is_connect(tmp))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004434 break;
4435
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004436 /* Serialize parallel scan and p2p_scan operations on the same
4437 * interface since the driver_nl80211 mechanism for tracking
4438 * scan cookies does not yet have support for this. */
4439 if (active_work->wpa_s == tmp->wpa_s &&
4440 radio_work_is_scan(active_work) &&
4441 radio_work_is_scan(tmp)) {
4442 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4443 "Do not start work '%s' when another work '%s' is already scheduled",
4444 tmp->type, active_work->type);
4445 continue;
4446 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004447 /*
4448 * Check that the radio works are distinct and
4449 * on different bands.
4450 */
4451 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4452 (active_work->bands != tmp->bands)) {
4453 /*
4454 * If a scan has to be scheduled through nl80211 scan
4455 * interface and if an external scan is already running,
4456 * do not schedule the scan since it is likely to get
4457 * rejected by kernel.
4458 */
4459 if (os_strcmp(tmp->type, "scan") == 0 &&
4460 radio->external_scan_running &&
4461 (((struct wpa_driver_scan_params *)
4462 tmp->ctx)->only_new_results ||
4463 tmp->wpa_s->clear_driver_scan_cache))
4464 continue;
4465
4466 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4467 "active_work:%s new_work:%s",
4468 active_work->type, tmp->type);
4469 return tmp;
4470 }
4471 }
4472
4473 /* Did not find a radio work to schedule in parallel. */
4474 return NULL;
4475}
4476
4477
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004478static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4479{
4480 struct wpa_radio *radio = eloop_ctx;
4481 struct wpa_radio_work *work;
4482 struct os_reltime now, diff;
4483 struct wpa_supplicant *wpa_s;
4484
4485 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004486 if (work == NULL) {
4487 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004488 return;
4489 }
4490
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004491 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4492 radio_list);
4493
4494 if (!(wpa_s &&
4495 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4496 if (work->started)
4497 return; /* already started and still in progress */
4498
4499 if (wpa_s && wpa_s->radio->external_scan_running) {
4500 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4501 return;
4502 }
4503 } else {
4504 work = NULL;
4505 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4506 /* get the work to schedule next */
4507 work = radio_work_get_next_work(radio);
4508 }
4509 if (!work)
4510 return;
4511 }
4512
4513 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004514 os_get_reltime(&now);
4515 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004516 wpa_dbg(wpa_s, MSG_DEBUG,
4517 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004518 work->type, work, diff.sec, diff.usec);
4519 work->started = 1;
4520 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004521 radio->num_active_works++;
4522
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004523 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004524
4525 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4526 radio->num_active_works < MAX_ACTIVE_WORKS)
4527 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004528}
4529
4530
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004531/*
4532 * This function removes both started and pending radio works running on
4533 * the provided interface's radio.
4534 * Prior to the removal of the radio work, its callback (cb) is called with
4535 * deinit set to be 1. Each work's callback is responsible for clearing its
4536 * internal data and restoring to a correct state.
4537 * @wpa_s: wpa_supplicant data
4538 * @type: type of works to be removed
4539 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4540 * this interface's works.
4541 */
4542void radio_remove_works(struct wpa_supplicant *wpa_s,
4543 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004544{
4545 struct wpa_radio_work *work, *tmp;
4546 struct wpa_radio *radio = wpa_s->radio;
4547
4548 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4549 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004550 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004551 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004552
4553 /* skip other ifaces' works */
4554 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004555 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004556
4557 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4558 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004559 work->cb(work, 1);
4560 radio_work_free(work);
4561 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004562
4563 /* in case we removed the started work */
4564 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004565}
4566
4567
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004568static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4569{
4570 struct wpa_radio *radio = wpa_s->radio;
4571
4572 if (!radio)
4573 return;
4574
4575 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4576 wpa_s->ifname, radio->name);
4577 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004578 radio_remove_works(wpa_s, NULL, 0);
4579 wpa_s->radio = NULL;
4580 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004581 return; /* Interfaces remain for this radio */
4582
4583 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004584 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004585 os_free(radio);
4586}
4587
4588
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004589void radio_work_check_next(struct wpa_supplicant *wpa_s)
4590{
4591 struct wpa_radio *radio = wpa_s->radio;
4592
4593 if (dl_list_empty(&radio->work))
4594 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004595 if (wpa_s->ext_work_in_progress) {
4596 wpa_printf(MSG_DEBUG,
4597 "External radio work in progress - delay start of pending item");
4598 return;
4599 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004600 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4601 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4602}
4603
4604
4605/**
4606 * radio_add_work - Add a radio work item
4607 * @wpa_s: Pointer to wpa_supplicant data
4608 * @freq: Frequency of the offchannel operation in MHz or 0
4609 * @type: Unique identifier for each type of work
4610 * @next: Force as the next work to be executed
4611 * @cb: Callback function for indicating when radio is available
4612 * @ctx: Context pointer for the work (work->ctx in cb())
4613 * Returns: 0 on success, -1 on failure
4614 *
4615 * This function is used to request time for an operation that requires
4616 * exclusive radio control. Once the radio is available, the registered callback
4617 * function will be called. radio_work_done() must be called once the exclusive
4618 * radio operation has been completed, so that the radio is freed for other
4619 * operations. The special case of deinit=1 is used to free the context data
4620 * during interface removal. That does not allow the callback function to start
4621 * the radio operation, i.e., it must free any resources allocated for the radio
4622 * work and return.
4623 *
4624 * The @freq parameter can be used to indicate a single channel on which the
4625 * offchannel operation will occur. This may allow multiple radio work
4626 * operations to be performed in parallel if they apply for the same channel.
4627 * Setting this to 0 indicates that the work item may use multiple channels or
4628 * requires exclusive control of the radio.
4629 */
4630int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4631 const char *type, int next,
4632 void (*cb)(struct wpa_radio_work *work, int deinit),
4633 void *ctx)
4634{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004635 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004636 struct wpa_radio_work *work;
4637 int was_empty;
4638
4639 work = os_zalloc(sizeof(*work));
4640 if (work == NULL)
4641 return -1;
4642 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4643 os_get_reltime(&work->time);
4644 work->freq = freq;
4645 work->type = type;
4646 work->wpa_s = wpa_s;
4647 work->cb = cb;
4648 work->ctx = ctx;
4649
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004650 if (freq)
4651 work->bands = wpas_freq_to_band(freq);
4652 else if (os_strcmp(type, "scan") == 0 ||
4653 os_strcmp(type, "p2p-scan") == 0)
4654 work->bands = wpas_get_bands(wpa_s,
4655 ((struct wpa_driver_scan_params *)
4656 ctx)->freqs);
4657 else
4658 work->bands = wpas_get_bands(wpa_s, NULL);
4659
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004660 was_empty = dl_list_empty(&wpa_s->radio->work);
4661 if (next)
4662 dl_list_add(&wpa_s->radio->work, &work->list);
4663 else
4664 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4665 if (was_empty) {
4666 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4667 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004668 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4669 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4670 wpa_dbg(wpa_s, MSG_DEBUG,
4671 "Try to schedule a radio work (num_active_works=%u)",
4672 radio->num_active_works);
4673 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004674 }
4675
4676 return 0;
4677}
4678
4679
4680/**
4681 * radio_work_done - Indicate that a radio work item has been completed
4682 * @work: Completed work
4683 *
4684 * This function is called once the callback function registered with
4685 * radio_add_work() has completed its work.
4686 */
4687void radio_work_done(struct wpa_radio_work *work)
4688{
4689 struct wpa_supplicant *wpa_s = work->wpa_s;
4690 struct os_reltime now, diff;
4691 unsigned int started = work->started;
4692
4693 os_get_reltime(&now);
4694 os_reltime_sub(&now, &work->time, &diff);
4695 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4696 work->type, work, started ? "done" : "canceled",
4697 diff.sec, diff.usec);
4698 radio_work_free(work);
4699 if (started)
4700 radio_work_check_next(wpa_s);
4701}
4702
4703
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004704struct wpa_radio_work *
4705radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004706{
4707 struct wpa_radio_work *work;
4708 struct wpa_radio *radio = wpa_s->radio;
4709
4710 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4711 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004712 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004713 }
4714
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004715 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004716}
4717
4718
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004719static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4720 struct wpa_interface *iface)
4721{
4722 const char *ifname, *driver, *rn;
4723
4724 driver = iface->driver;
4725next_driver:
4726 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4727 return -1;
4728
4729 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4730 if (wpa_s->drv_priv == NULL) {
4731 const char *pos;
4732 pos = driver ? os_strchr(driver, ',') : NULL;
4733 if (pos) {
4734 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4735 "driver interface - try next driver wrapper");
4736 driver = pos + 1;
4737 goto next_driver;
4738 }
4739 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4740 "interface");
4741 return -1;
4742 }
4743 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4744 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4745 "driver_param '%s'", wpa_s->conf->driver_param);
4746 return -1;
4747 }
4748
4749 ifname = wpa_drv_get_ifname(wpa_s);
4750 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4751 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4752 "interface name with '%s'", ifname);
4753 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4754 }
4755
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004756 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004757 if (rn && rn[0] == '\0')
4758 rn = NULL;
4759
4760 wpa_s->radio = radio_add_interface(wpa_s, rn);
4761 if (wpa_s->radio == NULL)
4762 return -1;
4763
4764 return 0;
4765}
4766
4767
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004768static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4769 struct wpa_interface *iface)
4770{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004771 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004772 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004773
4774 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4775 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4776 iface->confname ? iface->confname : "N/A",
4777 iface->driver ? iface->driver : "default",
4778 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4779 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4780
4781 if (iface->confname) {
4782#ifdef CONFIG_BACKEND_FILE
4783 wpa_s->confname = os_rel2abs_path(iface->confname);
4784 if (wpa_s->confname == NULL) {
4785 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4786 "for configuration file '%s'.",
4787 iface->confname);
4788 return -1;
4789 }
4790 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4791 iface->confname, wpa_s->confname);
4792#else /* CONFIG_BACKEND_FILE */
4793 wpa_s->confname = os_strdup(iface->confname);
4794#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004795 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004796 if (wpa_s->conf == NULL) {
4797 wpa_printf(MSG_ERROR, "Failed to read or parse "
4798 "configuration '%s'.", wpa_s->confname);
4799 return -1;
4800 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004801 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4802 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004803
4804 /*
4805 * Override ctrl_interface and driver_param if set on command
4806 * line.
4807 */
4808 if (iface->ctrl_interface) {
4809 os_free(wpa_s->conf->ctrl_interface);
4810 wpa_s->conf->ctrl_interface =
4811 os_strdup(iface->ctrl_interface);
4812 }
4813
4814 if (iface->driver_param) {
4815 os_free(wpa_s->conf->driver_param);
4816 wpa_s->conf->driver_param =
4817 os_strdup(iface->driver_param);
4818 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004819
4820 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4821 os_free(wpa_s->conf->ctrl_interface);
4822 wpa_s->conf->ctrl_interface = NULL;
4823 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004824 } else
4825 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4826 iface->driver_param);
4827
4828 if (wpa_s->conf == NULL) {
4829 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4830 return -1;
4831 }
4832
4833 if (iface->ifname == NULL) {
4834 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4835 return -1;
4836 }
4837 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4838 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4839 iface->ifname);
4840 return -1;
4841 }
4842 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4843
4844 if (iface->bridge_ifname) {
4845 if (os_strlen(iface->bridge_ifname) >=
4846 sizeof(wpa_s->bridge_ifname)) {
4847 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4848 "name '%s'.", iface->bridge_ifname);
4849 return -1;
4850 }
4851 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4852 sizeof(wpa_s->bridge_ifname));
4853 }
4854
4855 /* RSNA Supplicant Key Management - INITIALIZE */
4856 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4857 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4858
4859 /* Initialize driver interface and register driver event handler before
4860 * L2 receive handler so that association events are processed before
4861 * EAPOL-Key packets if both become available for the same select()
4862 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004863 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004864 return -1;
4865
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004866 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4867 return -1;
4868
4869 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4870 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4871 NULL);
4872 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4873
4874 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4875 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4876 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4877 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4878 "dot11RSNAConfigPMKLifetime");
4879 return -1;
4880 }
4881
4882 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4883 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4884 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4885 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4886 "dot11RSNAConfigPMKReauthThreshold");
4887 return -1;
4888 }
4889
4890 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4891 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4892 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4893 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4894 "dot11RSNAConfigSATimeout");
4895 return -1;
4896 }
4897
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004898 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4899 &wpa_s->hw.num_modes,
4900 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004901 if (wpa_s->hw.modes) {
4902 u16 i;
4903
4904 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4905 if (wpa_s->hw.modes[i].vht_capab) {
4906 wpa_s->hw_capab = CAPAB_VHT;
4907 break;
4908 }
4909
4910 if (wpa_s->hw.modes[i].ht_capab &
4911 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4912 wpa_s->hw_capab = CAPAB_HT40;
4913 else if (wpa_s->hw.modes[i].ht_capab &&
4914 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4915 wpa_s->hw_capab = CAPAB_HT;
4916 }
4917 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004918
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004919 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4920 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004921 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004922 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004923 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004924 wpa_s->drv_smps_modes = capa.smps_modes;
4925 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004926 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004927 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004928 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004929 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
4930 wpa_s->max_sched_scan_plan_interval =
4931 capa.max_sched_scan_plan_interval;
4932 wpa_s->max_sched_scan_plan_iterations =
4933 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004934 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4935 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004936 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4937 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004938 wpa_s->extended_capa = capa.extended_capa;
4939 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4940 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004941 wpa_s->num_multichan_concurrent =
4942 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004943 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4944
4945 if (capa.mac_addr_rand_scan_supported)
4946 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4947 if (wpa_s->sched_scan_supported &&
4948 capa.mac_addr_rand_sched_scan_supported)
4949 wpa_s->mac_addr_rand_supported |=
4950 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004951 }
4952 if (wpa_s->max_remain_on_chan == 0)
4953 wpa_s->max_remain_on_chan = 1000;
4954
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004955 /*
4956 * Only take p2p_mgmt parameters when P2P Device is supported.
4957 * Doing it here as it determines whether l2_packet_init() will be done
4958 * during wpa_supplicant_driver_init().
4959 */
4960 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4961 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4962 else
4963 iface->p2p_mgmt = 1;
4964
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004965 if (wpa_s->num_multichan_concurrent == 0)
4966 wpa_s->num_multichan_concurrent = 1;
4967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004968 if (wpa_supplicant_driver_init(wpa_s) < 0)
4969 return -1;
4970
4971#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004972 if ((!iface->p2p_mgmt ||
4973 !(wpa_s->drv_flags &
4974 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4975 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004976 return -1;
4977#endif /* CONFIG_TDLS */
4978
4979 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4980 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4981 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4982 return -1;
4983 }
4984
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004985#ifdef CONFIG_FST
4986 if (wpa_s->conf->fst_group_id) {
4987 struct fst_iface_cfg cfg;
4988 struct fst_wpa_obj iface_obj;
4989
4990 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4991 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4992 sizeof(cfg.group_id));
4993 cfg.priority = wpa_s->conf->fst_priority;
4994 cfg.llt = wpa_s->conf->fst_llt;
4995
4996 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4997 &iface_obj, &cfg);
4998 if (!wpa_s->fst) {
4999 wpa_msg(wpa_s, MSG_ERROR,
5000 "FST: Cannot attach iface %s to group %s",
5001 wpa_s->ifname, cfg.group_id);
5002 return -1;
5003 }
5004 }
5005#endif /* CONFIG_FST */
5006
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005007 if (wpas_wps_init(wpa_s))
5008 return -1;
5009
5010 if (wpa_supplicant_init_eapol(wpa_s) < 0)
5011 return -1;
5012 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5013
5014 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
5015 if (wpa_s->ctrl_iface == NULL) {
5016 wpa_printf(MSG_ERROR,
5017 "Failed to initialize control interface '%s'.\n"
5018 "You may have another wpa_supplicant process "
5019 "already running or the file was\n"
5020 "left by an unclean termination of wpa_supplicant "
5021 "in which case you will need\n"
5022 "to manually remove this file before starting "
5023 "wpa_supplicant again.\n",
5024 wpa_s->conf->ctrl_interface);
5025 return -1;
5026 }
5027
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005028 wpa_s->gas = gas_query_init(wpa_s);
5029 if (wpa_s->gas == NULL) {
5030 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5031 return -1;
5032 }
5033
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005034 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005035 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5036 return -1;
5037 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005038
5039 if (wpa_bss_init(wpa_s) < 0)
5040 return -1;
5041
Paul Stewart092955c2017-02-06 09:13:09 -08005042#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5043#ifdef CONFIG_MESH
5044 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
5045#endif /* CONFIG_MESH */
5046#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5047
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005048 /*
5049 * Set Wake-on-WLAN triggers, if configured.
5050 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5051 * have effect anyway when the interface is down).
5052 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005053 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005054 return -1;
5055
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005056#ifdef CONFIG_EAP_PROXY
5057{
5058 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005059 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
5060 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005061 if (wpa_s->mnc_len > 0) {
5062 wpa_s->imsi[len] = '\0';
5063 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5064 wpa_s->imsi, wpa_s->mnc_len);
5065 } else {
5066 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5067 }
5068}
5069#endif /* CONFIG_EAP_PROXY */
5070
Dmitry Shmidt04949592012-07-19 12:16:46 -07005071 if (pcsc_reader_init(wpa_s) < 0)
5072 return -1;
5073
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005074 if (wpas_init_ext_pw(wpa_s) < 0)
5075 return -1;
5076
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005077 wpas_rrm_reset(wpa_s);
5078
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005079 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5080
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005081#ifdef CONFIG_HS20
5082 hs20_init(wpa_s);
5083#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005084#ifdef CONFIG_MBO
5085 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5086#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005087
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005088 wpa_supplicant_set_default_scan_ies(wpa_s);
5089
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005090 return 0;
5091}
5092
5093
5094static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005095 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005096{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005097 struct wpa_global *global = wpa_s->global;
5098 struct wpa_supplicant *iface, *prev;
5099
5100 if (wpa_s == wpa_s->parent)
5101 wpas_p2p_group_remove(wpa_s, "*");
5102
5103 iface = global->ifaces;
5104 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005105 if (iface->p2pdev == wpa_s)
5106 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005107 if (iface == wpa_s || iface->parent != wpa_s) {
5108 iface = iface->next;
5109 continue;
5110 }
5111 wpa_printf(MSG_DEBUG,
5112 "Remove remaining child interface %s from parent %s",
5113 iface->ifname, wpa_s->ifname);
5114 prev = iface;
5115 iface = iface->next;
5116 wpa_supplicant_remove_iface(global, prev, terminate);
5117 }
5118
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005119 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005120 if (wpa_s->drv_priv) {
5121 wpa_supplicant_deauthenticate(wpa_s,
5122 WLAN_REASON_DEAUTH_LEAVING);
5123
5124 wpa_drv_set_countermeasures(wpa_s, 0);
5125 wpa_clear_keys(wpa_s, NULL);
5126 }
5127
5128 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005129 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005130
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005131 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005132 radio_remove_interface(wpa_s);
5133
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005134#ifdef CONFIG_FST
5135 if (wpa_s->fst) {
5136 fst_detach(wpa_s->fst);
5137 wpa_s->fst = NULL;
5138 }
5139 if (wpa_s->received_mb_ies) {
5140 wpabuf_free(wpa_s->received_mb_ies);
5141 wpa_s->received_mb_ies = NULL;
5142 }
5143#endif /* CONFIG_FST */
5144
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005145 if (wpa_s->drv_priv)
5146 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005147
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005148 if (notify)
5149 wpas_notify_iface_removed(wpa_s);
5150
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005151 if (terminate)
5152 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005153
5154 if (wpa_s->ctrl_iface) {
5155 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5156 wpa_s->ctrl_iface = NULL;
5157 }
5158
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005159#ifdef CONFIG_MESH
5160 if (wpa_s->ifmsh) {
5161 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5162 wpa_s->ifmsh = NULL;
5163 }
5164#endif /* CONFIG_MESH */
5165
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005166 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005167 wpa_config_free(wpa_s->conf);
5168 wpa_s->conf = NULL;
5169 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005170
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005171 os_free(wpa_s->ssids_from_scan_req);
5172
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005173 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005174}
5175
5176
Dmitry Shmidte4663042016-04-04 10:07:49 -07005177#ifdef CONFIG_MATCH_IFACE
5178
5179/**
5180 * wpa_supplicant_match_iface - Match an interface description to a name
5181 * @global: Pointer to global data from wpa_supplicant_init()
5182 * @ifname: Name of the interface to match
5183 * Returns: Pointer to the created interface description or %NULL on failure
5184 */
5185struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5186 const char *ifname)
5187{
5188 int i;
5189 struct wpa_interface *iface, *miface;
5190
5191 for (i = 0; i < global->params.match_iface_count; i++) {
5192 miface = &global->params.match_ifaces[i];
5193 if (!miface->ifname ||
5194 fnmatch(miface->ifname, ifname, 0) == 0) {
5195 iface = os_zalloc(sizeof(*iface));
5196 if (!iface)
5197 return NULL;
5198 *iface = *miface;
5199 iface->ifname = ifname;
5200 return iface;
5201 }
5202 }
5203
5204 return NULL;
5205}
5206
5207
5208/**
5209 * wpa_supplicant_match_existing - Match existing interfaces
5210 * @global: Pointer to global data from wpa_supplicant_init()
5211 * Returns: 0 on success, -1 on failure
5212 */
5213static int wpa_supplicant_match_existing(struct wpa_global *global)
5214{
5215 struct if_nameindex *ifi, *ifp;
5216 struct wpa_supplicant *wpa_s;
5217 struct wpa_interface *iface;
5218
5219 ifp = if_nameindex();
5220 if (!ifp) {
5221 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5222 return -1;
5223 }
5224
5225 for (ifi = ifp; ifi->if_name; ifi++) {
5226 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5227 if (wpa_s)
5228 continue;
5229 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5230 if (iface) {
5231 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5232 os_free(iface);
5233 if (wpa_s)
5234 wpa_s->matched = 1;
5235 }
5236 }
5237
5238 if_freenameindex(ifp);
5239 return 0;
5240}
5241
5242#endif /* CONFIG_MATCH_IFACE */
5243
5244
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005245/**
5246 * wpa_supplicant_add_iface - Add a new network interface
5247 * @global: Pointer to global data from wpa_supplicant_init()
5248 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005249 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005250 * Returns: Pointer to the created interface or %NULL on failure
5251 *
5252 * This function is used to add new network interfaces for %wpa_supplicant.
5253 * This can be called before wpa_supplicant_run() to add interfaces before the
5254 * main event loop has been started. In addition, new interfaces can be added
5255 * dynamically while %wpa_supplicant is already running. This could happen,
5256 * e.g., when a hotplug network adapter is inserted.
5257 */
5258struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005259 struct wpa_interface *iface,
5260 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005261{
5262 struct wpa_supplicant *wpa_s;
5263 struct wpa_interface t_iface;
5264 struct wpa_ssid *ssid;
5265
5266 if (global == NULL || iface == NULL)
5267 return NULL;
5268
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005269 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005270 if (wpa_s == NULL)
5271 return NULL;
5272
5273 wpa_s->global = global;
5274
5275 t_iface = *iface;
5276 if (global->params.override_driver) {
5277 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5278 "('%s' -> '%s')",
5279 iface->driver, global->params.override_driver);
5280 t_iface.driver = global->params.override_driver;
5281 }
5282 if (global->params.override_ctrl_interface) {
5283 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5284 "ctrl_interface ('%s' -> '%s')",
5285 iface->ctrl_interface,
5286 global->params.override_ctrl_interface);
5287 t_iface.ctrl_interface =
5288 global->params.override_ctrl_interface;
5289 }
5290 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5291 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5292 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005293 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005294 return NULL;
5295 }
5296
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005297 /* Notify the control interfaces about new iface */
5298 if (wpas_notify_iface_added(wpa_s)) {
5299 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5300 return NULL;
5301 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005302
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005303 /* Notify the control interfaces about new networks for non p2p mgmt
5304 * ifaces. */
5305 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005306 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5307 wpas_notify_network_added(wpa_s, ssid);
5308 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005309
5310 wpa_s->next = global->ifaces;
5311 global->ifaces = wpa_s;
5312
5313 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005314 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005315
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005316#ifdef CONFIG_P2P
5317 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005318 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005319 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005320 wpas_p2p_add_p2pdev_interface(
5321 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005322 wpa_printf(MSG_INFO,
5323 "P2P: Failed to enable P2P Device interface");
5324 /* Try to continue without. P2P will be disabled. */
5325 }
5326#endif /* CONFIG_P2P */
5327
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005328 return wpa_s;
5329}
5330
5331
5332/**
5333 * wpa_supplicant_remove_iface - Remove a network interface
5334 * @global: Pointer to global data from wpa_supplicant_init()
5335 * @wpa_s: Pointer to the network interface to be removed
5336 * Returns: 0 if interface was removed, -1 if interface was not found
5337 *
5338 * This function can be used to dynamically remove network interfaces from
5339 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5340 * addition, this function is used to remove all remaining interfaces when
5341 * %wpa_supplicant is terminated.
5342 */
5343int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005344 struct wpa_supplicant *wpa_s,
5345 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005346{
5347 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005348#ifdef CONFIG_MESH
5349 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5350 char *ifname = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005351 struct wpa_supplicant *parent = wpa_s->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005352#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005353
5354 /* Remove interface from the global list of interfaces */
5355 prev = global->ifaces;
5356 if (prev == wpa_s) {
5357 global->ifaces = wpa_s->next;
5358 } else {
5359 while (prev && prev->next != wpa_s)
5360 prev = prev->next;
5361 if (prev == NULL)
5362 return -1;
5363 prev->next = wpa_s->next;
5364 }
5365
5366 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5367
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005368#ifdef CONFIG_MESH
5369 if (mesh_if_created) {
5370 ifname = os_strdup(wpa_s->ifname);
5371 if (ifname == NULL) {
5372 wpa_dbg(wpa_s, MSG_ERROR,
5373 "mesh: Failed to malloc ifname");
5374 return -1;
5375 }
5376 }
5377#endif /* CONFIG_MESH */
5378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005379 if (global->p2p_group_formation == wpa_s)
5380 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005381 if (global->p2p_invite_group == wpa_s)
5382 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005383 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005384
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005385#ifdef CONFIG_MESH
5386 if (mesh_if_created) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005387 wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005388 os_free(ifname);
5389 }
5390#endif /* CONFIG_MESH */
5391
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005392 return 0;
5393}
5394
5395
5396/**
5397 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5398 * @wpa_s: Pointer to the network interface
5399 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5400 */
5401const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5402{
5403 const char *eapol_method;
5404
5405 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5406 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5407 return "NO-EAP";
5408 }
5409
5410 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5411 if (eapol_method == NULL)
5412 return "UNKNOWN-EAP";
5413
5414 return eapol_method;
5415}
5416
5417
5418/**
5419 * wpa_supplicant_get_iface - Get a new network interface
5420 * @global: Pointer to global data from wpa_supplicant_init()
5421 * @ifname: Interface name
5422 * Returns: Pointer to the interface or %NULL if not found
5423 */
5424struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5425 const char *ifname)
5426{
5427 struct wpa_supplicant *wpa_s;
5428
5429 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5430 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5431 return wpa_s;
5432 }
5433 return NULL;
5434}
5435
5436
5437#ifndef CONFIG_NO_WPA_MSG
5438static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5439{
5440 struct wpa_supplicant *wpa_s = ctx;
5441 if (wpa_s == NULL)
5442 return NULL;
5443 return wpa_s->ifname;
5444}
5445#endif /* CONFIG_NO_WPA_MSG */
5446
5447
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005448#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5449#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5450#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5451
5452/* Periodic cleanup tasks */
5453static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5454{
5455 struct wpa_global *global = eloop_ctx;
5456 struct wpa_supplicant *wpa_s;
5457
5458 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5459 wpas_periodic, global, NULL);
5460
5461#ifdef CONFIG_P2P
5462 if (global->p2p)
5463 p2p_expire_peers(global->p2p);
5464#endif /* CONFIG_P2P */
5465
5466 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5467 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5468#ifdef CONFIG_AP
5469 ap_periodic(wpa_s);
5470#endif /* CONFIG_AP */
5471 }
5472}
5473
5474
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005475/**
5476 * wpa_supplicant_init - Initialize %wpa_supplicant
5477 * @params: Parameters for %wpa_supplicant
5478 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5479 *
5480 * This function is used to initialize %wpa_supplicant. After successful
5481 * initialization, the returned data pointer can be used to add and remove
5482 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5483 */
5484struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5485{
5486 struct wpa_global *global;
5487 int ret, i;
5488
5489 if (params == NULL)
5490 return NULL;
5491
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005492#ifdef CONFIG_DRIVER_NDIS
5493 {
5494 void driver_ndis_init_ops(void);
5495 driver_ndis_init_ops();
5496 }
5497#endif /* CONFIG_DRIVER_NDIS */
5498
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005499#ifndef CONFIG_NO_WPA_MSG
5500 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5501#endif /* CONFIG_NO_WPA_MSG */
5502
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005503 if (params->wpa_debug_file_path)
5504 wpa_debug_open_file(params->wpa_debug_file_path);
5505 else
5506 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005507 if (params->wpa_debug_syslog)
5508 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005509 if (params->wpa_debug_tracing) {
5510 ret = wpa_debug_open_linux_tracing();
5511 if (ret) {
5512 wpa_printf(MSG_ERROR,
5513 "Failed to enable trace logging");
5514 return NULL;
5515 }
5516 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005517
5518 ret = eap_register_methods();
5519 if (ret) {
5520 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5521 if (ret == -2)
5522 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5523 "the same EAP type.");
5524 return NULL;
5525 }
5526
5527 global = os_zalloc(sizeof(*global));
5528 if (global == NULL)
5529 return NULL;
5530 dl_list_init(&global->p2p_srv_bonjour);
5531 dl_list_init(&global->p2p_srv_upnp);
5532 global->params.daemonize = params->daemonize;
5533 global->params.wait_for_monitor = params->wait_for_monitor;
5534 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5535 if (params->pid_file)
5536 global->params.pid_file = os_strdup(params->pid_file);
5537 if (params->ctrl_interface)
5538 global->params.ctrl_interface =
5539 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005540 if (params->ctrl_interface_group)
5541 global->params.ctrl_interface_group =
5542 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005543 if (params->override_driver)
5544 global->params.override_driver =
5545 os_strdup(params->override_driver);
5546 if (params->override_ctrl_interface)
5547 global->params.override_ctrl_interface =
5548 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005549#ifdef CONFIG_MATCH_IFACE
5550 global->params.match_iface_count = params->match_iface_count;
5551 if (params->match_iface_count) {
5552 global->params.match_ifaces =
5553 os_calloc(params->match_iface_count,
5554 sizeof(struct wpa_interface));
5555 os_memcpy(global->params.match_ifaces,
5556 params->match_ifaces,
5557 params->match_iface_count *
5558 sizeof(struct wpa_interface));
5559 }
5560#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005561#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005562 if (params->conf_p2p_dev)
5563 global->params.conf_p2p_dev =
5564 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005565#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005566 wpa_debug_level = global->params.wpa_debug_level =
5567 params->wpa_debug_level;
5568 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5569 params->wpa_debug_show_keys;
5570 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5571 params->wpa_debug_timestamp;
5572
5573 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5574
5575 if (eloop_init()) {
5576 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5577 wpa_supplicant_deinit(global);
5578 return NULL;
5579 }
5580
Jouni Malinen75ecf522011-06-27 15:19:46 -07005581 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005582
5583 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5584 if (global->ctrl_iface == NULL) {
5585 wpa_supplicant_deinit(global);
5586 return NULL;
5587 }
5588
5589 if (wpas_notify_supplicant_initialized(global)) {
5590 wpa_supplicant_deinit(global);
5591 return NULL;
5592 }
5593
5594 for (i = 0; wpa_drivers[i]; i++)
5595 global->drv_count++;
5596 if (global->drv_count == 0) {
5597 wpa_printf(MSG_ERROR, "No drivers enabled");
5598 wpa_supplicant_deinit(global);
5599 return NULL;
5600 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005601 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005602 if (global->drv_priv == NULL) {
5603 wpa_supplicant_deinit(global);
5604 return NULL;
5605 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005606
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005607#ifdef CONFIG_WIFI_DISPLAY
5608 if (wifi_display_init(global) < 0) {
5609 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5610 wpa_supplicant_deinit(global);
5611 return NULL;
5612 }
5613#endif /* CONFIG_WIFI_DISPLAY */
5614
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005615 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5616 wpas_periodic, global, NULL);
5617
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005618 return global;
5619}
5620
5621
5622/**
5623 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5624 * @global: Pointer to global data from wpa_supplicant_init()
5625 * Returns: 0 after successful event loop run, -1 on failure
5626 *
5627 * This function starts the main event loop and continues running as long as
5628 * there are any remaining events. In most cases, this function is running as
5629 * long as the %wpa_supplicant process in still in use.
5630 */
5631int wpa_supplicant_run(struct wpa_global *global)
5632{
5633 struct wpa_supplicant *wpa_s;
5634
5635 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005636 (wpa_supplicant_daemon(global->params.pid_file) ||
5637 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005638 return -1;
5639
Dmitry Shmidte4663042016-04-04 10:07:49 -07005640#ifdef CONFIG_MATCH_IFACE
5641 if (wpa_supplicant_match_existing(global))
5642 return -1;
5643#endif
5644
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005645 if (global->params.wait_for_monitor) {
5646 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005647 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005648 wpa_supplicant_ctrl_iface_wait(
5649 wpa_s->ctrl_iface);
5650 }
5651
5652 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5653 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5654
5655 eloop_run();
5656
5657 return 0;
5658}
5659
5660
5661/**
5662 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5663 * @global: Pointer to global data from wpa_supplicant_init()
5664 *
5665 * This function is called to deinitialize %wpa_supplicant and to free all
5666 * allocated resources. Remaining network interfaces will also be removed.
5667 */
5668void wpa_supplicant_deinit(struct wpa_global *global)
5669{
5670 int i;
5671
5672 if (global == NULL)
5673 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005674
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005675 eloop_cancel_timeout(wpas_periodic, global, NULL);
5676
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005677#ifdef CONFIG_WIFI_DISPLAY
5678 wifi_display_deinit(global);
5679#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005680
5681 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005682 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005683
5684 if (global->ctrl_iface)
5685 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5686
5687 wpas_notify_supplicant_deinitialized(global);
5688
5689 eap_peer_unregister_methods();
5690#ifdef CONFIG_AP
5691 eap_server_unregister_methods();
5692#endif /* CONFIG_AP */
5693
5694 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5695 if (!global->drv_priv[i])
5696 continue;
5697 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5698 }
5699 os_free(global->drv_priv);
5700
5701 random_deinit();
5702
5703 eloop_destroy();
5704
5705 if (global->params.pid_file) {
5706 os_daemonize_terminate(global->params.pid_file);
5707 os_free(global->params.pid_file);
5708 }
5709 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005710 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005711 os_free(global->params.override_driver);
5712 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005713#ifdef CONFIG_MATCH_IFACE
5714 os_free(global->params.match_ifaces);
5715#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005716#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005717 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005718#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005719
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005720 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005721 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005722 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005723
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005724 os_free(global);
5725 wpa_debug_close_syslog();
5726 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005727 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005728}
5729
5730
5731void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5732{
5733 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5734 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5735 char country[3];
5736 country[0] = wpa_s->conf->country[0];
5737 country[1] = wpa_s->conf->country[1];
5738 country[2] = '\0';
5739 if (wpa_drv_set_country(wpa_s, country) < 0) {
5740 wpa_printf(MSG_ERROR, "Failed to set country code "
5741 "'%s'", country);
5742 }
5743 }
5744
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005745 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5746 wpas_init_ext_pw(wpa_s);
5747
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005748 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5749 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5750
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005751#ifdef CONFIG_WPS
5752 wpas_wps_update_config(wpa_s);
5753#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005754 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005755 wpa_s->conf->changed_parameters = 0;
5756}
5757
5758
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005759void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005760{
5761 int i;
5762
5763 for (i = 0; i < *num_freqs; i++) {
5764 if (freqs[i] == freq)
5765 return;
5766 }
5767
5768 freqs[*num_freqs] = freq;
5769 (*num_freqs)++;
5770}
5771
5772
5773static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5774{
5775 struct wpa_bss *bss, *cbss;
5776 const int max_freqs = 10;
5777 int *freqs;
5778 int num_freqs = 0;
5779
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005780 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005781 if (freqs == NULL)
5782 return NULL;
5783
5784 cbss = wpa_s->current_bss;
5785
5786 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5787 if (bss == cbss)
5788 continue;
5789 if (bss->ssid_len == cbss->ssid_len &&
5790 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5791 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5792 add_freq(freqs, &num_freqs, bss->freq);
5793 if (num_freqs == max_freqs)
5794 break;
5795 }
5796 }
5797
5798 if (num_freqs == 0) {
5799 os_free(freqs);
5800 freqs = NULL;
5801 }
5802
5803 return freqs;
5804}
5805
5806
5807void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5808{
5809 int timeout;
5810 int count;
5811 int *freqs = NULL;
5812
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005813 wpas_connect_work_done(wpa_s);
5814
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005815 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005816 * Remove possible authentication timeout since the connection failed.
5817 */
5818 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5819
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005820 /*
5821 * There is no point in blacklisting the AP if this event is
5822 * generated based on local request to disconnect.
5823 */
5824 if (wpa_s->own_disconnect_req) {
5825 wpa_s->own_disconnect_req = 0;
5826 wpa_dbg(wpa_s, MSG_DEBUG,
5827 "Ignore connection failure due to local request to disconnect");
5828 return;
5829 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005830 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005831 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5832 "indication since interface has been put into "
5833 "disconnected state");
5834 return;
5835 }
5836
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005837 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005838 * Add the failed BSSID into the blacklist and speed up next scan
5839 * attempt if there could be other APs that could accept association.
5840 * The current blacklist count indicates how many times we have tried
5841 * connecting to this AP and multiple attempts mean that other APs are
5842 * either not available or has already been tried, so that we can start
5843 * increasing the delay here to avoid constant scanning.
5844 */
5845 count = wpa_blacklist_add(wpa_s, bssid);
5846 if (count == 1 && wpa_s->current_bss) {
5847 /*
5848 * This BSS was not in the blacklist before. If there is
5849 * another BSS available for the same ESS, we should try that
5850 * next. Otherwise, we may as well try this one once more
5851 * before allowing other, likely worse, ESSes to be considered.
5852 */
5853 freqs = get_bss_freqs_in_ess(wpa_s);
5854 if (freqs) {
5855 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5856 "has been seen; try it next");
5857 wpa_blacklist_add(wpa_s, bssid);
5858 /*
5859 * On the next scan, go through only the known channels
5860 * used in this ESS based on previous scans to speed up
5861 * common load balancing use case.
5862 */
5863 os_free(wpa_s->next_scan_freqs);
5864 wpa_s->next_scan_freqs = freqs;
5865 }
5866 }
5867
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005868 /*
5869 * Add previous failure count in case the temporary blacklist was
5870 * cleared due to no other BSSes being available.
5871 */
5872 count += wpa_s->extra_blacklist_count;
5873
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005874 if (count > 3 && wpa_s->current_ssid) {
5875 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5876 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005877 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005878 }
5879
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005880 switch (count) {
5881 case 1:
5882 timeout = 100;
5883 break;
5884 case 2:
5885 timeout = 500;
5886 break;
5887 case 3:
5888 timeout = 1000;
5889 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005890 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005891 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005892 break;
5893 default:
5894 timeout = 10000;
5895 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005896 }
5897
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005898 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5899 "ms", count, timeout);
5900
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005901 /*
5902 * TODO: if more than one possible AP is available in scan results,
5903 * could try the other ones before requesting a new scan.
5904 */
5905 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5906 1000 * (timeout % 1000));
5907}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005908
5909
5910int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5911{
5912 return wpa_s->conf->ap_scan == 2 ||
5913 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5914}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005915
Dmitry Shmidt04949592012-07-19 12:16:46 -07005916
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005917#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005918int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5919 struct wpa_ssid *ssid,
5920 const char *field,
5921 const char *value)
5922{
5923#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005924 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005925
5926 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5927 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5928 (const u8 *) value, os_strlen(value));
5929
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005930 rtype = wpa_supplicant_ctrl_req_from_string(field);
5931 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
5932#else /* IEEE8021X_EAPOL */
5933 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5934 return -1;
5935#endif /* IEEE8021X_EAPOL */
5936}
5937
5938int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5939 struct wpa_ssid *ssid,
5940 enum wpa_ctrl_req_type rtype,
5941 const char *value)
5942{
5943#ifdef IEEE8021X_EAPOL
5944 struct eap_peer_config *eap = &ssid->eap;
5945
5946 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005947 case WPA_CTRL_REQ_EAP_IDENTITY:
5948 os_free(eap->identity);
5949 eap->identity = (u8 *) os_strdup(value);
5950 eap->identity_len = os_strlen(value);
5951 eap->pending_req_identity = 0;
5952 if (ssid == wpa_s->current_ssid)
5953 wpa_s->reassociate = 1;
5954 break;
5955 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005956 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005957 eap->password = (u8 *) os_strdup(value);
5958 eap->password_len = os_strlen(value);
5959 eap->pending_req_password = 0;
5960 if (ssid == wpa_s->current_ssid)
5961 wpa_s->reassociate = 1;
5962 break;
5963 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005964 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005965 eap->new_password = (u8 *) os_strdup(value);
5966 eap->new_password_len = os_strlen(value);
5967 eap->pending_req_new_password = 0;
5968 if (ssid == wpa_s->current_ssid)
5969 wpa_s->reassociate = 1;
5970 break;
5971 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005972 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005973 eap->pin = os_strdup(value);
5974 eap->pending_req_pin = 0;
5975 if (ssid == wpa_s->current_ssid)
5976 wpa_s->reassociate = 1;
5977 break;
5978 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005979 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005980 eap->otp = (u8 *) os_strdup(value);
5981 eap->otp_len = os_strlen(value);
5982 os_free(eap->pending_req_otp);
5983 eap->pending_req_otp = NULL;
5984 eap->pending_req_otp_len = 0;
5985 break;
5986 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005987 str_clear_free(eap->private_key_passwd);
5988 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005989 eap->pending_req_passphrase = 0;
5990 if (ssid == wpa_s->current_ssid)
5991 wpa_s->reassociate = 1;
5992 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005993 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005994 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005995 eap->external_sim_resp = os_strdup(value);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005996 eap->pending_req_sim = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005997 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005998 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5999 if (wpa_config_set(ssid, "psk", value, 0) < 0)
6000 return -1;
6001 ssid->mem_only_psk = 1;
6002 if (ssid->passphrase)
6003 wpa_config_update_psk(ssid);
6004 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
6005 wpa_supplicant_req_scan(wpa_s, 0, 0);
6006 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006007 case WPA_CTRL_REQ_EXT_CERT_CHECK:
6008 if (eap->pending_ext_cert_check != PENDING_CHECK)
6009 return -1;
6010 if (os_strcmp(value, "good") == 0)
6011 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
6012 else if (os_strcmp(value, "bad") == 0)
6013 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
6014 else
6015 return -1;
6016 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006017 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006018 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006019 return -1;
6020 }
6021
6022 return 0;
6023#else /* IEEE8021X_EAPOL */
6024 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6025 return -1;
6026#endif /* IEEE8021X_EAPOL */
6027}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006028#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006029
6030
6031int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6032{
6033 int i;
6034 unsigned int drv_enc;
6035
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006036 if (wpa_s->p2p_mgmt)
6037 return 1; /* no normal network profiles on p2p_mgmt interface */
6038
Dmitry Shmidt04949592012-07-19 12:16:46 -07006039 if (ssid == NULL)
6040 return 1;
6041
6042 if (ssid->disabled)
6043 return 1;
6044
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006045 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006046 drv_enc = wpa_s->drv_enc;
6047 else
6048 drv_enc = (unsigned int) -1;
6049
6050 for (i = 0; i < NUM_WEP_KEYS; i++) {
6051 size_t len = ssid->wep_key_len[i];
6052 if (len == 0)
6053 continue;
6054 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
6055 continue;
6056 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
6057 continue;
6058 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
6059 continue;
6060 return 1; /* invalid WEP key */
6061 }
6062
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006063 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006064 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
6065 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006066 return 1;
6067
Dmitry Shmidt04949592012-07-19 12:16:46 -07006068 return 0;
6069}
6070
6071
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006072int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6073{
6074#ifdef CONFIG_IEEE80211W
6075 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6076 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6077 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6078 /*
6079 * Driver does not support BIP -- ignore pmf=1 default
6080 * since the connection with PMF would fail and the
6081 * configuration does not require PMF to be enabled.
6082 */
6083 return NO_MGMT_FRAME_PROTECTION;
6084 }
6085
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006086 if (ssid &&
6087 (ssid->key_mgmt &
6088 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6089 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6090 /*
6091 * Do not use the default PMF value for non-RSN networks
6092 * since PMF is available only with RSN and pmf=2
6093 * configuration would otherwise prevent connections to
6094 * all open networks.
6095 */
6096 return NO_MGMT_FRAME_PROTECTION;
6097 }
6098
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006099 return wpa_s->conf->pmf;
6100 }
6101
6102 return ssid->ieee80211w;
6103#else /* CONFIG_IEEE80211W */
6104 return NO_MGMT_FRAME_PROTECTION;
6105#endif /* CONFIG_IEEE80211W */
6106}
6107
6108
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006109int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006110{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006111 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006112 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006113 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006114 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006115 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006116}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006117
6118
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006119void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006120{
6121 struct wpa_ssid *ssid = wpa_s->current_ssid;
6122 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006123 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006124
6125 if (ssid == NULL) {
6126 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6127 "SSID block");
6128 return;
6129 }
6130
6131 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6132 return;
6133
6134 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006135
6136#ifdef CONFIG_P2P
6137 if (ssid->p2p_group &&
6138 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6139 /*
6140 * Skip the wait time since there is a short timeout on the
6141 * connection to a P2P group.
6142 */
6143 return;
6144 }
6145#endif /* CONFIG_P2P */
6146
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006147 if (ssid->auth_failures > 50)
6148 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006149 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006150 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006151 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006152 dur = 90;
6153 else if (ssid->auth_failures > 3)
6154 dur = 60;
6155 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006156 dur = 30;
6157 else if (ssid->auth_failures > 1)
6158 dur = 20;
6159 else
6160 dur = 10;
6161
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006162 if (ssid->auth_failures > 1 &&
6163 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6164 dur += os_random() % (ssid->auth_failures * 10);
6165
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006166 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006167 if (now.sec + dur <= ssid->disabled_until.sec)
6168 return;
6169
6170 ssid->disabled_until.sec = now.sec + dur;
6171
6172 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006173 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006174 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006175 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006176}
6177
6178
6179void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6180 struct wpa_ssid *ssid, int clear_failures)
6181{
6182 if (ssid == NULL)
6183 return;
6184
6185 if (ssid->disabled_until.sec) {
6186 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6187 "id=%d ssid=\"%s\"",
6188 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6189 }
6190 ssid->disabled_until.sec = 0;
6191 ssid->disabled_until.usec = 0;
6192 if (clear_failures)
6193 ssid->auth_failures = 0;
6194}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006195
6196
6197int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6198{
6199 size_t i;
6200
6201 if (wpa_s->disallow_aps_bssid == NULL)
6202 return 0;
6203
6204 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6205 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6206 bssid, ETH_ALEN) == 0)
6207 return 1;
6208 }
6209
6210 return 0;
6211}
6212
6213
6214int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6215 size_t ssid_len)
6216{
6217 size_t i;
6218
6219 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6220 return 0;
6221
6222 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6223 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6224 if (ssid_len == s->ssid_len &&
6225 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6226 return 1;
6227 }
6228
6229 return 0;
6230}
6231
6232
6233/**
6234 * wpas_request_connection - Request a new connection
6235 * @wpa_s: Pointer to the network interface
6236 *
6237 * This function is used to request a new connection to be found. It will mark
6238 * the interface to allow reassociation and request a new scan to find a
6239 * suitable network to connect to.
6240 */
6241void wpas_request_connection(struct wpa_supplicant *wpa_s)
6242{
6243 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006244 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006245 wpa_supplicant_reinit_autoscan(wpa_s);
6246 wpa_s->extra_blacklist_count = 0;
6247 wpa_s->disconnected = 0;
6248 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006249
6250 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6251 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006252 else
6253 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006254}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006255
Roshan Pius02242d72016-08-09 15:31:48 -07006256/**
6257 * wpas_request_disconnection - Request disconnection
6258 * @wpa_s: Pointer to the network interface
6259 *
6260 * This function is used to request disconnection from the currently connected
6261 * network. This will stop any ongoing scans and initiate deauthentication.
6262 */
6263void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6264{
6265#ifdef CONFIG_SME
6266 wpa_s->sme.prev_bssid_set = 0;
6267#endif /* CONFIG_SME */
6268 wpa_s->reassociate = 0;
6269 wpa_s->disconnected = 1;
6270 wpa_supplicant_cancel_sched_scan(wpa_s);
6271 wpa_supplicant_cancel_scan(wpa_s);
6272 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6273 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6274}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006275
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006276
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006277void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6278 struct wpa_used_freq_data *freqs_data,
6279 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006280{
6281 unsigned int i;
6282
6283 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6284 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006285 for (i = 0; i < len; i++) {
6286 struct wpa_used_freq_data *cur = &freqs_data[i];
6287 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6288 i, cur->freq, cur->flags);
6289 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006290}
6291
6292
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006293/*
6294 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006295 * are using the same radio as the current interface, and in addition, get
6296 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006297 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006298int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6299 struct wpa_used_freq_data *freqs_data,
6300 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006301{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006302 struct wpa_supplicant *ifs;
6303 u8 bssid[ETH_ALEN];
6304 int freq;
6305 unsigned int idx = 0, i;
6306
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006307 wpa_dbg(wpa_s, MSG_DEBUG,
6308 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006309 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006310
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006311 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6312 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006313 if (idx == len)
6314 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006315
6316 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6317 continue;
6318
6319 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006320 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6321 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006322 freq = ifs->current_ssid->frequency;
6323 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6324 freq = ifs->assoc_freq;
6325 else
6326 continue;
6327
6328 /* Hold only distinct freqs */
6329 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006330 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006331 break;
6332
6333 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006334 freqs_data[idx++].freq = freq;
6335
6336 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006337 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006338 WPA_FREQ_USED_BY_P2P_CLIENT :
6339 WPA_FREQ_USED_BY_INFRA_STATION;
6340 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006341 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006342
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006343 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006344 return idx;
6345}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006346
6347
6348/*
6349 * Find the operating frequencies of any of the virtual interfaces that
6350 * are using the same radio as the current interface.
6351 */
6352int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6353 int *freq_array, unsigned int len)
6354{
6355 struct wpa_used_freq_data *freqs_data;
6356 int num, i;
6357
6358 os_memset(freq_array, 0, sizeof(int) * len);
6359
6360 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6361 if (!freqs_data)
6362 return -1;
6363
6364 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6365 for (i = 0; i < num; i++)
6366 freq_array[i] = freqs_data[i].freq;
6367
6368 os_free(freqs_data);
6369
6370 return num;
6371}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006372
6373
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006374struct wpa_supplicant *
6375wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6376{
6377 switch (frame) {
6378#ifdef CONFIG_P2P
6379 case VENDOR_ELEM_PROBE_REQ_P2P:
6380 case VENDOR_ELEM_PROBE_RESP_P2P:
6381 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6382 case VENDOR_ELEM_BEACON_P2P_GO:
6383 case VENDOR_ELEM_P2P_PD_REQ:
6384 case VENDOR_ELEM_P2P_PD_RESP:
6385 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6386 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6387 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6388 case VENDOR_ELEM_P2P_INV_REQ:
6389 case VENDOR_ELEM_P2P_INV_RESP:
6390 case VENDOR_ELEM_P2P_ASSOC_REQ:
6391 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006392 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006393#endif /* CONFIG_P2P */
6394 default:
6395 return wpa_s;
6396 }
6397}
6398
6399
6400void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6401{
6402 unsigned int i;
6403 char buf[30];
6404
6405 wpa_printf(MSG_DEBUG, "Update vendor elements");
6406
6407 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6408 if (wpa_s->vendor_elem[i]) {
6409 int res;
6410
6411 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6412 if (!os_snprintf_error(sizeof(buf), res)) {
6413 wpa_hexdump_buf(MSG_DEBUG, buf,
6414 wpa_s->vendor_elem[i]);
6415 }
6416 }
6417 }
6418
6419#ifdef CONFIG_P2P
6420 if (wpa_s->parent == wpa_s &&
6421 wpa_s->global->p2p &&
6422 !wpa_s->global->p2p_disabled)
6423 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6424#endif /* CONFIG_P2P */
6425}
6426
6427
6428int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6429 const u8 *elem, size_t len)
6430{
6431 u8 *ie, *end;
6432
6433 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6434 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6435
6436 for (; ie + 1 < end; ie += 2 + ie[1]) {
6437 if (ie + len > end)
6438 break;
6439 if (os_memcmp(ie, elem, len) != 0)
6440 continue;
6441
6442 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6443 wpabuf_free(wpa_s->vendor_elem[frame]);
6444 wpa_s->vendor_elem[frame] = NULL;
6445 } else {
6446 os_memmove(ie, ie + len, end - (ie + len));
6447 wpa_s->vendor_elem[frame]->used -= len;
6448 }
6449 wpas_vendor_elem_update(wpa_s);
6450 return 0;
6451 }
6452
6453 return -1;
6454}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006455
6456
6457struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6458 u16 num_modes, enum hostapd_hw_mode mode)
6459{
6460 u16 i;
6461
6462 for (i = 0; i < num_modes; i++) {
6463 if (modes[i].mode == mode)
6464 return &modes[i];
6465 }
6466
6467 return NULL;
6468}
6469
6470
6471static struct
6472wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6473 const u8 *bssid)
6474{
6475 struct wpa_bss_tmp_disallowed *bss;
6476
6477 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6478 struct wpa_bss_tmp_disallowed, list) {
6479 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6480 return bss;
6481 }
6482
6483 return NULL;
6484}
6485
6486
6487void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6488 unsigned int sec)
6489{
6490 struct wpa_bss_tmp_disallowed *bss;
6491 struct os_reltime until;
6492
6493 os_get_reltime(&until);
6494 until.sec += sec;
6495
6496 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6497 if (bss) {
6498 bss->disallowed_until = until;
6499 return;
6500 }
6501
6502 bss = os_malloc(sizeof(*bss));
6503 if (!bss) {
6504 wpa_printf(MSG_DEBUG,
6505 "Failed to allocate memory for temp disallow BSS");
6506 return;
6507 }
6508
6509 bss->disallowed_until = until;
6510 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6511 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
6512}
6513
6514
6515int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6516{
6517 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
6518 struct os_reltime now, age;
6519
6520 os_get_reltime(&now);
6521
6522 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6523 struct wpa_bss_tmp_disallowed, list) {
6524 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
6525 /* This BSS is not disallowed anymore */
6526 dl_list_del(&tmp->list);
6527 os_free(tmp);
6528 continue;
6529 }
6530 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6531 bss = tmp;
6532 break;
6533 }
6534 }
6535 if (!bss)
6536 return 0;
6537
6538 os_reltime_sub(&bss->disallowed_until, &now, &age);
6539 wpa_printf(MSG_DEBUG,
6540 "BSS " MACSTR " disabled for %ld.%0ld seconds",
6541 MAC2STR(bss->bssid), age.sec, age.usec);
6542 return 1;
6543}