blob: 69918e1a8106f896a8d29936f0b178afd883ffa4 [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;
205
206 /*
207 * If we timed out, the AP or the local radio may be busy.
208 * So, wait a second until scanning again.
209 */
210 wpa_supplicant_req_scan(wpa_s, 1, 0);
211}
212
213
214/**
215 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
216 * @wpa_s: Pointer to wpa_supplicant data
217 * @sec: Number of seconds after which to time out authentication
218 * @usec: Number of microseconds after which to time out authentication
219 *
220 * This function is used to schedule a timeout for the current authentication
221 * attempt.
222 */
223void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
224 int sec, int usec)
225{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700226 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700227 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
228 return;
229
230 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
231 "%d usec", sec, usec);
232 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
233 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
234}
235
236
237/**
238 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
239 * @wpa_s: Pointer to wpa_supplicant data
240 *
241 * This function is used to cancel authentication timeout scheduled with
242 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
243 * been completed.
244 */
245void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
246{
247 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
248 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
249 wpa_blacklist_del(wpa_s, wpa_s->bssid);
250}
251
252
253/**
254 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
255 * @wpa_s: Pointer to wpa_supplicant data
256 *
257 * This function is used to configure EAPOL state machine based on the selected
258 * authentication mode.
259 */
260void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
261{
262#ifdef IEEE8021X_EAPOL
263 struct eapol_config eapol_conf;
264 struct wpa_ssid *ssid = wpa_s->current_ssid;
265
266#ifdef CONFIG_IBSS_RSN
267 if (ssid->mode == WPAS_MODE_IBSS &&
268 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
269 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
270 /*
271 * RSN IBSS authentication is per-STA and we can disable the
272 * per-BSSID EAPOL authentication.
273 */
274 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
275 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
276 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
277 return;
278 }
279#endif /* CONFIG_IBSS_RSN */
280
281 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
282 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
283
284 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
285 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
286 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
287 else
288 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
289
290 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
291 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
292 eapol_conf.accept_802_1x_keys = 1;
293 eapol_conf.required_keys = 0;
294 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
295 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
296 }
297 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
298 eapol_conf.required_keys |=
299 EAPOL_REQUIRE_KEY_BROADCAST;
300 }
301
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700302 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303 eapol_conf.required_keys = 0;
304 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700305 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700306 eapol_conf.workaround = ssid->eap_workaround;
307 eapol_conf.eap_disabled =
308 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
309 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
310 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700311 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800312
313#ifdef CONFIG_WPS
314 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
315 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
316 if (wpa_s->current_bss) {
317 struct wpabuf *ie;
318 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
319 WPS_IE_VENDOR_TYPE);
320 if (ie) {
321 if (wps_is_20(ie))
322 eapol_conf.wps |=
323 EAPOL_PEER_IS_WPS20_AP;
324 wpabuf_free(ie);
325 }
326 }
327 }
328#endif /* CONFIG_WPS */
329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700330 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700331
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800332#ifdef CONFIG_MACSEC
333 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
334 ieee802_1x_create_preshared_mka(wpa_s, ssid);
335 else
336 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
337#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800338#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700339}
340
341
342/**
343 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
344 * @wpa_s: Pointer to wpa_supplicant data
345 * @ssid: Configuration data for the network
346 *
347 * This function is used to configure WPA state machine and related parameters
348 * to a mode where WPA is not enabled. This is called as part of the
349 * authentication configuration when the selected network does not use WPA.
350 */
351void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
352 struct wpa_ssid *ssid)
353{
354 int i;
355
356 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
357 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
358 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
359 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
360 else
361 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
362 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
363 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
364 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
365 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
366 wpa_s->group_cipher = WPA_CIPHER_NONE;
367 wpa_s->mgmt_group_cipher = 0;
368
369 for (i = 0; i < NUM_WEP_KEYS; i++) {
370 if (ssid->wep_key_len[i] > 5) {
371 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
372 wpa_s->group_cipher = WPA_CIPHER_WEP104;
373 break;
374 } else if (ssid->wep_key_len[i] > 0) {
375 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
376 wpa_s->group_cipher = WPA_CIPHER_WEP40;
377 break;
378 }
379 }
380
381 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
382 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
383 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
384 wpa_s->pairwise_cipher);
385 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
386#ifdef CONFIG_IEEE80211W
387 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
388 wpa_s->mgmt_group_cipher);
389#endif /* CONFIG_IEEE80211W */
390
391 pmksa_cache_clear_current(wpa_s->wpa);
392}
393
394
Dmitry Shmidt04949592012-07-19 12:16:46 -0700395void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800396{
397 int i;
398 if (wpa_s->hw.modes == NULL)
399 return;
400
401 for (i = 0; i < wpa_s->hw.num_modes; i++) {
402 os_free(wpa_s->hw.modes[i].channels);
403 os_free(wpa_s->hw.modes[i].rates);
404 }
405
406 os_free(wpa_s->hw.modes);
407 wpa_s->hw.modes = NULL;
408}
409
410
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800411static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
412{
413 struct wpa_bss_tmp_disallowed *bss, *prev;
414
415 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
416 struct wpa_bss_tmp_disallowed, list) {
417 dl_list_del(&bss->list);
418 os_free(bss);
419 }
420}
421
422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700423static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
424{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700425 int i;
426
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700427 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700428 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700429 scard_deinit(wpa_s->scard);
430 wpa_s->scard = NULL;
431 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
432 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
433 l2_packet_deinit(wpa_s->l2);
434 wpa_s->l2 = NULL;
435 if (wpa_s->l2_br) {
436 l2_packet_deinit(wpa_s->l2_br);
437 wpa_s->l2_br = NULL;
438 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800439#ifdef CONFIG_TESTING_OPTIONS
440 l2_packet_deinit(wpa_s->l2_test);
441 wpa_s->l2_test = NULL;
442#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444 if (wpa_s->conf != NULL) {
445 struct wpa_ssid *ssid;
446 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
447 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700448 }
449
450 os_free(wpa_s->confname);
451 wpa_s->confname = NULL;
452
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700453 os_free(wpa_s->confanother);
454 wpa_s->confanother = NULL;
455
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700456 wpa_sm_set_eapol(wpa_s->wpa, NULL);
457 eapol_sm_deinit(wpa_s->eapol);
458 wpa_s->eapol = NULL;
459
460 rsn_preauth_deinit(wpa_s->wpa);
461
462#ifdef CONFIG_TDLS
463 wpa_tdls_deinit(wpa_s->wpa);
464#endif /* CONFIG_TDLS */
465
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800466 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700467 pmksa_candidate_free(wpa_s->wpa);
468 wpa_sm_deinit(wpa_s->wpa);
469 wpa_s->wpa = NULL;
470 wpa_blacklist_clear(wpa_s);
471
472 wpa_bss_deinit(wpa_s);
473
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700474 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700475 wpa_supplicant_cancel_scan(wpa_s);
476 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800477 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
478#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
479 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
480 wpa_s, NULL);
481#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700482
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700483 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700485 wpas_wps_deinit(wpa_s);
486
487 wpabuf_free(wpa_s->pending_eapol_rx);
488 wpa_s->pending_eapol_rx = NULL;
489
490#ifdef CONFIG_IBSS_RSN
491 ibss_rsn_deinit(wpa_s->ibss_rsn);
492 wpa_s->ibss_rsn = NULL;
493#endif /* CONFIG_IBSS_RSN */
494
495 sme_deinit(wpa_s);
496
497#ifdef CONFIG_AP
498 wpa_supplicant_ap_deinit(wpa_s);
499#endif /* CONFIG_AP */
500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700501 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800503#ifdef CONFIG_OFFCHANNEL
504 offchannel_deinit(wpa_s);
505#endif /* CONFIG_OFFCHANNEL */
506
507 wpa_supplicant_cancel_sched_scan(wpa_s);
508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700509 os_free(wpa_s->next_scan_freqs);
510 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800511
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800512 os_free(wpa_s->manual_scan_freqs);
513 wpa_s->manual_scan_freqs = NULL;
514
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700515 os_free(wpa_s->manual_sched_scan_freqs);
516 wpa_s->manual_sched_scan_freqs = NULL;
517
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800518 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
519
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700520 /*
521 * Need to remove any pending gas-query radio work before the
522 * gas_query_deinit() call because gas_query::work has not yet been set
523 * for works that have not been started. gas_query_free() will be unable
524 * to cancel such pending radio works and once the pending gas-query
525 * radio work eventually gets removed, the deinit notification call to
526 * gas_query_start_cb() would result in dereferencing freed memory.
527 */
528 if (wpa_s->radio)
529 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800530 gas_query_deinit(wpa_s->gas);
531 wpa_s->gas = NULL;
532
533 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700534
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700535 ieee802_1x_dealloc_kay_sm(wpa_s);
536
Dmitry Shmidt04949592012-07-19 12:16:46 -0700537 os_free(wpa_s->bssid_filter);
538 wpa_s->bssid_filter = NULL;
539
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800540 os_free(wpa_s->disallow_aps_bssid);
541 wpa_s->disallow_aps_bssid = NULL;
542 os_free(wpa_s->disallow_aps_ssid);
543 wpa_s->disallow_aps_ssid = NULL;
544
Dmitry Shmidt04949592012-07-19 12:16:46 -0700545 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700546#ifdef CONFIG_WNM
547 wnm_deallocate_memory(wpa_s);
548#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700549
550 ext_password_deinit(wpa_s->ext_pw);
551 wpa_s->ext_pw = NULL;
552
553 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800554 wpa_s->last_gas_resp = NULL;
555 wpabuf_free(wpa_s->prev_gas_resp);
556 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700557
558 os_free(wpa_s->last_scan_res);
559 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800560
561#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700562 if (wpa_s->drv_priv)
563 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700564 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800565#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700566
567 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
568 wpabuf_free(wpa_s->vendor_elem[i]);
569 wpa_s->vendor_elem[i] = NULL;
570 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800571
572 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800573
574 wpa_s->sched_scan_plans_num = 0;
575 os_free(wpa_s->sched_scan_plans);
576 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800577
578#ifdef CONFIG_MBO
579 wpa_s->non_pref_chan_num = 0;
580 os_free(wpa_s->non_pref_chan);
581 wpa_s->non_pref_chan = NULL;
582#endif /* CONFIG_MBO */
583
584 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700585
586 wpabuf_free(wpa_s->lci);
587 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800588 wpas_clear_beacon_rep_data(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700589}
590
591
592/**
593 * wpa_clear_keys - Clear keys configured for the driver
594 * @wpa_s: Pointer to wpa_supplicant data
595 * @addr: Previously used BSSID or %NULL if not available
596 *
597 * This function clears the encryption keys that has been previously configured
598 * for the driver.
599 */
600void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
601{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800602 int i, max;
603
604#ifdef CONFIG_IEEE80211W
605 max = 6;
606#else /* CONFIG_IEEE80211W */
607 max = 4;
608#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700609
610 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800611 for (i = 0; i < max; i++) {
612 if (wpa_s->keys_cleared & BIT(i))
613 continue;
614 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
615 NULL, 0);
616 }
617 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
618 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700619 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
620 0);
621 /* MLME-SETPROTECTION.request(None) */
622 wpa_drv_mlme_setprotection(
623 wpa_s, addr,
624 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
625 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
626 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800627 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700628}
629
630
631/**
632 * wpa_supplicant_state_txt - Get the connection state name as a text string
633 * @state: State (wpa_state; WPA_*)
634 * Returns: The state name as a printable text string
635 */
636const char * wpa_supplicant_state_txt(enum wpa_states state)
637{
638 switch (state) {
639 case WPA_DISCONNECTED:
640 return "DISCONNECTED";
641 case WPA_INACTIVE:
642 return "INACTIVE";
643 case WPA_INTERFACE_DISABLED:
644 return "INTERFACE_DISABLED";
645 case WPA_SCANNING:
646 return "SCANNING";
647 case WPA_AUTHENTICATING:
648 return "AUTHENTICATING";
649 case WPA_ASSOCIATING:
650 return "ASSOCIATING";
651 case WPA_ASSOCIATED:
652 return "ASSOCIATED";
653 case WPA_4WAY_HANDSHAKE:
654 return "4WAY_HANDSHAKE";
655 case WPA_GROUP_HANDSHAKE:
656 return "GROUP_HANDSHAKE";
657 case WPA_COMPLETED:
658 return "COMPLETED";
659 default:
660 return "UNKNOWN";
661 }
662}
663
664
665#ifdef CONFIG_BGSCAN
666
667static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
668{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800669 const char *name;
670
671 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
672 name = wpa_s->current_ssid->bgscan;
673 else
674 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800675 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800676 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800677 if (wpas_driver_bss_selection(wpa_s))
678 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700679 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
680 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800681#ifdef CONFIG_P2P
682 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
683 return;
684#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685
686 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800687 if (wpa_s->current_ssid) {
688 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
690 "bgscan");
691 /*
692 * Live without bgscan; it is only used as a roaming
693 * optimization, so the initial connection is not
694 * affected.
695 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700696 } else {
697 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700698 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700699 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
700 0);
701 if (scan_res) {
702 bgscan_notify_scan(wpa_s, scan_res);
703 wpa_scan_results_free(scan_res);
704 }
705 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700706 } else
707 wpa_s->bgscan_ssid = NULL;
708}
709
710
711static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
712{
713 if (wpa_s->bgscan_ssid != NULL) {
714 bgscan_deinit(wpa_s);
715 wpa_s->bgscan_ssid = NULL;
716 }
717}
718
719#endif /* CONFIG_BGSCAN */
720
721
Dmitry Shmidt04949592012-07-19 12:16:46 -0700722static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
723{
724 if (autoscan_init(wpa_s, 0))
725 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
726}
727
728
729static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
730{
731 autoscan_deinit(wpa_s);
732}
733
734
735void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
736{
737 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
738 wpa_s->wpa_state == WPA_SCANNING) {
739 autoscan_deinit(wpa_s);
740 wpa_supplicant_start_autoscan(wpa_s);
741 }
742}
743
744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700745/**
746 * wpa_supplicant_set_state - Set current connection state
747 * @wpa_s: Pointer to wpa_supplicant data
748 * @state: The new connection state
749 *
750 * This function is called whenever the connection state changes, e.g.,
751 * association is completed for WPA/WPA2 4-Way Handshake is started.
752 */
753void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
754 enum wpa_states state)
755{
756 enum wpa_states old_state = wpa_s->wpa_state;
757
758 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
759 wpa_supplicant_state_txt(wpa_s->wpa_state),
760 wpa_supplicant_state_txt(state));
761
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800762 if (state == WPA_INTERFACE_DISABLED) {
763 /* Assure normal scan when interface is restored */
764 wpa_s->normal_scans = 0;
765 }
766
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700767 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800768 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700769 /* Reinitialize normal_scan counter */
770 wpa_s->normal_scans = 0;
771 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800772
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700773#ifdef CONFIG_P2P
774 /*
775 * P2PS client has to reply to Probe Request frames received on the
776 * group operating channel. Enable Probe Request frame reporting for
777 * P2P connected client in case p2p_cli_probe configuration property is
778 * set to 1.
779 */
780 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
781 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
782 wpa_s->current_ssid->p2p_group) {
783 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
784 wpa_dbg(wpa_s, MSG_DEBUG,
785 "P2P: Enable CLI Probe Request RX reporting");
786 wpa_s->p2p_cli_probe =
787 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
788 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
789 wpa_dbg(wpa_s, MSG_DEBUG,
790 "P2P: Disable CLI Probe Request RX reporting");
791 wpa_s->p2p_cli_probe = 0;
792 wpa_drv_probe_req_report(wpa_s, 0);
793 }
794 }
795#endif /* CONFIG_P2P */
796
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700797 if (state != WPA_SCANNING)
798 wpa_supplicant_notify_scanning(wpa_s, 0);
799
800 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700801 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700802#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700803 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800804 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800805 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700806 ssid ? ssid->id : -1,
807 ssid && ssid->id_str ? ssid->id_str : "");
808#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700809 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700810 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800811 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700812 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700813 wpa_drv_set_operstate(wpa_s, 1);
814#ifndef IEEE8021X_EAPOL
815 wpa_drv_set_supp_port(wpa_s, 1);
816#endif /* IEEE8021X_EAPOL */
817 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700818 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700820
821 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700822 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
823 state == WPA_ASSOCIATED) {
824 wpa_s->new_connection = 1;
825 wpa_drv_set_operstate(wpa_s, 0);
826#ifndef IEEE8021X_EAPOL
827 wpa_drv_set_supp_port(wpa_s, 0);
828#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700829 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700830 }
831 wpa_s->wpa_state = state;
832
833#ifdef CONFIG_BGSCAN
834 if (state == WPA_COMPLETED)
835 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800836 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700837 wpa_supplicant_stop_bgscan(wpa_s);
838#endif /* CONFIG_BGSCAN */
839
Dmitry Shmidt04949592012-07-19 12:16:46 -0700840 if (state == WPA_AUTHENTICATING)
841 wpa_supplicant_stop_autoscan(wpa_s);
842
843 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
844 wpa_supplicant_start_autoscan(wpa_s);
845
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800846 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
847 wmm_ac_notify_disassoc(wpa_s);
848
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849 if (wpa_s->wpa_state != old_state) {
850 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
851
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700852 /*
853 * Notify the P2P Device interface about a state change in one
854 * of the interfaces.
855 */
856 wpas_p2p_indicate_state_change(wpa_s);
857
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700858 if (wpa_s->wpa_state == WPA_COMPLETED ||
859 old_state == WPA_COMPLETED)
860 wpas_notify_auth_changed(wpa_s);
861 }
862}
863
864
865void wpa_supplicant_terminate_proc(struct wpa_global *global)
866{
867 int pending = 0;
868#ifdef CONFIG_WPS
869 struct wpa_supplicant *wpa_s = global->ifaces;
870 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800871 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700872 if (wpas_wps_terminate_pending(wpa_s) == 1)
873 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700874#ifdef CONFIG_P2P
875 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
876 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
877 wpas_p2p_disconnect(wpa_s);
878#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800879 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880 }
881#endif /* CONFIG_WPS */
882 if (pending)
883 return;
884 eloop_terminate();
885}
886
887
888static void wpa_supplicant_terminate(int sig, void *signal_ctx)
889{
890 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700891 wpa_supplicant_terminate_proc(global);
892}
893
894
895void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
896{
897 enum wpa_states old_state = wpa_s->wpa_state;
898
899 wpa_s->pairwise_cipher = 0;
900 wpa_s->group_cipher = 0;
901 wpa_s->mgmt_group_cipher = 0;
902 wpa_s->key_mgmt = 0;
903 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700904 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700905
906 if (wpa_s->wpa_state != old_state)
907 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
908}
909
910
911/**
912 * wpa_supplicant_reload_configuration - Reload configuration data
913 * @wpa_s: Pointer to wpa_supplicant data
914 * Returns: 0 on success or -1 if configuration parsing failed
915 *
916 * This function can be used to request that the configuration data is reloaded
917 * (e.g., after configuration file change). This function is reloading
918 * configuration only for one interface, so this may need to be called multiple
919 * times if %wpa_supplicant is controlling multiple interfaces and all
920 * interfaces need reconfiguration.
921 */
922int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
923{
924 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700925 int reconf_ctrl;
926 int old_ap_scan;
927
928 if (wpa_s->confname == NULL)
929 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700930 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700931 if (conf == NULL) {
932 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
933 "file '%s' - exiting", wpa_s->confname);
934 return -1;
935 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700936 wpa_config_read(wpa_s->confanother, conf);
937
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700938 conf->changed_parameters = (unsigned int) -1;
939
940 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
941 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
942 os_strcmp(conf->ctrl_interface,
943 wpa_s->conf->ctrl_interface) != 0);
944
945 if (reconf_ctrl && wpa_s->ctrl_iface) {
946 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
947 wpa_s->ctrl_iface = NULL;
948 }
949
950 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800951 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700952 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
953 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800954 wpa_supplicant_deauthenticate(wpa_s,
955 WLAN_REASON_DEAUTH_LEAVING);
956 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700957
958 /*
959 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800960 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700961 */
962 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
963 /*
964 * Clear forced success to clear EAP state for next
965 * authentication.
966 */
967 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
968 }
969 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
970 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800971 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700972 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
973 rsn_preauth_deinit(wpa_s->wpa);
974
975 old_ap_scan = wpa_s->conf->ap_scan;
976 wpa_config_free(wpa_s->conf);
977 wpa_s->conf = conf;
978 if (old_ap_scan != wpa_s->conf->ap_scan)
979 wpas_notify_ap_scan_changed(wpa_s);
980
981 if (reconf_ctrl)
982 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
983
984 wpa_supplicant_update_config(wpa_s);
985
986 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700987 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700988 wpa_s->reassociate = 1;
989 wpa_supplicant_req_scan(wpa_s, 0, 0);
990 }
991 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
992 return 0;
993}
994
995
996static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
997{
998 struct wpa_global *global = signal_ctx;
999 struct wpa_supplicant *wpa_s;
1000 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1001 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1002 sig);
1003 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1004 wpa_supplicant_terminate_proc(global);
1005 }
1006 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001007
1008 if (wpa_debug_reopen_file() < 0) {
1009 /* Ignore errors since we cannot really do much to fix this */
1010 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1011 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001012}
1013
1014
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001015static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1016 struct wpa_ssid *ssid,
1017 struct wpa_ie_data *ie)
1018{
1019 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1020 if (ret) {
1021 if (ret == -2) {
1022 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1023 "from association info");
1024 }
1025 return -1;
1026 }
1027
1028 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1029 "cipher suites");
1030 if (!(ie->group_cipher & ssid->group_cipher)) {
1031 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1032 "cipher 0x%x (mask 0x%x) - reject",
1033 ie->group_cipher, ssid->group_cipher);
1034 return -1;
1035 }
1036 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1037 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1038 "cipher 0x%x (mask 0x%x) - reject",
1039 ie->pairwise_cipher, ssid->pairwise_cipher);
1040 return -1;
1041 }
1042 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1043 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1044 "management 0x%x (mask 0x%x) - reject",
1045 ie->key_mgmt, ssid->key_mgmt);
1046 return -1;
1047 }
1048
1049#ifdef CONFIG_IEEE80211W
1050 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001051 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001052 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1053 "that does not support management frame protection - "
1054 "reject");
1055 return -1;
1056 }
1057#endif /* CONFIG_IEEE80211W */
1058
1059 return 0;
1060}
1061
1062
1063/**
1064 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1065 * @wpa_s: Pointer to wpa_supplicant data
1066 * @bss: Scan results for the selected BSS, or %NULL if not available
1067 * @ssid: Configuration data for the selected network
1068 * @wpa_ie: Buffer for the WPA/RSN IE
1069 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1070 * used buffer length in case the functions returns success.
1071 * Returns: 0 on success or -1 on failure
1072 *
1073 * This function is used to configure authentication and encryption parameters
1074 * based on the network configuration and scan result for the selected BSS (if
1075 * available).
1076 */
1077int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1078 struct wpa_bss *bss, struct wpa_ssid *ssid,
1079 u8 *wpa_ie, size_t *wpa_ie_len)
1080{
1081 struct wpa_ie_data ie;
1082 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001083 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001084
1085 if (bss) {
1086 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1087 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001088 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001090 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001091
1092 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1093 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1094 (ie.group_cipher & ssid->group_cipher) &&
1095 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1096 (ie.key_mgmt & ssid->key_mgmt)) {
1097 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1098 proto = WPA_PROTO_RSN;
1099 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001100 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001101 (ie.group_cipher & ssid->group_cipher) &&
1102 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1103 (ie.key_mgmt & ssid->key_mgmt)) {
1104 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1105 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001106#ifdef CONFIG_HS20
1107 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1108 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1109 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001110 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001111 ie.group_cipher = WPA_CIPHER_CCMP;
1112 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1113 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1114 proto = WPA_PROTO_OSEN;
1115#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001116 } else if (bss) {
1117 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001118 wpa_dbg(wpa_s, MSG_DEBUG,
1119 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1120 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1121 ssid->key_mgmt);
1122 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1123 MAC2STR(bss->bssid),
1124 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1125 bss_wpa ? " WPA" : "",
1126 bss_rsn ? " RSN" : "",
1127 bss_osen ? " OSEN" : "");
1128 if (bss_rsn) {
1129 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1130 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1131 wpa_dbg(wpa_s, MSG_DEBUG,
1132 "Could not parse RSN element");
1133 } else {
1134 wpa_dbg(wpa_s, MSG_DEBUG,
1135 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1136 ie.pairwise_cipher, ie.group_cipher,
1137 ie.key_mgmt);
1138 }
1139 }
1140 if (bss_wpa) {
1141 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1142 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1143 wpa_dbg(wpa_s, MSG_DEBUG,
1144 "Could not parse WPA element");
1145 } else {
1146 wpa_dbg(wpa_s, MSG_DEBUG,
1147 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1148 ie.pairwise_cipher, ie.group_cipher,
1149 ie.key_mgmt);
1150 }
1151 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152 return -1;
1153 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001154 if (ssid->proto & WPA_PROTO_OSEN)
1155 proto = WPA_PROTO_OSEN;
1156 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001157 proto = WPA_PROTO_RSN;
1158 else
1159 proto = WPA_PROTO_WPA;
1160 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1161 os_memset(&ie, 0, sizeof(ie));
1162 ie.group_cipher = ssid->group_cipher;
1163 ie.pairwise_cipher = ssid->pairwise_cipher;
1164 ie.key_mgmt = ssid->key_mgmt;
1165#ifdef CONFIG_IEEE80211W
1166 ie.mgmt_group_cipher =
1167 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1168 WPA_CIPHER_AES_128_CMAC : 0;
1169#endif /* CONFIG_IEEE80211W */
1170 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1171 "based on configuration");
1172 } else
1173 proto = ie.proto;
1174 }
1175
1176 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1177 "pairwise %d key_mgmt %d proto %d",
1178 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1179#ifdef CONFIG_IEEE80211W
1180 if (ssid->ieee80211w) {
1181 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1182 ie.mgmt_group_cipher);
1183 }
1184#endif /* CONFIG_IEEE80211W */
1185
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001186 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001187 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1188 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001189 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190
1191 if (bss || !wpa_s->ap_ies_from_associnfo) {
1192 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1193 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1194 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1195 bss_rsn ? 2 + bss_rsn[1] : 0))
1196 return -1;
1197 }
1198
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001199#ifdef CONFIG_NO_WPA
1200 wpa_s->group_cipher = WPA_CIPHER_NONE;
1201 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1202#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001203 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001204 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1205 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001206 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1207 "cipher");
1208 return -1;
1209 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001210 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1211 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001212
1213 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001214 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1215 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001216 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1217 "cipher");
1218 return -1;
1219 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001220 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1221 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001222#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001223
1224 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001225#ifdef CONFIG_SAE
1226 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1227 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1228#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001229 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001230#ifdef CONFIG_SUITEB192
1231 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1232 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1233 wpa_dbg(wpa_s, MSG_DEBUG,
1234 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1235#endif /* CONFIG_SUITEB192 */
1236#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001237 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1238 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1239 wpa_dbg(wpa_s, MSG_DEBUG,
1240 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001241#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001242#ifdef CONFIG_FILS
1243#ifdef CONFIG_IEEE80211R
1244 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1245 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1246 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1247 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1248 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1249 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1250#endif /* CONFIG_IEEE80211R */
1251 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1252 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1253 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1254 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1255 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1256 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1257#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001258#ifdef CONFIG_IEEE80211R
1259 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1260 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1261 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1262 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1263 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1264 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1265#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001266#ifdef CONFIG_SAE
1267 } else if (sel & WPA_KEY_MGMT_SAE) {
1268 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1269 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1270 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1271 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1272 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1273#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274#ifdef CONFIG_IEEE80211W
1275 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1276 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1277 wpa_dbg(wpa_s, MSG_DEBUG,
1278 "WPA: using KEY_MGMT 802.1X with SHA256");
1279 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1280 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1281 wpa_dbg(wpa_s, MSG_DEBUG,
1282 "WPA: using KEY_MGMT PSK with SHA256");
1283#endif /* CONFIG_IEEE80211W */
1284 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1285 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1286 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1287 } else if (sel & WPA_KEY_MGMT_PSK) {
1288 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1289 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1290 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1291 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1292 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001293#ifdef CONFIG_HS20
1294 } else if (sel & WPA_KEY_MGMT_OSEN) {
1295 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1296 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1297#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 } else {
1299 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1300 "authenticated key management type");
1301 return -1;
1302 }
1303
1304 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1305 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1306 wpa_s->pairwise_cipher);
1307 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1308
1309#ifdef CONFIG_IEEE80211W
1310 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001311 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001312 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1313 sel = 0;
1314 if (sel & WPA_CIPHER_AES_128_CMAC) {
1315 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1316 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1317 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001318 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1319 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1320 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1321 "BIP-GMAC-128");
1322 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1323 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1324 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1325 "BIP-GMAC-256");
1326 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1327 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1328 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1329 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 } else {
1331 wpa_s->mgmt_group_cipher = 0;
1332 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1333 }
1334 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1335 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001336 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001337 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001338#endif /* CONFIG_IEEE80211W */
1339
1340 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1341 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1342 return -1;
1343 }
1344
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001345 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001346 int psk_set = 0;
1347
1348 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001349 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1350 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001351 psk_set = 1;
1352 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001353#ifndef CONFIG_NO_PBKDF2
1354 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1355 ssid->passphrase) {
1356 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001357 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1358 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001359 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1360 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001361 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001362 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001363 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001364 }
1365#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001366#ifdef CONFIG_EXT_PASSWORD
1367 if (ssid->ext_psk) {
1368 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1369 ssid->ext_psk);
1370 char pw_str[64 + 1];
1371 u8 psk[PMK_LEN];
1372
1373 if (pw == NULL) {
1374 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1375 "found from external storage");
1376 return -1;
1377 }
1378
1379 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1380 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1381 "PSK length %d in external storage",
1382 (int) wpabuf_len(pw));
1383 ext_password_free(pw);
1384 return -1;
1385 }
1386
1387 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1388 pw_str[wpabuf_len(pw)] = '\0';
1389
1390#ifndef CONFIG_NO_PBKDF2
1391 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1392 {
1393 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1394 4096, psk, PMK_LEN);
1395 os_memset(pw_str, 0, sizeof(pw_str));
1396 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1397 "external passphrase)",
1398 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001399 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1400 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001401 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001402 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001403 } else
1404#endif /* CONFIG_NO_PBKDF2 */
1405 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1406 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1407 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1408 "Invalid PSK hex string");
1409 os_memset(pw_str, 0, sizeof(pw_str));
1410 ext_password_free(pw);
1411 return -1;
1412 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001413 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1414 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001415 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001416 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001417 } else {
1418 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1419 "PSK available");
1420 os_memset(pw_str, 0, sizeof(pw_str));
1421 ext_password_free(pw);
1422 return -1;
1423 }
1424
1425 os_memset(pw_str, 0, sizeof(pw_str));
1426 ext_password_free(pw);
1427 }
1428#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001429
1430 if (!psk_set) {
1431 wpa_msg(wpa_s, MSG_INFO,
1432 "No PSK available for association");
1433 return -1;
1434 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001435 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001436 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1437
1438 return 0;
1439}
1440
1441
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001442static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1443{
1444 *pos = 0x00;
1445
1446 switch (idx) {
1447 case 0: /* Bits 0-7 */
1448 break;
1449 case 1: /* Bits 8-15 */
1450 break;
1451 case 2: /* Bits 16-23 */
1452#ifdef CONFIG_WNM
1453 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1454 *pos |= 0x08; /* Bit 19 - BSS Transition */
1455#endif /* CONFIG_WNM */
1456 break;
1457 case 3: /* Bits 24-31 */
1458#ifdef CONFIG_WNM
1459 *pos |= 0x02; /* Bit 25 - SSID List */
1460#endif /* CONFIG_WNM */
1461#ifdef CONFIG_INTERWORKING
1462 if (wpa_s->conf->interworking)
1463 *pos |= 0x80; /* Bit 31 - Interworking */
1464#endif /* CONFIG_INTERWORKING */
1465 break;
1466 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001467#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001468 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1469 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001470#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001471 break;
1472 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001473#ifdef CONFIG_HS20
1474 if (wpa_s->conf->hs20)
1475 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1476#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001477#ifdef CONFIG_MBO
1478 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1479#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001480 break;
1481 case 6: /* Bits 48-55 */
1482 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001483 case 7: /* Bits 56-63 */
1484 break;
1485 case 8: /* Bits 64-71 */
1486 if (wpa_s->conf->ftm_responder)
1487 *pos |= 0x40; /* Bit 70 - FTM responder */
1488 if (wpa_s->conf->ftm_initiator)
1489 *pos |= 0x80; /* Bit 71 - FTM initiator */
1490 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001491 case 9: /* Bits 72-79 */
1492#ifdef CONFIG_FILS
1493 *pos |= 0x01;
1494#endif /* CONFIG_FILS */
1495 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001496 }
1497}
1498
1499
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001500int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001501{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001502 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001503 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001504
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001505 if (len < wpa_s->extended_capa_len)
1506 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001507 if (buflen < (size_t) len + 2) {
1508 wpa_printf(MSG_INFO,
1509 "Not enough room for building extended capabilities element");
1510 return -1;
1511 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001512
1513 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001514 *pos++ = len;
1515 for (i = 0; i < len; i++, pos++) {
1516 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001517
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001518 if (i < wpa_s->extended_capa_len) {
1519 *pos &= ~wpa_s->extended_capa_mask[i];
1520 *pos |= wpa_s->extended_capa[i];
1521 }
1522 }
1523
1524 while (len > 0 && buf[1 + len] == 0) {
1525 len--;
1526 buf[1] = len;
1527 }
1528 if (len == 0)
1529 return 0;
1530
1531 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001532}
1533
1534
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001535static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1536 struct wpa_bss *test_bss)
1537{
1538 struct wpa_bss *bss;
1539
1540 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1541 if (bss == test_bss)
1542 return 1;
1543 }
1544
1545 return 0;
1546}
1547
1548
1549static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1550 struct wpa_ssid *test_ssid)
1551{
1552 struct wpa_ssid *ssid;
1553
1554 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1555 if (ssid == test_ssid)
1556 return 1;
1557 }
1558
1559 return 0;
1560}
1561
1562
1563int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1564 struct wpa_ssid *test_ssid)
1565{
1566 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1567 return 0;
1568
1569 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1570}
1571
1572
1573void wpas_connect_work_free(struct wpa_connect_work *cwork)
1574{
1575 if (cwork == NULL)
1576 return;
1577 os_free(cwork);
1578}
1579
1580
1581void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1582{
1583 struct wpa_connect_work *cwork;
1584 struct wpa_radio_work *work = wpa_s->connect_work;
1585
1586 if (!work)
1587 return;
1588
1589 wpa_s->connect_work = NULL;
1590 cwork = work->ctx;
1591 work->ctx = NULL;
1592 wpas_connect_work_free(cwork);
1593 radio_work_done(work);
1594}
1595
1596
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001597int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1598{
1599 struct os_reltime now;
1600 u8 addr[ETH_ALEN];
1601
1602 os_get_reltime(&now);
1603 if (wpa_s->last_mac_addr_style == style &&
1604 wpa_s->last_mac_addr_change.sec != 0 &&
1605 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1606 wpa_s->conf->rand_addr_lifetime)) {
1607 wpa_msg(wpa_s, MSG_DEBUG,
1608 "Previously selected random MAC address has not yet expired");
1609 return 0;
1610 }
1611
1612 switch (style) {
1613 case 1:
1614 if (random_mac_addr(addr) < 0)
1615 return -1;
1616 break;
1617 case 2:
1618 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1619 if (random_mac_addr_keep_oui(addr) < 0)
1620 return -1;
1621 break;
1622 default:
1623 return -1;
1624 }
1625
1626 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1627 wpa_msg(wpa_s, MSG_INFO,
1628 "Failed to set random MAC address");
1629 return -1;
1630 }
1631
1632 os_get_reltime(&wpa_s->last_mac_addr_change);
1633 wpa_s->mac_addr_changed = 1;
1634 wpa_s->last_mac_addr_style = style;
1635
1636 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1637 wpa_msg(wpa_s, MSG_INFO,
1638 "Could not update MAC address information");
1639 return -1;
1640 }
1641
1642 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1643 MAC2STR(addr));
1644
1645 return 0;
1646}
1647
1648
1649int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1650{
1651 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1652 !wpa_s->conf->preassoc_mac_addr)
1653 return 0;
1654
1655 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1656}
1657
1658
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001659static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1660
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661/**
1662 * wpa_supplicant_associate - Request association
1663 * @wpa_s: Pointer to wpa_supplicant data
1664 * @bss: Scan results for the selected BSS, or %NULL if not available
1665 * @ssid: Configuration data for the selected network
1666 *
1667 * This function is used to request %wpa_supplicant to associate with a BSS.
1668 */
1669void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1670 struct wpa_bss *bss, struct wpa_ssid *ssid)
1671{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001672 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001673 int rand_style;
1674
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001675 wpa_s->own_disconnect_req = 0;
1676
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001677 /*
1678 * If we are starting a new connection, any previously pending EAPOL
1679 * RX cannot be valid anymore.
1680 */
1681 wpabuf_free(wpa_s->pending_eapol_rx);
1682 wpa_s->pending_eapol_rx = NULL;
1683
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001684 if (ssid->mac_addr == -1)
1685 rand_style = wpa_s->conf->mac_addr;
1686 else
1687 rand_style = ssid->mac_addr;
1688
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001689 wmm_ac_clear_saved_tspecs(wpa_s);
1690 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001691 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001692
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001693 if (wpa_s->last_ssid == ssid) {
1694 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001695 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001696 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1697 wmm_ac_save_tspecs(wpa_s);
1698 wpa_s->reassoc_same_bss = 1;
1699 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001700 }
1701
1702 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001703 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1704 return;
1705 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001706 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001707 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1708 wpa_msg(wpa_s, MSG_INFO,
1709 "Could not restore permanent MAC address");
1710 return;
1711 }
1712 wpa_s->mac_addr_changed = 0;
1713 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1714 wpa_msg(wpa_s, MSG_INFO,
1715 "Could not update MAC address information");
1716 return;
1717 }
1718 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1719 }
1720 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721
1722#ifdef CONFIG_IBSS_RSN
1723 ibss_rsn_deinit(wpa_s->ibss_rsn);
1724 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001725#else /* CONFIG_IBSS_RSN */
1726 if (ssid->mode == WPAS_MODE_IBSS &&
1727 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1728 wpa_msg(wpa_s, MSG_INFO,
1729 "IBSS RSN not supported in the build");
1730 return;
1731 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732#endif /* CONFIG_IBSS_RSN */
1733
1734 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1735 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1736#ifdef CONFIG_AP
1737 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1738 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1739 "mode");
1740 return;
1741 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001742 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1743 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001744 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1745 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001746 return;
1747 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001748 wpa_s->current_bss = bss;
1749#else /* CONFIG_AP */
1750 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1751 "the build");
1752#endif /* CONFIG_AP */
1753 return;
1754 }
1755
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001756 if (ssid->mode == WPAS_MODE_MESH) {
1757#ifdef CONFIG_MESH
1758 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1759 wpa_msg(wpa_s, MSG_INFO,
1760 "Driver does not support mesh mode");
1761 return;
1762 }
1763 if (bss)
1764 ssid->frequency = bss->freq;
1765 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1766 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1767 return;
1768 }
1769 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001770 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1771 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1772 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001773#else /* CONFIG_MESH */
1774 wpa_msg(wpa_s, MSG_ERROR,
1775 "mesh mode support not included in the build");
1776#endif /* CONFIG_MESH */
1777 return;
1778 }
1779
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780#ifdef CONFIG_TDLS
1781 if (bss)
1782 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1783 bss->ie_len);
1784#endif /* CONFIG_TDLS */
1785
1786 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1787 ssid->mode == IEEE80211_MODE_INFRA) {
1788 sme_authenticate(wpa_s, bss, ssid);
1789 return;
1790 }
1791
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001792 if (wpa_s->connect_work) {
1793 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1794 return;
1795 }
1796
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001797 if (radio_work_pending(wpa_s, "connect")) {
1798 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1799 return;
1800 }
1801
Dmitry Shmidt29333592017-01-09 12:27:11 -08001802#ifdef CONFIG_SME
1803 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
1804 /* Clear possibly set auth_alg, if any, from last attempt. */
1805 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
1806 }
1807#endif /* CONFIG_SME */
1808
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001809 wpas_abort_ongoing_scan(wpa_s);
1810
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001811 cwork = os_zalloc(sizeof(*cwork));
1812 if (cwork == NULL)
1813 return;
1814
1815 cwork->bss = bss;
1816 cwork->ssid = ssid;
1817
1818 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1819 wpas_start_assoc_cb, cwork) < 0) {
1820 os_free(cwork);
1821 }
1822}
1823
1824
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001825static int bss_is_ibss(struct wpa_bss *bss)
1826{
1827 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1828 IEEE80211_CAP_IBSS;
1829}
1830
1831
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001832static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1833 const struct wpa_ssid *ssid)
1834{
1835 enum hostapd_hw_mode hw_mode;
1836 struct hostapd_hw_modes *mode = NULL;
1837 u8 channel;
1838 int i;
1839
1840#ifdef CONFIG_HT_OVERRIDES
1841 if (ssid->disable_ht)
1842 return 0;
1843#endif /* CONFIG_HT_OVERRIDES */
1844
1845 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1846 if (hw_mode == NUM_HOSTAPD_MODES)
1847 return 0;
1848 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1849 if (wpa_s->hw.modes[i].mode == hw_mode) {
1850 mode = &wpa_s->hw.modes[i];
1851 break;
1852 }
1853 }
1854
1855 if (!mode)
1856 return 0;
1857
1858 return mode->vht_capab != 0;
1859}
1860
1861
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001862void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1863 const struct wpa_ssid *ssid,
1864 struct hostapd_freq_params *freq)
1865{
1866 enum hostapd_hw_mode hw_mode;
1867 struct hostapd_hw_modes *mode = NULL;
1868 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1869 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001870 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001871 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1872 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001873 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001874 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001875 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001876 int chwidth, seg0, seg1;
1877 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001878
1879 freq->freq = ssid->frequency;
1880
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001881 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1882 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1883
1884 if (ssid->mode != WPAS_MODE_IBSS)
1885 break;
1886
1887 /* Don't adjust control freq in case of fixed_freq */
1888 if (ssid->fixed_freq)
1889 break;
1890
1891 if (!bss_is_ibss(bss))
1892 continue;
1893
1894 if (ssid->ssid_len == bss->ssid_len &&
1895 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1896 wpa_printf(MSG_DEBUG,
1897 "IBSS already found in scan results, adjust control freq: %d",
1898 bss->freq);
1899 freq->freq = bss->freq;
1900 obss_scan = 0;
1901 break;
1902 }
1903 }
1904
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001905 /* For IBSS check HT_IBSS flag */
1906 if (ssid->mode == WPAS_MODE_IBSS &&
1907 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1908 return;
1909
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001910 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1911 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1912 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1913 wpa_printf(MSG_DEBUG,
1914 "IBSS: WEP/TKIP detected, do not try to enable HT");
1915 return;
1916 }
1917
1918 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001919 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1920 if (wpa_s->hw.modes[i].mode == hw_mode) {
1921 mode = &wpa_s->hw.modes[i];
1922 break;
1923 }
1924 }
1925
1926 if (!mode)
1927 return;
1928
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001929#ifdef CONFIG_HT_OVERRIDES
1930 if (ssid->disable_ht) {
1931 freq->ht_enabled = 0;
1932 return;
1933 }
1934#endif /* CONFIG_HT_OVERRIDES */
1935
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001936 freq->ht_enabled = ht_supported(mode);
1937 if (!freq->ht_enabled)
1938 return;
1939
1940 /* Setup higher BW only for 5 GHz */
1941 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1942 return;
1943
1944 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1945 pri_chan = &mode->channels[chan_idx];
1946 if (pri_chan->chan == channel)
1947 break;
1948 pri_chan = NULL;
1949 }
1950 if (!pri_chan)
1951 return;
1952
1953 /* Check primary channel flags */
1954 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1955 return;
1956
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001957#ifdef CONFIG_HT_OVERRIDES
1958 if (ssid->disable_ht40)
1959 return;
1960#endif /* CONFIG_HT_OVERRIDES */
1961
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001962 /* Check/setup HT40+/HT40- */
1963 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1964 if (ht40plus[j] == channel) {
1965 ht40 = 1;
1966 break;
1967 }
1968 }
1969
1970 /* Find secondary channel */
1971 for (i = 0; i < mode->num_channels; i++) {
1972 sec_chan = &mode->channels[i];
1973 if (sec_chan->chan == channel + ht40 * 4)
1974 break;
1975 sec_chan = NULL;
1976 }
1977 if (!sec_chan)
1978 return;
1979
1980 /* Check secondary channel flags */
1981 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1982 return;
1983
1984 freq->channel = pri_chan->chan;
1985
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001986 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001987 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1988 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001989 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001990 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1991 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001992 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001993 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001994
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001995 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001996 struct wpa_scan_results *scan_res;
1997
1998 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1999 if (scan_res == NULL) {
2000 /* Back to HT20 */
2001 freq->sec_channel_offset = 0;
2002 return;
2003 }
2004
2005 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2006 sec_chan->chan);
2007 switch (res) {
2008 case 0:
2009 /* Back to HT20 */
2010 freq->sec_channel_offset = 0;
2011 break;
2012 case 1:
2013 /* Configuration allowed */
2014 break;
2015 case 2:
2016 /* Switch pri/sec channels */
2017 freq->freq = hw_get_freq(mode, sec_chan->chan);
2018 freq->sec_channel_offset = -freq->sec_channel_offset;
2019 freq->channel = sec_chan->chan;
2020 break;
2021 default:
2022 freq->sec_channel_offset = 0;
2023 break;
2024 }
2025
2026 wpa_scan_results_free(scan_res);
2027 }
2028
2029 wpa_printf(MSG_DEBUG,
2030 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2031 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002032
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002033 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002034 return;
2035
2036 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002037 if (ssid->mode == WPAS_MODE_IBSS &&
2038 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002039 return;
2040
2041 vht_freq = *freq;
2042
2043 vht_freq.vht_enabled = vht_supported(mode);
2044 if (!vht_freq.vht_enabled)
2045 return;
2046
2047 /* setup center_freq1, bandwidth */
2048 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2049 if (freq->channel >= vht80[j] &&
2050 freq->channel < vht80[j] + 16)
2051 break;
2052 }
2053
2054 if (j == ARRAY_SIZE(vht80))
2055 return;
2056
2057 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2058 struct hostapd_channel_data *chan;
2059
2060 chan = hw_get_channel_chan(mode, i, NULL);
2061 if (!chan)
2062 return;
2063
2064 /* Back to HT configuration if channel not usable */
2065 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2066 return;
2067 }
2068
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002069 chwidth = VHT_CHANWIDTH_80MHZ;
2070 seg0 = vht80[j] + 6;
2071 seg1 = 0;
2072
2073 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2074 /* setup center_freq2, bandwidth */
2075 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2076 /* Only accept 80 MHz segments separated by a gap */
2077 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2078 continue;
2079 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2080 struct hostapd_channel_data *chan;
2081
2082 chan = hw_get_channel_chan(mode, i, NULL);
2083 if (!chan)
2084 continue;
2085
2086 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2087 HOSTAPD_CHAN_NO_IR |
2088 HOSTAPD_CHAN_RADAR))
2089 continue;
2090
2091 /* Found a suitable second segment for 80+80 */
2092 chwidth = VHT_CHANWIDTH_80P80MHZ;
2093 vht_caps |=
2094 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2095 seg1 = vht80[k] + 6;
2096 }
2097
2098 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2099 break;
2100 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002101 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2102 if (freq->freq == 5180) {
2103 chwidth = VHT_CHANWIDTH_160MHZ;
2104 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2105 seg0 = 50;
2106 } else if (freq->freq == 5520) {
2107 chwidth = VHT_CHANWIDTH_160MHZ;
2108 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2109 seg0 = 114;
2110 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002111 }
2112
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002113 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2114 freq->channel, freq->ht_enabled,
2115 vht_freq.vht_enabled,
2116 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002117 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002118 return;
2119
2120 *freq = vht_freq;
2121
2122 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2123 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002124}
2125
2126
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002127static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2128{
2129 struct wpa_connect_work *cwork = work->ctx;
2130 struct wpa_bss *bss = cwork->bss;
2131 struct wpa_ssid *ssid = cwork->ssid;
2132 struct wpa_supplicant *wpa_s = work->wpa_s;
2133 u8 wpa_ie[200];
2134 size_t wpa_ie_len;
2135 int use_crypt, ret, i, bssid_changed;
2136 int algs = WPA_AUTH_ALG_OPEN;
2137 unsigned int cipher_pairwise, cipher_group;
2138 struct wpa_driver_associate_params params;
2139 int wep_keys_set = 0;
2140 int assoc_failed = 0;
2141 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002142 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002143#ifdef CONFIG_HT_OVERRIDES
2144 struct ieee80211_ht_capabilities htcaps;
2145 struct ieee80211_ht_capabilities htcaps_mask;
2146#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002147#ifdef CONFIG_VHT_OVERRIDES
2148 struct ieee80211_vht_capabilities vhtcaps;
2149 struct ieee80211_vht_capabilities vhtcaps_mask;
2150#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002151
2152 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002153 if (work->started) {
2154 wpa_s->connect_work = NULL;
2155
2156 /* cancel possible auth. timeout */
2157 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2158 NULL);
2159 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002160 wpas_connect_work_free(cwork);
2161 return;
2162 }
2163
2164 wpa_s->connect_work = work;
2165
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002166 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2167 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002168 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2169 wpas_connect_work_done(wpa_s);
2170 return;
2171 }
2172
Dmitry Shmidte4663042016-04-04 10:07:49 -07002173 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002174 os_memset(&params, 0, sizeof(params));
2175 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002176 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002177 if (bss &&
2178 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002179#ifdef CONFIG_IEEE80211R
2180 const u8 *ie, *md = NULL;
2181#endif /* CONFIG_IEEE80211R */
2182 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2183 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2184 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2185 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2186 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2187 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2188 if (bssid_changed)
2189 wpas_notify_bssid_changed(wpa_s);
2190#ifdef CONFIG_IEEE80211R
2191 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2192 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2193 md = ie + 2;
2194 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2195 if (md) {
2196 /* Prepare for the next transition */
2197 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2198 }
2199#endif /* CONFIG_IEEE80211R */
2200#ifdef CONFIG_WPS
2201 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2202 wpa_s->conf->ap_scan == 2 &&
2203 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2204 /* Use ap_scan==1 style network selection to find the network
2205 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002206 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002207 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002208 wpa_s->reassociate = 1;
2209 wpa_supplicant_req_scan(wpa_s, 0, 0);
2210 return;
2211#endif /* CONFIG_WPS */
2212 } else {
2213 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2214 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002215 if (bss)
2216 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2217 else
2218 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002219 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002220 if (!wpa_s->pno)
2221 wpa_supplicant_cancel_sched_scan(wpa_s);
2222
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002223 wpa_supplicant_cancel_scan(wpa_s);
2224
2225 /* Starting new association, so clear the possibly used WPA IE from the
2226 * previous association. */
2227 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2228
2229#ifdef IEEE8021X_EAPOL
2230 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2231 if (ssid->leap) {
2232 if (ssid->non_leap == 0)
2233 algs = WPA_AUTH_ALG_LEAP;
2234 else
2235 algs |= WPA_AUTH_ALG_LEAP;
2236 }
2237 }
2238#endif /* IEEE8021X_EAPOL */
2239 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2240 if (ssid->auth_alg) {
2241 algs = ssid->auth_alg;
2242 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2243 "0x%x", algs);
2244 }
2245
2246 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2247 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002248 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002249 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002250 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2251 wpa_s->conf->okc :
2252 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002253 (ssid->proto & WPA_PROTO_RSN);
2254 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002255 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002256 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002257 wpa_ie_len = sizeof(wpa_ie);
2258 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2259 wpa_ie, &wpa_ie_len)) {
2260 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2261 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002262 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002263 return;
2264 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002265 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2266 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2267 /*
2268 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2269 * use non-WPA since the scan results did not indicate that the
2270 * AP is using WPA or WPA2.
2271 */
2272 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2273 wpa_ie_len = 0;
2274 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002275 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276 wpa_ie_len = sizeof(wpa_ie);
2277 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2278 wpa_ie, &wpa_ie_len)) {
2279 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2280 "key management and encryption suites (no "
2281 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002282 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002283 return;
2284 }
2285#ifdef CONFIG_WPS
2286 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2287 struct wpabuf *wps_ie;
2288 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2289 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2290 wpa_ie_len = wpabuf_len(wps_ie);
2291 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2292 } else
2293 wpa_ie_len = 0;
2294 wpabuf_free(wps_ie);
2295 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2296 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2297 params.wps = WPS_MODE_PRIVACY;
2298 else
2299 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002300 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301#endif /* CONFIG_WPS */
2302 } else {
2303 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2304 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002305 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002306 }
2307
2308#ifdef CONFIG_P2P
2309 if (wpa_s->global->p2p) {
2310 u8 *pos;
2311 size_t len;
2312 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313 pos = wpa_ie + wpa_ie_len;
2314 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002315 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2316 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002317 if (res >= 0)
2318 wpa_ie_len += res;
2319 }
2320
2321 wpa_s->cross_connect_disallowed = 0;
2322 if (bss) {
2323 struct wpabuf *p2p;
2324 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2325 if (p2p) {
2326 wpa_s->cross_connect_disallowed =
2327 p2p_get_cross_connect_disallowed(p2p);
2328 wpabuf_free(p2p);
2329 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2330 "connection",
2331 wpa_s->cross_connect_disallowed ?
2332 "disallows" : "allows");
2333 }
2334 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002335
2336 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002337#endif /* CONFIG_P2P */
2338
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002339 if (bss) {
Dmitry Shmidt29333592017-01-09 12:27:11 -08002340 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
2341 wpa_ie + wpa_ie_len,
2342 sizeof(wpa_ie) -
2343 wpa_ie_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002344 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002345
Dmitry Shmidt56052862013-10-04 10:23:25 -07002346 /*
2347 * Workaround: Add Extended Capabilities element only if the AP
2348 * included this element in Beacon/Probe Response frames. Some older
2349 * APs seem to have interoperability issues if this element is
2350 * included, so while the standard may require us to include the
2351 * element in all cases, it is justifiable to skip it to avoid
2352 * interoperability issues.
2353 */
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002354 if (ssid->p2p_group)
2355 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2356 else
2357 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2358
Dmitry Shmidt56052862013-10-04 10:23:25 -07002359 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002360 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002361 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002362 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2363 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002364 if (ext_capab_len > 0) {
2365 u8 *pos = wpa_ie;
2366 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2367 pos += 2 + pos[1];
2368 os_memmove(pos + ext_capab_len, pos,
2369 wpa_ie_len - (pos - wpa_ie));
2370 wpa_ie_len += ext_capab_len;
2371 os_memcpy(pos, ext_capab, ext_capab_len);
2372 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002373 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002374
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002375#ifdef CONFIG_HS20
2376 if (is_hs20_network(wpa_s, ssid, bss)) {
2377 struct wpabuf *hs20;
2378
2379 hs20 = wpabuf_alloc(20);
2380 if (hs20) {
2381 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2382 size_t len;
2383
2384 wpas_hs20_add_indication(hs20, pps_mo_id);
2385 len = sizeof(wpa_ie) - wpa_ie_len;
2386 if (wpabuf_len(hs20) <= len) {
2387 os_memcpy(wpa_ie + wpa_ie_len,
2388 wpabuf_head(hs20), wpabuf_len(hs20));
2389 wpa_ie_len += wpabuf_len(hs20);
2390 }
2391 wpabuf_free(hs20);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002392
2393 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002394 }
2395 }
2396#endif /* CONFIG_HS20 */
2397
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002398 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2399 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2400 size_t len;
2401
2402 len = sizeof(wpa_ie) - wpa_ie_len;
2403 if (wpabuf_len(buf) <= len) {
2404 os_memcpy(wpa_ie + wpa_ie_len,
2405 wpabuf_head(buf), wpabuf_len(buf));
2406 wpa_ie_len += wpabuf_len(buf);
2407 }
2408 }
2409
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002410#ifdef CONFIG_FST
2411 if (wpa_s->fst_ies) {
2412 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2413
2414 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2415 os_memcpy(wpa_ie + wpa_ie_len,
2416 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2417 wpa_ie_len += fst_ies_len;
2418 }
2419 }
2420#endif /* CONFIG_FST */
2421
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002422#ifdef CONFIG_MBO
Dmitry Shmidt29333592017-01-09 12:27:11 -08002423 if (bss && wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002424 int len;
2425
2426 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2427 sizeof(wpa_ie) - wpa_ie_len);
2428 if (len >= 0)
2429 wpa_ie_len += len;
2430 }
2431#endif /* CONFIG_MBO */
2432
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2434 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002435 cipher_pairwise = wpa_s->pairwise_cipher;
2436 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002437 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2438 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2439 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2440 use_crypt = 0;
2441 if (wpa_set_wep_keys(wpa_s, ssid)) {
2442 use_crypt = 1;
2443 wep_keys_set = 1;
2444 }
2445 }
2446 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2447 use_crypt = 0;
2448
2449#ifdef IEEE8021X_EAPOL
2450 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2451 if ((ssid->eapol_flags &
2452 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2453 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2454 !wep_keys_set) {
2455 use_crypt = 0;
2456 } else {
2457 /* Assume that dynamic WEP-104 keys will be used and
2458 * set cipher suites in order for drivers to expect
2459 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002460 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461 }
2462 }
2463#endif /* IEEE8021X_EAPOL */
2464
2465 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2466 /* Set the key before (and later after) association */
2467 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2468 }
2469
2470 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2471 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002472 params.ssid = bss->ssid;
2473 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002474 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2475 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002476 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2477 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002478 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002479 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002480 ssid->bssid_set,
2481 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002482 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002483 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002484 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002485 params.bssid_hint = bss->bssid;
2486 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002487 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488 } else {
2489 params.ssid = ssid->ssid;
2490 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002491 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002493
2494 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2495 wpa_s->conf->ap_scan == 2) {
2496 params.bssid = ssid->bssid;
2497 params.fixed_bssid = 1;
2498 }
2499
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002500 /* Initial frequency for IBSS/mesh */
2501 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002502 ssid->frequency > 0 && params.freq.freq == 0)
2503 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002504
2505 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002506 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002507 if (ssid->beacon_int)
2508 params.beacon_int = ssid->beacon_int;
2509 else
2510 params.beacon_int = wpa_s->conf->beacon_int;
2511 }
2512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 params.wpa_ie = wpa_ie;
2514 params.wpa_ie_len = wpa_ie_len;
2515 params.pairwise_suite = cipher_pairwise;
2516 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002517 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002518 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002519 params.auth_alg = algs;
2520 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002521 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002522 for (i = 0; i < NUM_WEP_KEYS; i++) {
2523 if (ssid->wep_key_len[i])
2524 params.wep_key[i] = ssid->wep_key[i];
2525 params.wep_key_len[i] = ssid->wep_key_len[i];
2526 }
2527 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2528
2529 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002530 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2531 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002532 params.passphrase = ssid->passphrase;
2533 if (ssid->psk_set)
2534 params.psk = ssid->psk;
2535 }
2536
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002537 if (wpa_s->conf->key_mgmt_offload) {
2538 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2539 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002540 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2541 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002542 params.req_key_mgmt_offload =
2543 ssid->proactive_key_caching < 0 ?
2544 wpa_s->conf->okc : ssid->proactive_key_caching;
2545 else
2546 params.req_key_mgmt_offload = 1;
2547
2548 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2549 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2550 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2551 ssid->psk_set)
2552 params.psk = ssid->psk;
2553 }
2554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 params.drop_unencrypted = use_crypt;
2556
2557#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002558 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002559 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2561 struct wpa_ie_data ie;
2562 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2563 ie.capabilities &
2564 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2565 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2566 "MFP: require MFP");
2567 params.mgmt_frame_protection =
2568 MGMT_FRAME_PROTECTION_REQUIRED;
2569 }
2570 }
2571#endif /* CONFIG_IEEE80211W */
2572
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002573 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002574
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002575 if (wpa_s->p2pdev->set_sta_uapsd)
2576 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002577 else
2578 params.uapsd = -1;
2579
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002580#ifdef CONFIG_HT_OVERRIDES
2581 os_memset(&htcaps, 0, sizeof(htcaps));
2582 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2583 params.htcaps = (u8 *) &htcaps;
2584 params.htcaps_mask = (u8 *) &htcaps_mask;
2585 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2586#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002587#ifdef CONFIG_VHT_OVERRIDES
2588 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2589 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2590 params.vhtcaps = &vhtcaps;
2591 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002592 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002593#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002594
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002595#ifdef CONFIG_P2P
2596 /*
2597 * If multi-channel concurrency is not supported, check for any
2598 * frequency conflict. In case of any frequency conflict, remove the
2599 * least prioritized connection.
2600 */
2601 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002602 int freq, num;
2603 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002604 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002605 wpa_printf(MSG_DEBUG,
2606 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002607 freq, params.freq.freq);
2608 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002609 wpa_s, params.freq.freq, ssid) < 0) {
2610 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002611 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002612 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002613 }
2614 }
2615#endif /* CONFIG_P2P */
2616
Dmitry Shmidte4663042016-04-04 10:07:49 -07002617 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2618 wpa_s->current_ssid)
2619 params.prev_bssid = prev_bssid;
2620
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002621 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622 if (ret < 0) {
2623 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2624 "failed");
2625 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2626 /*
2627 * The driver is known to mean what is saying, so we
2628 * can stop right here; the association will not
2629 * succeed.
2630 */
2631 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002632 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2634 return;
2635 }
2636 /* try to continue anyway; new association will be tried again
2637 * after timeout */
2638 assoc_failed = 1;
2639 }
2640
2641 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2642 /* Set the key after the association just in case association
2643 * cleared the previously configured key. */
2644 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2645 /* No need to timeout authentication since there is no key
2646 * management. */
2647 wpa_supplicant_cancel_auth_timeout(wpa_s);
2648 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2649#ifdef CONFIG_IBSS_RSN
2650 } else if (ssid->mode == WPAS_MODE_IBSS &&
2651 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2652 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2653 /*
2654 * RSN IBSS authentication is per-STA and we can disable the
2655 * per-BSSID authentication.
2656 */
2657 wpa_supplicant_cancel_auth_timeout(wpa_s);
2658#endif /* CONFIG_IBSS_RSN */
2659 } else {
2660 /* Timeout for IEEE 802.11 authentication and association */
2661 int timeout = 60;
2662
2663 if (assoc_failed) {
2664 /* give IBSS a bit more time */
2665 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2666 } else if (wpa_s->conf->ap_scan == 1) {
2667 /* give IBSS a bit more time */
2668 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2669 }
2670 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2671 }
2672
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002673 if (wep_keys_set &&
2674 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675 /* Set static WEP keys again */
2676 wpa_set_wep_keys(wpa_s, ssid);
2677 }
2678
2679 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2680 /*
2681 * Do not allow EAP session resumption between different
2682 * network configurations.
2683 */
2684 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2685 }
2686 old_ssid = wpa_s->current_ssid;
2687 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002688
2689 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002690 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002691#ifdef CONFIG_HS20
2692 hs20_configure_frame_filters(wpa_s);
2693#endif /* CONFIG_HS20 */
2694 }
2695
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2697 wpa_supplicant_initiate_eapol(wpa_s);
2698 if (old_ssid != wpa_s->current_ssid)
2699 wpas_notify_network_changed(wpa_s);
2700}
2701
2702
2703static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2704 const u8 *addr)
2705{
2706 struct wpa_ssid *old_ssid;
2707
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002708 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002710 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002711 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002712 wpa_sm_set_config(wpa_s->wpa, NULL);
2713 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2714 if (old_ssid != wpa_s->current_ssid)
2715 wpas_notify_network_changed(wpa_s);
2716 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2717}
2718
2719
2720/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002721 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2722 * @wpa_s: Pointer to wpa_supplicant data
2723 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2724 *
2725 * This function is used to request %wpa_supplicant to deauthenticate from the
2726 * current AP.
2727 */
2728void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2729 int reason_code)
2730{
2731 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002732 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002733 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002735 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2736 " pending_bssid=" MACSTR " reason=%d state=%s",
2737 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2738 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2739
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002740 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2741 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2742 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002743 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002744 else if (!is_zero_ether_addr(wpa_s->bssid))
2745 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002746 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2747 /*
2748 * When using driver-based BSS selection, we may not know the
2749 * BSSID with which we are currently trying to associate. We
2750 * need to notify the driver of this disconnection even in such
2751 * a case, so use the all zeros address here.
2752 */
2753 addr = wpa_s->bssid;
2754 zero_addr = 1;
2755 }
2756
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002757#ifdef CONFIG_TDLS
2758 wpa_tdls_teardown_peers(wpa_s->wpa);
2759#endif /* CONFIG_TDLS */
2760
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002761#ifdef CONFIG_MESH
2762 if (wpa_s->ifmsh) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002763 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2764 wpa_s->ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002765 wpa_supplicant_leave_mesh(wpa_s);
2766 }
2767#endif /* CONFIG_MESH */
2768
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002769 if (addr) {
2770 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002771 os_memset(&event, 0, sizeof(event));
2772 event.deauth_info.reason_code = (u16) reason_code;
2773 event.deauth_info.locally_generated = 1;
2774 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002775 if (zero_addr)
2776 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002777 }
2778
2779 wpa_supplicant_clear_connection(wpa_s, addr);
2780}
2781
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002782static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2783 struct wpa_ssid *ssid)
2784{
2785 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2786 return;
2787
2788 ssid->disabled = 0;
2789 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2790 wpas_notify_network_enabled_changed(wpa_s, ssid);
2791
2792 /*
2793 * Try to reassociate since there is no current configuration and a new
2794 * network was made available.
2795 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002796 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002797 wpa_s->reassociate = 1;
2798}
2799
Roshan Pius950bec92016-07-19 09:49:24 -07002800/**
2801 * wpa_supplicant_add_network - Add a new network.
2802 * @wpa_s: wpa_supplicant structure for a network interface
2803 * Returns: The new network configuration or %NULL if operation failed
2804 *
2805 * This function performs the following operations:
2806 * 1. Adds a new network.
2807 * 2. Send network addition notification.
2808 * 3. Marks the network disabled.
2809 * 4. Set network default parameters.
2810 */
2811struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2812{
2813 struct wpa_ssid *ssid;
2814
2815 ssid = wpa_config_add_network(wpa_s->conf);
2816 if (!ssid) {
2817 return NULL;
2818 }
2819 wpas_notify_network_added(wpa_s, ssid);
2820 ssid->disabled = 1;
2821 wpa_config_set_network_defaults(ssid);
2822
2823 return ssid;
2824}
2825
2826/**
2827 * wpa_supplicant_remove_network - Remove a configured network based on id
2828 * @wpa_s: wpa_supplicant structure for a network interface
2829 * @id: Unique network id to search for
2830 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2831 * could not be removed
2832 *
2833 * This function performs the following operations:
2834 * 1. Removes the network.
2835 * 2. Send network removal notification.
2836 * 3. Update internal state machines.
2837 * 4. Stop any running sched scans.
2838 */
2839int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2840{
2841 struct wpa_ssid *ssid;
2842 int was_disabled;
2843
2844 ssid = wpa_config_get_network(wpa_s->conf, id);
2845 if (ssid)
2846 wpas_notify_network_removed(wpa_s, ssid);
2847 if (ssid == NULL) {
2848 return -1;
2849 }
2850
2851 if (wpa_s->last_ssid == ssid)
2852 wpa_s->last_ssid = NULL;
2853
2854 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2855#ifdef CONFIG_SME
2856 wpa_s->sme.prev_bssid_set = 0;
2857#endif /* CONFIG_SME */
2858 /*
2859 * Invalidate the EAP session cache if the current or
2860 * previously used network is removed.
2861 */
2862 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2863 }
2864
2865 if (ssid == wpa_s->current_ssid) {
2866 wpa_sm_set_config(wpa_s->wpa, NULL);
2867 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2868
2869 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2870 wpa_s->own_disconnect_req = 1;
2871 wpa_supplicant_deauthenticate(wpa_s,
2872 WLAN_REASON_DEAUTH_LEAVING);
2873 }
2874
2875 was_disabled = ssid->disabled;
2876
2877 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2878 return -2;
2879 }
2880
2881 if (!was_disabled && wpa_s->sched_scanning) {
2882 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2883 "network from filters");
2884 wpa_supplicant_cancel_sched_scan(wpa_s);
2885 wpa_supplicant_req_scan(wpa_s, 0, 0);
2886 }
2887 return 0;
2888}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002889
2890/**
2891 * wpa_supplicant_enable_network - Mark a configured network as enabled
2892 * @wpa_s: wpa_supplicant structure for a network interface
2893 * @ssid: wpa_ssid structure for a configured network or %NULL
2894 *
2895 * Enables the specified network or all networks if no network specified.
2896 */
2897void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2898 struct wpa_ssid *ssid)
2899{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002900 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002901 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2902 wpa_supplicant_enable_one_network(wpa_s, ssid);
2903 } else
2904 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002905
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002906 if (wpa_s->reassociate && !wpa_s->disconnected &&
2907 (!wpa_s->current_ssid ||
2908 wpa_s->wpa_state == WPA_DISCONNECTED ||
2909 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002910 if (wpa_s->sched_scanning) {
2911 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2912 "new network to scan filters");
2913 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002914 }
2915
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002916 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2917 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002918 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002919 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002920 }
2921}
2922
2923
2924/**
2925 * wpa_supplicant_disable_network - Mark a configured network as disabled
2926 * @wpa_s: wpa_supplicant structure for a network interface
2927 * @ssid: wpa_ssid structure for a configured network or %NULL
2928 *
2929 * Disables the specified network or all networks if no network specified.
2930 */
2931void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2932 struct wpa_ssid *ssid)
2933{
2934 struct wpa_ssid *other_ssid;
2935 int was_disabled;
2936
2937 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002938 if (wpa_s->sched_scanning)
2939 wpa_supplicant_cancel_sched_scan(wpa_s);
2940
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002941 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2942 other_ssid = other_ssid->next) {
2943 was_disabled = other_ssid->disabled;
2944 if (was_disabled == 2)
2945 continue; /* do not change persistent P2P group
2946 * data */
2947
2948 other_ssid->disabled = 1;
2949
2950 if (was_disabled != other_ssid->disabled)
2951 wpas_notify_network_enabled_changed(
2952 wpa_s, other_ssid);
2953 }
2954 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002955 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002956 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2957 } else if (ssid->disabled != 2) {
2958 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002959 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002960 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2961
2962 was_disabled = ssid->disabled;
2963
2964 ssid->disabled = 1;
2965
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002966 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002967 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002968 if (wpa_s->sched_scanning) {
2969 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2970 "to remove network from filters");
2971 wpa_supplicant_cancel_sched_scan(wpa_s);
2972 wpa_supplicant_req_scan(wpa_s, 0, 0);
2973 }
2974 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002975 }
2976}
2977
2978
2979/**
2980 * wpa_supplicant_select_network - Attempt association with a network
2981 * @wpa_s: wpa_supplicant structure for a network interface
2982 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2983 */
2984void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2985 struct wpa_ssid *ssid)
2986{
2987
2988 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002989 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002990
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002991 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002992 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2993 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002994 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002996 disconnected = 1;
2997 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002998
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002999 if (ssid)
3000 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3001
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003002 /*
3003 * Mark all other networks disabled or mark all networks enabled if no
3004 * network specified.
3005 */
3006 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3007 other_ssid = other_ssid->next) {
3008 int was_disabled = other_ssid->disabled;
3009 if (was_disabled == 2)
3010 continue; /* do not change persistent P2P group data */
3011
3012 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003013 if (was_disabled && !other_ssid->disabled)
3014 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003015
3016 if (was_disabled != other_ssid->disabled)
3017 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3018 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003019
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003020 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3021 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003022 /* We are already associated with the selected network */
3023 wpa_printf(MSG_DEBUG, "Already associated with the "
3024 "selected network - do nothing");
3025 return;
3026 }
3027
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003028 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003029 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003030 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003031 wpa_s->connect_without_scan =
3032 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003033
3034 /*
3035 * Don't optimize next scan freqs since a new ESS has been
3036 * selected.
3037 */
3038 os_free(wpa_s->next_scan_freqs);
3039 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003040 } else {
3041 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003042 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003043
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003044 wpa_s->disconnected = 0;
3045 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003046
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003047 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003048 wpa_supplicant_fast_associate(wpa_s) != 1) {
3049 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003050 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003051 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003052 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003053
3054 if (ssid)
3055 wpas_notify_network_selected(wpa_s, ssid);
3056}
3057
3058
3059/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003060 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3061 * @wpa_s: wpa_supplicant structure for a network interface
3062 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3063 * @pkcs11_module_path: PKCS #11 module path or NULL
3064 * Returns: 0 on success; -1 on failure
3065 *
3066 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3067 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3068 * module path fails the paths will be reset to the default value (NULL).
3069 */
3070int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3071 const char *pkcs11_engine_path,
3072 const char *pkcs11_module_path)
3073{
3074 char *pkcs11_engine_path_copy = NULL;
3075 char *pkcs11_module_path_copy = NULL;
3076
3077 if (pkcs11_engine_path != NULL) {
3078 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3079 if (pkcs11_engine_path_copy == NULL)
3080 return -1;
3081 }
3082 if (pkcs11_module_path != NULL) {
3083 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003084 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003085 os_free(pkcs11_engine_path_copy);
3086 return -1;
3087 }
3088 }
3089
3090 os_free(wpa_s->conf->pkcs11_engine_path);
3091 os_free(wpa_s->conf->pkcs11_module_path);
3092 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3093 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3094
3095 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3096 eapol_sm_deinit(wpa_s->eapol);
3097 wpa_s->eapol = NULL;
3098 if (wpa_supplicant_init_eapol(wpa_s)) {
3099 /* Error -> Reset paths to the default value (NULL) once. */
3100 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3101 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3102 NULL);
3103
3104 return -1;
3105 }
3106 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3107
3108 return 0;
3109}
3110
3111
3112/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003113 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3114 * @wpa_s: wpa_supplicant structure for a network interface
3115 * @ap_scan: AP scan mode
3116 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3117 *
3118 */
3119int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3120{
3121
3122 int old_ap_scan;
3123
3124 if (ap_scan < 0 || ap_scan > 2)
3125 return -1;
3126
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003127 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3128 wpa_printf(MSG_INFO,
3129 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3130 }
3131
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003132#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003133 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3134 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3135 wpa_s->wpa_state < WPA_COMPLETED) {
3136 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3137 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003138 return 0;
3139 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003140#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003141
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003142 old_ap_scan = wpa_s->conf->ap_scan;
3143 wpa_s->conf->ap_scan = ap_scan;
3144
3145 if (old_ap_scan != wpa_s->conf->ap_scan)
3146 wpas_notify_ap_scan_changed(wpa_s);
3147
3148 return 0;
3149}
3150
3151
3152/**
3153 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3154 * @wpa_s: wpa_supplicant structure for a network interface
3155 * @expire_age: Expiration age in seconds
3156 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3157 *
3158 */
3159int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3160 unsigned int bss_expire_age)
3161{
3162 if (bss_expire_age < 10) {
3163 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3164 bss_expire_age);
3165 return -1;
3166 }
3167 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3168 bss_expire_age);
3169 wpa_s->conf->bss_expiration_age = bss_expire_age;
3170
3171 return 0;
3172}
3173
3174
3175/**
3176 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3177 * @wpa_s: wpa_supplicant structure for a network interface
3178 * @expire_count: number of scans after which an unseen BSS is reclaimed
3179 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3180 *
3181 */
3182int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3183 unsigned int bss_expire_count)
3184{
3185 if (bss_expire_count < 1) {
3186 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3187 bss_expire_count);
3188 return -1;
3189 }
3190 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3191 bss_expire_count);
3192 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3193
3194 return 0;
3195}
3196
3197
3198/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003199 * wpa_supplicant_set_scan_interval - Set scan interval
3200 * @wpa_s: wpa_supplicant structure for a network interface
3201 * @scan_interval: scan interval in seconds
3202 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3203 *
3204 */
3205int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3206 int scan_interval)
3207{
3208 if (scan_interval < 0) {
3209 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3210 scan_interval);
3211 return -1;
3212 }
3213 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3214 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003215 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003216
3217 return 0;
3218}
3219
3220
3221/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003222 * wpa_supplicant_set_debug_params - Set global debug params
3223 * @global: wpa_global structure
3224 * @debug_level: debug level
3225 * @debug_timestamp: determines if show timestamp in debug data
3226 * @debug_show_keys: determines if show keys in debug data
3227 * Returns: 0 if succeed or -1 if debug_level has wrong value
3228 */
3229int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3230 int debug_timestamp, int debug_show_keys)
3231{
3232
3233 int old_level, old_timestamp, old_show_keys;
3234
3235 /* check for allowed debuglevels */
3236 if (debug_level != MSG_EXCESSIVE &&
3237 debug_level != MSG_MSGDUMP &&
3238 debug_level != MSG_DEBUG &&
3239 debug_level != MSG_INFO &&
3240 debug_level != MSG_WARNING &&
3241 debug_level != MSG_ERROR)
3242 return -1;
3243
3244 old_level = wpa_debug_level;
3245 old_timestamp = wpa_debug_timestamp;
3246 old_show_keys = wpa_debug_show_keys;
3247
3248 wpa_debug_level = debug_level;
3249 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3250 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3251
3252 if (wpa_debug_level != old_level)
3253 wpas_notify_debug_level_changed(global);
3254 if (wpa_debug_timestamp != old_timestamp)
3255 wpas_notify_debug_timestamp_changed(global);
3256 if (wpa_debug_show_keys != old_show_keys)
3257 wpas_notify_debug_show_keys_changed(global);
3258
3259 return 0;
3260}
3261
3262
3263/**
3264 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3265 * @wpa_s: Pointer to wpa_supplicant data
3266 * Returns: A pointer to the current network structure or %NULL on failure
3267 */
3268struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3269{
3270 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003271 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003272 int res;
3273 size_t ssid_len;
3274 u8 bssid[ETH_ALEN];
3275 int wired;
3276
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003277 res = wpa_drv_get_ssid(wpa_s, ssid);
3278 if (res < 0) {
3279 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3280 "driver");
3281 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003282 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003283 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003284
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003285 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003286 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3287 "driver");
3288 return NULL;
3289 }
3290
3291 wired = wpa_s->conf->ap_scan == 0 &&
3292 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3293
3294 entry = wpa_s->conf->ssid;
3295 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003296 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003297 ((ssid_len == entry->ssid_len &&
3298 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3299 (!entry->bssid_set ||
3300 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3301 return entry;
3302#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003303 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003304 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3305 (entry->ssid == NULL || entry->ssid_len == 0) &&
3306 (!entry->bssid_set ||
3307 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3308 return entry;
3309#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003310
Dmitry Shmidt04949592012-07-19 12:16:46 -07003311 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003312 entry->ssid_len == 0 &&
3313 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3314 return entry;
3315
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003316 entry = entry->next;
3317 }
3318
3319 return NULL;
3320}
3321
3322
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003323static int select_driver(struct wpa_supplicant *wpa_s, int i)
3324{
3325 struct wpa_global *global = wpa_s->global;
3326
3327 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003328 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003329 if (global->drv_priv[i] == NULL) {
3330 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3331 "'%s'", wpa_drivers[i]->name);
3332 return -1;
3333 }
3334 }
3335
3336 wpa_s->driver = wpa_drivers[i];
3337 wpa_s->global_drv_priv = global->drv_priv[i];
3338
3339 return 0;
3340}
3341
3342
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003343static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3344 const char *name)
3345{
3346 int i;
3347 size_t len;
3348 const char *pos, *driver = name;
3349
3350 if (wpa_s == NULL)
3351 return -1;
3352
3353 if (wpa_drivers[0] == NULL) {
3354 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3355 "wpa_supplicant");
3356 return -1;
3357 }
3358
3359 if (name == NULL) {
3360 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003361 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003362 }
3363
3364 do {
3365 pos = os_strchr(driver, ',');
3366 if (pos)
3367 len = pos - driver;
3368 else
3369 len = os_strlen(driver);
3370
3371 for (i = 0; wpa_drivers[i]; i++) {
3372 if (os_strlen(wpa_drivers[i]->name) == len &&
3373 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003374 0) {
3375 /* First driver that succeeds wins */
3376 if (select_driver(wpa_s, i) == 0)
3377 return 0;
3378 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003379 }
3380
3381 driver = pos + 1;
3382 } while (pos);
3383
3384 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3385 return -1;
3386}
3387
3388
3389/**
3390 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3391 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3392 * with struct wpa_driver_ops::init()
3393 * @src_addr: Source address of the EAPOL frame
3394 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3395 * @len: Length of the EAPOL data
3396 *
3397 * This function is called for each received EAPOL frame. Most driver
3398 * interfaces rely on more generic OS mechanism for receiving frames through
3399 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3400 * take care of received EAPOL frames and deliver them to the core supplicant
3401 * code by calling this function.
3402 */
3403void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3404 const u8 *buf, size_t len)
3405{
3406 struct wpa_supplicant *wpa_s = ctx;
3407
3408 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3409 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3410
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003411#ifdef CONFIG_TESTING_OPTIONS
3412 if (wpa_s->ignore_auth_resp) {
3413 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3414 return;
3415 }
3416#endif /* CONFIG_TESTING_OPTIONS */
3417
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003418#ifdef CONFIG_PEERKEY
3419 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3420 wpa_s->current_ssid->peerkey &&
3421 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3422 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3423 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3424 return;
3425 }
3426#endif /* CONFIG_PEERKEY */
3427
Jouni Malinena05074c2012-12-21 21:35:35 +02003428 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3429 (wpa_s->last_eapol_matches_bssid &&
3430#ifdef CONFIG_AP
3431 !wpa_s->ap_iface &&
3432#endif /* CONFIG_AP */
3433 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003434 /*
3435 * There is possible race condition between receiving the
3436 * association event and the EAPOL frame since they are coming
3437 * through different paths from the driver. In order to avoid
3438 * issues in trying to process the EAPOL frame before receiving
3439 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003440 * the association event is received. This may also be needed in
3441 * driver-based roaming case, so also use src_addr != BSSID as a
3442 * trigger if we have previously confirmed that the
3443 * Authenticator uses BSSID as the src_addr (which is not the
3444 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003445 */
3446 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003447 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3448 wpa_supplicant_state_txt(wpa_s->wpa_state),
3449 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003450 wpabuf_free(wpa_s->pending_eapol_rx);
3451 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3452 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003453 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003454 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3455 ETH_ALEN);
3456 }
3457 return;
3458 }
3459
Jouni Malinena05074c2012-12-21 21:35:35 +02003460 wpa_s->last_eapol_matches_bssid =
3461 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463#ifdef CONFIG_AP
3464 if (wpa_s->ap_iface) {
3465 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3466 return;
3467 }
3468#endif /* CONFIG_AP */
3469
3470 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3471 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3472 "no key management is configured");
3473 return;
3474 }
3475
3476 if (wpa_s->eapol_received == 0 &&
3477 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3478 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3479 wpa_s->wpa_state != WPA_COMPLETED) &&
3480 (wpa_s->current_ssid == NULL ||
3481 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3482 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003483 int timeout = 10;
3484
3485 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3486 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3487 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3488 /* Use longer timeout for IEEE 802.1X/EAP */
3489 timeout = 70;
3490 }
3491
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003492#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003493 if (wpa_s->current_ssid && wpa_s->current_bss &&
3494 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3495 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3496 /*
3497 * Use shorter timeout if going through WPS AP iteration
3498 * for PIN config method with an AP that does not
3499 * advertise Selected Registrar.
3500 */
3501 struct wpabuf *wps_ie;
3502
3503 wps_ie = wpa_bss_get_vendor_ie_multi(
3504 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3505 if (wps_ie &&
3506 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3507 timeout = 10;
3508 wpabuf_free(wps_ie);
3509 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003510#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003511
3512 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003513 }
3514 wpa_s->eapol_received++;
3515
3516 if (wpa_s->countermeasures) {
3517 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3518 "EAPOL packet");
3519 return;
3520 }
3521
3522#ifdef CONFIG_IBSS_RSN
3523 if (wpa_s->current_ssid &&
3524 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3525 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3526 return;
3527 }
3528#endif /* CONFIG_IBSS_RSN */
3529
3530 /* Source address of the incoming EAPOL frame could be compared to the
3531 * current BSSID. However, it is possible that a centralized
3532 * Authenticator could be using another MAC address than the BSSID of
3533 * an AP, so just allow any address to be used for now. The replies are
3534 * still sent to the current BSSID (if available), though. */
3535
3536 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3537 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3538 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3539 return;
3540 wpa_drv_poll(wpa_s);
3541 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3542 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3543 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3544 /*
3545 * Set portValid = TRUE here since we are going to skip 4-way
3546 * handshake processing which would normally set portValid. We
3547 * need this to allow the EAPOL state machines to be completed
3548 * without going through EAPOL-Key handshake.
3549 */
3550 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3551 }
3552}
3553
3554
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003555int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003556{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003557 if ((!wpa_s->p2p_mgmt ||
3558 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3559 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003560 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003561 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3562 wpa_drv_get_mac_addr(wpa_s),
3563 ETH_P_EAPOL,
3564 wpa_supplicant_rx_eapol, wpa_s, 0);
3565 if (wpa_s->l2 == NULL)
3566 return -1;
3567 } else {
3568 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3569 if (addr)
3570 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3571 }
3572
3573 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3574 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3575 return -1;
3576 }
3577
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003578 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3579
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003580 return 0;
3581}
3582
3583
Dmitry Shmidt04949592012-07-19 12:16:46 -07003584static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3585 const u8 *buf, size_t len)
3586{
3587 struct wpa_supplicant *wpa_s = ctx;
3588 const struct l2_ethhdr *eth;
3589
3590 if (len < sizeof(*eth))
3591 return;
3592 eth = (const struct l2_ethhdr *) buf;
3593
3594 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3595 !(eth->h_dest[0] & 0x01)) {
3596 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3597 " (bridge - not for this interface - ignore)",
3598 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3599 return;
3600 }
3601
3602 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3603 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3604 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3605 len - sizeof(*eth));
3606}
3607
3608
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003609/**
3610 * wpa_supplicant_driver_init - Initialize driver interface parameters
3611 * @wpa_s: Pointer to wpa_supplicant data
3612 * Returns: 0 on success, -1 on failure
3613 *
3614 * This function is called to initialize driver interface parameters.
3615 * wpa_drv_init() must have been called before this function to initialize the
3616 * driver interface.
3617 */
3618int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3619{
3620 static int interface_count = 0;
3621
3622 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3623 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003624
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003625 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3626 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003627 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003628 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3629
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003630 if (wpa_s->bridge_ifname[0]) {
3631 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3632 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003633 wpa_s->l2_br = l2_packet_init_bridge(
3634 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3635 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003636 if (wpa_s->l2_br == NULL) {
3637 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3638 "connection for the bridge interface '%s'",
3639 wpa_s->bridge_ifname);
3640 return -1;
3641 }
3642 }
3643
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003644 if (wpa_s->conf->ap_scan == 2 &&
3645 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3646 wpa_printf(MSG_INFO,
3647 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3648 }
3649
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003650 wpa_clear_keys(wpa_s, NULL);
3651
3652 /* Make sure that TKIP countermeasures are not left enabled (could
3653 * happen if wpa_supplicant is killed during countermeasures. */
3654 wpa_drv_set_countermeasures(wpa_s, 0);
3655
3656 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3657 wpa_drv_flush_pmkid(wpa_s);
3658
3659 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003660 wpa_s->prev_scan_wildcard = 0;
3661
Dmitry Shmidt04949592012-07-19 12:16:46 -07003662 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003663 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3664 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3665 interface_count = 0;
3666 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003667#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003668 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003669 wpa_supplicant_delayed_sched_scan(wpa_s,
3670 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003671 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003672 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003673 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003674#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675 interface_count++;
3676 } else
3677 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3678
3679 return 0;
3680}
3681
3682
3683static int wpa_supplicant_daemon(const char *pid_file)
3684{
3685 wpa_printf(MSG_DEBUG, "Daemonize..");
3686 return os_daemonize(pid_file);
3687}
3688
3689
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003690static struct wpa_supplicant *
3691wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003692{
3693 struct wpa_supplicant *wpa_s;
3694
3695 wpa_s = os_zalloc(sizeof(*wpa_s));
3696 if (wpa_s == NULL)
3697 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003698 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003699 wpa_s->scan_interval = 5;
3700 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003701 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003702 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003703 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003704
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003705 dl_list_init(&wpa_s->bss_tmp_disallowed);
3706
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003707 return wpa_s;
3708}
3709
3710
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003711#ifdef CONFIG_HT_OVERRIDES
3712
3713static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3714 struct ieee80211_ht_capabilities *htcaps,
3715 struct ieee80211_ht_capabilities *htcaps_mask,
3716 const char *ht_mcs)
3717{
3718 /* parse ht_mcs into hex array */
3719 int i;
3720 const char *tmp = ht_mcs;
3721 char *end = NULL;
3722
3723 /* If ht_mcs is null, do not set anything */
3724 if (!ht_mcs)
3725 return 0;
3726
3727 /* This is what we are setting in the kernel */
3728 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3729
3730 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3731
3732 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3733 errno = 0;
3734 long v = strtol(tmp, &end, 16);
3735 if (errno == 0) {
3736 wpa_msg(wpa_s, MSG_DEBUG,
3737 "htcap value[%i]: %ld end: %p tmp: %p",
3738 i, v, end, tmp);
3739 if (end == tmp)
3740 break;
3741
3742 htcaps->supported_mcs_set[i] = v;
3743 tmp = end;
3744 } else {
3745 wpa_msg(wpa_s, MSG_ERROR,
3746 "Failed to parse ht-mcs: %s, error: %s\n",
3747 ht_mcs, strerror(errno));
3748 return -1;
3749 }
3750 }
3751
3752 /*
3753 * If we were able to parse any values, then set mask for the MCS set.
3754 */
3755 if (i) {
3756 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3757 IEEE80211_HT_MCS_MASK_LEN - 1);
3758 /* skip the 3 reserved bits */
3759 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3760 0x1f;
3761 }
3762
3763 return 0;
3764}
3765
3766
3767static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3768 struct ieee80211_ht_capabilities *htcaps,
3769 struct ieee80211_ht_capabilities *htcaps_mask,
3770 int disabled)
3771{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003772 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003773
3774 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3775
3776 if (disabled == -1)
3777 return 0;
3778
3779 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3780 htcaps_mask->ht_capabilities_info |= msk;
3781 if (disabled)
3782 htcaps->ht_capabilities_info &= msk;
3783 else
3784 htcaps->ht_capabilities_info |= msk;
3785
3786 return 0;
3787}
3788
3789
3790static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3791 struct ieee80211_ht_capabilities *htcaps,
3792 struct ieee80211_ht_capabilities *htcaps_mask,
3793 int factor)
3794{
3795 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3796
3797 if (factor == -1)
3798 return 0;
3799
3800 if (factor < 0 || factor > 3) {
3801 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3802 "Must be 0-3 or -1", factor);
3803 return -EINVAL;
3804 }
3805
3806 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3807 htcaps->a_mpdu_params &= ~0x3;
3808 htcaps->a_mpdu_params |= factor & 0x3;
3809
3810 return 0;
3811}
3812
3813
3814static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3815 struct ieee80211_ht_capabilities *htcaps,
3816 struct ieee80211_ht_capabilities *htcaps_mask,
3817 int density)
3818{
3819 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3820
3821 if (density == -1)
3822 return 0;
3823
3824 if (density < 0 || density > 7) {
3825 wpa_msg(wpa_s, MSG_ERROR,
3826 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3827 density);
3828 return -EINVAL;
3829 }
3830
3831 htcaps_mask->a_mpdu_params |= 0x1C;
3832 htcaps->a_mpdu_params &= ~(0x1C);
3833 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3834
3835 return 0;
3836}
3837
3838
3839static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3840 struct ieee80211_ht_capabilities *htcaps,
3841 struct ieee80211_ht_capabilities *htcaps_mask,
3842 int disabled)
3843{
3844 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003845 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3846 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003847
3848 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3849
3850 if (disabled)
3851 htcaps->ht_capabilities_info &= ~msk;
3852 else
3853 htcaps->ht_capabilities_info |= msk;
3854
3855 htcaps_mask->ht_capabilities_info |= msk;
3856
3857 return 0;
3858}
3859
3860
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003861static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3862 struct ieee80211_ht_capabilities *htcaps,
3863 struct ieee80211_ht_capabilities *htcaps_mask,
3864 int disabled)
3865{
3866 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003867 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3868 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003869
3870 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3871
3872 if (disabled)
3873 htcaps->ht_capabilities_info &= ~msk;
3874 else
3875 htcaps->ht_capabilities_info |= msk;
3876
3877 htcaps_mask->ht_capabilities_info |= msk;
3878
3879 return 0;
3880}
3881
3882
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003883static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3884 struct ieee80211_ht_capabilities *htcaps,
3885 struct ieee80211_ht_capabilities *htcaps_mask,
3886 int disabled)
3887{
3888 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003889 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003890
3891 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3892
3893 if (disabled)
3894 htcaps->ht_capabilities_info &= ~msk;
3895 else
3896 htcaps->ht_capabilities_info |= msk;
3897
3898 htcaps_mask->ht_capabilities_info |= msk;
3899
3900 return 0;
3901}
3902
3903
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003904void wpa_supplicant_apply_ht_overrides(
3905 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3906 struct wpa_driver_associate_params *params)
3907{
3908 struct ieee80211_ht_capabilities *htcaps;
3909 struct ieee80211_ht_capabilities *htcaps_mask;
3910
3911 if (!ssid)
3912 return;
3913
3914 params->disable_ht = ssid->disable_ht;
3915 if (!params->htcaps || !params->htcaps_mask)
3916 return;
3917
3918 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3919 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3920 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3921 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3922 ssid->disable_max_amsdu);
3923 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3924 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3925 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003926 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003927 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003928
3929 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003930 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003931 htcaps->ht_capabilities_info |= bit;
3932 htcaps_mask->ht_capabilities_info |= bit;
3933 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003934}
3935
3936#endif /* CONFIG_HT_OVERRIDES */
3937
3938
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003939#ifdef CONFIG_VHT_OVERRIDES
3940void wpa_supplicant_apply_vht_overrides(
3941 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3942 struct wpa_driver_associate_params *params)
3943{
3944 struct ieee80211_vht_capabilities *vhtcaps;
3945 struct ieee80211_vht_capabilities *vhtcaps_mask;
3946
3947 if (!ssid)
3948 return;
3949
3950 params->disable_vht = ssid->disable_vht;
3951
3952 vhtcaps = (void *) params->vhtcaps;
3953 vhtcaps_mask = (void *) params->vhtcaps_mask;
3954
3955 if (!vhtcaps || !vhtcaps_mask)
3956 return;
3957
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003958 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
3959 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003960
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003961#ifdef CONFIG_HT_OVERRIDES
3962 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003963 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3964 int max_ampdu;
3965
3966 max_ampdu = (ssid->vht_capa &
3967 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3968 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003969
3970 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3971 wpa_set_ampdu_factor(wpa_s,
3972 (void *) params->htcaps,
3973 (void *) params->htcaps_mask,
3974 max_ampdu);
3975 }
3976#endif /* CONFIG_HT_OVERRIDES */
3977
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003978#define OVERRIDE_MCS(i) \
3979 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3980 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003981 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003982 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003983 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
3984 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003985 } \
3986 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3987 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003988 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003989 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003990 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
3991 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003992 }
3993
3994 OVERRIDE_MCS(1);
3995 OVERRIDE_MCS(2);
3996 OVERRIDE_MCS(3);
3997 OVERRIDE_MCS(4);
3998 OVERRIDE_MCS(5);
3999 OVERRIDE_MCS(6);
4000 OVERRIDE_MCS(7);
4001 OVERRIDE_MCS(8);
4002}
4003#endif /* CONFIG_VHT_OVERRIDES */
4004
4005
Dmitry Shmidt04949592012-07-19 12:16:46 -07004006static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4007{
4008#ifdef PCSC_FUNCS
4009 size_t len;
4010
4011 if (!wpa_s->conf->pcsc_reader)
4012 return 0;
4013
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004014 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004015 if (!wpa_s->scard)
4016 return 1;
4017
4018 if (wpa_s->conf->pcsc_pin &&
4019 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4020 scard_deinit(wpa_s->scard);
4021 wpa_s->scard = NULL;
4022 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4023 return -1;
4024 }
4025
4026 len = sizeof(wpa_s->imsi) - 1;
4027 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4028 scard_deinit(wpa_s->scard);
4029 wpa_s->scard = NULL;
4030 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4031 return -1;
4032 }
4033 wpa_s->imsi[len] = '\0';
4034
4035 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4036
4037 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4038 wpa_s->imsi, wpa_s->mnc_len);
4039
4040 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4041 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4042#endif /* PCSC_FUNCS */
4043
4044 return 0;
4045}
4046
4047
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004048int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4049{
4050 char *val, *pos;
4051
4052 ext_password_deinit(wpa_s->ext_pw);
4053 wpa_s->ext_pw = NULL;
4054 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4055
4056 if (!wpa_s->conf->ext_password_backend)
4057 return 0;
4058
4059 val = os_strdup(wpa_s->conf->ext_password_backend);
4060 if (val == NULL)
4061 return -1;
4062 pos = os_strchr(val, ':');
4063 if (pos)
4064 *pos++ = '\0';
4065
4066 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4067
4068 wpa_s->ext_pw = ext_password_init(val, pos);
4069 os_free(val);
4070 if (wpa_s->ext_pw == NULL) {
4071 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4072 return -1;
4073 }
4074 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4075
4076 return 0;
4077}
4078
4079
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004080#ifdef CONFIG_FST
4081
4082static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4083{
4084 struct wpa_supplicant *wpa_s = ctx;
4085
4086 return (is_zero_ether_addr(wpa_s->bssid) ||
4087 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4088}
4089
4090
4091static void wpas_fst_get_channel_info_cb(void *ctx,
4092 enum hostapd_hw_mode *hw_mode,
4093 u8 *channel)
4094{
4095 struct wpa_supplicant *wpa_s = ctx;
4096
4097 if (wpa_s->current_bss) {
4098 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4099 channel);
4100 } else if (wpa_s->hw.num_modes) {
4101 *hw_mode = wpa_s->hw.modes[0].mode;
4102 } else {
4103 WPA_ASSERT(0);
4104 *hw_mode = 0;
4105 }
4106}
4107
4108
4109static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4110{
4111 struct wpa_supplicant *wpa_s = ctx;
4112
4113 *modes = wpa_s->hw.modes;
4114 return wpa_s->hw.num_modes;
4115}
4116
4117
4118static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4119{
4120 struct wpa_supplicant *wpa_s = ctx;
4121
4122 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4123 wpa_s->fst_ies = fst_ies;
4124}
4125
4126
4127static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4128{
4129 struct wpa_supplicant *wpa_s = ctx;
4130
4131 WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
4132 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
4133 wpa_s->own_addr, wpa_s->bssid,
4134 wpabuf_head(data), wpabuf_len(data),
4135 0);
4136}
4137
4138
4139static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4140{
4141 struct wpa_supplicant *wpa_s = ctx;
4142
4143 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4144 return wpa_s->received_mb_ies;
4145}
4146
4147
4148static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4149 const u8 *buf, size_t size)
4150{
4151 struct wpa_supplicant *wpa_s = ctx;
4152 struct mb_ies_info info;
4153
4154 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4155
4156 if (!mb_ies_info_by_ies(&info, buf, size)) {
4157 wpabuf_free(wpa_s->received_mb_ies);
4158 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4159 }
4160}
4161
4162
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004163static const u8 * wpas_fst_get_peer_first(void *ctx,
4164 struct fst_get_peer_ctx **get_ctx,
4165 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004166{
4167 struct wpa_supplicant *wpa_s = ctx;
4168
4169 *get_ctx = NULL;
4170 if (!is_zero_ether_addr(wpa_s->bssid))
4171 return (wpa_s->received_mb_ies || !mb_only) ?
4172 wpa_s->bssid : NULL;
4173 return NULL;
4174}
4175
4176
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004177static const u8 * wpas_fst_get_peer_next(void *ctx,
4178 struct fst_get_peer_ctx **get_ctx,
4179 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004180{
4181 return NULL;
4182}
4183
4184void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4185 struct fst_wpa_obj *iface_obj)
4186{
4187 iface_obj->ctx = wpa_s;
4188 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4189 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4190 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4191 iface_obj->set_ies = wpas_fst_set_ies_cb;
4192 iface_obj->send_action = wpas_fst_send_action_cb;
4193 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4194 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4195 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4196 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4197}
4198#endif /* CONFIG_FST */
4199
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004200static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004201 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004202{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004203 struct wowlan_triggers *triggers;
4204 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004205
4206 if (!wpa_s->conf->wowlan_triggers)
4207 return 0;
4208
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004209 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4210 if (triggers) {
4211 ret = wpa_drv_wowlan(wpa_s, triggers);
4212 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004213 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004214 return ret;
4215}
4216
4217
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004218enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004219{
4220 if (freq < 3000)
4221 return BAND_2_4_GHZ;
4222 if (freq > 50000)
4223 return BAND_60_GHZ;
4224 return BAND_5_GHZ;
4225}
4226
4227
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004228unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004229{
4230 int i;
4231 unsigned int band = 0;
4232
4233 if (freqs) {
4234 /* freqs are specified for the radio work */
4235 for (i = 0; freqs[i]; i++)
4236 band |= wpas_freq_to_band(freqs[i]);
4237 } else {
4238 /*
4239 * freqs are not specified, implies all
4240 * the supported freqs by HW
4241 */
4242 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4243 if (wpa_s->hw.modes[i].num_channels != 0) {
4244 if (wpa_s->hw.modes[i].mode ==
4245 HOSTAPD_MODE_IEEE80211B ||
4246 wpa_s->hw.modes[i].mode ==
4247 HOSTAPD_MODE_IEEE80211G)
4248 band |= BAND_2_4_GHZ;
4249 else if (wpa_s->hw.modes[i].mode ==
4250 HOSTAPD_MODE_IEEE80211A)
4251 band |= BAND_5_GHZ;
4252 else if (wpa_s->hw.modes[i].mode ==
4253 HOSTAPD_MODE_IEEE80211AD)
4254 band |= BAND_60_GHZ;
4255 else if (wpa_s->hw.modes[i].mode ==
4256 HOSTAPD_MODE_IEEE80211ANY)
4257 band = BAND_2_4_GHZ | BAND_5_GHZ |
4258 BAND_60_GHZ;
4259 }
4260 }
4261 }
4262
4263 return band;
4264}
4265
4266
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004267static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4268 const char *rn)
4269{
4270 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4271 struct wpa_radio *radio;
4272
4273 while (rn && iface) {
4274 radio = iface->radio;
4275 if (radio && os_strcmp(rn, radio->name) == 0) {
4276 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4277 wpa_s->ifname, rn);
4278 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4279 return radio;
4280 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004281
4282 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004283 }
4284
4285 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4286 wpa_s->ifname, rn ? rn : "N/A");
4287 radio = os_zalloc(sizeof(*radio));
4288 if (radio == NULL)
4289 return NULL;
4290
4291 if (rn)
4292 os_strlcpy(radio->name, rn, sizeof(radio->name));
4293 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004294 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004295 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4296
4297 return radio;
4298}
4299
4300
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004301static void radio_work_free(struct wpa_radio_work *work)
4302{
4303 if (work->wpa_s->scan_work == work) {
4304 /* This should not really happen. */
4305 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4306 work->type, work, work->started);
4307 work->wpa_s->scan_work = NULL;
4308 }
4309
4310#ifdef CONFIG_P2P
4311 if (work->wpa_s->p2p_scan_work == work) {
4312 /* This should not really happen. */
4313 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4314 work->type, work, work->started);
4315 work->wpa_s->p2p_scan_work = NULL;
4316 }
4317#endif /* CONFIG_P2P */
4318
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004319 if (work->started) {
4320 work->wpa_s->radio->num_active_works--;
4321 wpa_dbg(work->wpa_s, MSG_DEBUG,
4322 "radio_work_free('%s'@%p: num_active_works --> %u",
4323 work->type, work,
4324 work->wpa_s->radio->num_active_works);
4325 }
4326
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004327 dl_list_del(&work->list);
4328 os_free(work);
4329}
4330
4331
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004332static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4333{
4334 struct wpa_radio_work *active_work = NULL;
4335 struct wpa_radio_work *tmp;
4336
4337 /* Get the active work to know the type and band. */
4338 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4339 if (tmp->started) {
4340 active_work = tmp;
4341 break;
4342 }
4343 }
4344
4345 if (!active_work) {
4346 /* No active work, start one */
4347 radio->num_active_works = 0;
4348 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4349 list) {
4350 if (os_strcmp(tmp->type, "scan") == 0 &&
4351 radio->external_scan_running &&
4352 (((struct wpa_driver_scan_params *)
4353 tmp->ctx)->only_new_results ||
4354 tmp->wpa_s->clear_driver_scan_cache))
4355 continue;
4356 return tmp;
4357 }
4358 return NULL;
4359 }
4360
4361 if (os_strcmp(active_work->type, "sme-connect") == 0 ||
4362 os_strcmp(active_work->type, "connect") == 0) {
4363 /*
4364 * If the active work is either connect or sme-connect,
4365 * do not parallelize them with other radio works.
4366 */
4367 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4368 "Do not parallelize radio work with %s",
4369 active_work->type);
4370 return NULL;
4371 }
4372
4373 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4374 if (tmp->started)
4375 continue;
4376
4377 /*
4378 * If connect or sme-connect are enqueued, parallelize only
4379 * those operations ahead of them in the queue.
4380 */
4381 if (os_strcmp(tmp->type, "connect") == 0 ||
4382 os_strcmp(tmp->type, "sme-connect") == 0)
4383 break;
4384
4385 /*
4386 * Check that the radio works are distinct and
4387 * on different bands.
4388 */
4389 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4390 (active_work->bands != tmp->bands)) {
4391 /*
4392 * If a scan has to be scheduled through nl80211 scan
4393 * interface and if an external scan is already running,
4394 * do not schedule the scan since it is likely to get
4395 * rejected by kernel.
4396 */
4397 if (os_strcmp(tmp->type, "scan") == 0 &&
4398 radio->external_scan_running &&
4399 (((struct wpa_driver_scan_params *)
4400 tmp->ctx)->only_new_results ||
4401 tmp->wpa_s->clear_driver_scan_cache))
4402 continue;
4403
4404 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4405 "active_work:%s new_work:%s",
4406 active_work->type, tmp->type);
4407 return tmp;
4408 }
4409 }
4410
4411 /* Did not find a radio work to schedule in parallel. */
4412 return NULL;
4413}
4414
4415
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004416static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4417{
4418 struct wpa_radio *radio = eloop_ctx;
4419 struct wpa_radio_work *work;
4420 struct os_reltime now, diff;
4421 struct wpa_supplicant *wpa_s;
4422
4423 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004424 if (work == NULL) {
4425 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004426 return;
4427 }
4428
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004429 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4430 radio_list);
4431
4432 if (!(wpa_s &&
4433 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4434 if (work->started)
4435 return; /* already started and still in progress */
4436
4437 if (wpa_s && wpa_s->radio->external_scan_running) {
4438 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4439 return;
4440 }
4441 } else {
4442 work = NULL;
4443 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4444 /* get the work to schedule next */
4445 work = radio_work_get_next_work(radio);
4446 }
4447 if (!work)
4448 return;
4449 }
4450
4451 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004452 os_get_reltime(&now);
4453 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004454 wpa_dbg(wpa_s, MSG_DEBUG,
4455 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004456 work->type, work, diff.sec, diff.usec);
4457 work->started = 1;
4458 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004459 radio->num_active_works++;
4460
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004461 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004462
4463 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4464 radio->num_active_works < MAX_ACTIVE_WORKS)
4465 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004466}
4467
4468
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004469/*
4470 * This function removes both started and pending radio works running on
4471 * the provided interface's radio.
4472 * Prior to the removal of the radio work, its callback (cb) is called with
4473 * deinit set to be 1. Each work's callback is responsible for clearing its
4474 * internal data and restoring to a correct state.
4475 * @wpa_s: wpa_supplicant data
4476 * @type: type of works to be removed
4477 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4478 * this interface's works.
4479 */
4480void radio_remove_works(struct wpa_supplicant *wpa_s,
4481 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004482{
4483 struct wpa_radio_work *work, *tmp;
4484 struct wpa_radio *radio = wpa_s->radio;
4485
4486 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4487 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004488 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004489 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004490
4491 /* skip other ifaces' works */
4492 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004493 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004494
4495 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4496 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004497 work->cb(work, 1);
4498 radio_work_free(work);
4499 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004500
4501 /* in case we removed the started work */
4502 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004503}
4504
4505
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004506static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4507{
4508 struct wpa_radio *radio = wpa_s->radio;
4509
4510 if (!radio)
4511 return;
4512
4513 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4514 wpa_s->ifname, radio->name);
4515 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004516 radio_remove_works(wpa_s, NULL, 0);
4517 wpa_s->radio = NULL;
4518 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004519 return; /* Interfaces remain for this radio */
4520
4521 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004522 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004523 os_free(radio);
4524}
4525
4526
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004527void radio_work_check_next(struct wpa_supplicant *wpa_s)
4528{
4529 struct wpa_radio *radio = wpa_s->radio;
4530
4531 if (dl_list_empty(&radio->work))
4532 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004533 if (wpa_s->ext_work_in_progress) {
4534 wpa_printf(MSG_DEBUG,
4535 "External radio work in progress - delay start of pending item");
4536 return;
4537 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004538 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4539 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4540}
4541
4542
4543/**
4544 * radio_add_work - Add a radio work item
4545 * @wpa_s: Pointer to wpa_supplicant data
4546 * @freq: Frequency of the offchannel operation in MHz or 0
4547 * @type: Unique identifier for each type of work
4548 * @next: Force as the next work to be executed
4549 * @cb: Callback function for indicating when radio is available
4550 * @ctx: Context pointer for the work (work->ctx in cb())
4551 * Returns: 0 on success, -1 on failure
4552 *
4553 * This function is used to request time for an operation that requires
4554 * exclusive radio control. Once the radio is available, the registered callback
4555 * function will be called. radio_work_done() must be called once the exclusive
4556 * radio operation has been completed, so that the radio is freed for other
4557 * operations. The special case of deinit=1 is used to free the context data
4558 * during interface removal. That does not allow the callback function to start
4559 * the radio operation, i.e., it must free any resources allocated for the radio
4560 * work and return.
4561 *
4562 * The @freq parameter can be used to indicate a single channel on which the
4563 * offchannel operation will occur. This may allow multiple radio work
4564 * operations to be performed in parallel if they apply for the same channel.
4565 * Setting this to 0 indicates that the work item may use multiple channels or
4566 * requires exclusive control of the radio.
4567 */
4568int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4569 const char *type, int next,
4570 void (*cb)(struct wpa_radio_work *work, int deinit),
4571 void *ctx)
4572{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004573 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004574 struct wpa_radio_work *work;
4575 int was_empty;
4576
4577 work = os_zalloc(sizeof(*work));
4578 if (work == NULL)
4579 return -1;
4580 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4581 os_get_reltime(&work->time);
4582 work->freq = freq;
4583 work->type = type;
4584 work->wpa_s = wpa_s;
4585 work->cb = cb;
4586 work->ctx = ctx;
4587
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004588 if (freq)
4589 work->bands = wpas_freq_to_band(freq);
4590 else if (os_strcmp(type, "scan") == 0 ||
4591 os_strcmp(type, "p2p-scan") == 0)
4592 work->bands = wpas_get_bands(wpa_s,
4593 ((struct wpa_driver_scan_params *)
4594 ctx)->freqs);
4595 else
4596 work->bands = wpas_get_bands(wpa_s, NULL);
4597
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004598 was_empty = dl_list_empty(&wpa_s->radio->work);
4599 if (next)
4600 dl_list_add(&wpa_s->radio->work, &work->list);
4601 else
4602 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4603 if (was_empty) {
4604 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4605 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004606 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4607 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4608 wpa_dbg(wpa_s, MSG_DEBUG,
4609 "Try to schedule a radio work (num_active_works=%u)",
4610 radio->num_active_works);
4611 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004612 }
4613
4614 return 0;
4615}
4616
4617
4618/**
4619 * radio_work_done - Indicate that a radio work item has been completed
4620 * @work: Completed work
4621 *
4622 * This function is called once the callback function registered with
4623 * radio_add_work() has completed its work.
4624 */
4625void radio_work_done(struct wpa_radio_work *work)
4626{
4627 struct wpa_supplicant *wpa_s = work->wpa_s;
4628 struct os_reltime now, diff;
4629 unsigned int started = work->started;
4630
4631 os_get_reltime(&now);
4632 os_reltime_sub(&now, &work->time, &diff);
4633 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4634 work->type, work, started ? "done" : "canceled",
4635 diff.sec, diff.usec);
4636 radio_work_free(work);
4637 if (started)
4638 radio_work_check_next(wpa_s);
4639}
4640
4641
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004642struct wpa_radio_work *
4643radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004644{
4645 struct wpa_radio_work *work;
4646 struct wpa_radio *radio = wpa_s->radio;
4647
4648 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4649 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004650 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004651 }
4652
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004653 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004654}
4655
4656
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004657static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4658 struct wpa_interface *iface)
4659{
4660 const char *ifname, *driver, *rn;
4661
4662 driver = iface->driver;
4663next_driver:
4664 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4665 return -1;
4666
4667 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4668 if (wpa_s->drv_priv == NULL) {
4669 const char *pos;
4670 pos = driver ? os_strchr(driver, ',') : NULL;
4671 if (pos) {
4672 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4673 "driver interface - try next driver wrapper");
4674 driver = pos + 1;
4675 goto next_driver;
4676 }
4677 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4678 "interface");
4679 return -1;
4680 }
4681 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4682 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4683 "driver_param '%s'", wpa_s->conf->driver_param);
4684 return -1;
4685 }
4686
4687 ifname = wpa_drv_get_ifname(wpa_s);
4688 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4689 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4690 "interface name with '%s'", ifname);
4691 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4692 }
4693
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004694 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004695 if (rn && rn[0] == '\0')
4696 rn = NULL;
4697
4698 wpa_s->radio = radio_add_interface(wpa_s, rn);
4699 if (wpa_s->radio == NULL)
4700 return -1;
4701
4702 return 0;
4703}
4704
4705
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004706static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4707 struct wpa_interface *iface)
4708{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004709 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004710 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004711
4712 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4713 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4714 iface->confname ? iface->confname : "N/A",
4715 iface->driver ? iface->driver : "default",
4716 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4717 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4718
4719 if (iface->confname) {
4720#ifdef CONFIG_BACKEND_FILE
4721 wpa_s->confname = os_rel2abs_path(iface->confname);
4722 if (wpa_s->confname == NULL) {
4723 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4724 "for configuration file '%s'.",
4725 iface->confname);
4726 return -1;
4727 }
4728 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4729 iface->confname, wpa_s->confname);
4730#else /* CONFIG_BACKEND_FILE */
4731 wpa_s->confname = os_strdup(iface->confname);
4732#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004733 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004734 if (wpa_s->conf == NULL) {
4735 wpa_printf(MSG_ERROR, "Failed to read or parse "
4736 "configuration '%s'.", wpa_s->confname);
4737 return -1;
4738 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004739 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4740 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004741
4742 /*
4743 * Override ctrl_interface and driver_param if set on command
4744 * line.
4745 */
4746 if (iface->ctrl_interface) {
4747 os_free(wpa_s->conf->ctrl_interface);
4748 wpa_s->conf->ctrl_interface =
4749 os_strdup(iface->ctrl_interface);
4750 }
4751
4752 if (iface->driver_param) {
4753 os_free(wpa_s->conf->driver_param);
4754 wpa_s->conf->driver_param =
4755 os_strdup(iface->driver_param);
4756 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004757
4758 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4759 os_free(wpa_s->conf->ctrl_interface);
4760 wpa_s->conf->ctrl_interface = NULL;
4761 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004762 } else
4763 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4764 iface->driver_param);
4765
4766 if (wpa_s->conf == NULL) {
4767 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4768 return -1;
4769 }
4770
4771 if (iface->ifname == NULL) {
4772 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4773 return -1;
4774 }
4775 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4776 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4777 iface->ifname);
4778 return -1;
4779 }
4780 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4781
4782 if (iface->bridge_ifname) {
4783 if (os_strlen(iface->bridge_ifname) >=
4784 sizeof(wpa_s->bridge_ifname)) {
4785 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4786 "name '%s'.", iface->bridge_ifname);
4787 return -1;
4788 }
4789 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4790 sizeof(wpa_s->bridge_ifname));
4791 }
4792
4793 /* RSNA Supplicant Key Management - INITIALIZE */
4794 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4795 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4796
4797 /* Initialize driver interface and register driver event handler before
4798 * L2 receive handler so that association events are processed before
4799 * EAPOL-Key packets if both become available for the same select()
4800 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004801 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004802 return -1;
4803
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004804 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4805 return -1;
4806
4807 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4808 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4809 NULL);
4810 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4811
4812 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4813 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4814 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4815 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4816 "dot11RSNAConfigPMKLifetime");
4817 return -1;
4818 }
4819
4820 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4821 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4822 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4823 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4824 "dot11RSNAConfigPMKReauthThreshold");
4825 return -1;
4826 }
4827
4828 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4829 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4830 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4831 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4832 "dot11RSNAConfigSATimeout");
4833 return -1;
4834 }
4835
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004836 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4837 &wpa_s->hw.num_modes,
4838 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004839 if (wpa_s->hw.modes) {
4840 u16 i;
4841
4842 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4843 if (wpa_s->hw.modes[i].vht_capab) {
4844 wpa_s->hw_capab = CAPAB_VHT;
4845 break;
4846 }
4847
4848 if (wpa_s->hw.modes[i].ht_capab &
4849 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4850 wpa_s->hw_capab = CAPAB_HT40;
4851 else if (wpa_s->hw.modes[i].ht_capab &&
4852 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4853 wpa_s->hw_capab = CAPAB_HT;
4854 }
4855 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004856
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004857 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4858 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004859 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004860 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004861 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004862 wpa_s->drv_smps_modes = capa.smps_modes;
4863 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004864 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004865 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004866 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004867 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
4868 wpa_s->max_sched_scan_plan_interval =
4869 capa.max_sched_scan_plan_interval;
4870 wpa_s->max_sched_scan_plan_iterations =
4871 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004872 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4873 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004874 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4875 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004876 wpa_s->extended_capa = capa.extended_capa;
4877 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4878 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004879 wpa_s->num_multichan_concurrent =
4880 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004881 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4882
4883 if (capa.mac_addr_rand_scan_supported)
4884 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4885 if (wpa_s->sched_scan_supported &&
4886 capa.mac_addr_rand_sched_scan_supported)
4887 wpa_s->mac_addr_rand_supported |=
4888 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004889 }
4890 if (wpa_s->max_remain_on_chan == 0)
4891 wpa_s->max_remain_on_chan = 1000;
4892
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004893 /*
4894 * Only take p2p_mgmt parameters when P2P Device is supported.
4895 * Doing it here as it determines whether l2_packet_init() will be done
4896 * during wpa_supplicant_driver_init().
4897 */
4898 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4899 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4900 else
4901 iface->p2p_mgmt = 1;
4902
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004903 if (wpa_s->num_multichan_concurrent == 0)
4904 wpa_s->num_multichan_concurrent = 1;
4905
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004906 if (wpa_supplicant_driver_init(wpa_s) < 0)
4907 return -1;
4908
4909#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004910 if ((!iface->p2p_mgmt ||
4911 !(wpa_s->drv_flags &
4912 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4913 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004914 return -1;
4915#endif /* CONFIG_TDLS */
4916
4917 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4918 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4919 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4920 return -1;
4921 }
4922
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004923#ifdef CONFIG_FST
4924 if (wpa_s->conf->fst_group_id) {
4925 struct fst_iface_cfg cfg;
4926 struct fst_wpa_obj iface_obj;
4927
4928 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4929 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4930 sizeof(cfg.group_id));
4931 cfg.priority = wpa_s->conf->fst_priority;
4932 cfg.llt = wpa_s->conf->fst_llt;
4933
4934 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4935 &iface_obj, &cfg);
4936 if (!wpa_s->fst) {
4937 wpa_msg(wpa_s, MSG_ERROR,
4938 "FST: Cannot attach iface %s to group %s",
4939 wpa_s->ifname, cfg.group_id);
4940 return -1;
4941 }
4942 }
4943#endif /* CONFIG_FST */
4944
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004945 if (wpas_wps_init(wpa_s))
4946 return -1;
4947
4948 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4949 return -1;
4950 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4951
4952 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4953 if (wpa_s->ctrl_iface == NULL) {
4954 wpa_printf(MSG_ERROR,
4955 "Failed to initialize control interface '%s'.\n"
4956 "You may have another wpa_supplicant process "
4957 "already running or the file was\n"
4958 "left by an unclean termination of wpa_supplicant "
4959 "in which case you will need\n"
4960 "to manually remove this file before starting "
4961 "wpa_supplicant again.\n",
4962 wpa_s->conf->ctrl_interface);
4963 return -1;
4964 }
4965
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004966 wpa_s->gas = gas_query_init(wpa_s);
4967 if (wpa_s->gas == NULL) {
4968 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4969 return -1;
4970 }
4971
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004972 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004973 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4974 return -1;
4975 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004976
4977 if (wpa_bss_init(wpa_s) < 0)
4978 return -1;
4979
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004980 /*
4981 * Set Wake-on-WLAN triggers, if configured.
4982 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4983 * have effect anyway when the interface is down).
4984 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004985 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004986 return -1;
4987
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004988#ifdef CONFIG_EAP_PROXY
4989{
4990 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004991 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4992 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004993 if (wpa_s->mnc_len > 0) {
4994 wpa_s->imsi[len] = '\0';
4995 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4996 wpa_s->imsi, wpa_s->mnc_len);
4997 } else {
4998 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4999 }
5000}
5001#endif /* CONFIG_EAP_PROXY */
5002
Dmitry Shmidt04949592012-07-19 12:16:46 -07005003 if (pcsc_reader_init(wpa_s) < 0)
5004 return -1;
5005
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005006 if (wpas_init_ext_pw(wpa_s) < 0)
5007 return -1;
5008
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005009 wpas_rrm_reset(wpa_s);
5010
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005011 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5012
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005013#ifdef CONFIG_HS20
5014 hs20_init(wpa_s);
5015#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005016#ifdef CONFIG_MBO
5017 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5018#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005019
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005020 wpa_supplicant_set_default_scan_ies(wpa_s);
5021
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005022 return 0;
5023}
5024
5025
5026static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005027 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005028{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005029 struct wpa_global *global = wpa_s->global;
5030 struct wpa_supplicant *iface, *prev;
5031
5032 if (wpa_s == wpa_s->parent)
5033 wpas_p2p_group_remove(wpa_s, "*");
5034
5035 iface = global->ifaces;
5036 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005037 if (iface->p2pdev == wpa_s)
5038 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005039 if (iface == wpa_s || iface->parent != wpa_s) {
5040 iface = iface->next;
5041 continue;
5042 }
5043 wpa_printf(MSG_DEBUG,
5044 "Remove remaining child interface %s from parent %s",
5045 iface->ifname, wpa_s->ifname);
5046 prev = iface;
5047 iface = iface->next;
5048 wpa_supplicant_remove_iface(global, prev, terminate);
5049 }
5050
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005051 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005052 if (wpa_s->drv_priv) {
5053 wpa_supplicant_deauthenticate(wpa_s,
5054 WLAN_REASON_DEAUTH_LEAVING);
5055
5056 wpa_drv_set_countermeasures(wpa_s, 0);
5057 wpa_clear_keys(wpa_s, NULL);
5058 }
5059
5060 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005061 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005062
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005063 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005064 radio_remove_interface(wpa_s);
5065
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005066#ifdef CONFIG_FST
5067 if (wpa_s->fst) {
5068 fst_detach(wpa_s->fst);
5069 wpa_s->fst = NULL;
5070 }
5071 if (wpa_s->received_mb_ies) {
5072 wpabuf_free(wpa_s->received_mb_ies);
5073 wpa_s->received_mb_ies = NULL;
5074 }
5075#endif /* CONFIG_FST */
5076
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005077 if (wpa_s->drv_priv)
5078 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005079
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005080 if (notify)
5081 wpas_notify_iface_removed(wpa_s);
5082
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005083 if (terminate)
5084 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005085
5086 if (wpa_s->ctrl_iface) {
5087 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5088 wpa_s->ctrl_iface = NULL;
5089 }
5090
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005091#ifdef CONFIG_MESH
5092 if (wpa_s->ifmsh) {
5093 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5094 wpa_s->ifmsh = NULL;
5095 }
5096#endif /* CONFIG_MESH */
5097
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005098 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005099 wpa_config_free(wpa_s->conf);
5100 wpa_s->conf = NULL;
5101 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005102
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005103 os_free(wpa_s->ssids_from_scan_req);
5104
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005105 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005106}
5107
5108
Dmitry Shmidte4663042016-04-04 10:07:49 -07005109#ifdef CONFIG_MATCH_IFACE
5110
5111/**
5112 * wpa_supplicant_match_iface - Match an interface description to a name
5113 * @global: Pointer to global data from wpa_supplicant_init()
5114 * @ifname: Name of the interface to match
5115 * Returns: Pointer to the created interface description or %NULL on failure
5116 */
5117struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5118 const char *ifname)
5119{
5120 int i;
5121 struct wpa_interface *iface, *miface;
5122
5123 for (i = 0; i < global->params.match_iface_count; i++) {
5124 miface = &global->params.match_ifaces[i];
5125 if (!miface->ifname ||
5126 fnmatch(miface->ifname, ifname, 0) == 0) {
5127 iface = os_zalloc(sizeof(*iface));
5128 if (!iface)
5129 return NULL;
5130 *iface = *miface;
5131 iface->ifname = ifname;
5132 return iface;
5133 }
5134 }
5135
5136 return NULL;
5137}
5138
5139
5140/**
5141 * wpa_supplicant_match_existing - Match existing interfaces
5142 * @global: Pointer to global data from wpa_supplicant_init()
5143 * Returns: 0 on success, -1 on failure
5144 */
5145static int wpa_supplicant_match_existing(struct wpa_global *global)
5146{
5147 struct if_nameindex *ifi, *ifp;
5148 struct wpa_supplicant *wpa_s;
5149 struct wpa_interface *iface;
5150
5151 ifp = if_nameindex();
5152 if (!ifp) {
5153 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5154 return -1;
5155 }
5156
5157 for (ifi = ifp; ifi->if_name; ifi++) {
5158 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5159 if (wpa_s)
5160 continue;
5161 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5162 if (iface) {
5163 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5164 os_free(iface);
5165 if (wpa_s)
5166 wpa_s->matched = 1;
5167 }
5168 }
5169
5170 if_freenameindex(ifp);
5171 return 0;
5172}
5173
5174#endif /* CONFIG_MATCH_IFACE */
5175
5176
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005177/**
5178 * wpa_supplicant_add_iface - Add a new network interface
5179 * @global: Pointer to global data from wpa_supplicant_init()
5180 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005181 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005182 * Returns: Pointer to the created interface or %NULL on failure
5183 *
5184 * This function is used to add new network interfaces for %wpa_supplicant.
5185 * This can be called before wpa_supplicant_run() to add interfaces before the
5186 * main event loop has been started. In addition, new interfaces can be added
5187 * dynamically while %wpa_supplicant is already running. This could happen,
5188 * e.g., when a hotplug network adapter is inserted.
5189 */
5190struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005191 struct wpa_interface *iface,
5192 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005193{
5194 struct wpa_supplicant *wpa_s;
5195 struct wpa_interface t_iface;
5196 struct wpa_ssid *ssid;
5197
5198 if (global == NULL || iface == NULL)
5199 return NULL;
5200
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005201 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005202 if (wpa_s == NULL)
5203 return NULL;
5204
5205 wpa_s->global = global;
5206
5207 t_iface = *iface;
5208 if (global->params.override_driver) {
5209 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5210 "('%s' -> '%s')",
5211 iface->driver, global->params.override_driver);
5212 t_iface.driver = global->params.override_driver;
5213 }
5214 if (global->params.override_ctrl_interface) {
5215 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5216 "ctrl_interface ('%s' -> '%s')",
5217 iface->ctrl_interface,
5218 global->params.override_ctrl_interface);
5219 t_iface.ctrl_interface =
5220 global->params.override_ctrl_interface;
5221 }
5222 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5223 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5224 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005225 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005226 return NULL;
5227 }
5228
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005229 /* Notify the control interfaces about new iface */
5230 if (wpas_notify_iface_added(wpa_s)) {
5231 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5232 return NULL;
5233 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005234
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005235 /* Notify the control interfaces about new networks for non p2p mgmt
5236 * ifaces. */
5237 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005238 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5239 wpas_notify_network_added(wpa_s, ssid);
5240 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005241
5242 wpa_s->next = global->ifaces;
5243 global->ifaces = wpa_s;
5244
5245 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005246 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005247
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005248#ifdef CONFIG_P2P
5249 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005250 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005251 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005252 wpas_p2p_add_p2pdev_interface(
5253 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005254 wpa_printf(MSG_INFO,
5255 "P2P: Failed to enable P2P Device interface");
5256 /* Try to continue without. P2P will be disabled. */
5257 }
5258#endif /* CONFIG_P2P */
5259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005260 return wpa_s;
5261}
5262
5263
5264/**
5265 * wpa_supplicant_remove_iface - Remove a network interface
5266 * @global: Pointer to global data from wpa_supplicant_init()
5267 * @wpa_s: Pointer to the network interface to be removed
5268 * Returns: 0 if interface was removed, -1 if interface was not found
5269 *
5270 * This function can be used to dynamically remove network interfaces from
5271 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5272 * addition, this function is used to remove all remaining interfaces when
5273 * %wpa_supplicant is terminated.
5274 */
5275int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005276 struct wpa_supplicant *wpa_s,
5277 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005278{
5279 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005280#ifdef CONFIG_MESH
5281 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5282 char *ifname = NULL;
5283#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005284
5285 /* Remove interface from the global list of interfaces */
5286 prev = global->ifaces;
5287 if (prev == wpa_s) {
5288 global->ifaces = wpa_s->next;
5289 } else {
5290 while (prev && prev->next != wpa_s)
5291 prev = prev->next;
5292 if (prev == NULL)
5293 return -1;
5294 prev->next = wpa_s->next;
5295 }
5296
5297 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5298
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005299#ifdef CONFIG_MESH
5300 if (mesh_if_created) {
5301 ifname = os_strdup(wpa_s->ifname);
5302 if (ifname == NULL) {
5303 wpa_dbg(wpa_s, MSG_ERROR,
5304 "mesh: Failed to malloc ifname");
5305 return -1;
5306 }
5307 }
5308#endif /* CONFIG_MESH */
5309
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005310 if (global->p2p_group_formation == wpa_s)
5311 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005312 if (global->p2p_invite_group == wpa_s)
5313 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005314 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005315
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005316#ifdef CONFIG_MESH
5317 if (mesh_if_created) {
5318 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
5319 os_free(ifname);
5320 }
5321#endif /* CONFIG_MESH */
5322
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005323 return 0;
5324}
5325
5326
5327/**
5328 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5329 * @wpa_s: Pointer to the network interface
5330 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5331 */
5332const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5333{
5334 const char *eapol_method;
5335
5336 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5337 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5338 return "NO-EAP";
5339 }
5340
5341 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5342 if (eapol_method == NULL)
5343 return "UNKNOWN-EAP";
5344
5345 return eapol_method;
5346}
5347
5348
5349/**
5350 * wpa_supplicant_get_iface - Get a new network interface
5351 * @global: Pointer to global data from wpa_supplicant_init()
5352 * @ifname: Interface name
5353 * Returns: Pointer to the interface or %NULL if not found
5354 */
5355struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5356 const char *ifname)
5357{
5358 struct wpa_supplicant *wpa_s;
5359
5360 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5361 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5362 return wpa_s;
5363 }
5364 return NULL;
5365}
5366
5367
5368#ifndef CONFIG_NO_WPA_MSG
5369static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5370{
5371 struct wpa_supplicant *wpa_s = ctx;
5372 if (wpa_s == NULL)
5373 return NULL;
5374 return wpa_s->ifname;
5375}
5376#endif /* CONFIG_NO_WPA_MSG */
5377
5378
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005379#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5380#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5381#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5382
5383/* Periodic cleanup tasks */
5384static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5385{
5386 struct wpa_global *global = eloop_ctx;
5387 struct wpa_supplicant *wpa_s;
5388
5389 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5390 wpas_periodic, global, NULL);
5391
5392#ifdef CONFIG_P2P
5393 if (global->p2p)
5394 p2p_expire_peers(global->p2p);
5395#endif /* CONFIG_P2P */
5396
5397 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5398 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5399#ifdef CONFIG_AP
5400 ap_periodic(wpa_s);
5401#endif /* CONFIG_AP */
5402 }
5403}
5404
5405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005406/**
5407 * wpa_supplicant_init - Initialize %wpa_supplicant
5408 * @params: Parameters for %wpa_supplicant
5409 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5410 *
5411 * This function is used to initialize %wpa_supplicant. After successful
5412 * initialization, the returned data pointer can be used to add and remove
5413 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5414 */
5415struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5416{
5417 struct wpa_global *global;
5418 int ret, i;
5419
5420 if (params == NULL)
5421 return NULL;
5422
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005423#ifdef CONFIG_DRIVER_NDIS
5424 {
5425 void driver_ndis_init_ops(void);
5426 driver_ndis_init_ops();
5427 }
5428#endif /* CONFIG_DRIVER_NDIS */
5429
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005430#ifndef CONFIG_NO_WPA_MSG
5431 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5432#endif /* CONFIG_NO_WPA_MSG */
5433
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005434 if (params->wpa_debug_file_path)
5435 wpa_debug_open_file(params->wpa_debug_file_path);
5436 else
5437 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005438 if (params->wpa_debug_syslog)
5439 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005440 if (params->wpa_debug_tracing) {
5441 ret = wpa_debug_open_linux_tracing();
5442 if (ret) {
5443 wpa_printf(MSG_ERROR,
5444 "Failed to enable trace logging");
5445 return NULL;
5446 }
5447 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005448
5449 ret = eap_register_methods();
5450 if (ret) {
5451 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5452 if (ret == -2)
5453 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5454 "the same EAP type.");
5455 return NULL;
5456 }
5457
5458 global = os_zalloc(sizeof(*global));
5459 if (global == NULL)
5460 return NULL;
5461 dl_list_init(&global->p2p_srv_bonjour);
5462 dl_list_init(&global->p2p_srv_upnp);
5463 global->params.daemonize = params->daemonize;
5464 global->params.wait_for_monitor = params->wait_for_monitor;
5465 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5466 if (params->pid_file)
5467 global->params.pid_file = os_strdup(params->pid_file);
5468 if (params->ctrl_interface)
5469 global->params.ctrl_interface =
5470 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005471 if (params->ctrl_interface_group)
5472 global->params.ctrl_interface_group =
5473 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005474 if (params->override_driver)
5475 global->params.override_driver =
5476 os_strdup(params->override_driver);
5477 if (params->override_ctrl_interface)
5478 global->params.override_ctrl_interface =
5479 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005480#ifdef CONFIG_MATCH_IFACE
5481 global->params.match_iface_count = params->match_iface_count;
5482 if (params->match_iface_count) {
5483 global->params.match_ifaces =
5484 os_calloc(params->match_iface_count,
5485 sizeof(struct wpa_interface));
5486 os_memcpy(global->params.match_ifaces,
5487 params->match_ifaces,
5488 params->match_iface_count *
5489 sizeof(struct wpa_interface));
5490 }
5491#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005492#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005493 if (params->conf_p2p_dev)
5494 global->params.conf_p2p_dev =
5495 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005496#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005497 wpa_debug_level = global->params.wpa_debug_level =
5498 params->wpa_debug_level;
5499 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5500 params->wpa_debug_show_keys;
5501 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5502 params->wpa_debug_timestamp;
5503
5504 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5505
5506 if (eloop_init()) {
5507 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5508 wpa_supplicant_deinit(global);
5509 return NULL;
5510 }
5511
Jouni Malinen75ecf522011-06-27 15:19:46 -07005512 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005513
5514 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5515 if (global->ctrl_iface == NULL) {
5516 wpa_supplicant_deinit(global);
5517 return NULL;
5518 }
5519
5520 if (wpas_notify_supplicant_initialized(global)) {
5521 wpa_supplicant_deinit(global);
5522 return NULL;
5523 }
5524
5525 for (i = 0; wpa_drivers[i]; i++)
5526 global->drv_count++;
5527 if (global->drv_count == 0) {
5528 wpa_printf(MSG_ERROR, "No drivers enabled");
5529 wpa_supplicant_deinit(global);
5530 return NULL;
5531 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005532 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005533 if (global->drv_priv == NULL) {
5534 wpa_supplicant_deinit(global);
5535 return NULL;
5536 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005537
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005538#ifdef CONFIG_WIFI_DISPLAY
5539 if (wifi_display_init(global) < 0) {
5540 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5541 wpa_supplicant_deinit(global);
5542 return NULL;
5543 }
5544#endif /* CONFIG_WIFI_DISPLAY */
5545
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005546 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5547 wpas_periodic, global, NULL);
5548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005549 return global;
5550}
5551
5552
5553/**
5554 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5555 * @global: Pointer to global data from wpa_supplicant_init()
5556 * Returns: 0 after successful event loop run, -1 on failure
5557 *
5558 * This function starts the main event loop and continues running as long as
5559 * there are any remaining events. In most cases, this function is running as
5560 * long as the %wpa_supplicant process in still in use.
5561 */
5562int wpa_supplicant_run(struct wpa_global *global)
5563{
5564 struct wpa_supplicant *wpa_s;
5565
5566 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005567 (wpa_supplicant_daemon(global->params.pid_file) ||
5568 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005569 return -1;
5570
Dmitry Shmidte4663042016-04-04 10:07:49 -07005571#ifdef CONFIG_MATCH_IFACE
5572 if (wpa_supplicant_match_existing(global))
5573 return -1;
5574#endif
5575
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005576 if (global->params.wait_for_monitor) {
5577 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005578 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005579 wpa_supplicant_ctrl_iface_wait(
5580 wpa_s->ctrl_iface);
5581 }
5582
5583 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5584 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5585
5586 eloop_run();
5587
5588 return 0;
5589}
5590
5591
5592/**
5593 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5594 * @global: Pointer to global data from wpa_supplicant_init()
5595 *
5596 * This function is called to deinitialize %wpa_supplicant and to free all
5597 * allocated resources. Remaining network interfaces will also be removed.
5598 */
5599void wpa_supplicant_deinit(struct wpa_global *global)
5600{
5601 int i;
5602
5603 if (global == NULL)
5604 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005605
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005606 eloop_cancel_timeout(wpas_periodic, global, NULL);
5607
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005608#ifdef CONFIG_WIFI_DISPLAY
5609 wifi_display_deinit(global);
5610#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005611
5612 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005613 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005614
5615 if (global->ctrl_iface)
5616 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5617
5618 wpas_notify_supplicant_deinitialized(global);
5619
5620 eap_peer_unregister_methods();
5621#ifdef CONFIG_AP
5622 eap_server_unregister_methods();
5623#endif /* CONFIG_AP */
5624
5625 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5626 if (!global->drv_priv[i])
5627 continue;
5628 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5629 }
5630 os_free(global->drv_priv);
5631
5632 random_deinit();
5633
5634 eloop_destroy();
5635
5636 if (global->params.pid_file) {
5637 os_daemonize_terminate(global->params.pid_file);
5638 os_free(global->params.pid_file);
5639 }
5640 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005641 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005642 os_free(global->params.override_driver);
5643 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005644#ifdef CONFIG_MATCH_IFACE
5645 os_free(global->params.match_ifaces);
5646#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005647#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005648 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005649#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005650
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005651 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005652 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005653 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005654
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005655 os_free(global);
5656 wpa_debug_close_syslog();
5657 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005658 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005659}
5660
5661
5662void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5663{
5664 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5665 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5666 char country[3];
5667 country[0] = wpa_s->conf->country[0];
5668 country[1] = wpa_s->conf->country[1];
5669 country[2] = '\0';
5670 if (wpa_drv_set_country(wpa_s, country) < 0) {
5671 wpa_printf(MSG_ERROR, "Failed to set country code "
5672 "'%s'", country);
5673 }
5674 }
5675
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005676 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5677 wpas_init_ext_pw(wpa_s);
5678
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005679 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5680 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5681
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005682#ifdef CONFIG_WPS
5683 wpas_wps_update_config(wpa_s);
5684#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005685 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005686 wpa_s->conf->changed_parameters = 0;
5687}
5688
5689
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005690void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005691{
5692 int i;
5693
5694 for (i = 0; i < *num_freqs; i++) {
5695 if (freqs[i] == freq)
5696 return;
5697 }
5698
5699 freqs[*num_freqs] = freq;
5700 (*num_freqs)++;
5701}
5702
5703
5704static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5705{
5706 struct wpa_bss *bss, *cbss;
5707 const int max_freqs = 10;
5708 int *freqs;
5709 int num_freqs = 0;
5710
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005711 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005712 if (freqs == NULL)
5713 return NULL;
5714
5715 cbss = wpa_s->current_bss;
5716
5717 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5718 if (bss == cbss)
5719 continue;
5720 if (bss->ssid_len == cbss->ssid_len &&
5721 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5722 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5723 add_freq(freqs, &num_freqs, bss->freq);
5724 if (num_freqs == max_freqs)
5725 break;
5726 }
5727 }
5728
5729 if (num_freqs == 0) {
5730 os_free(freqs);
5731 freqs = NULL;
5732 }
5733
5734 return freqs;
5735}
5736
5737
5738void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5739{
5740 int timeout;
5741 int count;
5742 int *freqs = NULL;
5743
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005744 wpas_connect_work_done(wpa_s);
5745
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005746 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005747 * Remove possible authentication timeout since the connection failed.
5748 */
5749 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5750
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005751 /*
5752 * There is no point in blacklisting the AP if this event is
5753 * generated based on local request to disconnect.
5754 */
5755 if (wpa_s->own_disconnect_req) {
5756 wpa_s->own_disconnect_req = 0;
5757 wpa_dbg(wpa_s, MSG_DEBUG,
5758 "Ignore connection failure due to local request to disconnect");
5759 return;
5760 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005761 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005762 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5763 "indication since interface has been put into "
5764 "disconnected state");
5765 return;
5766 }
5767
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005768 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005769 * Add the failed BSSID into the blacklist and speed up next scan
5770 * attempt if there could be other APs that could accept association.
5771 * The current blacklist count indicates how many times we have tried
5772 * connecting to this AP and multiple attempts mean that other APs are
5773 * either not available or has already been tried, so that we can start
5774 * increasing the delay here to avoid constant scanning.
5775 */
5776 count = wpa_blacklist_add(wpa_s, bssid);
5777 if (count == 1 && wpa_s->current_bss) {
5778 /*
5779 * This BSS was not in the blacklist before. If there is
5780 * another BSS available for the same ESS, we should try that
5781 * next. Otherwise, we may as well try this one once more
5782 * before allowing other, likely worse, ESSes to be considered.
5783 */
5784 freqs = get_bss_freqs_in_ess(wpa_s);
5785 if (freqs) {
5786 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5787 "has been seen; try it next");
5788 wpa_blacklist_add(wpa_s, bssid);
5789 /*
5790 * On the next scan, go through only the known channels
5791 * used in this ESS based on previous scans to speed up
5792 * common load balancing use case.
5793 */
5794 os_free(wpa_s->next_scan_freqs);
5795 wpa_s->next_scan_freqs = freqs;
5796 }
5797 }
5798
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005799 /*
5800 * Add previous failure count in case the temporary blacklist was
5801 * cleared due to no other BSSes being available.
5802 */
5803 count += wpa_s->extra_blacklist_count;
5804
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005805 if (count > 3 && wpa_s->current_ssid) {
5806 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5807 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005808 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005809 }
5810
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005811 switch (count) {
5812 case 1:
5813 timeout = 100;
5814 break;
5815 case 2:
5816 timeout = 500;
5817 break;
5818 case 3:
5819 timeout = 1000;
5820 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005821 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005822 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005823 break;
5824 default:
5825 timeout = 10000;
5826 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005827 }
5828
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005829 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5830 "ms", count, timeout);
5831
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005832 /*
5833 * TODO: if more than one possible AP is available in scan results,
5834 * could try the other ones before requesting a new scan.
5835 */
5836 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5837 1000 * (timeout % 1000));
5838}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005839
5840
5841int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5842{
5843 return wpa_s->conf->ap_scan == 2 ||
5844 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5845}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005846
Dmitry Shmidt04949592012-07-19 12:16:46 -07005847
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005848#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005849int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5850 struct wpa_ssid *ssid,
5851 const char *field,
5852 const char *value)
5853{
5854#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005855 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005856
5857 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5858 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5859 (const u8 *) value, os_strlen(value));
5860
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005861 rtype = wpa_supplicant_ctrl_req_from_string(field);
5862 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
5863#else /* IEEE8021X_EAPOL */
5864 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5865 return -1;
5866#endif /* IEEE8021X_EAPOL */
5867}
5868
5869int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5870 struct wpa_ssid *ssid,
5871 enum wpa_ctrl_req_type rtype,
5872 const char *value)
5873{
5874#ifdef IEEE8021X_EAPOL
5875 struct eap_peer_config *eap = &ssid->eap;
5876
5877 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005878 case WPA_CTRL_REQ_EAP_IDENTITY:
5879 os_free(eap->identity);
5880 eap->identity = (u8 *) os_strdup(value);
5881 eap->identity_len = os_strlen(value);
5882 eap->pending_req_identity = 0;
5883 if (ssid == wpa_s->current_ssid)
5884 wpa_s->reassociate = 1;
5885 break;
5886 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005887 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005888 eap->password = (u8 *) os_strdup(value);
5889 eap->password_len = os_strlen(value);
5890 eap->pending_req_password = 0;
5891 if (ssid == wpa_s->current_ssid)
5892 wpa_s->reassociate = 1;
5893 break;
5894 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005895 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005896 eap->new_password = (u8 *) os_strdup(value);
5897 eap->new_password_len = os_strlen(value);
5898 eap->pending_req_new_password = 0;
5899 if (ssid == wpa_s->current_ssid)
5900 wpa_s->reassociate = 1;
5901 break;
5902 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005903 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005904 eap->pin = os_strdup(value);
5905 eap->pending_req_pin = 0;
5906 if (ssid == wpa_s->current_ssid)
5907 wpa_s->reassociate = 1;
5908 break;
5909 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005910 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005911 eap->otp = (u8 *) os_strdup(value);
5912 eap->otp_len = os_strlen(value);
5913 os_free(eap->pending_req_otp);
5914 eap->pending_req_otp = NULL;
5915 eap->pending_req_otp_len = 0;
5916 break;
5917 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005918 str_clear_free(eap->private_key_passwd);
5919 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005920 eap->pending_req_passphrase = 0;
5921 if (ssid == wpa_s->current_ssid)
5922 wpa_s->reassociate = 1;
5923 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005924 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005925 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005926 eap->external_sim_resp = os_strdup(value);
5927 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005928 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5929 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5930 return -1;
5931 ssid->mem_only_psk = 1;
5932 if (ssid->passphrase)
5933 wpa_config_update_psk(ssid);
5934 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5935 wpa_supplicant_req_scan(wpa_s, 0, 0);
5936 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005937 case WPA_CTRL_REQ_EXT_CERT_CHECK:
5938 if (eap->pending_ext_cert_check != PENDING_CHECK)
5939 return -1;
5940 if (os_strcmp(value, "good") == 0)
5941 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
5942 else if (os_strcmp(value, "bad") == 0)
5943 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
5944 else
5945 return -1;
5946 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005947 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005948 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005949 return -1;
5950 }
5951
5952 return 0;
5953#else /* IEEE8021X_EAPOL */
5954 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5955 return -1;
5956#endif /* IEEE8021X_EAPOL */
5957}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005958#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005959
5960
5961int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5962{
5963 int i;
5964 unsigned int drv_enc;
5965
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005966 if (wpa_s->p2p_mgmt)
5967 return 1; /* no normal network profiles on p2p_mgmt interface */
5968
Dmitry Shmidt04949592012-07-19 12:16:46 -07005969 if (ssid == NULL)
5970 return 1;
5971
5972 if (ssid->disabled)
5973 return 1;
5974
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005975 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005976 drv_enc = wpa_s->drv_enc;
5977 else
5978 drv_enc = (unsigned int) -1;
5979
5980 for (i = 0; i < NUM_WEP_KEYS; i++) {
5981 size_t len = ssid->wep_key_len[i];
5982 if (len == 0)
5983 continue;
5984 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5985 continue;
5986 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5987 continue;
5988 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5989 continue;
5990 return 1; /* invalid WEP key */
5991 }
5992
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005993 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005994 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5995 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005996 return 1;
5997
Dmitry Shmidt04949592012-07-19 12:16:46 -07005998 return 0;
5999}
6000
6001
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006002int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6003{
6004#ifdef CONFIG_IEEE80211W
6005 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6006 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6007 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6008 /*
6009 * Driver does not support BIP -- ignore pmf=1 default
6010 * since the connection with PMF would fail and the
6011 * configuration does not require PMF to be enabled.
6012 */
6013 return NO_MGMT_FRAME_PROTECTION;
6014 }
6015
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006016 if (ssid &&
6017 (ssid->key_mgmt &
6018 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6019 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6020 /*
6021 * Do not use the default PMF value for non-RSN networks
6022 * since PMF is available only with RSN and pmf=2
6023 * configuration would otherwise prevent connections to
6024 * all open networks.
6025 */
6026 return NO_MGMT_FRAME_PROTECTION;
6027 }
6028
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006029 return wpa_s->conf->pmf;
6030 }
6031
6032 return ssid->ieee80211w;
6033#else /* CONFIG_IEEE80211W */
6034 return NO_MGMT_FRAME_PROTECTION;
6035#endif /* CONFIG_IEEE80211W */
6036}
6037
6038
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006039int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006040{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006041 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006042 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006043 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006044 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006045 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006046}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006047
6048
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006049void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006050{
6051 struct wpa_ssid *ssid = wpa_s->current_ssid;
6052 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006053 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006054
6055 if (ssid == NULL) {
6056 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6057 "SSID block");
6058 return;
6059 }
6060
6061 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6062 return;
6063
6064 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006065
6066#ifdef CONFIG_P2P
6067 if (ssid->p2p_group &&
6068 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6069 /*
6070 * Skip the wait time since there is a short timeout on the
6071 * connection to a P2P group.
6072 */
6073 return;
6074 }
6075#endif /* CONFIG_P2P */
6076
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006077 if (ssid->auth_failures > 50)
6078 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006079 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006080 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006081 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006082 dur = 90;
6083 else if (ssid->auth_failures > 3)
6084 dur = 60;
6085 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006086 dur = 30;
6087 else if (ssid->auth_failures > 1)
6088 dur = 20;
6089 else
6090 dur = 10;
6091
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006092 if (ssid->auth_failures > 1 &&
6093 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6094 dur += os_random() % (ssid->auth_failures * 10);
6095
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006096 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006097 if (now.sec + dur <= ssid->disabled_until.sec)
6098 return;
6099
6100 ssid->disabled_until.sec = now.sec + dur;
6101
6102 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006103 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006104 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006105 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006106}
6107
6108
6109void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6110 struct wpa_ssid *ssid, int clear_failures)
6111{
6112 if (ssid == NULL)
6113 return;
6114
6115 if (ssid->disabled_until.sec) {
6116 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6117 "id=%d ssid=\"%s\"",
6118 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6119 }
6120 ssid->disabled_until.sec = 0;
6121 ssid->disabled_until.usec = 0;
6122 if (clear_failures)
6123 ssid->auth_failures = 0;
6124}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006125
6126
6127int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6128{
6129 size_t i;
6130
6131 if (wpa_s->disallow_aps_bssid == NULL)
6132 return 0;
6133
6134 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6135 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6136 bssid, ETH_ALEN) == 0)
6137 return 1;
6138 }
6139
6140 return 0;
6141}
6142
6143
6144int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6145 size_t ssid_len)
6146{
6147 size_t i;
6148
6149 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6150 return 0;
6151
6152 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6153 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6154 if (ssid_len == s->ssid_len &&
6155 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6156 return 1;
6157 }
6158
6159 return 0;
6160}
6161
6162
6163/**
6164 * wpas_request_connection - Request a new connection
6165 * @wpa_s: Pointer to the network interface
6166 *
6167 * This function is used to request a new connection to be found. It will mark
6168 * the interface to allow reassociation and request a new scan to find a
6169 * suitable network to connect to.
6170 */
6171void wpas_request_connection(struct wpa_supplicant *wpa_s)
6172{
6173 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006174 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006175 wpa_supplicant_reinit_autoscan(wpa_s);
6176 wpa_s->extra_blacklist_count = 0;
6177 wpa_s->disconnected = 0;
6178 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006179
6180 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6181 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006182 else
6183 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006184}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006185
Roshan Pius02242d72016-08-09 15:31:48 -07006186/**
6187 * wpas_request_disconnection - Request disconnection
6188 * @wpa_s: Pointer to the network interface
6189 *
6190 * This function is used to request disconnection from the currently connected
6191 * network. This will stop any ongoing scans and initiate deauthentication.
6192 */
6193void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6194{
6195#ifdef CONFIG_SME
6196 wpa_s->sme.prev_bssid_set = 0;
6197#endif /* CONFIG_SME */
6198 wpa_s->reassociate = 0;
6199 wpa_s->disconnected = 1;
6200 wpa_supplicant_cancel_sched_scan(wpa_s);
6201 wpa_supplicant_cancel_scan(wpa_s);
6202 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6203 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6204}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006205
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006206
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006207void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6208 struct wpa_used_freq_data *freqs_data,
6209 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006210{
6211 unsigned int i;
6212
6213 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6214 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006215 for (i = 0; i < len; i++) {
6216 struct wpa_used_freq_data *cur = &freqs_data[i];
6217 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6218 i, cur->freq, cur->flags);
6219 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006220}
6221
6222
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006223/*
6224 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006225 * are using the same radio as the current interface, and in addition, get
6226 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006227 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006228int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6229 struct wpa_used_freq_data *freqs_data,
6230 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006231{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006232 struct wpa_supplicant *ifs;
6233 u8 bssid[ETH_ALEN];
6234 int freq;
6235 unsigned int idx = 0, i;
6236
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006237 wpa_dbg(wpa_s, MSG_DEBUG,
6238 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006239 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006240
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006241 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6242 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006243 if (idx == len)
6244 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006245
6246 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6247 continue;
6248
6249 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006250 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6251 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006252 freq = ifs->current_ssid->frequency;
6253 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6254 freq = ifs->assoc_freq;
6255 else
6256 continue;
6257
6258 /* Hold only distinct freqs */
6259 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006260 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006261 break;
6262
6263 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006264 freqs_data[idx++].freq = freq;
6265
6266 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006267 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006268 WPA_FREQ_USED_BY_P2P_CLIENT :
6269 WPA_FREQ_USED_BY_INFRA_STATION;
6270 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006271 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006272
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006273 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006274 return idx;
6275}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006276
6277
6278/*
6279 * Find the operating frequencies of any of the virtual interfaces that
6280 * are using the same radio as the current interface.
6281 */
6282int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6283 int *freq_array, unsigned int len)
6284{
6285 struct wpa_used_freq_data *freqs_data;
6286 int num, i;
6287
6288 os_memset(freq_array, 0, sizeof(int) * len);
6289
6290 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6291 if (!freqs_data)
6292 return -1;
6293
6294 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6295 for (i = 0; i < num; i++)
6296 freq_array[i] = freqs_data[i].freq;
6297
6298 os_free(freqs_data);
6299
6300 return num;
6301}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006302
6303
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006304struct wpa_supplicant *
6305wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6306{
6307 switch (frame) {
6308#ifdef CONFIG_P2P
6309 case VENDOR_ELEM_PROBE_REQ_P2P:
6310 case VENDOR_ELEM_PROBE_RESP_P2P:
6311 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6312 case VENDOR_ELEM_BEACON_P2P_GO:
6313 case VENDOR_ELEM_P2P_PD_REQ:
6314 case VENDOR_ELEM_P2P_PD_RESP:
6315 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6316 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6317 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6318 case VENDOR_ELEM_P2P_INV_REQ:
6319 case VENDOR_ELEM_P2P_INV_RESP:
6320 case VENDOR_ELEM_P2P_ASSOC_REQ:
6321 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006322 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006323#endif /* CONFIG_P2P */
6324 default:
6325 return wpa_s;
6326 }
6327}
6328
6329
6330void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6331{
6332 unsigned int i;
6333 char buf[30];
6334
6335 wpa_printf(MSG_DEBUG, "Update vendor elements");
6336
6337 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6338 if (wpa_s->vendor_elem[i]) {
6339 int res;
6340
6341 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6342 if (!os_snprintf_error(sizeof(buf), res)) {
6343 wpa_hexdump_buf(MSG_DEBUG, buf,
6344 wpa_s->vendor_elem[i]);
6345 }
6346 }
6347 }
6348
6349#ifdef CONFIG_P2P
6350 if (wpa_s->parent == wpa_s &&
6351 wpa_s->global->p2p &&
6352 !wpa_s->global->p2p_disabled)
6353 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6354#endif /* CONFIG_P2P */
6355}
6356
6357
6358int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6359 const u8 *elem, size_t len)
6360{
6361 u8 *ie, *end;
6362
6363 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6364 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6365
6366 for (; ie + 1 < end; ie += 2 + ie[1]) {
6367 if (ie + len > end)
6368 break;
6369 if (os_memcmp(ie, elem, len) != 0)
6370 continue;
6371
6372 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6373 wpabuf_free(wpa_s->vendor_elem[frame]);
6374 wpa_s->vendor_elem[frame] = NULL;
6375 } else {
6376 os_memmove(ie, ie + len, end - (ie + len));
6377 wpa_s->vendor_elem[frame]->used -= len;
6378 }
6379 wpas_vendor_elem_update(wpa_s);
6380 return 0;
6381 }
6382
6383 return -1;
6384}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006385
6386
6387struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6388 u16 num_modes, enum hostapd_hw_mode mode)
6389{
6390 u16 i;
6391
6392 for (i = 0; i < num_modes; i++) {
6393 if (modes[i].mode == mode)
6394 return &modes[i];
6395 }
6396
6397 return NULL;
6398}
6399
6400
6401static struct
6402wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6403 const u8 *bssid)
6404{
6405 struct wpa_bss_tmp_disallowed *bss;
6406
6407 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6408 struct wpa_bss_tmp_disallowed, list) {
6409 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6410 return bss;
6411 }
6412
6413 return NULL;
6414}
6415
6416
6417void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6418 unsigned int sec)
6419{
6420 struct wpa_bss_tmp_disallowed *bss;
6421 struct os_reltime until;
6422
6423 os_get_reltime(&until);
6424 until.sec += sec;
6425
6426 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6427 if (bss) {
6428 bss->disallowed_until = until;
6429 return;
6430 }
6431
6432 bss = os_malloc(sizeof(*bss));
6433 if (!bss) {
6434 wpa_printf(MSG_DEBUG,
6435 "Failed to allocate memory for temp disallow BSS");
6436 return;
6437 }
6438
6439 bss->disallowed_until = until;
6440 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6441 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
6442}
6443
6444
6445int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6446{
6447 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
6448 struct os_reltime now, age;
6449
6450 os_get_reltime(&now);
6451
6452 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6453 struct wpa_bss_tmp_disallowed, list) {
6454 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
6455 /* This BSS is not disallowed anymore */
6456 dl_list_del(&tmp->list);
6457 os_free(tmp);
6458 continue;
6459 }
6460 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6461 bss = tmp;
6462 break;
6463 }
6464 }
6465 if (!bss)
6466 return 0;
6467
6468 os_reltime_sub(&bss->disallowed_until, &now, &age);
6469 wpa_printf(MSG_DEBUG,
6470 "BSS " MACSTR " disabled for %ld.%0ld seconds",
6471 MAC2STR(bss->bssid), age.sec, age.usec);
6472 return 1;
6473}