blob: fe14cc8d6216bd0a5d686d85a563114f49e9058e [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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
425{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700426 int i;
427
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700428 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700429 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700430 scard_deinit(wpa_s->scard);
431 wpa_s->scard = NULL;
432 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
433 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
434 l2_packet_deinit(wpa_s->l2);
435 wpa_s->l2 = NULL;
436 if (wpa_s->l2_br) {
437 l2_packet_deinit(wpa_s->l2_br);
438 wpa_s->l2_br = NULL;
439 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800440#ifdef CONFIG_TESTING_OPTIONS
441 l2_packet_deinit(wpa_s->l2_test);
442 wpa_s->l2_test = NULL;
443#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700445 if (wpa_s->conf != NULL) {
446 struct wpa_ssid *ssid;
447 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
448 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700449 }
450
451 os_free(wpa_s->confname);
452 wpa_s->confname = NULL;
453
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700454 os_free(wpa_s->confanother);
455 wpa_s->confanother = NULL;
456
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457 wpa_sm_set_eapol(wpa_s->wpa, NULL);
458 eapol_sm_deinit(wpa_s->eapol);
459 wpa_s->eapol = NULL;
460
461 rsn_preauth_deinit(wpa_s->wpa);
462
463#ifdef CONFIG_TDLS
464 wpa_tdls_deinit(wpa_s->wpa);
465#endif /* CONFIG_TDLS */
466
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800467 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700468 pmksa_candidate_free(wpa_s->wpa);
469 wpa_sm_deinit(wpa_s->wpa);
470 wpa_s->wpa = NULL;
471 wpa_blacklist_clear(wpa_s);
472
473 wpa_bss_deinit(wpa_s);
474
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700475 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700476 wpa_supplicant_cancel_scan(wpa_s);
477 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800478 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
479#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
480 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
481 wpa_s, NULL);
482#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700483
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700484 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
485
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700486 wpas_wps_deinit(wpa_s);
487
488 wpabuf_free(wpa_s->pending_eapol_rx);
489 wpa_s->pending_eapol_rx = NULL;
490
491#ifdef CONFIG_IBSS_RSN
492 ibss_rsn_deinit(wpa_s->ibss_rsn);
493 wpa_s->ibss_rsn = NULL;
494#endif /* CONFIG_IBSS_RSN */
495
496 sme_deinit(wpa_s);
497
498#ifdef CONFIG_AP
499 wpa_supplicant_ap_deinit(wpa_s);
500#endif /* CONFIG_AP */
501
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700503
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800504#ifdef CONFIG_OFFCHANNEL
505 offchannel_deinit(wpa_s);
506#endif /* CONFIG_OFFCHANNEL */
507
508 wpa_supplicant_cancel_sched_scan(wpa_s);
509
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700510 os_free(wpa_s->next_scan_freqs);
511 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800512
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800513 os_free(wpa_s->manual_scan_freqs);
514 wpa_s->manual_scan_freqs = NULL;
515
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700516 os_free(wpa_s->manual_sched_scan_freqs);
517 wpa_s->manual_sched_scan_freqs = NULL;
518
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800519 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
520
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700521 /*
522 * Need to remove any pending gas-query radio work before the
523 * gas_query_deinit() call because gas_query::work has not yet been set
524 * for works that have not been started. gas_query_free() will be unable
525 * to cancel such pending radio works and once the pending gas-query
526 * radio work eventually gets removed, the deinit notification call to
527 * gas_query_start_cb() would result in dereferencing freed memory.
528 */
529 if (wpa_s->radio)
530 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800531 gas_query_deinit(wpa_s->gas);
532 wpa_s->gas = NULL;
533
534 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700535
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700536 ieee802_1x_dealloc_kay_sm(wpa_s);
537
Dmitry Shmidt04949592012-07-19 12:16:46 -0700538 os_free(wpa_s->bssid_filter);
539 wpa_s->bssid_filter = NULL;
540
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800541 os_free(wpa_s->disallow_aps_bssid);
542 wpa_s->disallow_aps_bssid = NULL;
543 os_free(wpa_s->disallow_aps_ssid);
544 wpa_s->disallow_aps_ssid = NULL;
545
Dmitry Shmidt04949592012-07-19 12:16:46 -0700546 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700547#ifdef CONFIG_WNM
548 wnm_deallocate_memory(wpa_s);
549#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700550
551 ext_password_deinit(wpa_s->ext_pw);
552 wpa_s->ext_pw = NULL;
553
554 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800555 wpa_s->last_gas_resp = NULL;
556 wpabuf_free(wpa_s->prev_gas_resp);
557 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700558
559 os_free(wpa_s->last_scan_res);
560 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800561
562#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700563 if (wpa_s->drv_priv)
564 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700565 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800566#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700567
568 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
569 wpabuf_free(wpa_s->vendor_elem[i]);
570 wpa_s->vendor_elem[i] = NULL;
571 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800572
573 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800574
575 wpa_s->sched_scan_plans_num = 0;
576 os_free(wpa_s->sched_scan_plans);
577 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800578
579#ifdef CONFIG_MBO
580 wpa_s->non_pref_chan_num = 0;
581 os_free(wpa_s->non_pref_chan);
582 wpa_s->non_pref_chan = NULL;
583#endif /* CONFIG_MBO */
584
585 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700586
587 wpabuf_free(wpa_s->lci);
588 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800589 wpas_clear_beacon_rep_data(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700590}
591
592
593/**
594 * wpa_clear_keys - Clear keys configured for the driver
595 * @wpa_s: Pointer to wpa_supplicant data
596 * @addr: Previously used BSSID or %NULL if not available
597 *
598 * This function clears the encryption keys that has been previously configured
599 * for the driver.
600 */
601void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
602{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800603 int i, max;
604
605#ifdef CONFIG_IEEE80211W
606 max = 6;
607#else /* CONFIG_IEEE80211W */
608 max = 4;
609#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700610
611 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800612 for (i = 0; i < max; i++) {
613 if (wpa_s->keys_cleared & BIT(i))
614 continue;
615 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
616 NULL, 0);
617 }
618 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
619 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700620 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
621 0);
622 /* MLME-SETPROTECTION.request(None) */
623 wpa_drv_mlme_setprotection(
624 wpa_s, addr,
625 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
626 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
627 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800628 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700629}
630
631
632/**
633 * wpa_supplicant_state_txt - Get the connection state name as a text string
634 * @state: State (wpa_state; WPA_*)
635 * Returns: The state name as a printable text string
636 */
637const char * wpa_supplicant_state_txt(enum wpa_states state)
638{
639 switch (state) {
640 case WPA_DISCONNECTED:
641 return "DISCONNECTED";
642 case WPA_INACTIVE:
643 return "INACTIVE";
644 case WPA_INTERFACE_DISABLED:
645 return "INTERFACE_DISABLED";
646 case WPA_SCANNING:
647 return "SCANNING";
648 case WPA_AUTHENTICATING:
649 return "AUTHENTICATING";
650 case WPA_ASSOCIATING:
651 return "ASSOCIATING";
652 case WPA_ASSOCIATED:
653 return "ASSOCIATED";
654 case WPA_4WAY_HANDSHAKE:
655 return "4WAY_HANDSHAKE";
656 case WPA_GROUP_HANDSHAKE:
657 return "GROUP_HANDSHAKE";
658 case WPA_COMPLETED:
659 return "COMPLETED";
660 default:
661 return "UNKNOWN";
662 }
663}
664
665
666#ifdef CONFIG_BGSCAN
667
668static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
669{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800670 const char *name;
671
672 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
673 name = wpa_s->current_ssid->bgscan;
674 else
675 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800676 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800677 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800678 if (wpas_driver_bss_selection(wpa_s))
679 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700680 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
681 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800682#ifdef CONFIG_P2P
683 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
684 return;
685#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700686
687 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800688 if (wpa_s->current_ssid) {
689 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700690 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
691 "bgscan");
692 /*
693 * Live without bgscan; it is only used as a roaming
694 * optimization, so the initial connection is not
695 * affected.
696 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700697 } else {
698 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700699 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700700 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
701 0);
702 if (scan_res) {
703 bgscan_notify_scan(wpa_s, scan_res);
704 wpa_scan_results_free(scan_res);
705 }
706 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707 } else
708 wpa_s->bgscan_ssid = NULL;
709}
710
711
712static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
713{
714 if (wpa_s->bgscan_ssid != NULL) {
715 bgscan_deinit(wpa_s);
716 wpa_s->bgscan_ssid = NULL;
717 }
718}
719
720#endif /* CONFIG_BGSCAN */
721
722
Dmitry Shmidt04949592012-07-19 12:16:46 -0700723static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
724{
725 if (autoscan_init(wpa_s, 0))
726 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
727}
728
729
730static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
731{
732 autoscan_deinit(wpa_s);
733}
734
735
736void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
737{
738 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
739 wpa_s->wpa_state == WPA_SCANNING) {
740 autoscan_deinit(wpa_s);
741 wpa_supplicant_start_autoscan(wpa_s);
742 }
743}
744
745
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746/**
747 * wpa_supplicant_set_state - Set current connection state
748 * @wpa_s: Pointer to wpa_supplicant data
749 * @state: The new connection state
750 *
751 * This function is called whenever the connection state changes, e.g.,
752 * association is completed for WPA/WPA2 4-Way Handshake is started.
753 */
754void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
755 enum wpa_states state)
756{
757 enum wpa_states old_state = wpa_s->wpa_state;
758
759 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
760 wpa_supplicant_state_txt(wpa_s->wpa_state),
761 wpa_supplicant_state_txt(state));
762
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800763 if (state == WPA_INTERFACE_DISABLED) {
764 /* Assure normal scan when interface is restored */
765 wpa_s->normal_scans = 0;
766 }
767
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700768 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800769 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700770 /* Reinitialize normal_scan counter */
771 wpa_s->normal_scans = 0;
772 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800773
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700774#ifdef CONFIG_P2P
775 /*
776 * P2PS client has to reply to Probe Request frames received on the
777 * group operating channel. Enable Probe Request frame reporting for
778 * P2P connected client in case p2p_cli_probe configuration property is
779 * set to 1.
780 */
781 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
782 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
783 wpa_s->current_ssid->p2p_group) {
784 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
785 wpa_dbg(wpa_s, MSG_DEBUG,
786 "P2P: Enable CLI Probe Request RX reporting");
787 wpa_s->p2p_cli_probe =
788 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
789 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
790 wpa_dbg(wpa_s, MSG_DEBUG,
791 "P2P: Disable CLI Probe Request RX reporting");
792 wpa_s->p2p_cli_probe = 0;
793 wpa_drv_probe_req_report(wpa_s, 0);
794 }
795 }
796#endif /* CONFIG_P2P */
797
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798 if (state != WPA_SCANNING)
799 wpa_supplicant_notify_scanning(wpa_s, 0);
800
801 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700802 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700803#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800805 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800806 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807 ssid ? ssid->id : -1,
808 ssid && ssid->id_str ? ssid->id_str : "");
809#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700810 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700811 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800812 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700813 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700814 wpa_drv_set_operstate(wpa_s, 1);
815#ifndef IEEE8021X_EAPOL
816 wpa_drv_set_supp_port(wpa_s, 1);
817#endif /* IEEE8021X_EAPOL */
818 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700819 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700820 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700821
822 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700823 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
824 state == WPA_ASSOCIATED) {
825 wpa_s->new_connection = 1;
826 wpa_drv_set_operstate(wpa_s, 0);
827#ifndef IEEE8021X_EAPOL
828 wpa_drv_set_supp_port(wpa_s, 0);
829#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700830 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700831 }
832 wpa_s->wpa_state = state;
833
834#ifdef CONFIG_BGSCAN
835 if (state == WPA_COMPLETED)
836 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800837 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700838 wpa_supplicant_stop_bgscan(wpa_s);
839#endif /* CONFIG_BGSCAN */
840
Dmitry Shmidt04949592012-07-19 12:16:46 -0700841 if (state == WPA_AUTHENTICATING)
842 wpa_supplicant_stop_autoscan(wpa_s);
843
844 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
845 wpa_supplicant_start_autoscan(wpa_s);
846
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800847 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
848 wmm_ac_notify_disassoc(wpa_s);
849
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700850 if (wpa_s->wpa_state != old_state) {
851 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
852
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700853 /*
854 * Notify the P2P Device interface about a state change in one
855 * of the interfaces.
856 */
857 wpas_p2p_indicate_state_change(wpa_s);
858
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700859 if (wpa_s->wpa_state == WPA_COMPLETED ||
860 old_state == WPA_COMPLETED)
861 wpas_notify_auth_changed(wpa_s);
862 }
863}
864
865
866void wpa_supplicant_terminate_proc(struct wpa_global *global)
867{
868 int pending = 0;
869#ifdef CONFIG_WPS
870 struct wpa_supplicant *wpa_s = global->ifaces;
871 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800872 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700873 if (wpas_wps_terminate_pending(wpa_s) == 1)
874 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700875#ifdef CONFIG_P2P
876 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
877 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
878 wpas_p2p_disconnect(wpa_s);
879#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800880 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700881 }
882#endif /* CONFIG_WPS */
883 if (pending)
884 return;
885 eloop_terminate();
886}
887
888
889static void wpa_supplicant_terminate(int sig, void *signal_ctx)
890{
891 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892 wpa_supplicant_terminate_proc(global);
893}
894
895
896void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
897{
898 enum wpa_states old_state = wpa_s->wpa_state;
899
900 wpa_s->pairwise_cipher = 0;
901 wpa_s->group_cipher = 0;
902 wpa_s->mgmt_group_cipher = 0;
903 wpa_s->key_mgmt = 0;
904 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700905 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700906
907 if (wpa_s->wpa_state != old_state)
908 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
909}
910
911
912/**
913 * wpa_supplicant_reload_configuration - Reload configuration data
914 * @wpa_s: Pointer to wpa_supplicant data
915 * Returns: 0 on success or -1 if configuration parsing failed
916 *
917 * This function can be used to request that the configuration data is reloaded
918 * (e.g., after configuration file change). This function is reloading
919 * configuration only for one interface, so this may need to be called multiple
920 * times if %wpa_supplicant is controlling multiple interfaces and all
921 * interfaces need reconfiguration.
922 */
923int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
924{
925 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700926 int reconf_ctrl;
927 int old_ap_scan;
928
929 if (wpa_s->confname == NULL)
930 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700931 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700932 if (conf == NULL) {
933 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
934 "file '%s' - exiting", wpa_s->confname);
935 return -1;
936 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700937 wpa_config_read(wpa_s->confanother, conf);
938
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700939 conf->changed_parameters = (unsigned int) -1;
940
941 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
942 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
943 os_strcmp(conf->ctrl_interface,
944 wpa_s->conf->ctrl_interface) != 0);
945
946 if (reconf_ctrl && wpa_s->ctrl_iface) {
947 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
948 wpa_s->ctrl_iface = NULL;
949 }
950
951 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800952 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700953 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
954 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800955 wpa_supplicant_deauthenticate(wpa_s,
956 WLAN_REASON_DEAUTH_LEAVING);
957 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700958
959 /*
960 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800961 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700962 */
963 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
964 /*
965 * Clear forced success to clear EAP state for next
966 * authentication.
967 */
968 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
969 }
970 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
971 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800972 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700973 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
974 rsn_preauth_deinit(wpa_s->wpa);
975
976 old_ap_scan = wpa_s->conf->ap_scan;
977 wpa_config_free(wpa_s->conf);
978 wpa_s->conf = conf;
979 if (old_ap_scan != wpa_s->conf->ap_scan)
980 wpas_notify_ap_scan_changed(wpa_s);
981
982 if (reconf_ctrl)
983 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
984
985 wpa_supplicant_update_config(wpa_s);
986
987 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700988 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989 wpa_s->reassociate = 1;
990 wpa_supplicant_req_scan(wpa_s, 0, 0);
991 }
992 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
993 return 0;
994}
995
996
997static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
998{
999 struct wpa_global *global = signal_ctx;
1000 struct wpa_supplicant *wpa_s;
1001 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1002 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1003 sig);
1004 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1005 wpa_supplicant_terminate_proc(global);
1006 }
1007 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001008
1009 if (wpa_debug_reopen_file() < 0) {
1010 /* Ignore errors since we cannot really do much to fix this */
1011 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1012 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013}
1014
1015
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1017 struct wpa_ssid *ssid,
1018 struct wpa_ie_data *ie)
1019{
1020 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1021 if (ret) {
1022 if (ret == -2) {
1023 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1024 "from association info");
1025 }
1026 return -1;
1027 }
1028
1029 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1030 "cipher suites");
1031 if (!(ie->group_cipher & ssid->group_cipher)) {
1032 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1033 "cipher 0x%x (mask 0x%x) - reject",
1034 ie->group_cipher, ssid->group_cipher);
1035 return -1;
1036 }
1037 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1038 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1039 "cipher 0x%x (mask 0x%x) - reject",
1040 ie->pairwise_cipher, ssid->pairwise_cipher);
1041 return -1;
1042 }
1043 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1044 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1045 "management 0x%x (mask 0x%x) - reject",
1046 ie->key_mgmt, ssid->key_mgmt);
1047 return -1;
1048 }
1049
1050#ifdef CONFIG_IEEE80211W
1051 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001052 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1054 "that does not support management frame protection - "
1055 "reject");
1056 return -1;
1057 }
1058#endif /* CONFIG_IEEE80211W */
1059
1060 return 0;
1061}
1062
1063
1064/**
1065 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1066 * @wpa_s: Pointer to wpa_supplicant data
1067 * @bss: Scan results for the selected BSS, or %NULL if not available
1068 * @ssid: Configuration data for the selected network
1069 * @wpa_ie: Buffer for the WPA/RSN IE
1070 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1071 * used buffer length in case the functions returns success.
1072 * Returns: 0 on success or -1 on failure
1073 *
1074 * This function is used to configure authentication and encryption parameters
1075 * based on the network configuration and scan result for the selected BSS (if
1076 * available).
1077 */
1078int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1079 struct wpa_bss *bss, struct wpa_ssid *ssid,
1080 u8 *wpa_ie, size_t *wpa_ie_len)
1081{
1082 struct wpa_ie_data ie;
1083 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001084 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085
1086 if (bss) {
1087 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1088 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001089 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001091 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001092
1093 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1094 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1095 (ie.group_cipher & ssid->group_cipher) &&
1096 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1097 (ie.key_mgmt & ssid->key_mgmt)) {
1098 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1099 proto = WPA_PROTO_RSN;
1100 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001101 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001102 (ie.group_cipher & ssid->group_cipher) &&
1103 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1104 (ie.key_mgmt & ssid->key_mgmt)) {
1105 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1106 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001107#ifdef CONFIG_HS20
1108 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1109 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1110 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001111 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001112 ie.group_cipher = WPA_CIPHER_CCMP;
1113 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1114 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1115 proto = WPA_PROTO_OSEN;
1116#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117 } else if (bss) {
1118 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001119 wpa_dbg(wpa_s, MSG_DEBUG,
1120 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1121 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1122 ssid->key_mgmt);
1123 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1124 MAC2STR(bss->bssid),
1125 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1126 bss_wpa ? " WPA" : "",
1127 bss_rsn ? " RSN" : "",
1128 bss_osen ? " OSEN" : "");
1129 if (bss_rsn) {
1130 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1131 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1132 wpa_dbg(wpa_s, MSG_DEBUG,
1133 "Could not parse RSN element");
1134 } else {
1135 wpa_dbg(wpa_s, MSG_DEBUG,
1136 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1137 ie.pairwise_cipher, ie.group_cipher,
1138 ie.key_mgmt);
1139 }
1140 }
1141 if (bss_wpa) {
1142 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1143 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1144 wpa_dbg(wpa_s, MSG_DEBUG,
1145 "Could not parse WPA element");
1146 } else {
1147 wpa_dbg(wpa_s, MSG_DEBUG,
1148 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1149 ie.pairwise_cipher, ie.group_cipher,
1150 ie.key_mgmt);
1151 }
1152 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001153 return -1;
1154 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001155 if (ssid->proto & WPA_PROTO_OSEN)
1156 proto = WPA_PROTO_OSEN;
1157 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001158 proto = WPA_PROTO_RSN;
1159 else
1160 proto = WPA_PROTO_WPA;
1161 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1162 os_memset(&ie, 0, sizeof(ie));
1163 ie.group_cipher = ssid->group_cipher;
1164 ie.pairwise_cipher = ssid->pairwise_cipher;
1165 ie.key_mgmt = ssid->key_mgmt;
1166#ifdef CONFIG_IEEE80211W
1167 ie.mgmt_group_cipher =
1168 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1169 WPA_CIPHER_AES_128_CMAC : 0;
1170#endif /* CONFIG_IEEE80211W */
1171 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1172 "based on configuration");
1173 } else
1174 proto = ie.proto;
1175 }
1176
1177 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1178 "pairwise %d key_mgmt %d proto %d",
1179 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1180#ifdef CONFIG_IEEE80211W
1181 if (ssid->ieee80211w) {
1182 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1183 ie.mgmt_group_cipher);
1184 }
1185#endif /* CONFIG_IEEE80211W */
1186
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001187 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001188 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1189 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001190 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001191
1192 if (bss || !wpa_s->ap_ies_from_associnfo) {
1193 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1194 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1195 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1196 bss_rsn ? 2 + bss_rsn[1] : 0))
1197 return -1;
1198 }
1199
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001200#ifdef CONFIG_NO_WPA
1201 wpa_s->group_cipher = WPA_CIPHER_NONE;
1202 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1203#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001204 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001205 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1206 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001207 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1208 "cipher");
1209 return -1;
1210 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001211 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1212 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001213
1214 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001215 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1216 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001217 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1218 "cipher");
1219 return -1;
1220 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001221 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1222 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001223#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001224
1225 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001226#ifdef CONFIG_SAE
1227 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1228 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1229#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001230 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001231#ifdef CONFIG_SUITEB192
1232 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1233 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1234 wpa_dbg(wpa_s, MSG_DEBUG,
1235 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1236#endif /* CONFIG_SUITEB192 */
1237#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001238 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1239 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1240 wpa_dbg(wpa_s, MSG_DEBUG,
1241 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001242#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001243#ifdef CONFIG_FILS
1244#ifdef CONFIG_IEEE80211R
1245 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1246 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1247 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1248 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1249 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1250 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1251#endif /* CONFIG_IEEE80211R */
1252 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1253 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1254 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1255 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1256 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1257 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1258#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001259#ifdef CONFIG_IEEE80211R
1260 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1261 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1262 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1263 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1264 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1265 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1266#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001267#ifdef CONFIG_SAE
1268 } else if (sel & WPA_KEY_MGMT_SAE) {
1269 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1270 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1271 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1272 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1273 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1274#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001275#ifdef CONFIG_IEEE80211W
1276 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1277 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1278 wpa_dbg(wpa_s, MSG_DEBUG,
1279 "WPA: using KEY_MGMT 802.1X with SHA256");
1280 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1281 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1282 wpa_dbg(wpa_s, MSG_DEBUG,
1283 "WPA: using KEY_MGMT PSK with SHA256");
1284#endif /* CONFIG_IEEE80211W */
1285 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1286 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1287 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1288 } else if (sel & WPA_KEY_MGMT_PSK) {
1289 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1290 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1291 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1292 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1293 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001294#ifdef CONFIG_HS20
1295 } else if (sel & WPA_KEY_MGMT_OSEN) {
1296 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1297 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1298#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001299 } else {
1300 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1301 "authenticated key management type");
1302 return -1;
1303 }
1304
1305 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1306 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1307 wpa_s->pairwise_cipher);
1308 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1309
1310#ifdef CONFIG_IEEE80211W
1311 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001312 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001313 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1314 sel = 0;
1315 if (sel & WPA_CIPHER_AES_128_CMAC) {
1316 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1317 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1318 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001319 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1320 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1321 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1322 "BIP-GMAC-128");
1323 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1324 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1325 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1326 "BIP-GMAC-256");
1327 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1328 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1329 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1330 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001331 } else {
1332 wpa_s->mgmt_group_cipher = 0;
1333 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1334 }
1335 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1336 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001337 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001338 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001339#endif /* CONFIG_IEEE80211W */
1340
1341 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1342 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1343 return -1;
1344 }
1345
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001346 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001347 int psk_set = 0;
1348
1349 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001350 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1351 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001352 psk_set = 1;
1353 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001354#ifndef CONFIG_NO_PBKDF2
1355 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1356 ssid->passphrase) {
1357 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001358 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1359 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001360 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1361 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001362 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001363 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001364 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001365 }
1366#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001367#ifdef CONFIG_EXT_PASSWORD
1368 if (ssid->ext_psk) {
1369 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1370 ssid->ext_psk);
1371 char pw_str[64 + 1];
1372 u8 psk[PMK_LEN];
1373
1374 if (pw == NULL) {
1375 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1376 "found from external storage");
1377 return -1;
1378 }
1379
1380 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1381 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1382 "PSK length %d in external storage",
1383 (int) wpabuf_len(pw));
1384 ext_password_free(pw);
1385 return -1;
1386 }
1387
1388 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1389 pw_str[wpabuf_len(pw)] = '\0';
1390
1391#ifndef CONFIG_NO_PBKDF2
1392 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1393 {
1394 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1395 4096, psk, PMK_LEN);
1396 os_memset(pw_str, 0, sizeof(pw_str));
1397 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1398 "external passphrase)",
1399 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001400 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1401 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001402 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001403 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001404 } else
1405#endif /* CONFIG_NO_PBKDF2 */
1406 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1407 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1408 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1409 "Invalid PSK hex string");
1410 os_memset(pw_str, 0, sizeof(pw_str));
1411 ext_password_free(pw);
1412 return -1;
1413 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001414 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1415 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001416 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001417 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001418 } else {
1419 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1420 "PSK available");
1421 os_memset(pw_str, 0, sizeof(pw_str));
1422 ext_password_free(pw);
1423 return -1;
1424 }
1425
1426 os_memset(pw_str, 0, sizeof(pw_str));
1427 ext_password_free(pw);
1428 }
1429#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001430
1431 if (!psk_set) {
1432 wpa_msg(wpa_s, MSG_INFO,
1433 "No PSK available for association");
1434 return -1;
1435 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001436 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001437 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1438
1439 return 0;
1440}
1441
1442
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001443static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1444{
1445 *pos = 0x00;
1446
1447 switch (idx) {
1448 case 0: /* Bits 0-7 */
1449 break;
1450 case 1: /* Bits 8-15 */
1451 break;
1452 case 2: /* Bits 16-23 */
1453#ifdef CONFIG_WNM
1454 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1455 *pos |= 0x08; /* Bit 19 - BSS Transition */
1456#endif /* CONFIG_WNM */
1457 break;
1458 case 3: /* Bits 24-31 */
1459#ifdef CONFIG_WNM
1460 *pos |= 0x02; /* Bit 25 - SSID List */
1461#endif /* CONFIG_WNM */
1462#ifdef CONFIG_INTERWORKING
1463 if (wpa_s->conf->interworking)
1464 *pos |= 0x80; /* Bit 31 - Interworking */
1465#endif /* CONFIG_INTERWORKING */
1466 break;
1467 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001468#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001469 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1470 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001471#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001472 break;
1473 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001474#ifdef CONFIG_HS20
1475 if (wpa_s->conf->hs20)
1476 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1477#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001478#ifdef CONFIG_MBO
1479 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1480#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001481 break;
1482 case 6: /* Bits 48-55 */
1483 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001484 case 7: /* Bits 56-63 */
1485 break;
1486 case 8: /* Bits 64-71 */
1487 if (wpa_s->conf->ftm_responder)
1488 *pos |= 0x40; /* Bit 70 - FTM responder */
1489 if (wpa_s->conf->ftm_initiator)
1490 *pos |= 0x80; /* Bit 71 - FTM initiator */
1491 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001492 case 9: /* Bits 72-79 */
1493#ifdef CONFIG_FILS
1494 *pos |= 0x01;
1495#endif /* CONFIG_FILS */
1496 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001497 }
1498}
1499
1500
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001501int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001502{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001503 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001504 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001505
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001506 if (len < wpa_s->extended_capa_len)
1507 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001508 if (buflen < (size_t) len + 2) {
1509 wpa_printf(MSG_INFO,
1510 "Not enough room for building extended capabilities element");
1511 return -1;
1512 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001513
1514 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001515 *pos++ = len;
1516 for (i = 0; i < len; i++, pos++) {
1517 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001518
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001519 if (i < wpa_s->extended_capa_len) {
1520 *pos &= ~wpa_s->extended_capa_mask[i];
1521 *pos |= wpa_s->extended_capa[i];
1522 }
1523 }
1524
1525 while (len > 0 && buf[1 + len] == 0) {
1526 len--;
1527 buf[1] = len;
1528 }
1529 if (len == 0)
1530 return 0;
1531
1532 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001533}
1534
1535
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001536static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1537 struct wpa_bss *test_bss)
1538{
1539 struct wpa_bss *bss;
1540
1541 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1542 if (bss == test_bss)
1543 return 1;
1544 }
1545
1546 return 0;
1547}
1548
1549
1550static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1551 struct wpa_ssid *test_ssid)
1552{
1553 struct wpa_ssid *ssid;
1554
1555 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1556 if (ssid == test_ssid)
1557 return 1;
1558 }
1559
1560 return 0;
1561}
1562
1563
1564int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1565 struct wpa_ssid *test_ssid)
1566{
1567 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1568 return 0;
1569
1570 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1571}
1572
1573
1574void wpas_connect_work_free(struct wpa_connect_work *cwork)
1575{
1576 if (cwork == NULL)
1577 return;
1578 os_free(cwork);
1579}
1580
1581
1582void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1583{
1584 struct wpa_connect_work *cwork;
1585 struct wpa_radio_work *work = wpa_s->connect_work;
1586
1587 if (!work)
1588 return;
1589
1590 wpa_s->connect_work = NULL;
1591 cwork = work->ctx;
1592 work->ctx = NULL;
1593 wpas_connect_work_free(cwork);
1594 radio_work_done(work);
1595}
1596
1597
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001598int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1599{
1600 struct os_reltime now;
1601 u8 addr[ETH_ALEN];
1602
1603 os_get_reltime(&now);
1604 if (wpa_s->last_mac_addr_style == style &&
1605 wpa_s->last_mac_addr_change.sec != 0 &&
1606 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1607 wpa_s->conf->rand_addr_lifetime)) {
1608 wpa_msg(wpa_s, MSG_DEBUG,
1609 "Previously selected random MAC address has not yet expired");
1610 return 0;
1611 }
1612
1613 switch (style) {
1614 case 1:
1615 if (random_mac_addr(addr) < 0)
1616 return -1;
1617 break;
1618 case 2:
1619 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1620 if (random_mac_addr_keep_oui(addr) < 0)
1621 return -1;
1622 break;
1623 default:
1624 return -1;
1625 }
1626
1627 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1628 wpa_msg(wpa_s, MSG_INFO,
1629 "Failed to set random MAC address");
1630 return -1;
1631 }
1632
1633 os_get_reltime(&wpa_s->last_mac_addr_change);
1634 wpa_s->mac_addr_changed = 1;
1635 wpa_s->last_mac_addr_style = style;
1636
1637 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1638 wpa_msg(wpa_s, MSG_INFO,
1639 "Could not update MAC address information");
1640 return -1;
1641 }
1642
1643 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1644 MAC2STR(addr));
1645
1646 return 0;
1647}
1648
1649
1650int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1651{
1652 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1653 !wpa_s->conf->preassoc_mac_addr)
1654 return 0;
1655
1656 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1657}
1658
1659
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001660static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1661
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001662/**
1663 * wpa_supplicant_associate - Request association
1664 * @wpa_s: Pointer to wpa_supplicant data
1665 * @bss: Scan results for the selected BSS, or %NULL if not available
1666 * @ssid: Configuration data for the selected network
1667 *
1668 * This function is used to request %wpa_supplicant to associate with a BSS.
1669 */
1670void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1671 struct wpa_bss *bss, struct wpa_ssid *ssid)
1672{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001673 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001674 int rand_style;
1675
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001676 wpa_s->own_disconnect_req = 0;
1677
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001678 /*
1679 * If we are starting a new connection, any previously pending EAPOL
1680 * RX cannot be valid anymore.
1681 */
1682 wpabuf_free(wpa_s->pending_eapol_rx);
1683 wpa_s->pending_eapol_rx = NULL;
1684
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001685 if (ssid->mac_addr == -1)
1686 rand_style = wpa_s->conf->mac_addr;
1687 else
1688 rand_style = ssid->mac_addr;
1689
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001690 wmm_ac_clear_saved_tspecs(wpa_s);
1691 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001692 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001693
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001694 if (wpa_s->last_ssid == ssid) {
1695 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001696 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001697 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1698 wmm_ac_save_tspecs(wpa_s);
1699 wpa_s->reassoc_same_bss = 1;
1700 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001701 }
1702
1703 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001704 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1705 return;
1706 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001707 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001708 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1709 wpa_msg(wpa_s, MSG_INFO,
1710 "Could not restore permanent MAC address");
1711 return;
1712 }
1713 wpa_s->mac_addr_changed = 0;
1714 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1715 wpa_msg(wpa_s, MSG_INFO,
1716 "Could not update MAC address information");
1717 return;
1718 }
1719 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1720 }
1721 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001722
1723#ifdef CONFIG_IBSS_RSN
1724 ibss_rsn_deinit(wpa_s->ibss_rsn);
1725 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001726#else /* CONFIG_IBSS_RSN */
1727 if (ssid->mode == WPAS_MODE_IBSS &&
1728 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1729 wpa_msg(wpa_s, MSG_INFO,
1730 "IBSS RSN not supported in the build");
1731 return;
1732 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001733#endif /* CONFIG_IBSS_RSN */
1734
1735 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1736 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1737#ifdef CONFIG_AP
1738 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1739 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1740 "mode");
1741 return;
1742 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001743 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1744 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001745 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1746 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001747 return;
1748 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001749 wpa_s->current_bss = bss;
1750#else /* CONFIG_AP */
1751 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1752 "the build");
1753#endif /* CONFIG_AP */
1754 return;
1755 }
1756
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001757 if (ssid->mode == WPAS_MODE_MESH) {
1758#ifdef CONFIG_MESH
1759 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1760 wpa_msg(wpa_s, MSG_INFO,
1761 "Driver does not support mesh mode");
1762 return;
1763 }
1764 if (bss)
1765 ssid->frequency = bss->freq;
1766 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1767 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1768 return;
1769 }
1770 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001771 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1772 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1773 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001774#else /* CONFIG_MESH */
1775 wpa_msg(wpa_s, MSG_ERROR,
1776 "mesh mode support not included in the build");
1777#endif /* CONFIG_MESH */
1778 return;
1779 }
1780
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001781#ifdef CONFIG_TDLS
1782 if (bss)
1783 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1784 bss->ie_len);
1785#endif /* CONFIG_TDLS */
1786
1787 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1788 ssid->mode == IEEE80211_MODE_INFRA) {
1789 sme_authenticate(wpa_s, bss, ssid);
1790 return;
1791 }
1792
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001793 if (wpa_s->connect_work) {
1794 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1795 return;
1796 }
1797
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001798 if (radio_work_pending(wpa_s, "connect")) {
1799 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1800 return;
1801 }
1802
Dmitry Shmidt29333592017-01-09 12:27:11 -08001803#ifdef CONFIG_SME
1804 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
1805 /* Clear possibly set auth_alg, if any, from last attempt. */
1806 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
1807 }
1808#endif /* CONFIG_SME */
1809
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001810 wpas_abort_ongoing_scan(wpa_s);
1811
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001812 cwork = os_zalloc(sizeof(*cwork));
1813 if (cwork == NULL)
1814 return;
1815
1816 cwork->bss = bss;
1817 cwork->ssid = ssid;
1818
1819 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1820 wpas_start_assoc_cb, cwork) < 0) {
1821 os_free(cwork);
1822 }
1823}
1824
1825
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001826static int bss_is_ibss(struct wpa_bss *bss)
1827{
1828 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1829 IEEE80211_CAP_IBSS;
1830}
1831
1832
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001833static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1834 const struct wpa_ssid *ssid)
1835{
1836 enum hostapd_hw_mode hw_mode;
1837 struct hostapd_hw_modes *mode = NULL;
1838 u8 channel;
1839 int i;
1840
1841#ifdef CONFIG_HT_OVERRIDES
1842 if (ssid->disable_ht)
1843 return 0;
1844#endif /* CONFIG_HT_OVERRIDES */
1845
1846 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1847 if (hw_mode == NUM_HOSTAPD_MODES)
1848 return 0;
1849 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1850 if (wpa_s->hw.modes[i].mode == hw_mode) {
1851 mode = &wpa_s->hw.modes[i];
1852 break;
1853 }
1854 }
1855
1856 if (!mode)
1857 return 0;
1858
1859 return mode->vht_capab != 0;
1860}
1861
1862
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001863void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1864 const struct wpa_ssid *ssid,
1865 struct hostapd_freq_params *freq)
1866{
1867 enum hostapd_hw_mode hw_mode;
1868 struct hostapd_hw_modes *mode = NULL;
1869 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1870 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001871 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001872 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1873 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001874 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001875 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001876 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001877 int chwidth, seg0, seg1;
1878 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001879
1880 freq->freq = ssid->frequency;
1881
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001882 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1883 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1884
1885 if (ssid->mode != WPAS_MODE_IBSS)
1886 break;
1887
1888 /* Don't adjust control freq in case of fixed_freq */
1889 if (ssid->fixed_freq)
1890 break;
1891
1892 if (!bss_is_ibss(bss))
1893 continue;
1894
1895 if (ssid->ssid_len == bss->ssid_len &&
1896 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1897 wpa_printf(MSG_DEBUG,
1898 "IBSS already found in scan results, adjust control freq: %d",
1899 bss->freq);
1900 freq->freq = bss->freq;
1901 obss_scan = 0;
1902 break;
1903 }
1904 }
1905
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001906 /* For IBSS check HT_IBSS flag */
1907 if (ssid->mode == WPAS_MODE_IBSS &&
1908 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1909 return;
1910
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001911 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1912 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1913 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1914 wpa_printf(MSG_DEBUG,
1915 "IBSS: WEP/TKIP detected, do not try to enable HT");
1916 return;
1917 }
1918
1919 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001920 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1921 if (wpa_s->hw.modes[i].mode == hw_mode) {
1922 mode = &wpa_s->hw.modes[i];
1923 break;
1924 }
1925 }
1926
1927 if (!mode)
1928 return;
1929
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001930#ifdef CONFIG_HT_OVERRIDES
1931 if (ssid->disable_ht) {
1932 freq->ht_enabled = 0;
1933 return;
1934 }
1935#endif /* CONFIG_HT_OVERRIDES */
1936
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001937 freq->ht_enabled = ht_supported(mode);
1938 if (!freq->ht_enabled)
1939 return;
1940
1941 /* Setup higher BW only for 5 GHz */
1942 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1943 return;
1944
1945 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1946 pri_chan = &mode->channels[chan_idx];
1947 if (pri_chan->chan == channel)
1948 break;
1949 pri_chan = NULL;
1950 }
1951 if (!pri_chan)
1952 return;
1953
1954 /* Check primary channel flags */
1955 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1956 return;
1957
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001958#ifdef CONFIG_HT_OVERRIDES
1959 if (ssid->disable_ht40)
1960 return;
1961#endif /* CONFIG_HT_OVERRIDES */
1962
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001963 /* Check/setup HT40+/HT40- */
1964 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1965 if (ht40plus[j] == channel) {
1966 ht40 = 1;
1967 break;
1968 }
1969 }
1970
1971 /* Find secondary channel */
1972 for (i = 0; i < mode->num_channels; i++) {
1973 sec_chan = &mode->channels[i];
1974 if (sec_chan->chan == channel + ht40 * 4)
1975 break;
1976 sec_chan = NULL;
1977 }
1978 if (!sec_chan)
1979 return;
1980
1981 /* Check secondary channel flags */
1982 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1983 return;
1984
1985 freq->channel = pri_chan->chan;
1986
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001987 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001988 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1989 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001990 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001991 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1992 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001993 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001994 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001995
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001996 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001997 struct wpa_scan_results *scan_res;
1998
1999 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2000 if (scan_res == NULL) {
2001 /* Back to HT20 */
2002 freq->sec_channel_offset = 0;
2003 return;
2004 }
2005
2006 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2007 sec_chan->chan);
2008 switch (res) {
2009 case 0:
2010 /* Back to HT20 */
2011 freq->sec_channel_offset = 0;
2012 break;
2013 case 1:
2014 /* Configuration allowed */
2015 break;
2016 case 2:
2017 /* Switch pri/sec channels */
2018 freq->freq = hw_get_freq(mode, sec_chan->chan);
2019 freq->sec_channel_offset = -freq->sec_channel_offset;
2020 freq->channel = sec_chan->chan;
2021 break;
2022 default:
2023 freq->sec_channel_offset = 0;
2024 break;
2025 }
2026
2027 wpa_scan_results_free(scan_res);
2028 }
2029
2030 wpa_printf(MSG_DEBUG,
2031 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2032 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002033
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002034 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002035 return;
2036
2037 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002038 if (ssid->mode == WPAS_MODE_IBSS &&
2039 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002040 return;
2041
2042 vht_freq = *freq;
2043
2044 vht_freq.vht_enabled = vht_supported(mode);
2045 if (!vht_freq.vht_enabled)
2046 return;
2047
2048 /* setup center_freq1, bandwidth */
2049 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2050 if (freq->channel >= vht80[j] &&
2051 freq->channel < vht80[j] + 16)
2052 break;
2053 }
2054
2055 if (j == ARRAY_SIZE(vht80))
2056 return;
2057
2058 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2059 struct hostapd_channel_data *chan;
2060
2061 chan = hw_get_channel_chan(mode, i, NULL);
2062 if (!chan)
2063 return;
2064
2065 /* Back to HT configuration if channel not usable */
2066 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2067 return;
2068 }
2069
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002070 chwidth = VHT_CHANWIDTH_80MHZ;
2071 seg0 = vht80[j] + 6;
2072 seg1 = 0;
2073
2074 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2075 /* setup center_freq2, bandwidth */
2076 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2077 /* Only accept 80 MHz segments separated by a gap */
2078 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2079 continue;
2080 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2081 struct hostapd_channel_data *chan;
2082
2083 chan = hw_get_channel_chan(mode, i, NULL);
2084 if (!chan)
2085 continue;
2086
2087 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2088 HOSTAPD_CHAN_NO_IR |
2089 HOSTAPD_CHAN_RADAR))
2090 continue;
2091
2092 /* Found a suitable second segment for 80+80 */
2093 chwidth = VHT_CHANWIDTH_80P80MHZ;
2094 vht_caps |=
2095 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2096 seg1 = vht80[k] + 6;
2097 }
2098
2099 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2100 break;
2101 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002102 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2103 if (freq->freq == 5180) {
2104 chwidth = VHT_CHANWIDTH_160MHZ;
2105 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2106 seg0 = 50;
2107 } else if (freq->freq == 5520) {
2108 chwidth = VHT_CHANWIDTH_160MHZ;
2109 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2110 seg0 = 114;
2111 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002112 }
2113
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002114 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2115 freq->channel, freq->ht_enabled,
2116 vht_freq.vht_enabled,
2117 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002118 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002119 return;
2120
2121 *freq = vht_freq;
2122
2123 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2124 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002125}
2126
2127
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002128static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2129{
2130 struct wpa_connect_work *cwork = work->ctx;
2131 struct wpa_bss *bss = cwork->bss;
2132 struct wpa_ssid *ssid = cwork->ssid;
2133 struct wpa_supplicant *wpa_s = work->wpa_s;
2134 u8 wpa_ie[200];
2135 size_t wpa_ie_len;
2136 int use_crypt, ret, i, bssid_changed;
2137 int algs = WPA_AUTH_ALG_OPEN;
2138 unsigned int cipher_pairwise, cipher_group;
2139 struct wpa_driver_associate_params params;
2140 int wep_keys_set = 0;
2141 int assoc_failed = 0;
2142 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002143 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002144#ifdef CONFIG_HT_OVERRIDES
2145 struct ieee80211_ht_capabilities htcaps;
2146 struct ieee80211_ht_capabilities htcaps_mask;
2147#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002148#ifdef CONFIG_VHT_OVERRIDES
2149 struct ieee80211_vht_capabilities vhtcaps;
2150 struct ieee80211_vht_capabilities vhtcaps_mask;
2151#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002152
2153 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002154 if (work->started) {
2155 wpa_s->connect_work = NULL;
2156
2157 /* cancel possible auth. timeout */
2158 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2159 NULL);
2160 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002161 wpas_connect_work_free(cwork);
2162 return;
2163 }
2164
2165 wpa_s->connect_work = work;
2166
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002167 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2168 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002169 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2170 wpas_connect_work_done(wpa_s);
2171 return;
2172 }
2173
Dmitry Shmidte4663042016-04-04 10:07:49 -07002174 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002175 os_memset(&params, 0, sizeof(params));
2176 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002177 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002178 if (bss &&
2179 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002180#ifdef CONFIG_IEEE80211R
2181 const u8 *ie, *md = NULL;
2182#endif /* CONFIG_IEEE80211R */
2183 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2184 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2185 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2186 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2187 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2188 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2189 if (bssid_changed)
2190 wpas_notify_bssid_changed(wpa_s);
2191#ifdef CONFIG_IEEE80211R
2192 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2193 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2194 md = ie + 2;
2195 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2196 if (md) {
2197 /* Prepare for the next transition */
2198 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2199 }
2200#endif /* CONFIG_IEEE80211R */
2201#ifdef CONFIG_WPS
2202 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2203 wpa_s->conf->ap_scan == 2 &&
2204 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2205 /* Use ap_scan==1 style network selection to find the network
2206 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002207 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002208 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002209 wpa_s->reassociate = 1;
2210 wpa_supplicant_req_scan(wpa_s, 0, 0);
2211 return;
2212#endif /* CONFIG_WPS */
2213 } else {
2214 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2215 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002216 if (bss)
2217 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2218 else
2219 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002221 if (!wpa_s->pno)
2222 wpa_supplicant_cancel_sched_scan(wpa_s);
2223
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002224 wpa_supplicant_cancel_scan(wpa_s);
2225
2226 /* Starting new association, so clear the possibly used WPA IE from the
2227 * previous association. */
2228 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2229
2230#ifdef IEEE8021X_EAPOL
2231 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2232 if (ssid->leap) {
2233 if (ssid->non_leap == 0)
2234 algs = WPA_AUTH_ALG_LEAP;
2235 else
2236 algs |= WPA_AUTH_ALG_LEAP;
2237 }
2238 }
2239#endif /* IEEE8021X_EAPOL */
2240 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2241 if (ssid->auth_alg) {
2242 algs = ssid->auth_alg;
2243 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2244 "0x%x", algs);
2245 }
2246
2247 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2248 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002249 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002250 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002251 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2252 wpa_s->conf->okc :
2253 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002254 (ssid->proto & WPA_PROTO_RSN);
2255 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002256 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002257 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 wpa_ie_len = sizeof(wpa_ie);
2259 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2260 wpa_ie, &wpa_ie_len)) {
2261 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2262 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002263 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002264 return;
2265 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002266 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2267 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2268 /*
2269 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2270 * use non-WPA since the scan results did not indicate that the
2271 * AP is using WPA or WPA2.
2272 */
2273 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2274 wpa_ie_len = 0;
2275 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002276 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002277 wpa_ie_len = sizeof(wpa_ie);
2278 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2279 wpa_ie, &wpa_ie_len)) {
2280 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2281 "key management and encryption suites (no "
2282 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002283 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002284 return;
2285 }
2286#ifdef CONFIG_WPS
2287 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2288 struct wpabuf *wps_ie;
2289 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2290 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2291 wpa_ie_len = wpabuf_len(wps_ie);
2292 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2293 } else
2294 wpa_ie_len = 0;
2295 wpabuf_free(wps_ie);
2296 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2297 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2298 params.wps = WPS_MODE_PRIVACY;
2299 else
2300 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002301 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002302#endif /* CONFIG_WPS */
2303 } else {
2304 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2305 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002306 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002307 }
2308
2309#ifdef CONFIG_P2P
2310 if (wpa_s->global->p2p) {
2311 u8 *pos;
2312 size_t len;
2313 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314 pos = wpa_ie + wpa_ie_len;
2315 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002316 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2317 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002318 if (res >= 0)
2319 wpa_ie_len += res;
2320 }
2321
2322 wpa_s->cross_connect_disallowed = 0;
2323 if (bss) {
2324 struct wpabuf *p2p;
2325 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2326 if (p2p) {
2327 wpa_s->cross_connect_disallowed =
2328 p2p_get_cross_connect_disallowed(p2p);
2329 wpabuf_free(p2p);
2330 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2331 "connection",
2332 wpa_s->cross_connect_disallowed ?
2333 "disallows" : "allows");
2334 }
2335 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002336
2337 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002338#endif /* CONFIG_P2P */
2339
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002340 if (bss) {
Dmitry Shmidt29333592017-01-09 12:27:11 -08002341 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
2342 wpa_ie + wpa_ie_len,
2343 sizeof(wpa_ie) -
2344 wpa_ie_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002345 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002346
Dmitry Shmidt56052862013-10-04 10:23:25 -07002347 /*
2348 * Workaround: Add Extended Capabilities element only if the AP
2349 * included this element in Beacon/Probe Response frames. Some older
2350 * APs seem to have interoperability issues if this element is
2351 * included, so while the standard may require us to include the
2352 * element in all cases, it is justifiable to skip it to avoid
2353 * interoperability issues.
2354 */
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002355 if (ssid->p2p_group)
2356 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2357 else
2358 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2359
Dmitry Shmidt56052862013-10-04 10:23:25 -07002360 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002361 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002362 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002363 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2364 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002365 if (ext_capab_len > 0) {
2366 u8 *pos = wpa_ie;
2367 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2368 pos += 2 + pos[1];
2369 os_memmove(pos + ext_capab_len, pos,
2370 wpa_ie_len - (pos - wpa_ie));
2371 wpa_ie_len += ext_capab_len;
2372 os_memcpy(pos, ext_capab, ext_capab_len);
2373 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002374 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002375
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002376#ifdef CONFIG_HS20
2377 if (is_hs20_network(wpa_s, ssid, bss)) {
2378 struct wpabuf *hs20;
2379
2380 hs20 = wpabuf_alloc(20);
2381 if (hs20) {
2382 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2383 size_t len;
2384
2385 wpas_hs20_add_indication(hs20, pps_mo_id);
2386 len = sizeof(wpa_ie) - wpa_ie_len;
2387 if (wpabuf_len(hs20) <= len) {
2388 os_memcpy(wpa_ie + wpa_ie_len,
2389 wpabuf_head(hs20), wpabuf_len(hs20));
2390 wpa_ie_len += wpabuf_len(hs20);
2391 }
2392 wpabuf_free(hs20);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002393
2394 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002395 }
2396 }
2397#endif /* CONFIG_HS20 */
2398
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002399 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2400 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2401 size_t len;
2402
2403 len = sizeof(wpa_ie) - wpa_ie_len;
2404 if (wpabuf_len(buf) <= len) {
2405 os_memcpy(wpa_ie + wpa_ie_len,
2406 wpabuf_head(buf), wpabuf_len(buf));
2407 wpa_ie_len += wpabuf_len(buf);
2408 }
2409 }
2410
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002411#ifdef CONFIG_FST
2412 if (wpa_s->fst_ies) {
2413 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2414
2415 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2416 os_memcpy(wpa_ie + wpa_ie_len,
2417 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2418 wpa_ie_len += fst_ies_len;
2419 }
2420 }
2421#endif /* CONFIG_FST */
2422
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002423#ifdef CONFIG_MBO
Dmitry Shmidt29333592017-01-09 12:27:11 -08002424 if (bss && wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002425 int len;
2426
2427 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2428 sizeof(wpa_ie) - wpa_ie_len);
2429 if (len >= 0)
2430 wpa_ie_len += len;
2431 }
2432#endif /* CONFIG_MBO */
2433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002434 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2435 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002436 cipher_pairwise = wpa_s->pairwise_cipher;
2437 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2439 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2440 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2441 use_crypt = 0;
2442 if (wpa_set_wep_keys(wpa_s, ssid)) {
2443 use_crypt = 1;
2444 wep_keys_set = 1;
2445 }
2446 }
2447 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2448 use_crypt = 0;
2449
2450#ifdef IEEE8021X_EAPOL
2451 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2452 if ((ssid->eapol_flags &
2453 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2454 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2455 !wep_keys_set) {
2456 use_crypt = 0;
2457 } else {
2458 /* Assume that dynamic WEP-104 keys will be used and
2459 * set cipher suites in order for drivers to expect
2460 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002461 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002462 }
2463 }
2464#endif /* IEEE8021X_EAPOL */
2465
2466 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2467 /* Set the key before (and later after) association */
2468 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2469 }
2470
2471 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2472 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002473 params.ssid = bss->ssid;
2474 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002475 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2476 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002477 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2478 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002479 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002480 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002481 ssid->bssid_set,
2482 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002483 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002484 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002485 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002486 params.bssid_hint = bss->bssid;
2487 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002488 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 } else {
2490 params.ssid = ssid->ssid;
2491 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002492 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002494
2495 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2496 wpa_s->conf->ap_scan == 2) {
2497 params.bssid = ssid->bssid;
2498 params.fixed_bssid = 1;
2499 }
2500
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002501 /* Initial frequency for IBSS/mesh */
2502 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002503 ssid->frequency > 0 && params.freq.freq == 0)
2504 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002505
2506 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002507 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002508 if (ssid->beacon_int)
2509 params.beacon_int = ssid->beacon_int;
2510 else
2511 params.beacon_int = wpa_s->conf->beacon_int;
2512 }
2513
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 params.wpa_ie = wpa_ie;
2515 params.wpa_ie_len = wpa_ie_len;
2516 params.pairwise_suite = cipher_pairwise;
2517 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002518 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002519 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 params.auth_alg = algs;
2521 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002522 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 for (i = 0; i < NUM_WEP_KEYS; i++) {
2524 if (ssid->wep_key_len[i])
2525 params.wep_key[i] = ssid->wep_key[i];
2526 params.wep_key_len[i] = ssid->wep_key_len[i];
2527 }
2528 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2529
2530 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002531 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2532 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533 params.passphrase = ssid->passphrase;
2534 if (ssid->psk_set)
2535 params.psk = ssid->psk;
2536 }
2537
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002538 if (wpa_s->conf->key_mgmt_offload) {
2539 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2540 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002541 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2542 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002543 params.req_key_mgmt_offload =
2544 ssid->proactive_key_caching < 0 ?
2545 wpa_s->conf->okc : ssid->proactive_key_caching;
2546 else
2547 params.req_key_mgmt_offload = 1;
2548
2549 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2550 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2551 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2552 ssid->psk_set)
2553 params.psk = ssid->psk;
2554 }
2555
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002556 params.drop_unencrypted = use_crypt;
2557
2558#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002559 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002560 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2562 struct wpa_ie_data ie;
2563 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2564 ie.capabilities &
2565 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2566 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2567 "MFP: require MFP");
2568 params.mgmt_frame_protection =
2569 MGMT_FRAME_PROTECTION_REQUIRED;
2570 }
2571 }
2572#endif /* CONFIG_IEEE80211W */
2573
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002574 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002575
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002576 if (wpa_s->p2pdev->set_sta_uapsd)
2577 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578 else
2579 params.uapsd = -1;
2580
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002581#ifdef CONFIG_HT_OVERRIDES
2582 os_memset(&htcaps, 0, sizeof(htcaps));
2583 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2584 params.htcaps = (u8 *) &htcaps;
2585 params.htcaps_mask = (u8 *) &htcaps_mask;
2586 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2587#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002588#ifdef CONFIG_VHT_OVERRIDES
2589 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2590 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2591 params.vhtcaps = &vhtcaps;
2592 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002593 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002594#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002595
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002596#ifdef CONFIG_P2P
2597 /*
2598 * If multi-channel concurrency is not supported, check for any
2599 * frequency conflict. In case of any frequency conflict, remove the
2600 * least prioritized connection.
2601 */
2602 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002603 int freq, num;
2604 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002605 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002606 wpa_printf(MSG_DEBUG,
2607 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002608 freq, params.freq.freq);
2609 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002610 wpa_s, params.freq.freq, ssid) < 0) {
2611 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002612 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002613 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002614 }
2615 }
2616#endif /* CONFIG_P2P */
2617
Dmitry Shmidte4663042016-04-04 10:07:49 -07002618 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2619 wpa_s->current_ssid)
2620 params.prev_bssid = prev_bssid;
2621
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002622 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002623 if (ret < 0) {
2624 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2625 "failed");
2626 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2627 /*
2628 * The driver is known to mean what is saying, so we
2629 * can stop right here; the association will not
2630 * succeed.
2631 */
2632 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002633 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002634 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2635 return;
2636 }
2637 /* try to continue anyway; new association will be tried again
2638 * after timeout */
2639 assoc_failed = 1;
2640 }
2641
2642 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2643 /* Set the key after the association just in case association
2644 * cleared the previously configured key. */
2645 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2646 /* No need to timeout authentication since there is no key
2647 * management. */
2648 wpa_supplicant_cancel_auth_timeout(wpa_s);
2649 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2650#ifdef CONFIG_IBSS_RSN
2651 } else if (ssid->mode == WPAS_MODE_IBSS &&
2652 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2653 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2654 /*
2655 * RSN IBSS authentication is per-STA and we can disable the
2656 * per-BSSID authentication.
2657 */
2658 wpa_supplicant_cancel_auth_timeout(wpa_s);
2659#endif /* CONFIG_IBSS_RSN */
2660 } else {
2661 /* Timeout for IEEE 802.11 authentication and association */
2662 int timeout = 60;
2663
2664 if (assoc_failed) {
2665 /* give IBSS a bit more time */
2666 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2667 } else if (wpa_s->conf->ap_scan == 1) {
2668 /* give IBSS a bit more time */
2669 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2670 }
2671 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2672 }
2673
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002674 if (wep_keys_set &&
2675 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002676 /* Set static WEP keys again */
2677 wpa_set_wep_keys(wpa_s, ssid);
2678 }
2679
2680 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2681 /*
2682 * Do not allow EAP session resumption between different
2683 * network configurations.
2684 */
2685 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2686 }
2687 old_ssid = wpa_s->current_ssid;
2688 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002689
2690 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002691 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002692#ifdef CONFIG_HS20
2693 hs20_configure_frame_filters(wpa_s);
2694#endif /* CONFIG_HS20 */
2695 }
2696
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002697 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2698 wpa_supplicant_initiate_eapol(wpa_s);
2699 if (old_ssid != wpa_s->current_ssid)
2700 wpas_notify_network_changed(wpa_s);
2701}
2702
2703
2704static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2705 const u8 *addr)
2706{
2707 struct wpa_ssid *old_ssid;
2708
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002709 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002710 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002712 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 wpa_sm_set_config(wpa_s->wpa, NULL);
2714 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2715 if (old_ssid != wpa_s->current_ssid)
2716 wpas_notify_network_changed(wpa_s);
2717 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2718}
2719
2720
2721/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2723 * @wpa_s: Pointer to wpa_supplicant data
2724 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2725 *
2726 * This function is used to request %wpa_supplicant to deauthenticate from the
2727 * current AP.
2728 */
2729void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2730 int reason_code)
2731{
2732 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002733 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002734 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002736 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2737 " pending_bssid=" MACSTR " reason=%d state=%s",
2738 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2739 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2740
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002741 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2742 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2743 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002744 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002745 else if (!is_zero_ether_addr(wpa_s->bssid))
2746 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002747 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2748 /*
2749 * When using driver-based BSS selection, we may not know the
2750 * BSSID with which we are currently trying to associate. We
2751 * need to notify the driver of this disconnection even in such
2752 * a case, so use the all zeros address here.
2753 */
2754 addr = wpa_s->bssid;
2755 zero_addr = 1;
2756 }
2757
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002758#ifdef CONFIG_TDLS
2759 wpa_tdls_teardown_peers(wpa_s->wpa);
2760#endif /* CONFIG_TDLS */
2761
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002762#ifdef CONFIG_MESH
2763 if (wpa_s->ifmsh) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002764 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2765 wpa_s->ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002766 wpa_supplicant_leave_mesh(wpa_s);
2767 }
2768#endif /* CONFIG_MESH */
2769
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002770 if (addr) {
2771 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002772 os_memset(&event, 0, sizeof(event));
2773 event.deauth_info.reason_code = (u16) reason_code;
2774 event.deauth_info.locally_generated = 1;
2775 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002776 if (zero_addr)
2777 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 }
2779
2780 wpa_supplicant_clear_connection(wpa_s, addr);
2781}
2782
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002783static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2784 struct wpa_ssid *ssid)
2785{
2786 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2787 return;
2788
2789 ssid->disabled = 0;
2790 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2791 wpas_notify_network_enabled_changed(wpa_s, ssid);
2792
2793 /*
2794 * Try to reassociate since there is no current configuration and a new
2795 * network was made available.
2796 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002797 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002798 wpa_s->reassociate = 1;
2799}
2800
Roshan Pius950bec92016-07-19 09:49:24 -07002801/**
2802 * wpa_supplicant_add_network - Add a new network.
2803 * @wpa_s: wpa_supplicant structure for a network interface
2804 * Returns: The new network configuration or %NULL if operation failed
2805 *
2806 * This function performs the following operations:
2807 * 1. Adds a new network.
2808 * 2. Send network addition notification.
2809 * 3. Marks the network disabled.
2810 * 4. Set network default parameters.
2811 */
2812struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2813{
2814 struct wpa_ssid *ssid;
2815
2816 ssid = wpa_config_add_network(wpa_s->conf);
2817 if (!ssid) {
2818 return NULL;
2819 }
2820 wpas_notify_network_added(wpa_s, ssid);
2821 ssid->disabled = 1;
2822 wpa_config_set_network_defaults(ssid);
2823
2824 return ssid;
2825}
2826
2827/**
2828 * wpa_supplicant_remove_network - Remove a configured network based on id
2829 * @wpa_s: wpa_supplicant structure for a network interface
2830 * @id: Unique network id to search for
2831 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2832 * could not be removed
2833 *
2834 * This function performs the following operations:
2835 * 1. Removes the network.
2836 * 2. Send network removal notification.
2837 * 3. Update internal state machines.
2838 * 4. Stop any running sched scans.
2839 */
2840int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2841{
2842 struct wpa_ssid *ssid;
2843 int was_disabled;
2844
2845 ssid = wpa_config_get_network(wpa_s->conf, id);
2846 if (ssid)
2847 wpas_notify_network_removed(wpa_s, ssid);
2848 if (ssid == NULL) {
2849 return -1;
2850 }
2851
2852 if (wpa_s->last_ssid == ssid)
2853 wpa_s->last_ssid = NULL;
2854
2855 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2856#ifdef CONFIG_SME
2857 wpa_s->sme.prev_bssid_set = 0;
2858#endif /* CONFIG_SME */
2859 /*
2860 * Invalidate the EAP session cache if the current or
2861 * previously used network is removed.
2862 */
2863 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2864 }
2865
2866 if (ssid == wpa_s->current_ssid) {
2867 wpa_sm_set_config(wpa_s->wpa, NULL);
2868 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2869
2870 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2871 wpa_s->own_disconnect_req = 1;
2872 wpa_supplicant_deauthenticate(wpa_s,
2873 WLAN_REASON_DEAUTH_LEAVING);
2874 }
2875
2876 was_disabled = ssid->disabled;
2877
2878 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2879 return -2;
2880 }
2881
2882 if (!was_disabled && wpa_s->sched_scanning) {
2883 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2884 "network from filters");
2885 wpa_supplicant_cancel_sched_scan(wpa_s);
2886 wpa_supplicant_req_scan(wpa_s, 0, 0);
2887 }
2888 return 0;
2889}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002890
2891/**
2892 * wpa_supplicant_enable_network - Mark a configured network as enabled
2893 * @wpa_s: wpa_supplicant structure for a network interface
2894 * @ssid: wpa_ssid structure for a configured network or %NULL
2895 *
2896 * Enables the specified network or all networks if no network specified.
2897 */
2898void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2899 struct wpa_ssid *ssid)
2900{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002901 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002902 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2903 wpa_supplicant_enable_one_network(wpa_s, ssid);
2904 } else
2905 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002906
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002907 if (wpa_s->reassociate && !wpa_s->disconnected &&
2908 (!wpa_s->current_ssid ||
2909 wpa_s->wpa_state == WPA_DISCONNECTED ||
2910 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002911 if (wpa_s->sched_scanning) {
2912 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2913 "new network to scan filters");
2914 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002915 }
2916
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002917 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2918 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002919 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002920 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921 }
2922}
2923
2924
2925/**
2926 * wpa_supplicant_disable_network - Mark a configured network as disabled
2927 * @wpa_s: wpa_supplicant structure for a network interface
2928 * @ssid: wpa_ssid structure for a configured network or %NULL
2929 *
2930 * Disables the specified network or all networks if no network specified.
2931 */
2932void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2933 struct wpa_ssid *ssid)
2934{
2935 struct wpa_ssid *other_ssid;
2936 int was_disabled;
2937
2938 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002939 if (wpa_s->sched_scanning)
2940 wpa_supplicant_cancel_sched_scan(wpa_s);
2941
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002942 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2943 other_ssid = other_ssid->next) {
2944 was_disabled = other_ssid->disabled;
2945 if (was_disabled == 2)
2946 continue; /* do not change persistent P2P group
2947 * data */
2948
2949 other_ssid->disabled = 1;
2950
2951 if (was_disabled != other_ssid->disabled)
2952 wpas_notify_network_enabled_changed(
2953 wpa_s, other_ssid);
2954 }
2955 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002956 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002957 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2958 } else if (ssid->disabled != 2) {
2959 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002960 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002961 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2962
2963 was_disabled = ssid->disabled;
2964
2965 ssid->disabled = 1;
2966
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002967 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002968 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002969 if (wpa_s->sched_scanning) {
2970 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2971 "to remove network from filters");
2972 wpa_supplicant_cancel_sched_scan(wpa_s);
2973 wpa_supplicant_req_scan(wpa_s, 0, 0);
2974 }
2975 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002976 }
2977}
2978
2979
2980/**
2981 * wpa_supplicant_select_network - Attempt association with a network
2982 * @wpa_s: wpa_supplicant structure for a network interface
2983 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2984 */
2985void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2986 struct wpa_ssid *ssid)
2987{
2988
2989 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002990 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002991
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002992 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002993 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2994 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002995 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002996 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002997 disconnected = 1;
2998 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002999
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003000 if (ssid)
3001 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3002
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003003 /*
3004 * Mark all other networks disabled or mark all networks enabled if no
3005 * network specified.
3006 */
3007 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3008 other_ssid = other_ssid->next) {
3009 int was_disabled = other_ssid->disabled;
3010 if (was_disabled == 2)
3011 continue; /* do not change persistent P2P group data */
3012
3013 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003014 if (was_disabled && !other_ssid->disabled)
3015 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003016
3017 if (was_disabled != other_ssid->disabled)
3018 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3019 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003020
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003021 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3022 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003023 /* We are already associated with the selected network */
3024 wpa_printf(MSG_DEBUG, "Already associated with the "
3025 "selected network - do nothing");
3026 return;
3027 }
3028
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003029 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003030 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003031 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003032 wpa_s->connect_without_scan =
3033 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003034
3035 /*
3036 * Don't optimize next scan freqs since a new ESS has been
3037 * selected.
3038 */
3039 os_free(wpa_s->next_scan_freqs);
3040 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003041 } else {
3042 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003043 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003044
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003045 wpa_s->disconnected = 0;
3046 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003047
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003048 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003049 wpa_supplicant_fast_associate(wpa_s) != 1) {
3050 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003051 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003052 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003053 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003054
3055 if (ssid)
3056 wpas_notify_network_selected(wpa_s, ssid);
3057}
3058
3059
3060/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003061 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3062 * @wpa_s: wpa_supplicant structure for a network interface
3063 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3064 * @pkcs11_module_path: PKCS #11 module path or NULL
3065 * Returns: 0 on success; -1 on failure
3066 *
3067 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3068 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3069 * module path fails the paths will be reset to the default value (NULL).
3070 */
3071int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3072 const char *pkcs11_engine_path,
3073 const char *pkcs11_module_path)
3074{
3075 char *pkcs11_engine_path_copy = NULL;
3076 char *pkcs11_module_path_copy = NULL;
3077
3078 if (pkcs11_engine_path != NULL) {
3079 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3080 if (pkcs11_engine_path_copy == NULL)
3081 return -1;
3082 }
3083 if (pkcs11_module_path != NULL) {
3084 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003085 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003086 os_free(pkcs11_engine_path_copy);
3087 return -1;
3088 }
3089 }
3090
3091 os_free(wpa_s->conf->pkcs11_engine_path);
3092 os_free(wpa_s->conf->pkcs11_module_path);
3093 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3094 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3095
3096 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3097 eapol_sm_deinit(wpa_s->eapol);
3098 wpa_s->eapol = NULL;
3099 if (wpa_supplicant_init_eapol(wpa_s)) {
3100 /* Error -> Reset paths to the default value (NULL) once. */
3101 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3102 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3103 NULL);
3104
3105 return -1;
3106 }
3107 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3108
3109 return 0;
3110}
3111
3112
3113/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003114 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3115 * @wpa_s: wpa_supplicant structure for a network interface
3116 * @ap_scan: AP scan mode
3117 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3118 *
3119 */
3120int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3121{
3122
3123 int old_ap_scan;
3124
3125 if (ap_scan < 0 || ap_scan > 2)
3126 return -1;
3127
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003128 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3129 wpa_printf(MSG_INFO,
3130 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3131 }
3132
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003133#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003134 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3135 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3136 wpa_s->wpa_state < WPA_COMPLETED) {
3137 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3138 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003139 return 0;
3140 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003141#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003142
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003143 old_ap_scan = wpa_s->conf->ap_scan;
3144 wpa_s->conf->ap_scan = ap_scan;
3145
3146 if (old_ap_scan != wpa_s->conf->ap_scan)
3147 wpas_notify_ap_scan_changed(wpa_s);
3148
3149 return 0;
3150}
3151
3152
3153/**
3154 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3155 * @wpa_s: wpa_supplicant structure for a network interface
3156 * @expire_age: Expiration age in seconds
3157 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3158 *
3159 */
3160int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3161 unsigned int bss_expire_age)
3162{
3163 if (bss_expire_age < 10) {
3164 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3165 bss_expire_age);
3166 return -1;
3167 }
3168 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3169 bss_expire_age);
3170 wpa_s->conf->bss_expiration_age = bss_expire_age;
3171
3172 return 0;
3173}
3174
3175
3176/**
3177 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3178 * @wpa_s: wpa_supplicant structure for a network interface
3179 * @expire_count: number of scans after which an unseen BSS is reclaimed
3180 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3181 *
3182 */
3183int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3184 unsigned int bss_expire_count)
3185{
3186 if (bss_expire_count < 1) {
3187 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3188 bss_expire_count);
3189 return -1;
3190 }
3191 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3192 bss_expire_count);
3193 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3194
3195 return 0;
3196}
3197
3198
3199/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003200 * wpa_supplicant_set_scan_interval - Set scan interval
3201 * @wpa_s: wpa_supplicant structure for a network interface
3202 * @scan_interval: scan interval in seconds
3203 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3204 *
3205 */
3206int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3207 int scan_interval)
3208{
3209 if (scan_interval < 0) {
3210 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3211 scan_interval);
3212 return -1;
3213 }
3214 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3215 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003216 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003217
3218 return 0;
3219}
3220
3221
3222/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003223 * wpa_supplicant_set_debug_params - Set global debug params
3224 * @global: wpa_global structure
3225 * @debug_level: debug level
3226 * @debug_timestamp: determines if show timestamp in debug data
3227 * @debug_show_keys: determines if show keys in debug data
3228 * Returns: 0 if succeed or -1 if debug_level has wrong value
3229 */
3230int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3231 int debug_timestamp, int debug_show_keys)
3232{
3233
3234 int old_level, old_timestamp, old_show_keys;
3235
3236 /* check for allowed debuglevels */
3237 if (debug_level != MSG_EXCESSIVE &&
3238 debug_level != MSG_MSGDUMP &&
3239 debug_level != MSG_DEBUG &&
3240 debug_level != MSG_INFO &&
3241 debug_level != MSG_WARNING &&
3242 debug_level != MSG_ERROR)
3243 return -1;
3244
3245 old_level = wpa_debug_level;
3246 old_timestamp = wpa_debug_timestamp;
3247 old_show_keys = wpa_debug_show_keys;
3248
3249 wpa_debug_level = debug_level;
3250 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3251 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3252
3253 if (wpa_debug_level != old_level)
3254 wpas_notify_debug_level_changed(global);
3255 if (wpa_debug_timestamp != old_timestamp)
3256 wpas_notify_debug_timestamp_changed(global);
3257 if (wpa_debug_show_keys != old_show_keys)
3258 wpas_notify_debug_show_keys_changed(global);
3259
3260 return 0;
3261}
3262
3263
3264/**
3265 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3266 * @wpa_s: Pointer to wpa_supplicant data
3267 * Returns: A pointer to the current network structure or %NULL on failure
3268 */
3269struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3270{
3271 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003272 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003273 int res;
3274 size_t ssid_len;
3275 u8 bssid[ETH_ALEN];
3276 int wired;
3277
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003278 res = wpa_drv_get_ssid(wpa_s, ssid);
3279 if (res < 0) {
3280 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3281 "driver");
3282 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003283 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003284 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003285
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003286 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003287 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3288 "driver");
3289 return NULL;
3290 }
3291
3292 wired = wpa_s->conf->ap_scan == 0 &&
3293 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3294
3295 entry = wpa_s->conf->ssid;
3296 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003297 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003298 ((ssid_len == entry->ssid_len &&
3299 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3300 (!entry->bssid_set ||
3301 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3302 return entry;
3303#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003304 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003305 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3306 (entry->ssid == NULL || entry->ssid_len == 0) &&
3307 (!entry->bssid_set ||
3308 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3309 return entry;
3310#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003311
Dmitry Shmidt04949592012-07-19 12:16:46 -07003312 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003313 entry->ssid_len == 0 &&
3314 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3315 return entry;
3316
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003317 entry = entry->next;
3318 }
3319
3320 return NULL;
3321}
3322
3323
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003324static int select_driver(struct wpa_supplicant *wpa_s, int i)
3325{
3326 struct wpa_global *global = wpa_s->global;
3327
3328 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003329 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003330 if (global->drv_priv[i] == NULL) {
3331 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3332 "'%s'", wpa_drivers[i]->name);
3333 return -1;
3334 }
3335 }
3336
3337 wpa_s->driver = wpa_drivers[i];
3338 wpa_s->global_drv_priv = global->drv_priv[i];
3339
3340 return 0;
3341}
3342
3343
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003344static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3345 const char *name)
3346{
3347 int i;
3348 size_t len;
3349 const char *pos, *driver = name;
3350
3351 if (wpa_s == NULL)
3352 return -1;
3353
3354 if (wpa_drivers[0] == NULL) {
3355 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3356 "wpa_supplicant");
3357 return -1;
3358 }
3359
3360 if (name == NULL) {
3361 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003362 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003363 }
3364
3365 do {
3366 pos = os_strchr(driver, ',');
3367 if (pos)
3368 len = pos - driver;
3369 else
3370 len = os_strlen(driver);
3371
3372 for (i = 0; wpa_drivers[i]; i++) {
3373 if (os_strlen(wpa_drivers[i]->name) == len &&
3374 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003375 0) {
3376 /* First driver that succeeds wins */
3377 if (select_driver(wpa_s, i) == 0)
3378 return 0;
3379 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003380 }
3381
3382 driver = pos + 1;
3383 } while (pos);
3384
3385 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3386 return -1;
3387}
3388
3389
3390/**
3391 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3392 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3393 * with struct wpa_driver_ops::init()
3394 * @src_addr: Source address of the EAPOL frame
3395 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3396 * @len: Length of the EAPOL data
3397 *
3398 * This function is called for each received EAPOL frame. Most driver
3399 * interfaces rely on more generic OS mechanism for receiving frames through
3400 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3401 * take care of received EAPOL frames and deliver them to the core supplicant
3402 * code by calling this function.
3403 */
3404void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3405 const u8 *buf, size_t len)
3406{
3407 struct wpa_supplicant *wpa_s = ctx;
3408
3409 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3410 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3411
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003412#ifdef CONFIG_TESTING_OPTIONS
3413 if (wpa_s->ignore_auth_resp) {
3414 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3415 return;
3416 }
3417#endif /* CONFIG_TESTING_OPTIONS */
3418
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003419#ifdef CONFIG_PEERKEY
3420 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3421 wpa_s->current_ssid->peerkey &&
3422 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3423 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3424 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3425 return;
3426 }
3427#endif /* CONFIG_PEERKEY */
3428
Jouni Malinena05074c2012-12-21 21:35:35 +02003429 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3430 (wpa_s->last_eapol_matches_bssid &&
3431#ifdef CONFIG_AP
3432 !wpa_s->ap_iface &&
3433#endif /* CONFIG_AP */
3434 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003435 /*
3436 * There is possible race condition between receiving the
3437 * association event and the EAPOL frame since they are coming
3438 * through different paths from the driver. In order to avoid
3439 * issues in trying to process the EAPOL frame before receiving
3440 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003441 * the association event is received. This may also be needed in
3442 * driver-based roaming case, so also use src_addr != BSSID as a
3443 * trigger if we have previously confirmed that the
3444 * Authenticator uses BSSID as the src_addr (which is not the
3445 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003446 */
3447 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003448 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3449 wpa_supplicant_state_txt(wpa_s->wpa_state),
3450 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003451 wpabuf_free(wpa_s->pending_eapol_rx);
3452 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3453 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003454 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003455 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3456 ETH_ALEN);
3457 }
3458 return;
3459 }
3460
Jouni Malinena05074c2012-12-21 21:35:35 +02003461 wpa_s->last_eapol_matches_bssid =
3462 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3463
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003464#ifdef CONFIG_AP
3465 if (wpa_s->ap_iface) {
3466 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3467 return;
3468 }
3469#endif /* CONFIG_AP */
3470
3471 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3472 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3473 "no key management is configured");
3474 return;
3475 }
3476
3477 if (wpa_s->eapol_received == 0 &&
3478 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3479 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3480 wpa_s->wpa_state != WPA_COMPLETED) &&
3481 (wpa_s->current_ssid == NULL ||
3482 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3483 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003484 int timeout = 10;
3485
3486 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3487 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3488 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3489 /* Use longer timeout for IEEE 802.1X/EAP */
3490 timeout = 70;
3491 }
3492
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003493#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003494 if (wpa_s->current_ssid && wpa_s->current_bss &&
3495 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3496 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3497 /*
3498 * Use shorter timeout if going through WPS AP iteration
3499 * for PIN config method with an AP that does not
3500 * advertise Selected Registrar.
3501 */
3502 struct wpabuf *wps_ie;
3503
3504 wps_ie = wpa_bss_get_vendor_ie_multi(
3505 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3506 if (wps_ie &&
3507 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3508 timeout = 10;
3509 wpabuf_free(wps_ie);
3510 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003511#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003512
3513 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003514 }
3515 wpa_s->eapol_received++;
3516
3517 if (wpa_s->countermeasures) {
3518 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3519 "EAPOL packet");
3520 return;
3521 }
3522
3523#ifdef CONFIG_IBSS_RSN
3524 if (wpa_s->current_ssid &&
3525 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3526 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3527 return;
3528 }
3529#endif /* CONFIG_IBSS_RSN */
3530
3531 /* Source address of the incoming EAPOL frame could be compared to the
3532 * current BSSID. However, it is possible that a centralized
3533 * Authenticator could be using another MAC address than the BSSID of
3534 * an AP, so just allow any address to be used for now. The replies are
3535 * still sent to the current BSSID (if available), though. */
3536
3537 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3538 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3539 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3540 return;
3541 wpa_drv_poll(wpa_s);
3542 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3543 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3544 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3545 /*
3546 * Set portValid = TRUE here since we are going to skip 4-way
3547 * handshake processing which would normally set portValid. We
3548 * need this to allow the EAPOL state machines to be completed
3549 * without going through EAPOL-Key handshake.
3550 */
3551 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3552 }
3553}
3554
3555
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003556int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003557{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003558 if ((!wpa_s->p2p_mgmt ||
3559 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3560 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003561 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003562 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3563 wpa_drv_get_mac_addr(wpa_s),
3564 ETH_P_EAPOL,
3565 wpa_supplicant_rx_eapol, wpa_s, 0);
3566 if (wpa_s->l2 == NULL)
3567 return -1;
3568 } else {
3569 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3570 if (addr)
3571 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3572 }
3573
3574 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3575 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3576 return -1;
3577 }
3578
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003579 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3580
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003581 return 0;
3582}
3583
3584
Dmitry Shmidt04949592012-07-19 12:16:46 -07003585static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3586 const u8 *buf, size_t len)
3587{
3588 struct wpa_supplicant *wpa_s = ctx;
3589 const struct l2_ethhdr *eth;
3590
3591 if (len < sizeof(*eth))
3592 return;
3593 eth = (const struct l2_ethhdr *) buf;
3594
3595 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3596 !(eth->h_dest[0] & 0x01)) {
3597 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3598 " (bridge - not for this interface - ignore)",
3599 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3600 return;
3601 }
3602
3603 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3604 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3605 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3606 len - sizeof(*eth));
3607}
3608
3609
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003610/**
3611 * wpa_supplicant_driver_init - Initialize driver interface parameters
3612 * @wpa_s: Pointer to wpa_supplicant data
3613 * Returns: 0 on success, -1 on failure
3614 *
3615 * This function is called to initialize driver interface parameters.
3616 * wpa_drv_init() must have been called before this function to initialize the
3617 * driver interface.
3618 */
3619int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3620{
3621 static int interface_count = 0;
3622
3623 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3624 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003625
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003626 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3627 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003628 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003629 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3630
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003631 if (wpa_s->bridge_ifname[0]) {
3632 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3633 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003634 wpa_s->l2_br = l2_packet_init_bridge(
3635 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3636 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003637 if (wpa_s->l2_br == NULL) {
3638 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3639 "connection for the bridge interface '%s'",
3640 wpa_s->bridge_ifname);
3641 return -1;
3642 }
3643 }
3644
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003645 if (wpa_s->conf->ap_scan == 2 &&
3646 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3647 wpa_printf(MSG_INFO,
3648 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3649 }
3650
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003651 wpa_clear_keys(wpa_s, NULL);
3652
3653 /* Make sure that TKIP countermeasures are not left enabled (could
3654 * happen if wpa_supplicant is killed during countermeasures. */
3655 wpa_drv_set_countermeasures(wpa_s, 0);
3656
3657 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3658 wpa_drv_flush_pmkid(wpa_s);
3659
3660 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003661 wpa_s->prev_scan_wildcard = 0;
3662
Dmitry Shmidt04949592012-07-19 12:16:46 -07003663 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003664 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3665 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3666 interface_count = 0;
3667 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003668#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003669 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003670 wpa_supplicant_delayed_sched_scan(wpa_s,
3671 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003672 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003673 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003674 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003675#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003676 interface_count++;
3677 } else
3678 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3679
3680 return 0;
3681}
3682
3683
3684static int wpa_supplicant_daemon(const char *pid_file)
3685{
3686 wpa_printf(MSG_DEBUG, "Daemonize..");
3687 return os_daemonize(pid_file);
3688}
3689
3690
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003691static struct wpa_supplicant *
3692wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003693{
3694 struct wpa_supplicant *wpa_s;
3695
3696 wpa_s = os_zalloc(sizeof(*wpa_s));
3697 if (wpa_s == NULL)
3698 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003699 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003700 wpa_s->scan_interval = 5;
3701 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003702 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003703 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003704 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003705
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003706 dl_list_init(&wpa_s->bss_tmp_disallowed);
3707
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708 return wpa_s;
3709}
3710
3711
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003712#ifdef CONFIG_HT_OVERRIDES
3713
3714static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3715 struct ieee80211_ht_capabilities *htcaps,
3716 struct ieee80211_ht_capabilities *htcaps_mask,
3717 const char *ht_mcs)
3718{
3719 /* parse ht_mcs into hex array */
3720 int i;
3721 const char *tmp = ht_mcs;
3722 char *end = NULL;
3723
3724 /* If ht_mcs is null, do not set anything */
3725 if (!ht_mcs)
3726 return 0;
3727
3728 /* This is what we are setting in the kernel */
3729 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3730
3731 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3732
3733 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3734 errno = 0;
3735 long v = strtol(tmp, &end, 16);
3736 if (errno == 0) {
3737 wpa_msg(wpa_s, MSG_DEBUG,
3738 "htcap value[%i]: %ld end: %p tmp: %p",
3739 i, v, end, tmp);
3740 if (end == tmp)
3741 break;
3742
3743 htcaps->supported_mcs_set[i] = v;
3744 tmp = end;
3745 } else {
3746 wpa_msg(wpa_s, MSG_ERROR,
3747 "Failed to parse ht-mcs: %s, error: %s\n",
3748 ht_mcs, strerror(errno));
3749 return -1;
3750 }
3751 }
3752
3753 /*
3754 * If we were able to parse any values, then set mask for the MCS set.
3755 */
3756 if (i) {
3757 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3758 IEEE80211_HT_MCS_MASK_LEN - 1);
3759 /* skip the 3 reserved bits */
3760 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3761 0x1f;
3762 }
3763
3764 return 0;
3765}
3766
3767
3768static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3769 struct ieee80211_ht_capabilities *htcaps,
3770 struct ieee80211_ht_capabilities *htcaps_mask,
3771 int disabled)
3772{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003773 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003774
3775 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3776
3777 if (disabled == -1)
3778 return 0;
3779
3780 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3781 htcaps_mask->ht_capabilities_info |= msk;
3782 if (disabled)
3783 htcaps->ht_capabilities_info &= msk;
3784 else
3785 htcaps->ht_capabilities_info |= msk;
3786
3787 return 0;
3788}
3789
3790
3791static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3792 struct ieee80211_ht_capabilities *htcaps,
3793 struct ieee80211_ht_capabilities *htcaps_mask,
3794 int factor)
3795{
3796 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3797
3798 if (factor == -1)
3799 return 0;
3800
3801 if (factor < 0 || factor > 3) {
3802 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3803 "Must be 0-3 or -1", factor);
3804 return -EINVAL;
3805 }
3806
3807 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3808 htcaps->a_mpdu_params &= ~0x3;
3809 htcaps->a_mpdu_params |= factor & 0x3;
3810
3811 return 0;
3812}
3813
3814
3815static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3816 struct ieee80211_ht_capabilities *htcaps,
3817 struct ieee80211_ht_capabilities *htcaps_mask,
3818 int density)
3819{
3820 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3821
3822 if (density == -1)
3823 return 0;
3824
3825 if (density < 0 || density > 7) {
3826 wpa_msg(wpa_s, MSG_ERROR,
3827 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3828 density);
3829 return -EINVAL;
3830 }
3831
3832 htcaps_mask->a_mpdu_params |= 0x1C;
3833 htcaps->a_mpdu_params &= ~(0x1C);
3834 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3835
3836 return 0;
3837}
3838
3839
3840static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3841 struct ieee80211_ht_capabilities *htcaps,
3842 struct ieee80211_ht_capabilities *htcaps_mask,
3843 int disabled)
3844{
3845 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003846 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3847 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003848
3849 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3850
3851 if (disabled)
3852 htcaps->ht_capabilities_info &= ~msk;
3853 else
3854 htcaps->ht_capabilities_info |= msk;
3855
3856 htcaps_mask->ht_capabilities_info |= msk;
3857
3858 return 0;
3859}
3860
3861
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003862static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3863 struct ieee80211_ht_capabilities *htcaps,
3864 struct ieee80211_ht_capabilities *htcaps_mask,
3865 int disabled)
3866{
3867 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003868 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3869 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003870
3871 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3872
3873 if (disabled)
3874 htcaps->ht_capabilities_info &= ~msk;
3875 else
3876 htcaps->ht_capabilities_info |= msk;
3877
3878 htcaps_mask->ht_capabilities_info |= msk;
3879
3880 return 0;
3881}
3882
3883
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003884static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3885 struct ieee80211_ht_capabilities *htcaps,
3886 struct ieee80211_ht_capabilities *htcaps_mask,
3887 int disabled)
3888{
3889 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003890 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003891
3892 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3893
3894 if (disabled)
3895 htcaps->ht_capabilities_info &= ~msk;
3896 else
3897 htcaps->ht_capabilities_info |= msk;
3898
3899 htcaps_mask->ht_capabilities_info |= msk;
3900
3901 return 0;
3902}
3903
3904
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003905void wpa_supplicant_apply_ht_overrides(
3906 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3907 struct wpa_driver_associate_params *params)
3908{
3909 struct ieee80211_ht_capabilities *htcaps;
3910 struct ieee80211_ht_capabilities *htcaps_mask;
3911
3912 if (!ssid)
3913 return;
3914
3915 params->disable_ht = ssid->disable_ht;
3916 if (!params->htcaps || !params->htcaps_mask)
3917 return;
3918
3919 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3920 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3921 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3922 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3923 ssid->disable_max_amsdu);
3924 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3925 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3926 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003927 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003928 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003929
3930 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003931 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003932 htcaps->ht_capabilities_info |= bit;
3933 htcaps_mask->ht_capabilities_info |= bit;
3934 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003935}
3936
3937#endif /* CONFIG_HT_OVERRIDES */
3938
3939
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003940#ifdef CONFIG_VHT_OVERRIDES
3941void wpa_supplicant_apply_vht_overrides(
3942 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3943 struct wpa_driver_associate_params *params)
3944{
3945 struct ieee80211_vht_capabilities *vhtcaps;
3946 struct ieee80211_vht_capabilities *vhtcaps_mask;
3947
3948 if (!ssid)
3949 return;
3950
3951 params->disable_vht = ssid->disable_vht;
3952
3953 vhtcaps = (void *) params->vhtcaps;
3954 vhtcaps_mask = (void *) params->vhtcaps_mask;
3955
3956 if (!vhtcaps || !vhtcaps_mask)
3957 return;
3958
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003959 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
3960 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003961
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003962#ifdef CONFIG_HT_OVERRIDES
3963 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003964 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3965 int max_ampdu;
3966
3967 max_ampdu = (ssid->vht_capa &
3968 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3969 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003970
3971 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3972 wpa_set_ampdu_factor(wpa_s,
3973 (void *) params->htcaps,
3974 (void *) params->htcaps_mask,
3975 max_ampdu);
3976 }
3977#endif /* CONFIG_HT_OVERRIDES */
3978
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003979#define OVERRIDE_MCS(i) \
3980 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3981 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003982 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003983 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003984 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
3985 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003986 } \
3987 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3988 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003989 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003990 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003991 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
3992 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003993 }
3994
3995 OVERRIDE_MCS(1);
3996 OVERRIDE_MCS(2);
3997 OVERRIDE_MCS(3);
3998 OVERRIDE_MCS(4);
3999 OVERRIDE_MCS(5);
4000 OVERRIDE_MCS(6);
4001 OVERRIDE_MCS(7);
4002 OVERRIDE_MCS(8);
4003}
4004#endif /* CONFIG_VHT_OVERRIDES */
4005
4006
Dmitry Shmidt04949592012-07-19 12:16:46 -07004007static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4008{
4009#ifdef PCSC_FUNCS
4010 size_t len;
4011
4012 if (!wpa_s->conf->pcsc_reader)
4013 return 0;
4014
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004015 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004016 if (!wpa_s->scard)
4017 return 1;
4018
4019 if (wpa_s->conf->pcsc_pin &&
4020 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4021 scard_deinit(wpa_s->scard);
4022 wpa_s->scard = NULL;
4023 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4024 return -1;
4025 }
4026
4027 len = sizeof(wpa_s->imsi) - 1;
4028 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4029 scard_deinit(wpa_s->scard);
4030 wpa_s->scard = NULL;
4031 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4032 return -1;
4033 }
4034 wpa_s->imsi[len] = '\0';
4035
4036 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4037
4038 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4039 wpa_s->imsi, wpa_s->mnc_len);
4040
4041 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4042 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4043#endif /* PCSC_FUNCS */
4044
4045 return 0;
4046}
4047
4048
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004049int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4050{
4051 char *val, *pos;
4052
4053 ext_password_deinit(wpa_s->ext_pw);
4054 wpa_s->ext_pw = NULL;
4055 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4056
4057 if (!wpa_s->conf->ext_password_backend)
4058 return 0;
4059
4060 val = os_strdup(wpa_s->conf->ext_password_backend);
4061 if (val == NULL)
4062 return -1;
4063 pos = os_strchr(val, ':');
4064 if (pos)
4065 *pos++ = '\0';
4066
4067 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4068
4069 wpa_s->ext_pw = ext_password_init(val, pos);
4070 os_free(val);
4071 if (wpa_s->ext_pw == NULL) {
4072 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4073 return -1;
4074 }
4075 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4076
4077 return 0;
4078}
4079
4080
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004081#ifdef CONFIG_FST
4082
4083static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4084{
4085 struct wpa_supplicant *wpa_s = ctx;
4086
4087 return (is_zero_ether_addr(wpa_s->bssid) ||
4088 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4089}
4090
4091
4092static void wpas_fst_get_channel_info_cb(void *ctx,
4093 enum hostapd_hw_mode *hw_mode,
4094 u8 *channel)
4095{
4096 struct wpa_supplicant *wpa_s = ctx;
4097
4098 if (wpa_s->current_bss) {
4099 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4100 channel);
4101 } else if (wpa_s->hw.num_modes) {
4102 *hw_mode = wpa_s->hw.modes[0].mode;
4103 } else {
4104 WPA_ASSERT(0);
4105 *hw_mode = 0;
4106 }
4107}
4108
4109
4110static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4111{
4112 struct wpa_supplicant *wpa_s = ctx;
4113
4114 *modes = wpa_s->hw.modes;
4115 return wpa_s->hw.num_modes;
4116}
4117
4118
4119static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4120{
4121 struct wpa_supplicant *wpa_s = ctx;
4122
4123 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4124 wpa_s->fst_ies = fst_ies;
4125}
4126
4127
4128static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4129{
4130 struct wpa_supplicant *wpa_s = ctx;
4131
4132 WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
4133 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
4134 wpa_s->own_addr, wpa_s->bssid,
4135 wpabuf_head(data), wpabuf_len(data),
4136 0);
4137}
4138
4139
4140static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4141{
4142 struct wpa_supplicant *wpa_s = ctx;
4143
4144 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4145 return wpa_s->received_mb_ies;
4146}
4147
4148
4149static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4150 const u8 *buf, size_t size)
4151{
4152 struct wpa_supplicant *wpa_s = ctx;
4153 struct mb_ies_info info;
4154
4155 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4156
4157 if (!mb_ies_info_by_ies(&info, buf, size)) {
4158 wpabuf_free(wpa_s->received_mb_ies);
4159 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4160 }
4161}
4162
4163
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004164static const u8 * wpas_fst_get_peer_first(void *ctx,
4165 struct fst_get_peer_ctx **get_ctx,
4166 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004167{
4168 struct wpa_supplicant *wpa_s = ctx;
4169
4170 *get_ctx = NULL;
4171 if (!is_zero_ether_addr(wpa_s->bssid))
4172 return (wpa_s->received_mb_ies || !mb_only) ?
4173 wpa_s->bssid : NULL;
4174 return NULL;
4175}
4176
4177
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004178static const u8 * wpas_fst_get_peer_next(void *ctx,
4179 struct fst_get_peer_ctx **get_ctx,
4180 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004181{
4182 return NULL;
4183}
4184
4185void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4186 struct fst_wpa_obj *iface_obj)
4187{
4188 iface_obj->ctx = wpa_s;
4189 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4190 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4191 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4192 iface_obj->set_ies = wpas_fst_set_ies_cb;
4193 iface_obj->send_action = wpas_fst_send_action_cb;
4194 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4195 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4196 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4197 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4198}
4199#endif /* CONFIG_FST */
4200
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004201static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004202 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004203{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004204 struct wowlan_triggers *triggers;
4205 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004206
4207 if (!wpa_s->conf->wowlan_triggers)
4208 return 0;
4209
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004210 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4211 if (triggers) {
4212 ret = wpa_drv_wowlan(wpa_s, triggers);
4213 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004214 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004215 return ret;
4216}
4217
4218
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004219enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004220{
4221 if (freq < 3000)
4222 return BAND_2_4_GHZ;
4223 if (freq > 50000)
4224 return BAND_60_GHZ;
4225 return BAND_5_GHZ;
4226}
4227
4228
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004229unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004230{
4231 int i;
4232 unsigned int band = 0;
4233
4234 if (freqs) {
4235 /* freqs are specified for the radio work */
4236 for (i = 0; freqs[i]; i++)
4237 band |= wpas_freq_to_band(freqs[i]);
4238 } else {
4239 /*
4240 * freqs are not specified, implies all
4241 * the supported freqs by HW
4242 */
4243 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4244 if (wpa_s->hw.modes[i].num_channels != 0) {
4245 if (wpa_s->hw.modes[i].mode ==
4246 HOSTAPD_MODE_IEEE80211B ||
4247 wpa_s->hw.modes[i].mode ==
4248 HOSTAPD_MODE_IEEE80211G)
4249 band |= BAND_2_4_GHZ;
4250 else if (wpa_s->hw.modes[i].mode ==
4251 HOSTAPD_MODE_IEEE80211A)
4252 band |= BAND_5_GHZ;
4253 else if (wpa_s->hw.modes[i].mode ==
4254 HOSTAPD_MODE_IEEE80211AD)
4255 band |= BAND_60_GHZ;
4256 else if (wpa_s->hw.modes[i].mode ==
4257 HOSTAPD_MODE_IEEE80211ANY)
4258 band = BAND_2_4_GHZ | BAND_5_GHZ |
4259 BAND_60_GHZ;
4260 }
4261 }
4262 }
4263
4264 return band;
4265}
4266
4267
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004268static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4269 const char *rn)
4270{
4271 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4272 struct wpa_radio *radio;
4273
4274 while (rn && iface) {
4275 radio = iface->radio;
4276 if (radio && os_strcmp(rn, radio->name) == 0) {
4277 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4278 wpa_s->ifname, rn);
4279 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4280 return radio;
4281 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004282
4283 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004284 }
4285
4286 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4287 wpa_s->ifname, rn ? rn : "N/A");
4288 radio = os_zalloc(sizeof(*radio));
4289 if (radio == NULL)
4290 return NULL;
4291
4292 if (rn)
4293 os_strlcpy(radio->name, rn, sizeof(radio->name));
4294 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004295 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004296 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4297
4298 return radio;
4299}
4300
4301
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004302static void radio_work_free(struct wpa_radio_work *work)
4303{
4304 if (work->wpa_s->scan_work == work) {
4305 /* This should not really happen. */
4306 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4307 work->type, work, work->started);
4308 work->wpa_s->scan_work = NULL;
4309 }
4310
4311#ifdef CONFIG_P2P
4312 if (work->wpa_s->p2p_scan_work == work) {
4313 /* This should not really happen. */
4314 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4315 work->type, work, work->started);
4316 work->wpa_s->p2p_scan_work = NULL;
4317 }
4318#endif /* CONFIG_P2P */
4319
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004320 if (work->started) {
4321 work->wpa_s->radio->num_active_works--;
4322 wpa_dbg(work->wpa_s, MSG_DEBUG,
4323 "radio_work_free('%s'@%p: num_active_works --> %u",
4324 work->type, work,
4325 work->wpa_s->radio->num_active_works);
4326 }
4327
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004328 dl_list_del(&work->list);
4329 os_free(work);
4330}
4331
4332
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004333static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4334{
4335 struct wpa_radio_work *active_work = NULL;
4336 struct wpa_radio_work *tmp;
4337
4338 /* Get the active work to know the type and band. */
4339 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4340 if (tmp->started) {
4341 active_work = tmp;
4342 break;
4343 }
4344 }
4345
4346 if (!active_work) {
4347 /* No active work, start one */
4348 radio->num_active_works = 0;
4349 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4350 list) {
4351 if (os_strcmp(tmp->type, "scan") == 0 &&
4352 radio->external_scan_running &&
4353 (((struct wpa_driver_scan_params *)
4354 tmp->ctx)->only_new_results ||
4355 tmp->wpa_s->clear_driver_scan_cache))
4356 continue;
4357 return tmp;
4358 }
4359 return NULL;
4360 }
4361
4362 if (os_strcmp(active_work->type, "sme-connect") == 0 ||
4363 os_strcmp(active_work->type, "connect") == 0) {
4364 /*
4365 * If the active work is either connect or sme-connect,
4366 * do not parallelize them with other radio works.
4367 */
4368 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4369 "Do not parallelize radio work with %s",
4370 active_work->type);
4371 return NULL;
4372 }
4373
4374 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4375 if (tmp->started)
4376 continue;
4377
4378 /*
4379 * If connect or sme-connect are enqueued, parallelize only
4380 * those operations ahead of them in the queue.
4381 */
4382 if (os_strcmp(tmp->type, "connect") == 0 ||
4383 os_strcmp(tmp->type, "sme-connect") == 0)
4384 break;
4385
4386 /*
4387 * Check that the radio works are distinct and
4388 * on different bands.
4389 */
4390 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4391 (active_work->bands != tmp->bands)) {
4392 /*
4393 * If a scan has to be scheduled through nl80211 scan
4394 * interface and if an external scan is already running,
4395 * do not schedule the scan since it is likely to get
4396 * rejected by kernel.
4397 */
4398 if (os_strcmp(tmp->type, "scan") == 0 &&
4399 radio->external_scan_running &&
4400 (((struct wpa_driver_scan_params *)
4401 tmp->ctx)->only_new_results ||
4402 tmp->wpa_s->clear_driver_scan_cache))
4403 continue;
4404
4405 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4406 "active_work:%s new_work:%s",
4407 active_work->type, tmp->type);
4408 return tmp;
4409 }
4410 }
4411
4412 /* Did not find a radio work to schedule in parallel. */
4413 return NULL;
4414}
4415
4416
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004417static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4418{
4419 struct wpa_radio *radio = eloop_ctx;
4420 struct wpa_radio_work *work;
4421 struct os_reltime now, diff;
4422 struct wpa_supplicant *wpa_s;
4423
4424 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004425 if (work == NULL) {
4426 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004427 return;
4428 }
4429
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004430 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4431 radio_list);
4432
4433 if (!(wpa_s &&
4434 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4435 if (work->started)
4436 return; /* already started and still in progress */
4437
4438 if (wpa_s && wpa_s->radio->external_scan_running) {
4439 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4440 return;
4441 }
4442 } else {
4443 work = NULL;
4444 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4445 /* get the work to schedule next */
4446 work = radio_work_get_next_work(radio);
4447 }
4448 if (!work)
4449 return;
4450 }
4451
4452 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004453 os_get_reltime(&now);
4454 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004455 wpa_dbg(wpa_s, MSG_DEBUG,
4456 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004457 work->type, work, diff.sec, diff.usec);
4458 work->started = 1;
4459 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004460 radio->num_active_works++;
4461
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004462 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004463
4464 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4465 radio->num_active_works < MAX_ACTIVE_WORKS)
4466 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004467}
4468
4469
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004470/*
4471 * This function removes both started and pending radio works running on
4472 * the provided interface's radio.
4473 * Prior to the removal of the radio work, its callback (cb) is called with
4474 * deinit set to be 1. Each work's callback is responsible for clearing its
4475 * internal data and restoring to a correct state.
4476 * @wpa_s: wpa_supplicant data
4477 * @type: type of works to be removed
4478 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4479 * this interface's works.
4480 */
4481void radio_remove_works(struct wpa_supplicant *wpa_s,
4482 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004483{
4484 struct wpa_radio_work *work, *tmp;
4485 struct wpa_radio *radio = wpa_s->radio;
4486
4487 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4488 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004489 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004490 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004491
4492 /* skip other ifaces' works */
4493 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004494 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004495
4496 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4497 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004498 work->cb(work, 1);
4499 radio_work_free(work);
4500 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004501
4502 /* in case we removed the started work */
4503 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004504}
4505
4506
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004507static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4508{
4509 struct wpa_radio *radio = wpa_s->radio;
4510
4511 if (!radio)
4512 return;
4513
4514 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4515 wpa_s->ifname, radio->name);
4516 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004517 radio_remove_works(wpa_s, NULL, 0);
4518 wpa_s->radio = NULL;
4519 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004520 return; /* Interfaces remain for this radio */
4521
4522 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004523 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004524 os_free(radio);
4525}
4526
4527
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004528void radio_work_check_next(struct wpa_supplicant *wpa_s)
4529{
4530 struct wpa_radio *radio = wpa_s->radio;
4531
4532 if (dl_list_empty(&radio->work))
4533 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004534 if (wpa_s->ext_work_in_progress) {
4535 wpa_printf(MSG_DEBUG,
4536 "External radio work in progress - delay start of pending item");
4537 return;
4538 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004539 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4540 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4541}
4542
4543
4544/**
4545 * radio_add_work - Add a radio work item
4546 * @wpa_s: Pointer to wpa_supplicant data
4547 * @freq: Frequency of the offchannel operation in MHz or 0
4548 * @type: Unique identifier for each type of work
4549 * @next: Force as the next work to be executed
4550 * @cb: Callback function for indicating when radio is available
4551 * @ctx: Context pointer for the work (work->ctx in cb())
4552 * Returns: 0 on success, -1 on failure
4553 *
4554 * This function is used to request time for an operation that requires
4555 * exclusive radio control. Once the radio is available, the registered callback
4556 * function will be called. radio_work_done() must be called once the exclusive
4557 * radio operation has been completed, so that the radio is freed for other
4558 * operations. The special case of deinit=1 is used to free the context data
4559 * during interface removal. That does not allow the callback function to start
4560 * the radio operation, i.e., it must free any resources allocated for the radio
4561 * work and return.
4562 *
4563 * The @freq parameter can be used to indicate a single channel on which the
4564 * offchannel operation will occur. This may allow multiple radio work
4565 * operations to be performed in parallel if they apply for the same channel.
4566 * Setting this to 0 indicates that the work item may use multiple channels or
4567 * requires exclusive control of the radio.
4568 */
4569int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4570 const char *type, int next,
4571 void (*cb)(struct wpa_radio_work *work, int deinit),
4572 void *ctx)
4573{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004574 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004575 struct wpa_radio_work *work;
4576 int was_empty;
4577
4578 work = os_zalloc(sizeof(*work));
4579 if (work == NULL)
4580 return -1;
4581 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4582 os_get_reltime(&work->time);
4583 work->freq = freq;
4584 work->type = type;
4585 work->wpa_s = wpa_s;
4586 work->cb = cb;
4587 work->ctx = ctx;
4588
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004589 if (freq)
4590 work->bands = wpas_freq_to_band(freq);
4591 else if (os_strcmp(type, "scan") == 0 ||
4592 os_strcmp(type, "p2p-scan") == 0)
4593 work->bands = wpas_get_bands(wpa_s,
4594 ((struct wpa_driver_scan_params *)
4595 ctx)->freqs);
4596 else
4597 work->bands = wpas_get_bands(wpa_s, NULL);
4598
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004599 was_empty = dl_list_empty(&wpa_s->radio->work);
4600 if (next)
4601 dl_list_add(&wpa_s->radio->work, &work->list);
4602 else
4603 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4604 if (was_empty) {
4605 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4606 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004607 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4608 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4609 wpa_dbg(wpa_s, MSG_DEBUG,
4610 "Try to schedule a radio work (num_active_works=%u)",
4611 radio->num_active_works);
4612 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004613 }
4614
4615 return 0;
4616}
4617
4618
4619/**
4620 * radio_work_done - Indicate that a radio work item has been completed
4621 * @work: Completed work
4622 *
4623 * This function is called once the callback function registered with
4624 * radio_add_work() has completed its work.
4625 */
4626void radio_work_done(struct wpa_radio_work *work)
4627{
4628 struct wpa_supplicant *wpa_s = work->wpa_s;
4629 struct os_reltime now, diff;
4630 unsigned int started = work->started;
4631
4632 os_get_reltime(&now);
4633 os_reltime_sub(&now, &work->time, &diff);
4634 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4635 work->type, work, started ? "done" : "canceled",
4636 diff.sec, diff.usec);
4637 radio_work_free(work);
4638 if (started)
4639 radio_work_check_next(wpa_s);
4640}
4641
4642
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004643struct wpa_radio_work *
4644radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004645{
4646 struct wpa_radio_work *work;
4647 struct wpa_radio *radio = wpa_s->radio;
4648
4649 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4650 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004651 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004652 }
4653
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004654 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004655}
4656
4657
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004658static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4659 struct wpa_interface *iface)
4660{
4661 const char *ifname, *driver, *rn;
4662
4663 driver = iface->driver;
4664next_driver:
4665 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4666 return -1;
4667
4668 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4669 if (wpa_s->drv_priv == NULL) {
4670 const char *pos;
4671 pos = driver ? os_strchr(driver, ',') : NULL;
4672 if (pos) {
4673 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4674 "driver interface - try next driver wrapper");
4675 driver = pos + 1;
4676 goto next_driver;
4677 }
4678 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4679 "interface");
4680 return -1;
4681 }
4682 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4683 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4684 "driver_param '%s'", wpa_s->conf->driver_param);
4685 return -1;
4686 }
4687
4688 ifname = wpa_drv_get_ifname(wpa_s);
4689 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4690 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4691 "interface name with '%s'", ifname);
4692 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4693 }
4694
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004695 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004696 if (rn && rn[0] == '\0')
4697 rn = NULL;
4698
4699 wpa_s->radio = radio_add_interface(wpa_s, rn);
4700 if (wpa_s->radio == NULL)
4701 return -1;
4702
4703 return 0;
4704}
4705
4706
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004707static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4708 struct wpa_interface *iface)
4709{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004710 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004711 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004712
4713 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4714 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4715 iface->confname ? iface->confname : "N/A",
4716 iface->driver ? iface->driver : "default",
4717 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4718 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4719
4720 if (iface->confname) {
4721#ifdef CONFIG_BACKEND_FILE
4722 wpa_s->confname = os_rel2abs_path(iface->confname);
4723 if (wpa_s->confname == NULL) {
4724 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4725 "for configuration file '%s'.",
4726 iface->confname);
4727 return -1;
4728 }
4729 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4730 iface->confname, wpa_s->confname);
4731#else /* CONFIG_BACKEND_FILE */
4732 wpa_s->confname = os_strdup(iface->confname);
4733#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004734 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004735 if (wpa_s->conf == NULL) {
4736 wpa_printf(MSG_ERROR, "Failed to read or parse "
4737 "configuration '%s'.", wpa_s->confname);
4738 return -1;
4739 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004740 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4741 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004742
4743 /*
4744 * Override ctrl_interface and driver_param if set on command
4745 * line.
4746 */
4747 if (iface->ctrl_interface) {
4748 os_free(wpa_s->conf->ctrl_interface);
4749 wpa_s->conf->ctrl_interface =
4750 os_strdup(iface->ctrl_interface);
4751 }
4752
4753 if (iface->driver_param) {
4754 os_free(wpa_s->conf->driver_param);
4755 wpa_s->conf->driver_param =
4756 os_strdup(iface->driver_param);
4757 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004758
4759 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4760 os_free(wpa_s->conf->ctrl_interface);
4761 wpa_s->conf->ctrl_interface = NULL;
4762 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004763 } else
4764 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4765 iface->driver_param);
4766
4767 if (wpa_s->conf == NULL) {
4768 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4769 return -1;
4770 }
4771
4772 if (iface->ifname == NULL) {
4773 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4774 return -1;
4775 }
4776 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4777 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4778 iface->ifname);
4779 return -1;
4780 }
4781 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4782
4783 if (iface->bridge_ifname) {
4784 if (os_strlen(iface->bridge_ifname) >=
4785 sizeof(wpa_s->bridge_ifname)) {
4786 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4787 "name '%s'.", iface->bridge_ifname);
4788 return -1;
4789 }
4790 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4791 sizeof(wpa_s->bridge_ifname));
4792 }
4793
4794 /* RSNA Supplicant Key Management - INITIALIZE */
4795 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4796 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4797
4798 /* Initialize driver interface and register driver event handler before
4799 * L2 receive handler so that association events are processed before
4800 * EAPOL-Key packets if both become available for the same select()
4801 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004802 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004803 return -1;
4804
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004805 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4806 return -1;
4807
4808 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4809 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4810 NULL);
4811 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4812
4813 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4814 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4815 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4816 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4817 "dot11RSNAConfigPMKLifetime");
4818 return -1;
4819 }
4820
4821 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4822 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4823 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4824 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4825 "dot11RSNAConfigPMKReauthThreshold");
4826 return -1;
4827 }
4828
4829 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4830 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4831 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4832 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4833 "dot11RSNAConfigSATimeout");
4834 return -1;
4835 }
4836
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004837 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4838 &wpa_s->hw.num_modes,
4839 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004840 if (wpa_s->hw.modes) {
4841 u16 i;
4842
4843 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4844 if (wpa_s->hw.modes[i].vht_capab) {
4845 wpa_s->hw_capab = CAPAB_VHT;
4846 break;
4847 }
4848
4849 if (wpa_s->hw.modes[i].ht_capab &
4850 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4851 wpa_s->hw_capab = CAPAB_HT40;
4852 else if (wpa_s->hw.modes[i].ht_capab &&
4853 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4854 wpa_s->hw_capab = CAPAB_HT;
4855 }
4856 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004857
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004858 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4859 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004860 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004861 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004862 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004863 wpa_s->drv_smps_modes = capa.smps_modes;
4864 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004865 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004866 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004867 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004868 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
4869 wpa_s->max_sched_scan_plan_interval =
4870 capa.max_sched_scan_plan_interval;
4871 wpa_s->max_sched_scan_plan_iterations =
4872 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004873 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4874 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004875 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4876 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004877 wpa_s->extended_capa = capa.extended_capa;
4878 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4879 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004880 wpa_s->num_multichan_concurrent =
4881 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004882 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4883
4884 if (capa.mac_addr_rand_scan_supported)
4885 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4886 if (wpa_s->sched_scan_supported &&
4887 capa.mac_addr_rand_sched_scan_supported)
4888 wpa_s->mac_addr_rand_supported |=
4889 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004890 }
4891 if (wpa_s->max_remain_on_chan == 0)
4892 wpa_s->max_remain_on_chan = 1000;
4893
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004894 /*
4895 * Only take p2p_mgmt parameters when P2P Device is supported.
4896 * Doing it here as it determines whether l2_packet_init() will be done
4897 * during wpa_supplicant_driver_init().
4898 */
4899 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4900 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4901 else
4902 iface->p2p_mgmt = 1;
4903
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004904 if (wpa_s->num_multichan_concurrent == 0)
4905 wpa_s->num_multichan_concurrent = 1;
4906
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004907 if (wpa_supplicant_driver_init(wpa_s) < 0)
4908 return -1;
4909
4910#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004911 if ((!iface->p2p_mgmt ||
4912 !(wpa_s->drv_flags &
4913 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4914 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004915 return -1;
4916#endif /* CONFIG_TDLS */
4917
4918 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4919 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4920 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4921 return -1;
4922 }
4923
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004924#ifdef CONFIG_FST
4925 if (wpa_s->conf->fst_group_id) {
4926 struct fst_iface_cfg cfg;
4927 struct fst_wpa_obj iface_obj;
4928
4929 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4930 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4931 sizeof(cfg.group_id));
4932 cfg.priority = wpa_s->conf->fst_priority;
4933 cfg.llt = wpa_s->conf->fst_llt;
4934
4935 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4936 &iface_obj, &cfg);
4937 if (!wpa_s->fst) {
4938 wpa_msg(wpa_s, MSG_ERROR,
4939 "FST: Cannot attach iface %s to group %s",
4940 wpa_s->ifname, cfg.group_id);
4941 return -1;
4942 }
4943 }
4944#endif /* CONFIG_FST */
4945
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004946 if (wpas_wps_init(wpa_s))
4947 return -1;
4948
4949 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4950 return -1;
4951 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4952
4953 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4954 if (wpa_s->ctrl_iface == NULL) {
4955 wpa_printf(MSG_ERROR,
4956 "Failed to initialize control interface '%s'.\n"
4957 "You may have another wpa_supplicant process "
4958 "already running or the file was\n"
4959 "left by an unclean termination of wpa_supplicant "
4960 "in which case you will need\n"
4961 "to manually remove this file before starting "
4962 "wpa_supplicant again.\n",
4963 wpa_s->conf->ctrl_interface);
4964 return -1;
4965 }
4966
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004967 wpa_s->gas = gas_query_init(wpa_s);
4968 if (wpa_s->gas == NULL) {
4969 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4970 return -1;
4971 }
4972
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004973 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004974 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4975 return -1;
4976 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004977
4978 if (wpa_bss_init(wpa_s) < 0)
4979 return -1;
4980
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004981 /*
4982 * Set Wake-on-WLAN triggers, if configured.
4983 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4984 * have effect anyway when the interface is down).
4985 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004986 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004987 return -1;
4988
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004989#ifdef CONFIG_EAP_PROXY
4990{
4991 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004992 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4993 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004994 if (wpa_s->mnc_len > 0) {
4995 wpa_s->imsi[len] = '\0';
4996 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4997 wpa_s->imsi, wpa_s->mnc_len);
4998 } else {
4999 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5000 }
5001}
5002#endif /* CONFIG_EAP_PROXY */
5003
Dmitry Shmidt04949592012-07-19 12:16:46 -07005004 if (pcsc_reader_init(wpa_s) < 0)
5005 return -1;
5006
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005007 if (wpas_init_ext_pw(wpa_s) < 0)
5008 return -1;
5009
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005010 wpas_rrm_reset(wpa_s);
5011
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005012 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5013
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005014#ifdef CONFIG_HS20
5015 hs20_init(wpa_s);
5016#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005017#ifdef CONFIG_MBO
5018 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5019#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005020
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005021 wpa_supplicant_set_default_scan_ies(wpa_s);
5022
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005023 return 0;
5024}
5025
5026
5027static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005028 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005029{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005030 struct wpa_global *global = wpa_s->global;
5031 struct wpa_supplicant *iface, *prev;
5032
5033 if (wpa_s == wpa_s->parent)
5034 wpas_p2p_group_remove(wpa_s, "*");
5035
5036 iface = global->ifaces;
5037 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005038 if (iface->p2pdev == wpa_s)
5039 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005040 if (iface == wpa_s || iface->parent != wpa_s) {
5041 iface = iface->next;
5042 continue;
5043 }
5044 wpa_printf(MSG_DEBUG,
5045 "Remove remaining child interface %s from parent %s",
5046 iface->ifname, wpa_s->ifname);
5047 prev = iface;
5048 iface = iface->next;
5049 wpa_supplicant_remove_iface(global, prev, terminate);
5050 }
5051
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005052 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005053 if (wpa_s->drv_priv) {
5054 wpa_supplicant_deauthenticate(wpa_s,
5055 WLAN_REASON_DEAUTH_LEAVING);
5056
5057 wpa_drv_set_countermeasures(wpa_s, 0);
5058 wpa_clear_keys(wpa_s, NULL);
5059 }
5060
5061 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005062 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005063
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005064 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005065 radio_remove_interface(wpa_s);
5066
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005067#ifdef CONFIG_FST
5068 if (wpa_s->fst) {
5069 fst_detach(wpa_s->fst);
5070 wpa_s->fst = NULL;
5071 }
5072 if (wpa_s->received_mb_ies) {
5073 wpabuf_free(wpa_s->received_mb_ies);
5074 wpa_s->received_mb_ies = NULL;
5075 }
5076#endif /* CONFIG_FST */
5077
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005078 if (wpa_s->drv_priv)
5079 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005080
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005081 if (notify)
5082 wpas_notify_iface_removed(wpa_s);
5083
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005084 if (terminate)
5085 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005086
5087 if (wpa_s->ctrl_iface) {
5088 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5089 wpa_s->ctrl_iface = NULL;
5090 }
5091
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005092#ifdef CONFIG_MESH
5093 if (wpa_s->ifmsh) {
5094 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5095 wpa_s->ifmsh = NULL;
5096 }
5097#endif /* CONFIG_MESH */
5098
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005099 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005100 wpa_config_free(wpa_s->conf);
5101 wpa_s->conf = NULL;
5102 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005103
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005104 os_free(wpa_s->ssids_from_scan_req);
5105
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005106 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005107}
5108
5109
Dmitry Shmidte4663042016-04-04 10:07:49 -07005110#ifdef CONFIG_MATCH_IFACE
5111
5112/**
5113 * wpa_supplicant_match_iface - Match an interface description to a name
5114 * @global: Pointer to global data from wpa_supplicant_init()
5115 * @ifname: Name of the interface to match
5116 * Returns: Pointer to the created interface description or %NULL on failure
5117 */
5118struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5119 const char *ifname)
5120{
5121 int i;
5122 struct wpa_interface *iface, *miface;
5123
5124 for (i = 0; i < global->params.match_iface_count; i++) {
5125 miface = &global->params.match_ifaces[i];
5126 if (!miface->ifname ||
5127 fnmatch(miface->ifname, ifname, 0) == 0) {
5128 iface = os_zalloc(sizeof(*iface));
5129 if (!iface)
5130 return NULL;
5131 *iface = *miface;
5132 iface->ifname = ifname;
5133 return iface;
5134 }
5135 }
5136
5137 return NULL;
5138}
5139
5140
5141/**
5142 * wpa_supplicant_match_existing - Match existing interfaces
5143 * @global: Pointer to global data from wpa_supplicant_init()
5144 * Returns: 0 on success, -1 on failure
5145 */
5146static int wpa_supplicant_match_existing(struct wpa_global *global)
5147{
5148 struct if_nameindex *ifi, *ifp;
5149 struct wpa_supplicant *wpa_s;
5150 struct wpa_interface *iface;
5151
5152 ifp = if_nameindex();
5153 if (!ifp) {
5154 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5155 return -1;
5156 }
5157
5158 for (ifi = ifp; ifi->if_name; ifi++) {
5159 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5160 if (wpa_s)
5161 continue;
5162 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5163 if (iface) {
5164 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5165 os_free(iface);
5166 if (wpa_s)
5167 wpa_s->matched = 1;
5168 }
5169 }
5170
5171 if_freenameindex(ifp);
5172 return 0;
5173}
5174
5175#endif /* CONFIG_MATCH_IFACE */
5176
5177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005178/**
5179 * wpa_supplicant_add_iface - Add a new network interface
5180 * @global: Pointer to global data from wpa_supplicant_init()
5181 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005182 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005183 * Returns: Pointer to the created interface or %NULL on failure
5184 *
5185 * This function is used to add new network interfaces for %wpa_supplicant.
5186 * This can be called before wpa_supplicant_run() to add interfaces before the
5187 * main event loop has been started. In addition, new interfaces can be added
5188 * dynamically while %wpa_supplicant is already running. This could happen,
5189 * e.g., when a hotplug network adapter is inserted.
5190 */
5191struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005192 struct wpa_interface *iface,
5193 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005194{
5195 struct wpa_supplicant *wpa_s;
5196 struct wpa_interface t_iface;
5197 struct wpa_ssid *ssid;
5198
5199 if (global == NULL || iface == NULL)
5200 return NULL;
5201
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005202 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005203 if (wpa_s == NULL)
5204 return NULL;
5205
5206 wpa_s->global = global;
5207
5208 t_iface = *iface;
5209 if (global->params.override_driver) {
5210 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5211 "('%s' -> '%s')",
5212 iface->driver, global->params.override_driver);
5213 t_iface.driver = global->params.override_driver;
5214 }
5215 if (global->params.override_ctrl_interface) {
5216 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5217 "ctrl_interface ('%s' -> '%s')",
5218 iface->ctrl_interface,
5219 global->params.override_ctrl_interface);
5220 t_iface.ctrl_interface =
5221 global->params.override_ctrl_interface;
5222 }
5223 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5224 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5225 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005226 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005227 return NULL;
5228 }
5229
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005230 /* Notify the control interfaces about new iface */
5231 if (wpas_notify_iface_added(wpa_s)) {
5232 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5233 return NULL;
5234 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005235
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005236 /* Notify the control interfaces about new networks for non p2p mgmt
5237 * ifaces. */
5238 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005239 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5240 wpas_notify_network_added(wpa_s, ssid);
5241 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005242
5243 wpa_s->next = global->ifaces;
5244 global->ifaces = wpa_s;
5245
5246 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005247 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005248
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005249#ifdef CONFIG_P2P
5250 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005251 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005252 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005253 wpas_p2p_add_p2pdev_interface(
5254 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005255 wpa_printf(MSG_INFO,
5256 "P2P: Failed to enable P2P Device interface");
5257 /* Try to continue without. P2P will be disabled. */
5258 }
5259#endif /* CONFIG_P2P */
5260
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005261 return wpa_s;
5262}
5263
5264
5265/**
5266 * wpa_supplicant_remove_iface - Remove a network interface
5267 * @global: Pointer to global data from wpa_supplicant_init()
5268 * @wpa_s: Pointer to the network interface to be removed
5269 * Returns: 0 if interface was removed, -1 if interface was not found
5270 *
5271 * This function can be used to dynamically remove network interfaces from
5272 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5273 * addition, this function is used to remove all remaining interfaces when
5274 * %wpa_supplicant is terminated.
5275 */
5276int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005277 struct wpa_supplicant *wpa_s,
5278 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005279{
5280 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005281#ifdef CONFIG_MESH
5282 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5283 char *ifname = NULL;
5284#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005285
5286 /* Remove interface from the global list of interfaces */
5287 prev = global->ifaces;
5288 if (prev == wpa_s) {
5289 global->ifaces = wpa_s->next;
5290 } else {
5291 while (prev && prev->next != wpa_s)
5292 prev = prev->next;
5293 if (prev == NULL)
5294 return -1;
5295 prev->next = wpa_s->next;
5296 }
5297
5298 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5299
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005300#ifdef CONFIG_MESH
5301 if (mesh_if_created) {
5302 ifname = os_strdup(wpa_s->ifname);
5303 if (ifname == NULL) {
5304 wpa_dbg(wpa_s, MSG_ERROR,
5305 "mesh: Failed to malloc ifname");
5306 return -1;
5307 }
5308 }
5309#endif /* CONFIG_MESH */
5310
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005311 if (global->p2p_group_formation == wpa_s)
5312 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005313 if (global->p2p_invite_group == wpa_s)
5314 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005315 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005316
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005317#ifdef CONFIG_MESH
5318 if (mesh_if_created) {
5319 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
5320 os_free(ifname);
5321 }
5322#endif /* CONFIG_MESH */
5323
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005324 return 0;
5325}
5326
5327
5328/**
5329 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5330 * @wpa_s: Pointer to the network interface
5331 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5332 */
5333const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5334{
5335 const char *eapol_method;
5336
5337 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5338 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5339 return "NO-EAP";
5340 }
5341
5342 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5343 if (eapol_method == NULL)
5344 return "UNKNOWN-EAP";
5345
5346 return eapol_method;
5347}
5348
5349
5350/**
5351 * wpa_supplicant_get_iface - Get a new network interface
5352 * @global: Pointer to global data from wpa_supplicant_init()
5353 * @ifname: Interface name
5354 * Returns: Pointer to the interface or %NULL if not found
5355 */
5356struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5357 const char *ifname)
5358{
5359 struct wpa_supplicant *wpa_s;
5360
5361 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5362 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5363 return wpa_s;
5364 }
5365 return NULL;
5366}
5367
5368
5369#ifndef CONFIG_NO_WPA_MSG
5370static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5371{
5372 struct wpa_supplicant *wpa_s = ctx;
5373 if (wpa_s == NULL)
5374 return NULL;
5375 return wpa_s->ifname;
5376}
5377#endif /* CONFIG_NO_WPA_MSG */
5378
5379
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005380#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5381#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5382#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5383
5384/* Periodic cleanup tasks */
5385static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5386{
5387 struct wpa_global *global = eloop_ctx;
5388 struct wpa_supplicant *wpa_s;
5389
5390 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5391 wpas_periodic, global, NULL);
5392
5393#ifdef CONFIG_P2P
5394 if (global->p2p)
5395 p2p_expire_peers(global->p2p);
5396#endif /* CONFIG_P2P */
5397
5398 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5399 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5400#ifdef CONFIG_AP
5401 ap_periodic(wpa_s);
5402#endif /* CONFIG_AP */
5403 }
5404}
5405
5406
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005407/**
5408 * wpa_supplicant_init - Initialize %wpa_supplicant
5409 * @params: Parameters for %wpa_supplicant
5410 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5411 *
5412 * This function is used to initialize %wpa_supplicant. After successful
5413 * initialization, the returned data pointer can be used to add and remove
5414 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5415 */
5416struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5417{
5418 struct wpa_global *global;
5419 int ret, i;
5420
5421 if (params == NULL)
5422 return NULL;
5423
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005424#ifdef CONFIG_DRIVER_NDIS
5425 {
5426 void driver_ndis_init_ops(void);
5427 driver_ndis_init_ops();
5428 }
5429#endif /* CONFIG_DRIVER_NDIS */
5430
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005431#ifndef CONFIG_NO_WPA_MSG
5432 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5433#endif /* CONFIG_NO_WPA_MSG */
5434
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005435 if (params->wpa_debug_file_path)
5436 wpa_debug_open_file(params->wpa_debug_file_path);
5437 else
5438 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005439 if (params->wpa_debug_syslog)
5440 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005441 if (params->wpa_debug_tracing) {
5442 ret = wpa_debug_open_linux_tracing();
5443 if (ret) {
5444 wpa_printf(MSG_ERROR,
5445 "Failed to enable trace logging");
5446 return NULL;
5447 }
5448 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005449
5450 ret = eap_register_methods();
5451 if (ret) {
5452 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5453 if (ret == -2)
5454 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5455 "the same EAP type.");
5456 return NULL;
5457 }
5458
5459 global = os_zalloc(sizeof(*global));
5460 if (global == NULL)
5461 return NULL;
5462 dl_list_init(&global->p2p_srv_bonjour);
5463 dl_list_init(&global->p2p_srv_upnp);
5464 global->params.daemonize = params->daemonize;
5465 global->params.wait_for_monitor = params->wait_for_monitor;
5466 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5467 if (params->pid_file)
5468 global->params.pid_file = os_strdup(params->pid_file);
5469 if (params->ctrl_interface)
5470 global->params.ctrl_interface =
5471 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005472 if (params->ctrl_interface_group)
5473 global->params.ctrl_interface_group =
5474 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005475 if (params->override_driver)
5476 global->params.override_driver =
5477 os_strdup(params->override_driver);
5478 if (params->override_ctrl_interface)
5479 global->params.override_ctrl_interface =
5480 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005481#ifdef CONFIG_MATCH_IFACE
5482 global->params.match_iface_count = params->match_iface_count;
5483 if (params->match_iface_count) {
5484 global->params.match_ifaces =
5485 os_calloc(params->match_iface_count,
5486 sizeof(struct wpa_interface));
5487 os_memcpy(global->params.match_ifaces,
5488 params->match_ifaces,
5489 params->match_iface_count *
5490 sizeof(struct wpa_interface));
5491 }
5492#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005493#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005494 if (params->conf_p2p_dev)
5495 global->params.conf_p2p_dev =
5496 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005497#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005498 wpa_debug_level = global->params.wpa_debug_level =
5499 params->wpa_debug_level;
5500 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5501 params->wpa_debug_show_keys;
5502 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5503 params->wpa_debug_timestamp;
5504
5505 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5506
5507 if (eloop_init()) {
5508 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5509 wpa_supplicant_deinit(global);
5510 return NULL;
5511 }
5512
Jouni Malinen75ecf522011-06-27 15:19:46 -07005513 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005514
5515 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5516 if (global->ctrl_iface == NULL) {
5517 wpa_supplicant_deinit(global);
5518 return NULL;
5519 }
5520
5521 if (wpas_notify_supplicant_initialized(global)) {
5522 wpa_supplicant_deinit(global);
5523 return NULL;
5524 }
5525
5526 for (i = 0; wpa_drivers[i]; i++)
5527 global->drv_count++;
5528 if (global->drv_count == 0) {
5529 wpa_printf(MSG_ERROR, "No drivers enabled");
5530 wpa_supplicant_deinit(global);
5531 return NULL;
5532 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005533 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005534 if (global->drv_priv == NULL) {
5535 wpa_supplicant_deinit(global);
5536 return NULL;
5537 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005538
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005539#ifdef CONFIG_WIFI_DISPLAY
5540 if (wifi_display_init(global) < 0) {
5541 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5542 wpa_supplicant_deinit(global);
5543 return NULL;
5544 }
5545#endif /* CONFIG_WIFI_DISPLAY */
5546
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005547 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5548 wpas_periodic, global, NULL);
5549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005550 return global;
5551}
5552
5553
5554/**
5555 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5556 * @global: Pointer to global data from wpa_supplicant_init()
5557 * Returns: 0 after successful event loop run, -1 on failure
5558 *
5559 * This function starts the main event loop and continues running as long as
5560 * there are any remaining events. In most cases, this function is running as
5561 * long as the %wpa_supplicant process in still in use.
5562 */
5563int wpa_supplicant_run(struct wpa_global *global)
5564{
5565 struct wpa_supplicant *wpa_s;
5566
5567 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005568 (wpa_supplicant_daemon(global->params.pid_file) ||
5569 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005570 return -1;
5571
Dmitry Shmidte4663042016-04-04 10:07:49 -07005572#ifdef CONFIG_MATCH_IFACE
5573 if (wpa_supplicant_match_existing(global))
5574 return -1;
5575#endif
5576
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005577 if (global->params.wait_for_monitor) {
5578 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005579 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005580 wpa_supplicant_ctrl_iface_wait(
5581 wpa_s->ctrl_iface);
5582 }
5583
5584 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5585 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5586
5587 eloop_run();
5588
5589 return 0;
5590}
5591
5592
5593/**
5594 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5595 * @global: Pointer to global data from wpa_supplicant_init()
5596 *
5597 * This function is called to deinitialize %wpa_supplicant and to free all
5598 * allocated resources. Remaining network interfaces will also be removed.
5599 */
5600void wpa_supplicant_deinit(struct wpa_global *global)
5601{
5602 int i;
5603
5604 if (global == NULL)
5605 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005606
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005607 eloop_cancel_timeout(wpas_periodic, global, NULL);
5608
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005609#ifdef CONFIG_WIFI_DISPLAY
5610 wifi_display_deinit(global);
5611#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005612
5613 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005614 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005615
5616 if (global->ctrl_iface)
5617 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5618
5619 wpas_notify_supplicant_deinitialized(global);
5620
5621 eap_peer_unregister_methods();
5622#ifdef CONFIG_AP
5623 eap_server_unregister_methods();
5624#endif /* CONFIG_AP */
5625
5626 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5627 if (!global->drv_priv[i])
5628 continue;
5629 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5630 }
5631 os_free(global->drv_priv);
5632
5633 random_deinit();
5634
5635 eloop_destroy();
5636
5637 if (global->params.pid_file) {
5638 os_daemonize_terminate(global->params.pid_file);
5639 os_free(global->params.pid_file);
5640 }
5641 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005642 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005643 os_free(global->params.override_driver);
5644 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005645#ifdef CONFIG_MATCH_IFACE
5646 os_free(global->params.match_ifaces);
5647#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005648#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005649 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005650#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005651
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005652 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005653 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005654 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005655
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005656 os_free(global);
5657 wpa_debug_close_syslog();
5658 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005659 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005660}
5661
5662
5663void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5664{
5665 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5666 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5667 char country[3];
5668 country[0] = wpa_s->conf->country[0];
5669 country[1] = wpa_s->conf->country[1];
5670 country[2] = '\0';
5671 if (wpa_drv_set_country(wpa_s, country) < 0) {
5672 wpa_printf(MSG_ERROR, "Failed to set country code "
5673 "'%s'", country);
5674 }
5675 }
5676
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005677 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5678 wpas_init_ext_pw(wpa_s);
5679
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005680 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5681 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5682
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005683#ifdef CONFIG_WPS
5684 wpas_wps_update_config(wpa_s);
5685#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005686 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005687 wpa_s->conf->changed_parameters = 0;
5688}
5689
5690
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005691void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005692{
5693 int i;
5694
5695 for (i = 0; i < *num_freqs; i++) {
5696 if (freqs[i] == freq)
5697 return;
5698 }
5699
5700 freqs[*num_freqs] = freq;
5701 (*num_freqs)++;
5702}
5703
5704
5705static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5706{
5707 struct wpa_bss *bss, *cbss;
5708 const int max_freqs = 10;
5709 int *freqs;
5710 int num_freqs = 0;
5711
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005712 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005713 if (freqs == NULL)
5714 return NULL;
5715
5716 cbss = wpa_s->current_bss;
5717
5718 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5719 if (bss == cbss)
5720 continue;
5721 if (bss->ssid_len == cbss->ssid_len &&
5722 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5723 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5724 add_freq(freqs, &num_freqs, bss->freq);
5725 if (num_freqs == max_freqs)
5726 break;
5727 }
5728 }
5729
5730 if (num_freqs == 0) {
5731 os_free(freqs);
5732 freqs = NULL;
5733 }
5734
5735 return freqs;
5736}
5737
5738
5739void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5740{
5741 int timeout;
5742 int count;
5743 int *freqs = NULL;
5744
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005745 wpas_connect_work_done(wpa_s);
5746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005747 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005748 * Remove possible authentication timeout since the connection failed.
5749 */
5750 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5751
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005752 /*
5753 * There is no point in blacklisting the AP if this event is
5754 * generated based on local request to disconnect.
5755 */
5756 if (wpa_s->own_disconnect_req) {
5757 wpa_s->own_disconnect_req = 0;
5758 wpa_dbg(wpa_s, MSG_DEBUG,
5759 "Ignore connection failure due to local request to disconnect");
5760 return;
5761 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005762 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005763 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5764 "indication since interface has been put into "
5765 "disconnected state");
5766 return;
5767 }
5768
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005769 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005770 * Add the failed BSSID into the blacklist and speed up next scan
5771 * attempt if there could be other APs that could accept association.
5772 * The current blacklist count indicates how many times we have tried
5773 * connecting to this AP and multiple attempts mean that other APs are
5774 * either not available or has already been tried, so that we can start
5775 * increasing the delay here to avoid constant scanning.
5776 */
5777 count = wpa_blacklist_add(wpa_s, bssid);
5778 if (count == 1 && wpa_s->current_bss) {
5779 /*
5780 * This BSS was not in the blacklist before. If there is
5781 * another BSS available for the same ESS, we should try that
5782 * next. Otherwise, we may as well try this one once more
5783 * before allowing other, likely worse, ESSes to be considered.
5784 */
5785 freqs = get_bss_freqs_in_ess(wpa_s);
5786 if (freqs) {
5787 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5788 "has been seen; try it next");
5789 wpa_blacklist_add(wpa_s, bssid);
5790 /*
5791 * On the next scan, go through only the known channels
5792 * used in this ESS based on previous scans to speed up
5793 * common load balancing use case.
5794 */
5795 os_free(wpa_s->next_scan_freqs);
5796 wpa_s->next_scan_freqs = freqs;
5797 }
5798 }
5799
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005800 /*
5801 * Add previous failure count in case the temporary blacklist was
5802 * cleared due to no other BSSes being available.
5803 */
5804 count += wpa_s->extra_blacklist_count;
5805
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005806 if (count > 3 && wpa_s->current_ssid) {
5807 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5808 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005809 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005810 }
5811
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005812 switch (count) {
5813 case 1:
5814 timeout = 100;
5815 break;
5816 case 2:
5817 timeout = 500;
5818 break;
5819 case 3:
5820 timeout = 1000;
5821 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005822 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005823 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005824 break;
5825 default:
5826 timeout = 10000;
5827 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005828 }
5829
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005830 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5831 "ms", count, timeout);
5832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005833 /*
5834 * TODO: if more than one possible AP is available in scan results,
5835 * could try the other ones before requesting a new scan.
5836 */
5837 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5838 1000 * (timeout % 1000));
5839}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005840
5841
5842int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5843{
5844 return wpa_s->conf->ap_scan == 2 ||
5845 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5846}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005847
Dmitry Shmidt04949592012-07-19 12:16:46 -07005848
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005849#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005850int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5851 struct wpa_ssid *ssid,
5852 const char *field,
5853 const char *value)
5854{
5855#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005856 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005857
5858 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5859 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5860 (const u8 *) value, os_strlen(value));
5861
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005862 rtype = wpa_supplicant_ctrl_req_from_string(field);
5863 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
5864#else /* IEEE8021X_EAPOL */
5865 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5866 return -1;
5867#endif /* IEEE8021X_EAPOL */
5868}
5869
5870int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5871 struct wpa_ssid *ssid,
5872 enum wpa_ctrl_req_type rtype,
5873 const char *value)
5874{
5875#ifdef IEEE8021X_EAPOL
5876 struct eap_peer_config *eap = &ssid->eap;
5877
5878 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005879 case WPA_CTRL_REQ_EAP_IDENTITY:
5880 os_free(eap->identity);
5881 eap->identity = (u8 *) os_strdup(value);
5882 eap->identity_len = os_strlen(value);
5883 eap->pending_req_identity = 0;
5884 if (ssid == wpa_s->current_ssid)
5885 wpa_s->reassociate = 1;
5886 break;
5887 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005888 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005889 eap->password = (u8 *) os_strdup(value);
5890 eap->password_len = os_strlen(value);
5891 eap->pending_req_password = 0;
5892 if (ssid == wpa_s->current_ssid)
5893 wpa_s->reassociate = 1;
5894 break;
5895 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005896 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005897 eap->new_password = (u8 *) os_strdup(value);
5898 eap->new_password_len = os_strlen(value);
5899 eap->pending_req_new_password = 0;
5900 if (ssid == wpa_s->current_ssid)
5901 wpa_s->reassociate = 1;
5902 break;
5903 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005904 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005905 eap->pin = os_strdup(value);
5906 eap->pending_req_pin = 0;
5907 if (ssid == wpa_s->current_ssid)
5908 wpa_s->reassociate = 1;
5909 break;
5910 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005911 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005912 eap->otp = (u8 *) os_strdup(value);
5913 eap->otp_len = os_strlen(value);
5914 os_free(eap->pending_req_otp);
5915 eap->pending_req_otp = NULL;
5916 eap->pending_req_otp_len = 0;
5917 break;
5918 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005919 str_clear_free(eap->private_key_passwd);
5920 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005921 eap->pending_req_passphrase = 0;
5922 if (ssid == wpa_s->current_ssid)
5923 wpa_s->reassociate = 1;
5924 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005925 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005926 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005927 eap->external_sim_resp = os_strdup(value);
5928 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005929 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5930 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5931 return -1;
5932 ssid->mem_only_psk = 1;
5933 if (ssid->passphrase)
5934 wpa_config_update_psk(ssid);
5935 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5936 wpa_supplicant_req_scan(wpa_s, 0, 0);
5937 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005938 case WPA_CTRL_REQ_EXT_CERT_CHECK:
5939 if (eap->pending_ext_cert_check != PENDING_CHECK)
5940 return -1;
5941 if (os_strcmp(value, "good") == 0)
5942 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
5943 else if (os_strcmp(value, "bad") == 0)
5944 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
5945 else
5946 return -1;
5947 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005948 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005949 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005950 return -1;
5951 }
5952
5953 return 0;
5954#else /* IEEE8021X_EAPOL */
5955 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5956 return -1;
5957#endif /* IEEE8021X_EAPOL */
5958}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005959#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005960
5961
5962int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5963{
5964 int i;
5965 unsigned int drv_enc;
5966
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005967 if (wpa_s->p2p_mgmt)
5968 return 1; /* no normal network profiles on p2p_mgmt interface */
5969
Dmitry Shmidt04949592012-07-19 12:16:46 -07005970 if (ssid == NULL)
5971 return 1;
5972
5973 if (ssid->disabled)
5974 return 1;
5975
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005976 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005977 drv_enc = wpa_s->drv_enc;
5978 else
5979 drv_enc = (unsigned int) -1;
5980
5981 for (i = 0; i < NUM_WEP_KEYS; i++) {
5982 size_t len = ssid->wep_key_len[i];
5983 if (len == 0)
5984 continue;
5985 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5986 continue;
5987 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5988 continue;
5989 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5990 continue;
5991 return 1; /* invalid WEP key */
5992 }
5993
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005994 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005995 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5996 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005997 return 1;
5998
Dmitry Shmidt04949592012-07-19 12:16:46 -07005999 return 0;
6000}
6001
6002
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006003int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6004{
6005#ifdef CONFIG_IEEE80211W
6006 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6007 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6008 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6009 /*
6010 * Driver does not support BIP -- ignore pmf=1 default
6011 * since the connection with PMF would fail and the
6012 * configuration does not require PMF to be enabled.
6013 */
6014 return NO_MGMT_FRAME_PROTECTION;
6015 }
6016
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006017 if (ssid &&
6018 (ssid->key_mgmt &
6019 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6020 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6021 /*
6022 * Do not use the default PMF value for non-RSN networks
6023 * since PMF is available only with RSN and pmf=2
6024 * configuration would otherwise prevent connections to
6025 * all open networks.
6026 */
6027 return NO_MGMT_FRAME_PROTECTION;
6028 }
6029
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006030 return wpa_s->conf->pmf;
6031 }
6032
6033 return ssid->ieee80211w;
6034#else /* CONFIG_IEEE80211W */
6035 return NO_MGMT_FRAME_PROTECTION;
6036#endif /* CONFIG_IEEE80211W */
6037}
6038
6039
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006040int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006041{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006042 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006043 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006044 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006045 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006046 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006047}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006048
6049
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006050void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006051{
6052 struct wpa_ssid *ssid = wpa_s->current_ssid;
6053 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006054 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006055
6056 if (ssid == NULL) {
6057 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6058 "SSID block");
6059 return;
6060 }
6061
6062 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6063 return;
6064
6065 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006066
6067#ifdef CONFIG_P2P
6068 if (ssid->p2p_group &&
6069 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6070 /*
6071 * Skip the wait time since there is a short timeout on the
6072 * connection to a P2P group.
6073 */
6074 return;
6075 }
6076#endif /* CONFIG_P2P */
6077
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006078 if (ssid->auth_failures > 50)
6079 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006080 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006081 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006082 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006083 dur = 90;
6084 else if (ssid->auth_failures > 3)
6085 dur = 60;
6086 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006087 dur = 30;
6088 else if (ssid->auth_failures > 1)
6089 dur = 20;
6090 else
6091 dur = 10;
6092
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006093 if (ssid->auth_failures > 1 &&
6094 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6095 dur += os_random() % (ssid->auth_failures * 10);
6096
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006097 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006098 if (now.sec + dur <= ssid->disabled_until.sec)
6099 return;
6100
6101 ssid->disabled_until.sec = now.sec + dur;
6102
6103 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006104 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006105 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006106 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006107}
6108
6109
6110void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6111 struct wpa_ssid *ssid, int clear_failures)
6112{
6113 if (ssid == NULL)
6114 return;
6115
6116 if (ssid->disabled_until.sec) {
6117 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6118 "id=%d ssid=\"%s\"",
6119 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6120 }
6121 ssid->disabled_until.sec = 0;
6122 ssid->disabled_until.usec = 0;
6123 if (clear_failures)
6124 ssid->auth_failures = 0;
6125}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006126
6127
6128int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6129{
6130 size_t i;
6131
6132 if (wpa_s->disallow_aps_bssid == NULL)
6133 return 0;
6134
6135 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6136 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6137 bssid, ETH_ALEN) == 0)
6138 return 1;
6139 }
6140
6141 return 0;
6142}
6143
6144
6145int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6146 size_t ssid_len)
6147{
6148 size_t i;
6149
6150 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6151 return 0;
6152
6153 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6154 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6155 if (ssid_len == s->ssid_len &&
6156 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6157 return 1;
6158 }
6159
6160 return 0;
6161}
6162
6163
6164/**
6165 * wpas_request_connection - Request a new connection
6166 * @wpa_s: Pointer to the network interface
6167 *
6168 * This function is used to request a new connection to be found. It will mark
6169 * the interface to allow reassociation and request a new scan to find a
6170 * suitable network to connect to.
6171 */
6172void wpas_request_connection(struct wpa_supplicant *wpa_s)
6173{
6174 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006175 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006176 wpa_supplicant_reinit_autoscan(wpa_s);
6177 wpa_s->extra_blacklist_count = 0;
6178 wpa_s->disconnected = 0;
6179 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006180
6181 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6182 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006183 else
6184 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006185}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006186
Roshan Pius02242d72016-08-09 15:31:48 -07006187/**
6188 * wpas_request_disconnection - Request disconnection
6189 * @wpa_s: Pointer to the network interface
6190 *
6191 * This function is used to request disconnection from the currently connected
6192 * network. This will stop any ongoing scans and initiate deauthentication.
6193 */
6194void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6195{
6196#ifdef CONFIG_SME
6197 wpa_s->sme.prev_bssid_set = 0;
6198#endif /* CONFIG_SME */
6199 wpa_s->reassociate = 0;
6200 wpa_s->disconnected = 1;
6201 wpa_supplicant_cancel_sched_scan(wpa_s);
6202 wpa_supplicant_cancel_scan(wpa_s);
6203 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6204 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6205}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006206
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006207
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006208void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6209 struct wpa_used_freq_data *freqs_data,
6210 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006211{
6212 unsigned int i;
6213
6214 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6215 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006216 for (i = 0; i < len; i++) {
6217 struct wpa_used_freq_data *cur = &freqs_data[i];
6218 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6219 i, cur->freq, cur->flags);
6220 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006221}
6222
6223
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006224/*
6225 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006226 * are using the same radio as the current interface, and in addition, get
6227 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006228 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006229int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6230 struct wpa_used_freq_data *freqs_data,
6231 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006232{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006233 struct wpa_supplicant *ifs;
6234 u8 bssid[ETH_ALEN];
6235 int freq;
6236 unsigned int idx = 0, i;
6237
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006238 wpa_dbg(wpa_s, MSG_DEBUG,
6239 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006240 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006241
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006242 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6243 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006244 if (idx == len)
6245 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006246
6247 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6248 continue;
6249
6250 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006251 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6252 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006253 freq = ifs->current_ssid->frequency;
6254 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6255 freq = ifs->assoc_freq;
6256 else
6257 continue;
6258
6259 /* Hold only distinct freqs */
6260 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006261 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006262 break;
6263
6264 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006265 freqs_data[idx++].freq = freq;
6266
6267 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006268 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006269 WPA_FREQ_USED_BY_P2P_CLIENT :
6270 WPA_FREQ_USED_BY_INFRA_STATION;
6271 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006272 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006273
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006274 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006275 return idx;
6276}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006277
6278
6279/*
6280 * Find the operating frequencies of any of the virtual interfaces that
6281 * are using the same radio as the current interface.
6282 */
6283int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6284 int *freq_array, unsigned int len)
6285{
6286 struct wpa_used_freq_data *freqs_data;
6287 int num, i;
6288
6289 os_memset(freq_array, 0, sizeof(int) * len);
6290
6291 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6292 if (!freqs_data)
6293 return -1;
6294
6295 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6296 for (i = 0; i < num; i++)
6297 freq_array[i] = freqs_data[i].freq;
6298
6299 os_free(freqs_data);
6300
6301 return num;
6302}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006303
6304
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006305struct wpa_supplicant *
6306wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6307{
6308 switch (frame) {
6309#ifdef CONFIG_P2P
6310 case VENDOR_ELEM_PROBE_REQ_P2P:
6311 case VENDOR_ELEM_PROBE_RESP_P2P:
6312 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6313 case VENDOR_ELEM_BEACON_P2P_GO:
6314 case VENDOR_ELEM_P2P_PD_REQ:
6315 case VENDOR_ELEM_P2P_PD_RESP:
6316 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6317 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6318 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6319 case VENDOR_ELEM_P2P_INV_REQ:
6320 case VENDOR_ELEM_P2P_INV_RESP:
6321 case VENDOR_ELEM_P2P_ASSOC_REQ:
6322 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006323 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006324#endif /* CONFIG_P2P */
6325 default:
6326 return wpa_s;
6327 }
6328}
6329
6330
6331void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6332{
6333 unsigned int i;
6334 char buf[30];
6335
6336 wpa_printf(MSG_DEBUG, "Update vendor elements");
6337
6338 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6339 if (wpa_s->vendor_elem[i]) {
6340 int res;
6341
6342 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6343 if (!os_snprintf_error(sizeof(buf), res)) {
6344 wpa_hexdump_buf(MSG_DEBUG, buf,
6345 wpa_s->vendor_elem[i]);
6346 }
6347 }
6348 }
6349
6350#ifdef CONFIG_P2P
6351 if (wpa_s->parent == wpa_s &&
6352 wpa_s->global->p2p &&
6353 !wpa_s->global->p2p_disabled)
6354 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6355#endif /* CONFIG_P2P */
6356}
6357
6358
6359int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6360 const u8 *elem, size_t len)
6361{
6362 u8 *ie, *end;
6363
6364 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6365 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6366
6367 for (; ie + 1 < end; ie += 2 + ie[1]) {
6368 if (ie + len > end)
6369 break;
6370 if (os_memcmp(ie, elem, len) != 0)
6371 continue;
6372
6373 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6374 wpabuf_free(wpa_s->vendor_elem[frame]);
6375 wpa_s->vendor_elem[frame] = NULL;
6376 } else {
6377 os_memmove(ie, ie + len, end - (ie + len));
6378 wpa_s->vendor_elem[frame]->used -= len;
6379 }
6380 wpas_vendor_elem_update(wpa_s);
6381 return 0;
6382 }
6383
6384 return -1;
6385}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006386
6387
6388struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6389 u16 num_modes, enum hostapd_hw_mode mode)
6390{
6391 u16 i;
6392
6393 for (i = 0; i < num_modes; i++) {
6394 if (modes[i].mode == mode)
6395 return &modes[i];
6396 }
6397
6398 return NULL;
6399}
6400
6401
6402static struct
6403wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6404 const u8 *bssid)
6405{
6406 struct wpa_bss_tmp_disallowed *bss;
6407
6408 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6409 struct wpa_bss_tmp_disallowed, list) {
6410 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6411 return bss;
6412 }
6413
6414 return NULL;
6415}
6416
6417
6418void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6419 unsigned int sec)
6420{
6421 struct wpa_bss_tmp_disallowed *bss;
6422 struct os_reltime until;
6423
6424 os_get_reltime(&until);
6425 until.sec += sec;
6426
6427 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6428 if (bss) {
6429 bss->disallowed_until = until;
6430 return;
6431 }
6432
6433 bss = os_malloc(sizeof(*bss));
6434 if (!bss) {
6435 wpa_printf(MSG_DEBUG,
6436 "Failed to allocate memory for temp disallow BSS");
6437 return;
6438 }
6439
6440 bss->disallowed_until = until;
6441 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6442 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
6443}
6444
6445
6446int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6447{
6448 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
6449 struct os_reltime now, age;
6450
6451 os_get_reltime(&now);
6452
6453 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6454 struct wpa_bss_tmp_disallowed, list) {
6455 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
6456 /* This BSS is not disallowed anymore */
6457 dl_list_del(&tmp->list);
6458 os_free(tmp);
6459 continue;
6460 }
6461 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6462 bss = tmp;
6463 break;
6464 }
6465 }
6466 if (!bss)
6467 return 0;
6468
6469 os_reltime_sub(&bss->disallowed_until, &now, &age);
6470 wpa_printf(MSG_DEBUG,
6471 "BSS " MACSTR " disabled for %ld.%0ld seconds",
6472 MAC2STR(bss->bssid), age.sec, age.usec);
6473 return 1;
6474}