blob: 25ec50274a720ccd00718af3986df5b0d927ff4e [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003 * Copyright (c) 2003-2016, 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 Shmidtde47be72016-01-07 12:52:55 -080065"Copyright (c) 2003-2016, 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
332 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800333#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700334}
335
336
337/**
338 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
339 * @wpa_s: Pointer to wpa_supplicant data
340 * @ssid: Configuration data for the network
341 *
342 * This function is used to configure WPA state machine and related parameters
343 * to a mode where WPA is not enabled. This is called as part of the
344 * authentication configuration when the selected network does not use WPA.
345 */
346void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
347 struct wpa_ssid *ssid)
348{
349 int i;
350
351 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
352 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
353 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
354 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
355 else
356 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
357 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
358 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
359 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
360 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
361 wpa_s->group_cipher = WPA_CIPHER_NONE;
362 wpa_s->mgmt_group_cipher = 0;
363
364 for (i = 0; i < NUM_WEP_KEYS; i++) {
365 if (ssid->wep_key_len[i] > 5) {
366 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
367 wpa_s->group_cipher = WPA_CIPHER_WEP104;
368 break;
369 } else if (ssid->wep_key_len[i] > 0) {
370 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
371 wpa_s->group_cipher = WPA_CIPHER_WEP40;
372 break;
373 }
374 }
375
376 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
377 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
378 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
379 wpa_s->pairwise_cipher);
380 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
381#ifdef CONFIG_IEEE80211W
382 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
383 wpa_s->mgmt_group_cipher);
384#endif /* CONFIG_IEEE80211W */
385
386 pmksa_cache_clear_current(wpa_s->wpa);
387}
388
389
Dmitry Shmidt04949592012-07-19 12:16:46 -0700390void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800391{
392 int i;
393 if (wpa_s->hw.modes == NULL)
394 return;
395
396 for (i = 0; i < wpa_s->hw.num_modes; i++) {
397 os_free(wpa_s->hw.modes[i].channels);
398 os_free(wpa_s->hw.modes[i].rates);
399 }
400
401 os_free(wpa_s->hw.modes);
402 wpa_s->hw.modes = NULL;
403}
404
405
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800406static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
407{
408 struct wpa_bss_tmp_disallowed *bss, *prev;
409
410 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
411 struct wpa_bss_tmp_disallowed, list) {
412 dl_list_del(&bss->list);
413 os_free(bss);
414 }
415}
416
417
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
419{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700420 int i;
421
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700422 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700423 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 scard_deinit(wpa_s->scard);
425 wpa_s->scard = NULL;
426 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
427 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
428 l2_packet_deinit(wpa_s->l2);
429 wpa_s->l2 = NULL;
430 if (wpa_s->l2_br) {
431 l2_packet_deinit(wpa_s->l2_br);
432 wpa_s->l2_br = NULL;
433 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800434#ifdef CONFIG_TESTING_OPTIONS
435 l2_packet_deinit(wpa_s->l2_test);
436 wpa_s->l2_test = NULL;
437#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700438
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700439 if (wpa_s->conf != NULL) {
440 struct wpa_ssid *ssid;
441 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
442 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 }
444
445 os_free(wpa_s->confname);
446 wpa_s->confname = NULL;
447
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700448 os_free(wpa_s->confanother);
449 wpa_s->confanother = NULL;
450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451 wpa_sm_set_eapol(wpa_s->wpa, NULL);
452 eapol_sm_deinit(wpa_s->eapol);
453 wpa_s->eapol = NULL;
454
455 rsn_preauth_deinit(wpa_s->wpa);
456
457#ifdef CONFIG_TDLS
458 wpa_tdls_deinit(wpa_s->wpa);
459#endif /* CONFIG_TDLS */
460
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800461 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700462 pmksa_candidate_free(wpa_s->wpa);
463 wpa_sm_deinit(wpa_s->wpa);
464 wpa_s->wpa = NULL;
465 wpa_blacklist_clear(wpa_s);
466
467 wpa_bss_deinit(wpa_s);
468
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700469 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700470 wpa_supplicant_cancel_scan(wpa_s);
471 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800472 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
473#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
474 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
475 wpa_s, NULL);
476#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700477
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700478 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700480 wpas_wps_deinit(wpa_s);
481
482 wpabuf_free(wpa_s->pending_eapol_rx);
483 wpa_s->pending_eapol_rx = NULL;
484
485#ifdef CONFIG_IBSS_RSN
486 ibss_rsn_deinit(wpa_s->ibss_rsn);
487 wpa_s->ibss_rsn = NULL;
488#endif /* CONFIG_IBSS_RSN */
489
490 sme_deinit(wpa_s);
491
492#ifdef CONFIG_AP
493 wpa_supplicant_ap_deinit(wpa_s);
494#endif /* CONFIG_AP */
495
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700496 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700497
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800498#ifdef CONFIG_OFFCHANNEL
499 offchannel_deinit(wpa_s);
500#endif /* CONFIG_OFFCHANNEL */
501
502 wpa_supplicant_cancel_sched_scan(wpa_s);
503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700504 os_free(wpa_s->next_scan_freqs);
505 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800506
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800507 os_free(wpa_s->manual_scan_freqs);
508 wpa_s->manual_scan_freqs = NULL;
509
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700510 os_free(wpa_s->manual_sched_scan_freqs);
511 wpa_s->manual_sched_scan_freqs = NULL;
512
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800513 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
514
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700515 /*
516 * Need to remove any pending gas-query radio work before the
517 * gas_query_deinit() call because gas_query::work has not yet been set
518 * for works that have not been started. gas_query_free() will be unable
519 * to cancel such pending radio works and once the pending gas-query
520 * radio work eventually gets removed, the deinit notification call to
521 * gas_query_start_cb() would result in dereferencing freed memory.
522 */
523 if (wpa_s->radio)
524 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800525 gas_query_deinit(wpa_s->gas);
526 wpa_s->gas = NULL;
527
528 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700529
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700530 ieee802_1x_dealloc_kay_sm(wpa_s);
531
Dmitry Shmidt04949592012-07-19 12:16:46 -0700532 os_free(wpa_s->bssid_filter);
533 wpa_s->bssid_filter = NULL;
534
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800535 os_free(wpa_s->disallow_aps_bssid);
536 wpa_s->disallow_aps_bssid = NULL;
537 os_free(wpa_s->disallow_aps_ssid);
538 wpa_s->disallow_aps_ssid = NULL;
539
Dmitry Shmidt04949592012-07-19 12:16:46 -0700540 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700541#ifdef CONFIG_WNM
542 wnm_deallocate_memory(wpa_s);
543#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700544
545 ext_password_deinit(wpa_s->ext_pw);
546 wpa_s->ext_pw = NULL;
547
548 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800549 wpa_s->last_gas_resp = NULL;
550 wpabuf_free(wpa_s->prev_gas_resp);
551 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700552
553 os_free(wpa_s->last_scan_res);
554 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800555
556#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700557 if (wpa_s->drv_priv)
558 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700559 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800560#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700561
562 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
563 wpabuf_free(wpa_s->vendor_elem[i]);
564 wpa_s->vendor_elem[i] = NULL;
565 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800566
567 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800568
569 wpa_s->sched_scan_plans_num = 0;
570 os_free(wpa_s->sched_scan_plans);
571 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800572
573#ifdef CONFIG_MBO
574 wpa_s->non_pref_chan_num = 0;
575 os_free(wpa_s->non_pref_chan);
576 wpa_s->non_pref_chan = NULL;
577#endif /* CONFIG_MBO */
578
579 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700580
581 wpabuf_free(wpa_s->lci);
582 wpa_s->lci = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700583}
584
585
586/**
587 * wpa_clear_keys - Clear keys configured for the driver
588 * @wpa_s: Pointer to wpa_supplicant data
589 * @addr: Previously used BSSID or %NULL if not available
590 *
591 * This function clears the encryption keys that has been previously configured
592 * for the driver.
593 */
594void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
595{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800596 int i, max;
597
598#ifdef CONFIG_IEEE80211W
599 max = 6;
600#else /* CONFIG_IEEE80211W */
601 max = 4;
602#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700603
604 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800605 for (i = 0; i < max; i++) {
606 if (wpa_s->keys_cleared & BIT(i))
607 continue;
608 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
609 NULL, 0);
610 }
611 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
612 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700613 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
614 0);
615 /* MLME-SETPROTECTION.request(None) */
616 wpa_drv_mlme_setprotection(
617 wpa_s, addr,
618 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
619 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
620 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800621 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700622}
623
624
625/**
626 * wpa_supplicant_state_txt - Get the connection state name as a text string
627 * @state: State (wpa_state; WPA_*)
628 * Returns: The state name as a printable text string
629 */
630const char * wpa_supplicant_state_txt(enum wpa_states state)
631{
632 switch (state) {
633 case WPA_DISCONNECTED:
634 return "DISCONNECTED";
635 case WPA_INACTIVE:
636 return "INACTIVE";
637 case WPA_INTERFACE_DISABLED:
638 return "INTERFACE_DISABLED";
639 case WPA_SCANNING:
640 return "SCANNING";
641 case WPA_AUTHENTICATING:
642 return "AUTHENTICATING";
643 case WPA_ASSOCIATING:
644 return "ASSOCIATING";
645 case WPA_ASSOCIATED:
646 return "ASSOCIATED";
647 case WPA_4WAY_HANDSHAKE:
648 return "4WAY_HANDSHAKE";
649 case WPA_GROUP_HANDSHAKE:
650 return "GROUP_HANDSHAKE";
651 case WPA_COMPLETED:
652 return "COMPLETED";
653 default:
654 return "UNKNOWN";
655 }
656}
657
658
659#ifdef CONFIG_BGSCAN
660
661static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
662{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800663 const char *name;
664
665 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
666 name = wpa_s->current_ssid->bgscan;
667 else
668 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800669 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800670 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800671 if (wpas_driver_bss_selection(wpa_s))
672 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700673 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
674 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800675#ifdef CONFIG_P2P
676 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
677 return;
678#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700679
680 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800681 if (wpa_s->current_ssid) {
682 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700683 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
684 "bgscan");
685 /*
686 * Live without bgscan; it is only used as a roaming
687 * optimization, so the initial connection is not
688 * affected.
689 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700690 } else {
691 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700693 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
694 0);
695 if (scan_res) {
696 bgscan_notify_scan(wpa_s, scan_res);
697 wpa_scan_results_free(scan_res);
698 }
699 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700700 } else
701 wpa_s->bgscan_ssid = NULL;
702}
703
704
705static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
706{
707 if (wpa_s->bgscan_ssid != NULL) {
708 bgscan_deinit(wpa_s);
709 wpa_s->bgscan_ssid = NULL;
710 }
711}
712
713#endif /* CONFIG_BGSCAN */
714
715
Dmitry Shmidt04949592012-07-19 12:16:46 -0700716static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
717{
718 if (autoscan_init(wpa_s, 0))
719 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
720}
721
722
723static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
724{
725 autoscan_deinit(wpa_s);
726}
727
728
729void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
730{
731 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
732 wpa_s->wpa_state == WPA_SCANNING) {
733 autoscan_deinit(wpa_s);
734 wpa_supplicant_start_autoscan(wpa_s);
735 }
736}
737
738
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739/**
740 * wpa_supplicant_set_state - Set current connection state
741 * @wpa_s: Pointer to wpa_supplicant data
742 * @state: The new connection state
743 *
744 * This function is called whenever the connection state changes, e.g.,
745 * association is completed for WPA/WPA2 4-Way Handshake is started.
746 */
747void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
748 enum wpa_states state)
749{
750 enum wpa_states old_state = wpa_s->wpa_state;
751
752 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
753 wpa_supplicant_state_txt(wpa_s->wpa_state),
754 wpa_supplicant_state_txt(state));
755
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800756 if (state == WPA_INTERFACE_DISABLED) {
757 /* Assure normal scan when interface is restored */
758 wpa_s->normal_scans = 0;
759 }
760
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700761 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800762 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700763 /* Reinitialize normal_scan counter */
764 wpa_s->normal_scans = 0;
765 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800766
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700767#ifdef CONFIG_P2P
768 /*
769 * P2PS client has to reply to Probe Request frames received on the
770 * group operating channel. Enable Probe Request frame reporting for
771 * P2P connected client in case p2p_cli_probe configuration property is
772 * set to 1.
773 */
774 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
775 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
776 wpa_s->current_ssid->p2p_group) {
777 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
778 wpa_dbg(wpa_s, MSG_DEBUG,
779 "P2P: Enable CLI Probe Request RX reporting");
780 wpa_s->p2p_cli_probe =
781 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
782 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
783 wpa_dbg(wpa_s, MSG_DEBUG,
784 "P2P: Disable CLI Probe Request RX reporting");
785 wpa_s->p2p_cli_probe = 0;
786 wpa_drv_probe_req_report(wpa_s, 0);
787 }
788 }
789#endif /* CONFIG_P2P */
790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700791 if (state != WPA_SCANNING)
792 wpa_supplicant_notify_scanning(wpa_s, 0);
793
794 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700795 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700796#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700797 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800798 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800799 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700800 ssid ? ssid->id : -1,
801 ssid && ssid->id_str ? ssid->id_str : "");
802#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700803 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700804 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800805 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700806 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807 wpa_drv_set_operstate(wpa_s, 1);
808#ifndef IEEE8021X_EAPOL
809 wpa_drv_set_supp_port(wpa_s, 1);
810#endif /* IEEE8021X_EAPOL */
811 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700812 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700813 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700814
815 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700816 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
817 state == WPA_ASSOCIATED) {
818 wpa_s->new_connection = 1;
819 wpa_drv_set_operstate(wpa_s, 0);
820#ifndef IEEE8021X_EAPOL
821 wpa_drv_set_supp_port(wpa_s, 0);
822#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700823 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700824 }
825 wpa_s->wpa_state = state;
826
827#ifdef CONFIG_BGSCAN
828 if (state == WPA_COMPLETED)
829 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800830 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700831 wpa_supplicant_stop_bgscan(wpa_s);
832#endif /* CONFIG_BGSCAN */
833
Dmitry Shmidt04949592012-07-19 12:16:46 -0700834 if (state == WPA_AUTHENTICATING)
835 wpa_supplicant_stop_autoscan(wpa_s);
836
837 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
838 wpa_supplicant_start_autoscan(wpa_s);
839
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800840 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
841 wmm_ac_notify_disassoc(wpa_s);
842
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700843 if (wpa_s->wpa_state != old_state) {
844 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
845
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700846 /*
847 * Notify the P2P Device interface about a state change in one
848 * of the interfaces.
849 */
850 wpas_p2p_indicate_state_change(wpa_s);
851
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700852 if (wpa_s->wpa_state == WPA_COMPLETED ||
853 old_state == WPA_COMPLETED)
854 wpas_notify_auth_changed(wpa_s);
855 }
856}
857
858
859void wpa_supplicant_terminate_proc(struct wpa_global *global)
860{
861 int pending = 0;
862#ifdef CONFIG_WPS
863 struct wpa_supplicant *wpa_s = global->ifaces;
864 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800865 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700866 if (wpas_wps_terminate_pending(wpa_s) == 1)
867 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700868#ifdef CONFIG_P2P
869 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
870 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
871 wpas_p2p_disconnect(wpa_s);
872#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800873 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700874 }
875#endif /* CONFIG_WPS */
876 if (pending)
877 return;
878 eloop_terminate();
879}
880
881
882static void wpa_supplicant_terminate(int sig, void *signal_ctx)
883{
884 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885 wpa_supplicant_terminate_proc(global);
886}
887
888
889void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
890{
891 enum wpa_states old_state = wpa_s->wpa_state;
892
893 wpa_s->pairwise_cipher = 0;
894 wpa_s->group_cipher = 0;
895 wpa_s->mgmt_group_cipher = 0;
896 wpa_s->key_mgmt = 0;
897 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700898 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700899
900 if (wpa_s->wpa_state != old_state)
901 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
902}
903
904
905/**
906 * wpa_supplicant_reload_configuration - Reload configuration data
907 * @wpa_s: Pointer to wpa_supplicant data
908 * Returns: 0 on success or -1 if configuration parsing failed
909 *
910 * This function can be used to request that the configuration data is reloaded
911 * (e.g., after configuration file change). This function is reloading
912 * configuration only for one interface, so this may need to be called multiple
913 * times if %wpa_supplicant is controlling multiple interfaces and all
914 * interfaces need reconfiguration.
915 */
916int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
917{
918 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700919 int reconf_ctrl;
920 int old_ap_scan;
921
922 if (wpa_s->confname == NULL)
923 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700924 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700925 if (conf == NULL) {
926 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
927 "file '%s' - exiting", wpa_s->confname);
928 return -1;
929 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700930 wpa_config_read(wpa_s->confanother, conf);
931
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700932 conf->changed_parameters = (unsigned int) -1;
933
934 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
935 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
936 os_strcmp(conf->ctrl_interface,
937 wpa_s->conf->ctrl_interface) != 0);
938
939 if (reconf_ctrl && wpa_s->ctrl_iface) {
940 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
941 wpa_s->ctrl_iface = NULL;
942 }
943
944 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800945 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700946 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
947 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800948 wpa_supplicant_deauthenticate(wpa_s,
949 WLAN_REASON_DEAUTH_LEAVING);
950 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700951
952 /*
953 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800954 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700955 */
956 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
957 /*
958 * Clear forced success to clear EAP state for next
959 * authentication.
960 */
961 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
962 }
963 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
964 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800965 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
967 rsn_preauth_deinit(wpa_s->wpa);
968
969 old_ap_scan = wpa_s->conf->ap_scan;
970 wpa_config_free(wpa_s->conf);
971 wpa_s->conf = conf;
972 if (old_ap_scan != wpa_s->conf->ap_scan)
973 wpas_notify_ap_scan_changed(wpa_s);
974
975 if (reconf_ctrl)
976 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
977
978 wpa_supplicant_update_config(wpa_s);
979
980 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700981 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700982 wpa_s->reassociate = 1;
983 wpa_supplicant_req_scan(wpa_s, 0, 0);
984 }
985 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
986 return 0;
987}
988
989
990static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
991{
992 struct wpa_global *global = signal_ctx;
993 struct wpa_supplicant *wpa_s;
994 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
995 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
996 sig);
997 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
998 wpa_supplicant_terminate_proc(global);
999 }
1000 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001001
1002 if (wpa_debug_reopen_file() < 0) {
1003 /* Ignore errors since we cannot really do much to fix this */
1004 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1005 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006}
1007
1008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1010 struct wpa_ssid *ssid,
1011 struct wpa_ie_data *ie)
1012{
1013 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1014 if (ret) {
1015 if (ret == -2) {
1016 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1017 "from association info");
1018 }
1019 return -1;
1020 }
1021
1022 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1023 "cipher suites");
1024 if (!(ie->group_cipher & ssid->group_cipher)) {
1025 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1026 "cipher 0x%x (mask 0x%x) - reject",
1027 ie->group_cipher, ssid->group_cipher);
1028 return -1;
1029 }
1030 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1031 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1032 "cipher 0x%x (mask 0x%x) - reject",
1033 ie->pairwise_cipher, ssid->pairwise_cipher);
1034 return -1;
1035 }
1036 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1037 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1038 "management 0x%x (mask 0x%x) - reject",
1039 ie->key_mgmt, ssid->key_mgmt);
1040 return -1;
1041 }
1042
1043#ifdef CONFIG_IEEE80211W
1044 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001045 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1047 "that does not support management frame protection - "
1048 "reject");
1049 return -1;
1050 }
1051#endif /* CONFIG_IEEE80211W */
1052
1053 return 0;
1054}
1055
1056
1057/**
1058 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1059 * @wpa_s: Pointer to wpa_supplicant data
1060 * @bss: Scan results for the selected BSS, or %NULL if not available
1061 * @ssid: Configuration data for the selected network
1062 * @wpa_ie: Buffer for the WPA/RSN IE
1063 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1064 * used buffer length in case the functions returns success.
1065 * Returns: 0 on success or -1 on failure
1066 *
1067 * This function is used to configure authentication and encryption parameters
1068 * based on the network configuration and scan result for the selected BSS (if
1069 * available).
1070 */
1071int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1072 struct wpa_bss *bss, struct wpa_ssid *ssid,
1073 u8 *wpa_ie, size_t *wpa_ie_len)
1074{
1075 struct wpa_ie_data ie;
1076 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001077 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001078
1079 if (bss) {
1080 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1081 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001082 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001083 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001084 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085
1086 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1087 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1088 (ie.group_cipher & ssid->group_cipher) &&
1089 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1090 (ie.key_mgmt & ssid->key_mgmt)) {
1091 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1092 proto = WPA_PROTO_RSN;
1093 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001094 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001095 (ie.group_cipher & ssid->group_cipher) &&
1096 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1097 (ie.key_mgmt & ssid->key_mgmt)) {
1098 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1099 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001100#ifdef CONFIG_HS20
1101 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1102 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1103 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001104 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001105 ie.group_cipher = WPA_CIPHER_CCMP;
1106 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1107 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1108 proto = WPA_PROTO_OSEN;
1109#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001110 } else if (bss) {
1111 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001112 wpa_dbg(wpa_s, MSG_DEBUG,
1113 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1114 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1115 ssid->key_mgmt);
1116 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1117 MAC2STR(bss->bssid),
1118 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1119 bss_wpa ? " WPA" : "",
1120 bss_rsn ? " RSN" : "",
1121 bss_osen ? " OSEN" : "");
1122 if (bss_rsn) {
1123 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1124 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1125 wpa_dbg(wpa_s, MSG_DEBUG,
1126 "Could not parse RSN element");
1127 } else {
1128 wpa_dbg(wpa_s, MSG_DEBUG,
1129 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1130 ie.pairwise_cipher, ie.group_cipher,
1131 ie.key_mgmt);
1132 }
1133 }
1134 if (bss_wpa) {
1135 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1136 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1137 wpa_dbg(wpa_s, MSG_DEBUG,
1138 "Could not parse WPA element");
1139 } else {
1140 wpa_dbg(wpa_s, MSG_DEBUG,
1141 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1142 ie.pairwise_cipher, ie.group_cipher,
1143 ie.key_mgmt);
1144 }
1145 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146 return -1;
1147 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001148 if (ssid->proto & WPA_PROTO_OSEN)
1149 proto = WPA_PROTO_OSEN;
1150 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001151 proto = WPA_PROTO_RSN;
1152 else
1153 proto = WPA_PROTO_WPA;
1154 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1155 os_memset(&ie, 0, sizeof(ie));
1156 ie.group_cipher = ssid->group_cipher;
1157 ie.pairwise_cipher = ssid->pairwise_cipher;
1158 ie.key_mgmt = ssid->key_mgmt;
1159#ifdef CONFIG_IEEE80211W
1160 ie.mgmt_group_cipher =
1161 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1162 WPA_CIPHER_AES_128_CMAC : 0;
1163#endif /* CONFIG_IEEE80211W */
1164 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1165 "based on configuration");
1166 } else
1167 proto = ie.proto;
1168 }
1169
1170 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1171 "pairwise %d key_mgmt %d proto %d",
1172 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1173#ifdef CONFIG_IEEE80211W
1174 if (ssid->ieee80211w) {
1175 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1176 ie.mgmt_group_cipher);
1177 }
1178#endif /* CONFIG_IEEE80211W */
1179
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001180 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001181 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1182 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001183 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184
1185 if (bss || !wpa_s->ap_ies_from_associnfo) {
1186 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1187 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1188 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1189 bss_rsn ? 2 + bss_rsn[1] : 0))
1190 return -1;
1191 }
1192
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001193#ifdef CONFIG_NO_WPA
1194 wpa_s->group_cipher = WPA_CIPHER_NONE;
1195 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1196#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001198 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1199 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001200 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1201 "cipher");
1202 return -1;
1203 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001204 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1205 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001206
1207 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001208 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1209 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1211 "cipher");
1212 return -1;
1213 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001214 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1215 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001216#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001217
1218 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001219#ifdef CONFIG_SAE
1220 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1221 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1222#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001223 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001224#ifdef CONFIG_SUITEB192
1225 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1226 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1227 wpa_dbg(wpa_s, MSG_DEBUG,
1228 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1229#endif /* CONFIG_SUITEB192 */
1230#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001231 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1232 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1233 wpa_dbg(wpa_s, MSG_DEBUG,
1234 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001235#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001236#ifdef CONFIG_FILS
1237#ifdef CONFIG_IEEE80211R
1238 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1239 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1240 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1241 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1242 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1243 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1244#endif /* CONFIG_IEEE80211R */
1245 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1246 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1247 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1248 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1249 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1250 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1251#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001252#ifdef CONFIG_IEEE80211R
1253 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1254 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1255 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1256 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1257 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1258 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1259#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001260#ifdef CONFIG_SAE
1261 } else if (sel & WPA_KEY_MGMT_SAE) {
1262 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1263 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1264 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1265 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1266 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1267#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001268#ifdef CONFIG_IEEE80211W
1269 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1270 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1271 wpa_dbg(wpa_s, MSG_DEBUG,
1272 "WPA: using KEY_MGMT 802.1X with SHA256");
1273 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1274 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1275 wpa_dbg(wpa_s, MSG_DEBUG,
1276 "WPA: using KEY_MGMT PSK with SHA256");
1277#endif /* CONFIG_IEEE80211W */
1278 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1279 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1280 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1281 } else if (sel & WPA_KEY_MGMT_PSK) {
1282 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1283 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1284 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1285 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1286 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001287#ifdef CONFIG_HS20
1288 } else if (sel & WPA_KEY_MGMT_OSEN) {
1289 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1290 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1291#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001292 } else {
1293 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1294 "authenticated key management type");
1295 return -1;
1296 }
1297
1298 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1299 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1300 wpa_s->pairwise_cipher);
1301 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1302
1303#ifdef CONFIG_IEEE80211W
1304 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001305 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001306 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1307 sel = 0;
1308 if (sel & WPA_CIPHER_AES_128_CMAC) {
1309 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1310 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1311 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001312 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1313 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1314 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1315 "BIP-GMAC-128");
1316 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1317 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1318 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1319 "BIP-GMAC-256");
1320 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1321 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1322 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1323 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001324 } else {
1325 wpa_s->mgmt_group_cipher = 0;
1326 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1327 }
1328 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1329 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001330 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001331 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001332#endif /* CONFIG_IEEE80211W */
1333
1334 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1335 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1336 return -1;
1337 }
1338
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001339 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001340 int psk_set = 0;
1341
1342 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001343 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1344 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001345 psk_set = 1;
1346 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001347#ifndef CONFIG_NO_PBKDF2
1348 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1349 ssid->passphrase) {
1350 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001351 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1352 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001353 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1354 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001355 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001356 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001357 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001358 }
1359#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001360#ifdef CONFIG_EXT_PASSWORD
1361 if (ssid->ext_psk) {
1362 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1363 ssid->ext_psk);
1364 char pw_str[64 + 1];
1365 u8 psk[PMK_LEN];
1366
1367 if (pw == NULL) {
1368 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1369 "found from external storage");
1370 return -1;
1371 }
1372
1373 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1374 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1375 "PSK length %d in external storage",
1376 (int) wpabuf_len(pw));
1377 ext_password_free(pw);
1378 return -1;
1379 }
1380
1381 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1382 pw_str[wpabuf_len(pw)] = '\0';
1383
1384#ifndef CONFIG_NO_PBKDF2
1385 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1386 {
1387 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1388 4096, psk, PMK_LEN);
1389 os_memset(pw_str, 0, sizeof(pw_str));
1390 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1391 "external passphrase)",
1392 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001393 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1394 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001395 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001396 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001397 } else
1398#endif /* CONFIG_NO_PBKDF2 */
1399 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1400 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1401 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1402 "Invalid PSK hex string");
1403 os_memset(pw_str, 0, sizeof(pw_str));
1404 ext_password_free(pw);
1405 return -1;
1406 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001407 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1408 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001409 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001410 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001411 } else {
1412 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1413 "PSK available");
1414 os_memset(pw_str, 0, sizeof(pw_str));
1415 ext_password_free(pw);
1416 return -1;
1417 }
1418
1419 os_memset(pw_str, 0, sizeof(pw_str));
1420 ext_password_free(pw);
1421 }
1422#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001423
1424 if (!psk_set) {
1425 wpa_msg(wpa_s, MSG_INFO,
1426 "No PSK available for association");
1427 return -1;
1428 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001429 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001430 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1431
1432 return 0;
1433}
1434
1435
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001436static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1437{
1438 *pos = 0x00;
1439
1440 switch (idx) {
1441 case 0: /* Bits 0-7 */
1442 break;
1443 case 1: /* Bits 8-15 */
1444 break;
1445 case 2: /* Bits 16-23 */
1446#ifdef CONFIG_WNM
1447 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1448 *pos |= 0x08; /* Bit 19 - BSS Transition */
1449#endif /* CONFIG_WNM */
1450 break;
1451 case 3: /* Bits 24-31 */
1452#ifdef CONFIG_WNM
1453 *pos |= 0x02; /* Bit 25 - SSID List */
1454#endif /* CONFIG_WNM */
1455#ifdef CONFIG_INTERWORKING
1456 if (wpa_s->conf->interworking)
1457 *pos |= 0x80; /* Bit 31 - Interworking */
1458#endif /* CONFIG_INTERWORKING */
1459 break;
1460 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001461#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001462 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1463 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001464#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001465 break;
1466 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001467#ifdef CONFIG_HS20
1468 if (wpa_s->conf->hs20)
1469 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1470#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001471#ifdef CONFIG_MBO
1472 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1473#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001474 break;
1475 case 6: /* Bits 48-55 */
1476 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001477 case 7: /* Bits 56-63 */
1478 break;
1479 case 8: /* Bits 64-71 */
1480 if (wpa_s->conf->ftm_responder)
1481 *pos |= 0x40; /* Bit 70 - FTM responder */
1482 if (wpa_s->conf->ftm_initiator)
1483 *pos |= 0x80; /* Bit 71 - FTM initiator */
1484 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001485 case 9: /* Bits 72-79 */
1486#ifdef CONFIG_FILS
1487 *pos |= 0x01;
1488#endif /* CONFIG_FILS */
1489 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001490 }
1491}
1492
1493
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001494int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001495{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001496 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001497 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001498
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001499 if (len < wpa_s->extended_capa_len)
1500 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001501 if (buflen < (size_t) len + 2) {
1502 wpa_printf(MSG_INFO,
1503 "Not enough room for building extended capabilities element");
1504 return -1;
1505 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001506
1507 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001508 *pos++ = len;
1509 for (i = 0; i < len; i++, pos++) {
1510 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001511
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001512 if (i < wpa_s->extended_capa_len) {
1513 *pos &= ~wpa_s->extended_capa_mask[i];
1514 *pos |= wpa_s->extended_capa[i];
1515 }
1516 }
1517
1518 while (len > 0 && buf[1 + len] == 0) {
1519 len--;
1520 buf[1] = len;
1521 }
1522 if (len == 0)
1523 return 0;
1524
1525 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001526}
1527
1528
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001529static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1530 struct wpa_bss *test_bss)
1531{
1532 struct wpa_bss *bss;
1533
1534 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1535 if (bss == test_bss)
1536 return 1;
1537 }
1538
1539 return 0;
1540}
1541
1542
1543static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1544 struct wpa_ssid *test_ssid)
1545{
1546 struct wpa_ssid *ssid;
1547
1548 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1549 if (ssid == test_ssid)
1550 return 1;
1551 }
1552
1553 return 0;
1554}
1555
1556
1557int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1558 struct wpa_ssid *test_ssid)
1559{
1560 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1561 return 0;
1562
1563 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1564}
1565
1566
1567void wpas_connect_work_free(struct wpa_connect_work *cwork)
1568{
1569 if (cwork == NULL)
1570 return;
1571 os_free(cwork);
1572}
1573
1574
1575void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1576{
1577 struct wpa_connect_work *cwork;
1578 struct wpa_radio_work *work = wpa_s->connect_work;
1579
1580 if (!work)
1581 return;
1582
1583 wpa_s->connect_work = NULL;
1584 cwork = work->ctx;
1585 work->ctx = NULL;
1586 wpas_connect_work_free(cwork);
1587 radio_work_done(work);
1588}
1589
1590
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001591int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1592{
1593 struct os_reltime now;
1594 u8 addr[ETH_ALEN];
1595
1596 os_get_reltime(&now);
1597 if (wpa_s->last_mac_addr_style == style &&
1598 wpa_s->last_mac_addr_change.sec != 0 &&
1599 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1600 wpa_s->conf->rand_addr_lifetime)) {
1601 wpa_msg(wpa_s, MSG_DEBUG,
1602 "Previously selected random MAC address has not yet expired");
1603 return 0;
1604 }
1605
1606 switch (style) {
1607 case 1:
1608 if (random_mac_addr(addr) < 0)
1609 return -1;
1610 break;
1611 case 2:
1612 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1613 if (random_mac_addr_keep_oui(addr) < 0)
1614 return -1;
1615 break;
1616 default:
1617 return -1;
1618 }
1619
1620 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1621 wpa_msg(wpa_s, MSG_INFO,
1622 "Failed to set random MAC address");
1623 return -1;
1624 }
1625
1626 os_get_reltime(&wpa_s->last_mac_addr_change);
1627 wpa_s->mac_addr_changed = 1;
1628 wpa_s->last_mac_addr_style = style;
1629
1630 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1631 wpa_msg(wpa_s, MSG_INFO,
1632 "Could not update MAC address information");
1633 return -1;
1634 }
1635
1636 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1637 MAC2STR(addr));
1638
1639 return 0;
1640}
1641
1642
1643int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1644{
1645 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1646 !wpa_s->conf->preassoc_mac_addr)
1647 return 0;
1648
1649 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1650}
1651
1652
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001653static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1654
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001655/**
1656 * wpa_supplicant_associate - Request association
1657 * @wpa_s: Pointer to wpa_supplicant data
1658 * @bss: Scan results for the selected BSS, or %NULL if not available
1659 * @ssid: Configuration data for the selected network
1660 *
1661 * This function is used to request %wpa_supplicant to associate with a BSS.
1662 */
1663void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1664 struct wpa_bss *bss, struct wpa_ssid *ssid)
1665{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001666 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001667 int rand_style;
1668
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001669 wpa_s->own_disconnect_req = 0;
1670
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001671 /*
1672 * If we are starting a new connection, any previously pending EAPOL
1673 * RX cannot be valid anymore.
1674 */
1675 wpabuf_free(wpa_s->pending_eapol_rx);
1676 wpa_s->pending_eapol_rx = NULL;
1677
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001678 if (ssid->mac_addr == -1)
1679 rand_style = wpa_s->conf->mac_addr;
1680 else
1681 rand_style = ssid->mac_addr;
1682
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001683 wmm_ac_clear_saved_tspecs(wpa_s);
1684 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001685 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001686
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001687 if (wpa_s->last_ssid == ssid) {
1688 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001689 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001690 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1691 wmm_ac_save_tspecs(wpa_s);
1692 wpa_s->reassoc_same_bss = 1;
1693 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001694 }
1695
1696 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001697 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1698 return;
1699 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001700 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001701 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1702 wpa_msg(wpa_s, MSG_INFO,
1703 "Could not restore permanent MAC address");
1704 return;
1705 }
1706 wpa_s->mac_addr_changed = 0;
1707 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1708 wpa_msg(wpa_s, MSG_INFO,
1709 "Could not update MAC address information");
1710 return;
1711 }
1712 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1713 }
1714 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001715
1716#ifdef CONFIG_IBSS_RSN
1717 ibss_rsn_deinit(wpa_s->ibss_rsn);
1718 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001719#else /* CONFIG_IBSS_RSN */
1720 if (ssid->mode == WPAS_MODE_IBSS &&
1721 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1722 wpa_msg(wpa_s, MSG_INFO,
1723 "IBSS RSN not supported in the build");
1724 return;
1725 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726#endif /* CONFIG_IBSS_RSN */
1727
1728 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1729 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1730#ifdef CONFIG_AP
1731 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1732 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1733 "mode");
1734 return;
1735 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001736 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1737 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001738 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1739 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001740 return;
1741 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001742 wpa_s->current_bss = bss;
1743#else /* CONFIG_AP */
1744 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1745 "the build");
1746#endif /* CONFIG_AP */
1747 return;
1748 }
1749
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001750 if (ssid->mode == WPAS_MODE_MESH) {
1751#ifdef CONFIG_MESH
1752 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1753 wpa_msg(wpa_s, MSG_INFO,
1754 "Driver does not support mesh mode");
1755 return;
1756 }
1757 if (bss)
1758 ssid->frequency = bss->freq;
1759 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1760 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1761 return;
1762 }
1763 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001764 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1765 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1766 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001767#else /* CONFIG_MESH */
1768 wpa_msg(wpa_s, MSG_ERROR,
1769 "mesh mode support not included in the build");
1770#endif /* CONFIG_MESH */
1771 return;
1772 }
1773
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001774#ifdef CONFIG_TDLS
1775 if (bss)
1776 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1777 bss->ie_len);
1778#endif /* CONFIG_TDLS */
1779
1780 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1781 ssid->mode == IEEE80211_MODE_INFRA) {
1782 sme_authenticate(wpa_s, bss, ssid);
1783 return;
1784 }
1785
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001786 if (wpa_s->connect_work) {
1787 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1788 return;
1789 }
1790
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001791 if (radio_work_pending(wpa_s, "connect")) {
1792 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1793 return;
1794 }
1795
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001796 wpas_abort_ongoing_scan(wpa_s);
1797
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001798 cwork = os_zalloc(sizeof(*cwork));
1799 if (cwork == NULL)
1800 return;
1801
1802 cwork->bss = bss;
1803 cwork->ssid = ssid;
1804
1805 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1806 wpas_start_assoc_cb, cwork) < 0) {
1807 os_free(cwork);
1808 }
1809}
1810
1811
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001812static int bss_is_ibss(struct wpa_bss *bss)
1813{
1814 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1815 IEEE80211_CAP_IBSS;
1816}
1817
1818
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001819static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1820 const struct wpa_ssid *ssid)
1821{
1822 enum hostapd_hw_mode hw_mode;
1823 struct hostapd_hw_modes *mode = NULL;
1824 u8 channel;
1825 int i;
1826
1827#ifdef CONFIG_HT_OVERRIDES
1828 if (ssid->disable_ht)
1829 return 0;
1830#endif /* CONFIG_HT_OVERRIDES */
1831
1832 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1833 if (hw_mode == NUM_HOSTAPD_MODES)
1834 return 0;
1835 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1836 if (wpa_s->hw.modes[i].mode == hw_mode) {
1837 mode = &wpa_s->hw.modes[i];
1838 break;
1839 }
1840 }
1841
1842 if (!mode)
1843 return 0;
1844
1845 return mode->vht_capab != 0;
1846}
1847
1848
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001849void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1850 const struct wpa_ssid *ssid,
1851 struct hostapd_freq_params *freq)
1852{
1853 enum hostapd_hw_mode hw_mode;
1854 struct hostapd_hw_modes *mode = NULL;
1855 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1856 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001857 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001858 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1859 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001860 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001861 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001862 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001863 int chwidth, seg0, seg1;
1864 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001865
1866 freq->freq = ssid->frequency;
1867
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001868 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1869 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1870
1871 if (ssid->mode != WPAS_MODE_IBSS)
1872 break;
1873
1874 /* Don't adjust control freq in case of fixed_freq */
1875 if (ssid->fixed_freq)
1876 break;
1877
1878 if (!bss_is_ibss(bss))
1879 continue;
1880
1881 if (ssid->ssid_len == bss->ssid_len &&
1882 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1883 wpa_printf(MSG_DEBUG,
1884 "IBSS already found in scan results, adjust control freq: %d",
1885 bss->freq);
1886 freq->freq = bss->freq;
1887 obss_scan = 0;
1888 break;
1889 }
1890 }
1891
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001892 /* For IBSS check HT_IBSS flag */
1893 if (ssid->mode == WPAS_MODE_IBSS &&
1894 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1895 return;
1896
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001897 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1898 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1899 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1900 wpa_printf(MSG_DEBUG,
1901 "IBSS: WEP/TKIP detected, do not try to enable HT");
1902 return;
1903 }
1904
1905 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001906 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1907 if (wpa_s->hw.modes[i].mode == hw_mode) {
1908 mode = &wpa_s->hw.modes[i];
1909 break;
1910 }
1911 }
1912
1913 if (!mode)
1914 return;
1915
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001916#ifdef CONFIG_HT_OVERRIDES
1917 if (ssid->disable_ht) {
1918 freq->ht_enabled = 0;
1919 return;
1920 }
1921#endif /* CONFIG_HT_OVERRIDES */
1922
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001923 freq->ht_enabled = ht_supported(mode);
1924 if (!freq->ht_enabled)
1925 return;
1926
1927 /* Setup higher BW only for 5 GHz */
1928 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1929 return;
1930
1931 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1932 pri_chan = &mode->channels[chan_idx];
1933 if (pri_chan->chan == channel)
1934 break;
1935 pri_chan = NULL;
1936 }
1937 if (!pri_chan)
1938 return;
1939
1940 /* Check primary channel flags */
1941 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1942 return;
1943
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001944#ifdef CONFIG_HT_OVERRIDES
1945 if (ssid->disable_ht40)
1946 return;
1947#endif /* CONFIG_HT_OVERRIDES */
1948
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001949 /* Check/setup HT40+/HT40- */
1950 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1951 if (ht40plus[j] == channel) {
1952 ht40 = 1;
1953 break;
1954 }
1955 }
1956
1957 /* Find secondary channel */
1958 for (i = 0; i < mode->num_channels; i++) {
1959 sec_chan = &mode->channels[i];
1960 if (sec_chan->chan == channel + ht40 * 4)
1961 break;
1962 sec_chan = NULL;
1963 }
1964 if (!sec_chan)
1965 return;
1966
1967 /* Check secondary channel flags */
1968 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1969 return;
1970
1971 freq->channel = pri_chan->chan;
1972
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001973 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001974 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1975 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001976 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001977 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1978 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001979 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001980 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001981
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001982 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001983 struct wpa_scan_results *scan_res;
1984
1985 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1986 if (scan_res == NULL) {
1987 /* Back to HT20 */
1988 freq->sec_channel_offset = 0;
1989 return;
1990 }
1991
1992 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1993 sec_chan->chan);
1994 switch (res) {
1995 case 0:
1996 /* Back to HT20 */
1997 freq->sec_channel_offset = 0;
1998 break;
1999 case 1:
2000 /* Configuration allowed */
2001 break;
2002 case 2:
2003 /* Switch pri/sec channels */
2004 freq->freq = hw_get_freq(mode, sec_chan->chan);
2005 freq->sec_channel_offset = -freq->sec_channel_offset;
2006 freq->channel = sec_chan->chan;
2007 break;
2008 default:
2009 freq->sec_channel_offset = 0;
2010 break;
2011 }
2012
2013 wpa_scan_results_free(scan_res);
2014 }
2015
2016 wpa_printf(MSG_DEBUG,
2017 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2018 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002019
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002020 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002021 return;
2022
2023 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002024 if (ssid->mode == WPAS_MODE_IBSS &&
2025 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002026 return;
2027
2028 vht_freq = *freq;
2029
2030 vht_freq.vht_enabled = vht_supported(mode);
2031 if (!vht_freq.vht_enabled)
2032 return;
2033
2034 /* setup center_freq1, bandwidth */
2035 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2036 if (freq->channel >= vht80[j] &&
2037 freq->channel < vht80[j] + 16)
2038 break;
2039 }
2040
2041 if (j == ARRAY_SIZE(vht80))
2042 return;
2043
2044 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2045 struct hostapd_channel_data *chan;
2046
2047 chan = hw_get_channel_chan(mode, i, NULL);
2048 if (!chan)
2049 return;
2050
2051 /* Back to HT configuration if channel not usable */
2052 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2053 return;
2054 }
2055
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002056 chwidth = VHT_CHANWIDTH_80MHZ;
2057 seg0 = vht80[j] + 6;
2058 seg1 = 0;
2059
2060 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2061 /* setup center_freq2, bandwidth */
2062 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2063 /* Only accept 80 MHz segments separated by a gap */
2064 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2065 continue;
2066 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2067 struct hostapd_channel_data *chan;
2068
2069 chan = hw_get_channel_chan(mode, i, NULL);
2070 if (!chan)
2071 continue;
2072
2073 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2074 HOSTAPD_CHAN_NO_IR |
2075 HOSTAPD_CHAN_RADAR))
2076 continue;
2077
2078 /* Found a suitable second segment for 80+80 */
2079 chwidth = VHT_CHANWIDTH_80P80MHZ;
2080 vht_caps |=
2081 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2082 seg1 = vht80[k] + 6;
2083 }
2084
2085 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2086 break;
2087 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002088 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2089 if (freq->freq == 5180) {
2090 chwidth = VHT_CHANWIDTH_160MHZ;
2091 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2092 seg0 = 50;
2093 } else if (freq->freq == 5520) {
2094 chwidth = VHT_CHANWIDTH_160MHZ;
2095 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2096 seg0 = 114;
2097 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002098 }
2099
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002100 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2101 freq->channel, freq->ht_enabled,
2102 vht_freq.vht_enabled,
2103 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002104 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002105 return;
2106
2107 *freq = vht_freq;
2108
2109 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2110 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002111}
2112
2113
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002114static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2115{
2116 struct wpa_connect_work *cwork = work->ctx;
2117 struct wpa_bss *bss = cwork->bss;
2118 struct wpa_ssid *ssid = cwork->ssid;
2119 struct wpa_supplicant *wpa_s = work->wpa_s;
2120 u8 wpa_ie[200];
2121 size_t wpa_ie_len;
2122 int use_crypt, ret, i, bssid_changed;
2123 int algs = WPA_AUTH_ALG_OPEN;
2124 unsigned int cipher_pairwise, cipher_group;
2125 struct wpa_driver_associate_params params;
2126 int wep_keys_set = 0;
2127 int assoc_failed = 0;
2128 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002129 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002130#ifdef CONFIG_HT_OVERRIDES
2131 struct ieee80211_ht_capabilities htcaps;
2132 struct ieee80211_ht_capabilities htcaps_mask;
2133#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002134#ifdef CONFIG_VHT_OVERRIDES
2135 struct ieee80211_vht_capabilities vhtcaps;
2136 struct ieee80211_vht_capabilities vhtcaps_mask;
2137#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002138#ifdef CONFIG_MBO
2139 const u8 *mbo = NULL;
2140#endif /* CONFIG_MBO */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002141
2142 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002143 if (work->started) {
2144 wpa_s->connect_work = NULL;
2145
2146 /* cancel possible auth. timeout */
2147 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2148 NULL);
2149 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002150 wpas_connect_work_free(cwork);
2151 return;
2152 }
2153
2154 wpa_s->connect_work = work;
2155
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002156 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2157 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002158 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2159 wpas_connect_work_done(wpa_s);
2160 return;
2161 }
2162
Dmitry Shmidte4663042016-04-04 10:07:49 -07002163 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002164 os_memset(&params, 0, sizeof(params));
2165 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002166 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002167 if (bss &&
2168 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169#ifdef CONFIG_IEEE80211R
2170 const u8 *ie, *md = NULL;
2171#endif /* CONFIG_IEEE80211R */
2172 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2173 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2174 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2175 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2176 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2177 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2178 if (bssid_changed)
2179 wpas_notify_bssid_changed(wpa_s);
2180#ifdef CONFIG_IEEE80211R
2181 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2182 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2183 md = ie + 2;
2184 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2185 if (md) {
2186 /* Prepare for the next transition */
2187 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2188 }
2189#endif /* CONFIG_IEEE80211R */
2190#ifdef CONFIG_WPS
2191 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2192 wpa_s->conf->ap_scan == 2 &&
2193 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2194 /* Use ap_scan==1 style network selection to find the network
2195 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002196 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002197 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002198 wpa_s->reassociate = 1;
2199 wpa_supplicant_req_scan(wpa_s, 0, 0);
2200 return;
2201#endif /* CONFIG_WPS */
2202 } else {
2203 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2204 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002205 if (bss)
2206 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2207 else
2208 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002209 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002210 if (!wpa_s->pno)
2211 wpa_supplicant_cancel_sched_scan(wpa_s);
2212
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002213 wpa_supplicant_cancel_scan(wpa_s);
2214
2215 /* Starting new association, so clear the possibly used WPA IE from the
2216 * previous association. */
2217 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2218
2219#ifdef IEEE8021X_EAPOL
2220 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2221 if (ssid->leap) {
2222 if (ssid->non_leap == 0)
2223 algs = WPA_AUTH_ALG_LEAP;
2224 else
2225 algs |= WPA_AUTH_ALG_LEAP;
2226 }
2227 }
2228#endif /* IEEE8021X_EAPOL */
2229 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2230 if (ssid->auth_alg) {
2231 algs = ssid->auth_alg;
2232 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2233 "0x%x", algs);
2234 }
2235
2236 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2237 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002238 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002239 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002240 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2241 wpa_s->conf->okc :
2242 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002243 (ssid->proto & WPA_PROTO_RSN);
2244 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002245 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002246 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002247 wpa_ie_len = sizeof(wpa_ie);
2248 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2249 wpa_ie, &wpa_ie_len)) {
2250 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2251 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002252 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002253 return;
2254 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002255 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2256 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2257 /*
2258 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2259 * use non-WPA since the scan results did not indicate that the
2260 * AP is using WPA or WPA2.
2261 */
2262 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2263 wpa_ie_len = 0;
2264 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002265 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002266 wpa_ie_len = sizeof(wpa_ie);
2267 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2268 wpa_ie, &wpa_ie_len)) {
2269 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2270 "key management and encryption suites (no "
2271 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002272 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002273 return;
2274 }
2275#ifdef CONFIG_WPS
2276 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2277 struct wpabuf *wps_ie;
2278 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2279 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2280 wpa_ie_len = wpabuf_len(wps_ie);
2281 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2282 } else
2283 wpa_ie_len = 0;
2284 wpabuf_free(wps_ie);
2285 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2286 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2287 params.wps = WPS_MODE_PRIVACY;
2288 else
2289 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002290 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002291#endif /* CONFIG_WPS */
2292 } else {
2293 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2294 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002295 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296 }
2297
2298#ifdef CONFIG_P2P
2299 if (wpa_s->global->p2p) {
2300 u8 *pos;
2301 size_t len;
2302 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002303 pos = wpa_ie + wpa_ie_len;
2304 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002305 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2306 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002307 if (res >= 0)
2308 wpa_ie_len += res;
2309 }
2310
2311 wpa_s->cross_connect_disallowed = 0;
2312 if (bss) {
2313 struct wpabuf *p2p;
2314 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2315 if (p2p) {
2316 wpa_s->cross_connect_disallowed =
2317 p2p_get_cross_connect_disallowed(p2p);
2318 wpabuf_free(p2p);
2319 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2320 "connection",
2321 wpa_s->cross_connect_disallowed ?
2322 "disallows" : "allows");
2323 }
2324 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002325
2326 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002327#endif /* CONFIG_P2P */
2328
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002329#ifdef CONFIG_MBO
2330 if (bss) {
2331 mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
2332 if (mbo) {
2333 int len;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002334
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002335 len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq,
2336 wpa_ie + wpa_ie_len,
2337 sizeof(wpa_ie) -
2338 wpa_ie_len);
2339 if (len > 0)
2340 wpa_ie_len += len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002341 }
2342 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002343#endif /* CONFIG_MBO */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002344
Dmitry Shmidt56052862013-10-04 10:23:25 -07002345 /*
2346 * Workaround: Add Extended Capabilities element only if the AP
2347 * included this element in Beacon/Probe Response frames. Some older
2348 * APs seem to have interoperability issues if this element is
2349 * included, so while the standard may require us to include the
2350 * element in all cases, it is justifiable to skip it to avoid
2351 * interoperability issues.
2352 */
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002353 if (ssid->p2p_group)
2354 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2355 else
2356 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2357
Dmitry Shmidt56052862013-10-04 10:23:25 -07002358 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002359 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002360 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002361 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2362 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002363 if (ext_capab_len > 0) {
2364 u8 *pos = wpa_ie;
2365 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2366 pos += 2 + pos[1];
2367 os_memmove(pos + ext_capab_len, pos,
2368 wpa_ie_len - (pos - wpa_ie));
2369 wpa_ie_len += ext_capab_len;
2370 os_memcpy(pos, ext_capab, ext_capab_len);
2371 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002372 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002373
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002374#ifdef CONFIG_HS20
2375 if (is_hs20_network(wpa_s, ssid, bss)) {
2376 struct wpabuf *hs20;
2377
2378 hs20 = wpabuf_alloc(20);
2379 if (hs20) {
2380 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2381 size_t len;
2382
2383 wpas_hs20_add_indication(hs20, pps_mo_id);
2384 len = sizeof(wpa_ie) - wpa_ie_len;
2385 if (wpabuf_len(hs20) <= len) {
2386 os_memcpy(wpa_ie + wpa_ie_len,
2387 wpabuf_head(hs20), wpabuf_len(hs20));
2388 wpa_ie_len += wpabuf_len(hs20);
2389 }
2390 wpabuf_free(hs20);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002391
2392 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002393 }
2394 }
2395#endif /* CONFIG_HS20 */
2396
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002397 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2398 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2399 size_t len;
2400
2401 len = sizeof(wpa_ie) - wpa_ie_len;
2402 if (wpabuf_len(buf) <= len) {
2403 os_memcpy(wpa_ie + wpa_ie_len,
2404 wpabuf_head(buf), wpabuf_len(buf));
2405 wpa_ie_len += wpabuf_len(buf);
2406 }
2407 }
2408
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002409#ifdef CONFIG_FST
2410 if (wpa_s->fst_ies) {
2411 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2412
2413 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2414 os_memcpy(wpa_ie + wpa_ie_len,
2415 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2416 wpa_ie_len += fst_ies_len;
2417 }
2418 }
2419#endif /* CONFIG_FST */
2420
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002421#ifdef CONFIG_MBO
2422 if (mbo) {
2423 int len;
2424
2425 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2426 sizeof(wpa_ie) - wpa_ie_len);
2427 if (len >= 0)
2428 wpa_ie_len += len;
2429 }
2430#endif /* CONFIG_MBO */
2431
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2433 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002434 cipher_pairwise = wpa_s->pairwise_cipher;
2435 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2437 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2438 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2439 use_crypt = 0;
2440 if (wpa_set_wep_keys(wpa_s, ssid)) {
2441 use_crypt = 1;
2442 wep_keys_set = 1;
2443 }
2444 }
2445 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2446 use_crypt = 0;
2447
2448#ifdef IEEE8021X_EAPOL
2449 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2450 if ((ssid->eapol_flags &
2451 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2452 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2453 !wep_keys_set) {
2454 use_crypt = 0;
2455 } else {
2456 /* Assume that dynamic WEP-104 keys will be used and
2457 * set cipher suites in order for drivers to expect
2458 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002459 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002460 }
2461 }
2462#endif /* IEEE8021X_EAPOL */
2463
2464 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2465 /* Set the key before (and later after) association */
2466 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2467 }
2468
2469 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2470 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471 params.ssid = bss->ssid;
2472 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002473 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2474 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002475 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2476 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002477 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002478 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002479 ssid->bssid_set,
2480 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002481 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002482 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002483 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002484 params.bssid_hint = bss->bssid;
2485 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002486 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002487 } else {
2488 params.ssid = ssid->ssid;
2489 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002490 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002491 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002492
2493 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2494 wpa_s->conf->ap_scan == 2) {
2495 params.bssid = ssid->bssid;
2496 params.fixed_bssid = 1;
2497 }
2498
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002499 /* Initial frequency for IBSS/mesh */
2500 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002501 ssid->frequency > 0 && params.freq.freq == 0)
2502 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002503
2504 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002505 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002506 if (ssid->beacon_int)
2507 params.beacon_int = ssid->beacon_int;
2508 else
2509 params.beacon_int = wpa_s->conf->beacon_int;
2510 }
2511
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002512 params.wpa_ie = wpa_ie;
2513 params.wpa_ie_len = wpa_ie_len;
2514 params.pairwise_suite = cipher_pairwise;
2515 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002516 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002517 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 params.auth_alg = algs;
2519 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002520 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 for (i = 0; i < NUM_WEP_KEYS; i++) {
2522 if (ssid->wep_key_len[i])
2523 params.wep_key[i] = ssid->wep_key[i];
2524 params.wep_key_len[i] = ssid->wep_key_len[i];
2525 }
2526 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2527
2528 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002529 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2530 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 params.passphrase = ssid->passphrase;
2532 if (ssid->psk_set)
2533 params.psk = ssid->psk;
2534 }
2535
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002536 if (wpa_s->conf->key_mgmt_offload) {
2537 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2538 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002539 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2540 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002541 params.req_key_mgmt_offload =
2542 ssid->proactive_key_caching < 0 ?
2543 wpa_s->conf->okc : ssid->proactive_key_caching;
2544 else
2545 params.req_key_mgmt_offload = 1;
2546
2547 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2548 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2549 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2550 ssid->psk_set)
2551 params.psk = ssid->psk;
2552 }
2553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554 params.drop_unencrypted = use_crypt;
2555
2556#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002557 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002558 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2560 struct wpa_ie_data ie;
2561 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2562 ie.capabilities &
2563 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2564 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2565 "MFP: require MFP");
2566 params.mgmt_frame_protection =
2567 MGMT_FRAME_PROTECTION_REQUIRED;
2568 }
2569 }
2570#endif /* CONFIG_IEEE80211W */
2571
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002572 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002574 if (wpa_s->p2pdev->set_sta_uapsd)
2575 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002576 else
2577 params.uapsd = -1;
2578
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002579#ifdef CONFIG_HT_OVERRIDES
2580 os_memset(&htcaps, 0, sizeof(htcaps));
2581 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2582 params.htcaps = (u8 *) &htcaps;
2583 params.htcaps_mask = (u8 *) &htcaps_mask;
2584 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2585#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002586#ifdef CONFIG_VHT_OVERRIDES
2587 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2588 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2589 params.vhtcaps = &vhtcaps;
2590 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002591 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002592#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002593
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002594#ifdef CONFIG_P2P
2595 /*
2596 * If multi-channel concurrency is not supported, check for any
2597 * frequency conflict. In case of any frequency conflict, remove the
2598 * least prioritized connection.
2599 */
2600 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002601 int freq, num;
2602 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002603 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002604 wpa_printf(MSG_DEBUG,
2605 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002606 freq, params.freq.freq);
2607 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002608 wpa_s, params.freq.freq, ssid) < 0) {
2609 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002610 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002611 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002612 }
2613 }
2614#endif /* CONFIG_P2P */
2615
Dmitry Shmidte4663042016-04-04 10:07:49 -07002616 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2617 wpa_s->current_ssid)
2618 params.prev_bssid = prev_bssid;
2619
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002620 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002621 if (ret < 0) {
2622 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2623 "failed");
2624 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2625 /*
2626 * The driver is known to mean what is saying, so we
2627 * can stop right here; the association will not
2628 * succeed.
2629 */
2630 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002631 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002632 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2633 return;
2634 }
2635 /* try to continue anyway; new association will be tried again
2636 * after timeout */
2637 assoc_failed = 1;
2638 }
2639
2640 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2641 /* Set the key after the association just in case association
2642 * cleared the previously configured key. */
2643 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2644 /* No need to timeout authentication since there is no key
2645 * management. */
2646 wpa_supplicant_cancel_auth_timeout(wpa_s);
2647 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2648#ifdef CONFIG_IBSS_RSN
2649 } else if (ssid->mode == WPAS_MODE_IBSS &&
2650 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2651 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2652 /*
2653 * RSN IBSS authentication is per-STA and we can disable the
2654 * per-BSSID authentication.
2655 */
2656 wpa_supplicant_cancel_auth_timeout(wpa_s);
2657#endif /* CONFIG_IBSS_RSN */
2658 } else {
2659 /* Timeout for IEEE 802.11 authentication and association */
2660 int timeout = 60;
2661
2662 if (assoc_failed) {
2663 /* give IBSS a bit more time */
2664 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2665 } else if (wpa_s->conf->ap_scan == 1) {
2666 /* give IBSS a bit more time */
2667 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2668 }
2669 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2670 }
2671
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002672 if (wep_keys_set &&
2673 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002674 /* Set static WEP keys again */
2675 wpa_set_wep_keys(wpa_s, ssid);
2676 }
2677
2678 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2679 /*
2680 * Do not allow EAP session resumption between different
2681 * network configurations.
2682 */
2683 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2684 }
2685 old_ssid = wpa_s->current_ssid;
2686 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002687
2688 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002689 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002690#ifdef CONFIG_HS20
2691 hs20_configure_frame_filters(wpa_s);
2692#endif /* CONFIG_HS20 */
2693 }
2694
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002695 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2696 wpa_supplicant_initiate_eapol(wpa_s);
2697 if (old_ssid != wpa_s->current_ssid)
2698 wpas_notify_network_changed(wpa_s);
2699}
2700
2701
2702static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2703 const u8 *addr)
2704{
2705 struct wpa_ssid *old_ssid;
2706
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002707 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002708 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002710 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711 wpa_sm_set_config(wpa_s->wpa, NULL);
2712 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2713 if (old_ssid != wpa_s->current_ssid)
2714 wpas_notify_network_changed(wpa_s);
2715 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2716}
2717
2718
2719/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002720 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2721 * @wpa_s: Pointer to wpa_supplicant data
2722 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2723 *
2724 * This function is used to request %wpa_supplicant to deauthenticate from the
2725 * current AP.
2726 */
2727void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2728 int reason_code)
2729{
2730 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002731 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002732 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002733
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002734 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2735 " pending_bssid=" MACSTR " reason=%d state=%s",
2736 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2737 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2738
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002739 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2740 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2741 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002742 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002743 else if (!is_zero_ether_addr(wpa_s->bssid))
2744 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002745 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2746 /*
2747 * When using driver-based BSS selection, we may not know the
2748 * BSSID with which we are currently trying to associate. We
2749 * need to notify the driver of this disconnection even in such
2750 * a case, so use the all zeros address here.
2751 */
2752 addr = wpa_s->bssid;
2753 zero_addr = 1;
2754 }
2755
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002756#ifdef CONFIG_TDLS
2757 wpa_tdls_teardown_peers(wpa_s->wpa);
2758#endif /* CONFIG_TDLS */
2759
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002760#ifdef CONFIG_MESH
2761 if (wpa_s->ifmsh) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002762 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2763 wpa_s->ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002764 wpa_supplicant_leave_mesh(wpa_s);
2765 }
2766#endif /* CONFIG_MESH */
2767
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002768 if (addr) {
2769 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002770 os_memset(&event, 0, sizeof(event));
2771 event.deauth_info.reason_code = (u16) reason_code;
2772 event.deauth_info.locally_generated = 1;
2773 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002774 if (zero_addr)
2775 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002776 }
2777
2778 wpa_supplicant_clear_connection(wpa_s, addr);
2779}
2780
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002781static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2782 struct wpa_ssid *ssid)
2783{
2784 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2785 return;
2786
2787 ssid->disabled = 0;
2788 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2789 wpas_notify_network_enabled_changed(wpa_s, ssid);
2790
2791 /*
2792 * Try to reassociate since there is no current configuration and a new
2793 * network was made available.
2794 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002795 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002796 wpa_s->reassociate = 1;
2797}
2798
Roshan Pius950bec92016-07-19 09:49:24 -07002799/**
2800 * wpa_supplicant_add_network - Add a new network.
2801 * @wpa_s: wpa_supplicant structure for a network interface
2802 * Returns: The new network configuration or %NULL if operation failed
2803 *
2804 * This function performs the following operations:
2805 * 1. Adds a new network.
2806 * 2. Send network addition notification.
2807 * 3. Marks the network disabled.
2808 * 4. Set network default parameters.
2809 */
2810struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2811{
2812 struct wpa_ssid *ssid;
2813
2814 ssid = wpa_config_add_network(wpa_s->conf);
2815 if (!ssid) {
2816 return NULL;
2817 }
2818 wpas_notify_network_added(wpa_s, ssid);
2819 ssid->disabled = 1;
2820 wpa_config_set_network_defaults(ssid);
2821
2822 return ssid;
2823}
2824
2825/**
2826 * wpa_supplicant_remove_network - Remove a configured network based on id
2827 * @wpa_s: wpa_supplicant structure for a network interface
2828 * @id: Unique network id to search for
2829 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2830 * could not be removed
2831 *
2832 * This function performs the following operations:
2833 * 1. Removes the network.
2834 * 2. Send network removal notification.
2835 * 3. Update internal state machines.
2836 * 4. Stop any running sched scans.
2837 */
2838int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2839{
2840 struct wpa_ssid *ssid;
2841 int was_disabled;
2842
2843 ssid = wpa_config_get_network(wpa_s->conf, id);
2844 if (ssid)
2845 wpas_notify_network_removed(wpa_s, ssid);
2846 if (ssid == NULL) {
2847 return -1;
2848 }
2849
2850 if (wpa_s->last_ssid == ssid)
2851 wpa_s->last_ssid = NULL;
2852
2853 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2854#ifdef CONFIG_SME
2855 wpa_s->sme.prev_bssid_set = 0;
2856#endif /* CONFIG_SME */
2857 /*
2858 * Invalidate the EAP session cache if the current or
2859 * previously used network is removed.
2860 */
2861 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2862 }
2863
2864 if (ssid == wpa_s->current_ssid) {
2865 wpa_sm_set_config(wpa_s->wpa, NULL);
2866 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2867
2868 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2869 wpa_s->own_disconnect_req = 1;
2870 wpa_supplicant_deauthenticate(wpa_s,
2871 WLAN_REASON_DEAUTH_LEAVING);
2872 }
2873
2874 was_disabled = ssid->disabled;
2875
2876 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2877 return -2;
2878 }
2879
2880 if (!was_disabled && wpa_s->sched_scanning) {
2881 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2882 "network from filters");
2883 wpa_supplicant_cancel_sched_scan(wpa_s);
2884 wpa_supplicant_req_scan(wpa_s, 0, 0);
2885 }
2886 return 0;
2887}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002888
2889/**
2890 * wpa_supplicant_enable_network - Mark a configured network as enabled
2891 * @wpa_s: wpa_supplicant structure for a network interface
2892 * @ssid: wpa_ssid structure for a configured network or %NULL
2893 *
2894 * Enables the specified network or all networks if no network specified.
2895 */
2896void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2897 struct wpa_ssid *ssid)
2898{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002899 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002900 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2901 wpa_supplicant_enable_one_network(wpa_s, ssid);
2902 } else
2903 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002905 if (wpa_s->reassociate && !wpa_s->disconnected &&
2906 (!wpa_s->current_ssid ||
2907 wpa_s->wpa_state == WPA_DISCONNECTED ||
2908 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002909 if (wpa_s->sched_scanning) {
2910 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2911 "new network to scan filters");
2912 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002913 }
2914
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002915 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2916 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002917 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002918 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919 }
2920}
2921
2922
2923/**
2924 * wpa_supplicant_disable_network - Mark a configured network as disabled
2925 * @wpa_s: wpa_supplicant structure for a network interface
2926 * @ssid: wpa_ssid structure for a configured network or %NULL
2927 *
2928 * Disables the specified network or all networks if no network specified.
2929 */
2930void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2931 struct wpa_ssid *ssid)
2932{
2933 struct wpa_ssid *other_ssid;
2934 int was_disabled;
2935
2936 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002937 if (wpa_s->sched_scanning)
2938 wpa_supplicant_cancel_sched_scan(wpa_s);
2939
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002940 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2941 other_ssid = other_ssid->next) {
2942 was_disabled = other_ssid->disabled;
2943 if (was_disabled == 2)
2944 continue; /* do not change persistent P2P group
2945 * data */
2946
2947 other_ssid->disabled = 1;
2948
2949 if (was_disabled != other_ssid->disabled)
2950 wpas_notify_network_enabled_changed(
2951 wpa_s, other_ssid);
2952 }
2953 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002954 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002955 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2956 } else if (ssid->disabled != 2) {
2957 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002958 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2960
2961 was_disabled = ssid->disabled;
2962
2963 ssid->disabled = 1;
2964
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002965 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002966 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002967 if (wpa_s->sched_scanning) {
2968 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2969 "to remove network from filters");
2970 wpa_supplicant_cancel_sched_scan(wpa_s);
2971 wpa_supplicant_req_scan(wpa_s, 0, 0);
2972 }
2973 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002974 }
2975}
2976
2977
2978/**
2979 * wpa_supplicant_select_network - Attempt association with a network
2980 * @wpa_s: wpa_supplicant structure for a network interface
2981 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2982 */
2983void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2984 struct wpa_ssid *ssid)
2985{
2986
2987 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002988 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002989
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002990 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002991 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2992 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002993 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002994 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002995 disconnected = 1;
2996 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002997
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002998 if (ssid)
2999 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3000
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003001 /*
3002 * Mark all other networks disabled or mark all networks enabled if no
3003 * network specified.
3004 */
3005 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3006 other_ssid = other_ssid->next) {
3007 int was_disabled = other_ssid->disabled;
3008 if (was_disabled == 2)
3009 continue; /* do not change persistent P2P group data */
3010
3011 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003012 if (was_disabled && !other_ssid->disabled)
3013 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003014
3015 if (was_disabled != other_ssid->disabled)
3016 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3017 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003018
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003019 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3020 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003021 /* We are already associated with the selected network */
3022 wpa_printf(MSG_DEBUG, "Already associated with the "
3023 "selected network - do nothing");
3024 return;
3025 }
3026
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003027 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003028 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003029 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003030 wpa_s->connect_without_scan =
3031 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003032
3033 /*
3034 * Don't optimize next scan freqs since a new ESS has been
3035 * selected.
3036 */
3037 os_free(wpa_s->next_scan_freqs);
3038 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003039 } else {
3040 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003041 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003042
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003043 wpa_s->disconnected = 0;
3044 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003045
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003046 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003047 wpa_supplicant_fast_associate(wpa_s) != 1) {
3048 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003049 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003050 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003051 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003052
3053 if (ssid)
3054 wpas_notify_network_selected(wpa_s, ssid);
3055}
3056
3057
3058/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003059 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3060 * @wpa_s: wpa_supplicant structure for a network interface
3061 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3062 * @pkcs11_module_path: PKCS #11 module path or NULL
3063 * Returns: 0 on success; -1 on failure
3064 *
3065 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3066 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3067 * module path fails the paths will be reset to the default value (NULL).
3068 */
3069int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3070 const char *pkcs11_engine_path,
3071 const char *pkcs11_module_path)
3072{
3073 char *pkcs11_engine_path_copy = NULL;
3074 char *pkcs11_module_path_copy = NULL;
3075
3076 if (pkcs11_engine_path != NULL) {
3077 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3078 if (pkcs11_engine_path_copy == NULL)
3079 return -1;
3080 }
3081 if (pkcs11_module_path != NULL) {
3082 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003083 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003084 os_free(pkcs11_engine_path_copy);
3085 return -1;
3086 }
3087 }
3088
3089 os_free(wpa_s->conf->pkcs11_engine_path);
3090 os_free(wpa_s->conf->pkcs11_module_path);
3091 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3092 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3093
3094 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3095 eapol_sm_deinit(wpa_s->eapol);
3096 wpa_s->eapol = NULL;
3097 if (wpa_supplicant_init_eapol(wpa_s)) {
3098 /* Error -> Reset paths to the default value (NULL) once. */
3099 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3100 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3101 NULL);
3102
3103 return -1;
3104 }
3105 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3106
3107 return 0;
3108}
3109
3110
3111/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003112 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3113 * @wpa_s: wpa_supplicant structure for a network interface
3114 * @ap_scan: AP scan mode
3115 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3116 *
3117 */
3118int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3119{
3120
3121 int old_ap_scan;
3122
3123 if (ap_scan < 0 || ap_scan > 2)
3124 return -1;
3125
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003126 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3127 wpa_printf(MSG_INFO,
3128 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3129 }
3130
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003131#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003132 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3133 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3134 wpa_s->wpa_state < WPA_COMPLETED) {
3135 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3136 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003137 return 0;
3138 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003139#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003140
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003141 old_ap_scan = wpa_s->conf->ap_scan;
3142 wpa_s->conf->ap_scan = ap_scan;
3143
3144 if (old_ap_scan != wpa_s->conf->ap_scan)
3145 wpas_notify_ap_scan_changed(wpa_s);
3146
3147 return 0;
3148}
3149
3150
3151/**
3152 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3153 * @wpa_s: wpa_supplicant structure for a network interface
3154 * @expire_age: Expiration age in seconds
3155 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3156 *
3157 */
3158int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3159 unsigned int bss_expire_age)
3160{
3161 if (bss_expire_age < 10) {
3162 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3163 bss_expire_age);
3164 return -1;
3165 }
3166 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3167 bss_expire_age);
3168 wpa_s->conf->bss_expiration_age = bss_expire_age;
3169
3170 return 0;
3171}
3172
3173
3174/**
3175 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3176 * @wpa_s: wpa_supplicant structure for a network interface
3177 * @expire_count: number of scans after which an unseen BSS is reclaimed
3178 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3179 *
3180 */
3181int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3182 unsigned int bss_expire_count)
3183{
3184 if (bss_expire_count < 1) {
3185 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3186 bss_expire_count);
3187 return -1;
3188 }
3189 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3190 bss_expire_count);
3191 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3192
3193 return 0;
3194}
3195
3196
3197/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003198 * wpa_supplicant_set_scan_interval - Set scan interval
3199 * @wpa_s: wpa_supplicant structure for a network interface
3200 * @scan_interval: scan interval in seconds
3201 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3202 *
3203 */
3204int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3205 int scan_interval)
3206{
3207 if (scan_interval < 0) {
3208 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3209 scan_interval);
3210 return -1;
3211 }
3212 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3213 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003214 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003215
3216 return 0;
3217}
3218
3219
3220/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003221 * wpa_supplicant_set_debug_params - Set global debug params
3222 * @global: wpa_global structure
3223 * @debug_level: debug level
3224 * @debug_timestamp: determines if show timestamp in debug data
3225 * @debug_show_keys: determines if show keys in debug data
3226 * Returns: 0 if succeed or -1 if debug_level has wrong value
3227 */
3228int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3229 int debug_timestamp, int debug_show_keys)
3230{
3231
3232 int old_level, old_timestamp, old_show_keys;
3233
3234 /* check for allowed debuglevels */
3235 if (debug_level != MSG_EXCESSIVE &&
3236 debug_level != MSG_MSGDUMP &&
3237 debug_level != MSG_DEBUG &&
3238 debug_level != MSG_INFO &&
3239 debug_level != MSG_WARNING &&
3240 debug_level != MSG_ERROR)
3241 return -1;
3242
3243 old_level = wpa_debug_level;
3244 old_timestamp = wpa_debug_timestamp;
3245 old_show_keys = wpa_debug_show_keys;
3246
3247 wpa_debug_level = debug_level;
3248 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3249 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3250
3251 if (wpa_debug_level != old_level)
3252 wpas_notify_debug_level_changed(global);
3253 if (wpa_debug_timestamp != old_timestamp)
3254 wpas_notify_debug_timestamp_changed(global);
3255 if (wpa_debug_show_keys != old_show_keys)
3256 wpas_notify_debug_show_keys_changed(global);
3257
3258 return 0;
3259}
3260
3261
3262/**
3263 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3264 * @wpa_s: Pointer to wpa_supplicant data
3265 * Returns: A pointer to the current network structure or %NULL on failure
3266 */
3267struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3268{
3269 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003270 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003271 int res;
3272 size_t ssid_len;
3273 u8 bssid[ETH_ALEN];
3274 int wired;
3275
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003276 res = wpa_drv_get_ssid(wpa_s, ssid);
3277 if (res < 0) {
3278 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3279 "driver");
3280 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003281 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003282 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003283
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003284 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003285 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3286 "driver");
3287 return NULL;
3288 }
3289
3290 wired = wpa_s->conf->ap_scan == 0 &&
3291 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3292
3293 entry = wpa_s->conf->ssid;
3294 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003295 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003296 ((ssid_len == entry->ssid_len &&
3297 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3298 (!entry->bssid_set ||
3299 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3300 return entry;
3301#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003302 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003303 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3304 (entry->ssid == NULL || entry->ssid_len == 0) &&
3305 (!entry->bssid_set ||
3306 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3307 return entry;
3308#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003309
Dmitry Shmidt04949592012-07-19 12:16:46 -07003310 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003311 entry->ssid_len == 0 &&
3312 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3313 return entry;
3314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003315 entry = entry->next;
3316 }
3317
3318 return NULL;
3319}
3320
3321
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003322static int select_driver(struct wpa_supplicant *wpa_s, int i)
3323{
3324 struct wpa_global *global = wpa_s->global;
3325
3326 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003327 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003328 if (global->drv_priv[i] == NULL) {
3329 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3330 "'%s'", wpa_drivers[i]->name);
3331 return -1;
3332 }
3333 }
3334
3335 wpa_s->driver = wpa_drivers[i];
3336 wpa_s->global_drv_priv = global->drv_priv[i];
3337
3338 return 0;
3339}
3340
3341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3343 const char *name)
3344{
3345 int i;
3346 size_t len;
3347 const char *pos, *driver = name;
3348
3349 if (wpa_s == NULL)
3350 return -1;
3351
3352 if (wpa_drivers[0] == NULL) {
3353 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3354 "wpa_supplicant");
3355 return -1;
3356 }
3357
3358 if (name == NULL) {
3359 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003360 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003361 }
3362
3363 do {
3364 pos = os_strchr(driver, ',');
3365 if (pos)
3366 len = pos - driver;
3367 else
3368 len = os_strlen(driver);
3369
3370 for (i = 0; wpa_drivers[i]; i++) {
3371 if (os_strlen(wpa_drivers[i]->name) == len &&
3372 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003373 0) {
3374 /* First driver that succeeds wins */
3375 if (select_driver(wpa_s, i) == 0)
3376 return 0;
3377 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003378 }
3379
3380 driver = pos + 1;
3381 } while (pos);
3382
3383 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3384 return -1;
3385}
3386
3387
3388/**
3389 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3390 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3391 * with struct wpa_driver_ops::init()
3392 * @src_addr: Source address of the EAPOL frame
3393 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3394 * @len: Length of the EAPOL data
3395 *
3396 * This function is called for each received EAPOL frame. Most driver
3397 * interfaces rely on more generic OS mechanism for receiving frames through
3398 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3399 * take care of received EAPOL frames and deliver them to the core supplicant
3400 * code by calling this function.
3401 */
3402void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3403 const u8 *buf, size_t len)
3404{
3405 struct wpa_supplicant *wpa_s = ctx;
3406
3407 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3408 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3409
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003410#ifdef CONFIG_TESTING_OPTIONS
3411 if (wpa_s->ignore_auth_resp) {
3412 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3413 return;
3414 }
3415#endif /* CONFIG_TESTING_OPTIONS */
3416
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003417#ifdef CONFIG_PEERKEY
3418 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3419 wpa_s->current_ssid->peerkey &&
3420 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3421 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3422 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3423 return;
3424 }
3425#endif /* CONFIG_PEERKEY */
3426
Jouni Malinena05074c2012-12-21 21:35:35 +02003427 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3428 (wpa_s->last_eapol_matches_bssid &&
3429#ifdef CONFIG_AP
3430 !wpa_s->ap_iface &&
3431#endif /* CONFIG_AP */
3432 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003433 /*
3434 * There is possible race condition between receiving the
3435 * association event and the EAPOL frame since they are coming
3436 * through different paths from the driver. In order to avoid
3437 * issues in trying to process the EAPOL frame before receiving
3438 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003439 * the association event is received. This may also be needed in
3440 * driver-based roaming case, so also use src_addr != BSSID as a
3441 * trigger if we have previously confirmed that the
3442 * Authenticator uses BSSID as the src_addr (which is not the
3443 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003444 */
3445 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003446 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3447 wpa_supplicant_state_txt(wpa_s->wpa_state),
3448 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003449 wpabuf_free(wpa_s->pending_eapol_rx);
3450 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3451 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003452 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003453 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3454 ETH_ALEN);
3455 }
3456 return;
3457 }
3458
Jouni Malinena05074c2012-12-21 21:35:35 +02003459 wpa_s->last_eapol_matches_bssid =
3460 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3461
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003462#ifdef CONFIG_AP
3463 if (wpa_s->ap_iface) {
3464 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3465 return;
3466 }
3467#endif /* CONFIG_AP */
3468
3469 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3470 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3471 "no key management is configured");
3472 return;
3473 }
3474
3475 if (wpa_s->eapol_received == 0 &&
3476 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3477 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3478 wpa_s->wpa_state != WPA_COMPLETED) &&
3479 (wpa_s->current_ssid == NULL ||
3480 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3481 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003482 int timeout = 10;
3483
3484 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3485 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3486 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3487 /* Use longer timeout for IEEE 802.1X/EAP */
3488 timeout = 70;
3489 }
3490
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003491#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003492 if (wpa_s->current_ssid && wpa_s->current_bss &&
3493 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3494 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3495 /*
3496 * Use shorter timeout if going through WPS AP iteration
3497 * for PIN config method with an AP that does not
3498 * advertise Selected Registrar.
3499 */
3500 struct wpabuf *wps_ie;
3501
3502 wps_ie = wpa_bss_get_vendor_ie_multi(
3503 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3504 if (wps_ie &&
3505 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3506 timeout = 10;
3507 wpabuf_free(wps_ie);
3508 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003509#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003510
3511 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003512 }
3513 wpa_s->eapol_received++;
3514
3515 if (wpa_s->countermeasures) {
3516 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3517 "EAPOL packet");
3518 return;
3519 }
3520
3521#ifdef CONFIG_IBSS_RSN
3522 if (wpa_s->current_ssid &&
3523 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3524 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3525 return;
3526 }
3527#endif /* CONFIG_IBSS_RSN */
3528
3529 /* Source address of the incoming EAPOL frame could be compared to the
3530 * current BSSID. However, it is possible that a centralized
3531 * Authenticator could be using another MAC address than the BSSID of
3532 * an AP, so just allow any address to be used for now. The replies are
3533 * still sent to the current BSSID (if available), though. */
3534
3535 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3536 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3537 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3538 return;
3539 wpa_drv_poll(wpa_s);
3540 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3541 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3542 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3543 /*
3544 * Set portValid = TRUE here since we are going to skip 4-way
3545 * handshake processing which would normally set portValid. We
3546 * need this to allow the EAPOL state machines to be completed
3547 * without going through EAPOL-Key handshake.
3548 */
3549 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3550 }
3551}
3552
3553
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003554int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003555{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003556 if ((!wpa_s->p2p_mgmt ||
3557 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3558 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003559 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003560 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3561 wpa_drv_get_mac_addr(wpa_s),
3562 ETH_P_EAPOL,
3563 wpa_supplicant_rx_eapol, wpa_s, 0);
3564 if (wpa_s->l2 == NULL)
3565 return -1;
3566 } else {
3567 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3568 if (addr)
3569 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3570 }
3571
3572 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3573 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3574 return -1;
3575 }
3576
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003577 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3578
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003579 return 0;
3580}
3581
3582
Dmitry Shmidt04949592012-07-19 12:16:46 -07003583static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3584 const u8 *buf, size_t len)
3585{
3586 struct wpa_supplicant *wpa_s = ctx;
3587 const struct l2_ethhdr *eth;
3588
3589 if (len < sizeof(*eth))
3590 return;
3591 eth = (const struct l2_ethhdr *) buf;
3592
3593 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3594 !(eth->h_dest[0] & 0x01)) {
3595 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3596 " (bridge - not for this interface - ignore)",
3597 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3598 return;
3599 }
3600
3601 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3602 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3603 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3604 len - sizeof(*eth));
3605}
3606
3607
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003608/**
3609 * wpa_supplicant_driver_init - Initialize driver interface parameters
3610 * @wpa_s: Pointer to wpa_supplicant data
3611 * Returns: 0 on success, -1 on failure
3612 *
3613 * This function is called to initialize driver interface parameters.
3614 * wpa_drv_init() must have been called before this function to initialize the
3615 * driver interface.
3616 */
3617int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3618{
3619 static int interface_count = 0;
3620
3621 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3622 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003623
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003624 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3625 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003626 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003627 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3628
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629 if (wpa_s->bridge_ifname[0]) {
3630 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3631 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003632 wpa_s->l2_br = l2_packet_init_bridge(
3633 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3634 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003635 if (wpa_s->l2_br == NULL) {
3636 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3637 "connection for the bridge interface '%s'",
3638 wpa_s->bridge_ifname);
3639 return -1;
3640 }
3641 }
3642
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003643 if (wpa_s->conf->ap_scan == 2 &&
3644 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3645 wpa_printf(MSG_INFO,
3646 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3647 }
3648
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003649 wpa_clear_keys(wpa_s, NULL);
3650
3651 /* Make sure that TKIP countermeasures are not left enabled (could
3652 * happen if wpa_supplicant is killed during countermeasures. */
3653 wpa_drv_set_countermeasures(wpa_s, 0);
3654
3655 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3656 wpa_drv_flush_pmkid(wpa_s);
3657
3658 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003659 wpa_s->prev_scan_wildcard = 0;
3660
Dmitry Shmidt04949592012-07-19 12:16:46 -07003661 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003662 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3663 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3664 interface_count = 0;
3665 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003666#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003667 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003668 wpa_supplicant_delayed_sched_scan(wpa_s,
3669 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003670 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003671 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003672 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003673#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003674 interface_count++;
3675 } else
3676 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3677
3678 return 0;
3679}
3680
3681
3682static int wpa_supplicant_daemon(const char *pid_file)
3683{
3684 wpa_printf(MSG_DEBUG, "Daemonize..");
3685 return os_daemonize(pid_file);
3686}
3687
3688
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003689static struct wpa_supplicant *
3690wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003691{
3692 struct wpa_supplicant *wpa_s;
3693
3694 wpa_s = os_zalloc(sizeof(*wpa_s));
3695 if (wpa_s == NULL)
3696 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003697 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003698 wpa_s->scan_interval = 5;
3699 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003700 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003701 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003702 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003703
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003704 dl_list_init(&wpa_s->bss_tmp_disallowed);
3705
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706 return wpa_s;
3707}
3708
3709
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003710#ifdef CONFIG_HT_OVERRIDES
3711
3712static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3713 struct ieee80211_ht_capabilities *htcaps,
3714 struct ieee80211_ht_capabilities *htcaps_mask,
3715 const char *ht_mcs)
3716{
3717 /* parse ht_mcs into hex array */
3718 int i;
3719 const char *tmp = ht_mcs;
3720 char *end = NULL;
3721
3722 /* If ht_mcs is null, do not set anything */
3723 if (!ht_mcs)
3724 return 0;
3725
3726 /* This is what we are setting in the kernel */
3727 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3728
3729 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3730
3731 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3732 errno = 0;
3733 long v = strtol(tmp, &end, 16);
3734 if (errno == 0) {
3735 wpa_msg(wpa_s, MSG_DEBUG,
3736 "htcap value[%i]: %ld end: %p tmp: %p",
3737 i, v, end, tmp);
3738 if (end == tmp)
3739 break;
3740
3741 htcaps->supported_mcs_set[i] = v;
3742 tmp = end;
3743 } else {
3744 wpa_msg(wpa_s, MSG_ERROR,
3745 "Failed to parse ht-mcs: %s, error: %s\n",
3746 ht_mcs, strerror(errno));
3747 return -1;
3748 }
3749 }
3750
3751 /*
3752 * If we were able to parse any values, then set mask for the MCS set.
3753 */
3754 if (i) {
3755 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3756 IEEE80211_HT_MCS_MASK_LEN - 1);
3757 /* skip the 3 reserved bits */
3758 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3759 0x1f;
3760 }
3761
3762 return 0;
3763}
3764
3765
3766static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3767 struct ieee80211_ht_capabilities *htcaps,
3768 struct ieee80211_ht_capabilities *htcaps_mask,
3769 int disabled)
3770{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003771 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003772
3773 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3774
3775 if (disabled == -1)
3776 return 0;
3777
3778 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3779 htcaps_mask->ht_capabilities_info |= msk;
3780 if (disabled)
3781 htcaps->ht_capabilities_info &= msk;
3782 else
3783 htcaps->ht_capabilities_info |= msk;
3784
3785 return 0;
3786}
3787
3788
3789static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3790 struct ieee80211_ht_capabilities *htcaps,
3791 struct ieee80211_ht_capabilities *htcaps_mask,
3792 int factor)
3793{
3794 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3795
3796 if (factor == -1)
3797 return 0;
3798
3799 if (factor < 0 || factor > 3) {
3800 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3801 "Must be 0-3 or -1", factor);
3802 return -EINVAL;
3803 }
3804
3805 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3806 htcaps->a_mpdu_params &= ~0x3;
3807 htcaps->a_mpdu_params |= factor & 0x3;
3808
3809 return 0;
3810}
3811
3812
3813static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3814 struct ieee80211_ht_capabilities *htcaps,
3815 struct ieee80211_ht_capabilities *htcaps_mask,
3816 int density)
3817{
3818 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3819
3820 if (density == -1)
3821 return 0;
3822
3823 if (density < 0 || density > 7) {
3824 wpa_msg(wpa_s, MSG_ERROR,
3825 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3826 density);
3827 return -EINVAL;
3828 }
3829
3830 htcaps_mask->a_mpdu_params |= 0x1C;
3831 htcaps->a_mpdu_params &= ~(0x1C);
3832 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3833
3834 return 0;
3835}
3836
3837
3838static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3839 struct ieee80211_ht_capabilities *htcaps,
3840 struct ieee80211_ht_capabilities *htcaps_mask,
3841 int disabled)
3842{
3843 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003844 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3845 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003846
3847 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3848
3849 if (disabled)
3850 htcaps->ht_capabilities_info &= ~msk;
3851 else
3852 htcaps->ht_capabilities_info |= msk;
3853
3854 htcaps_mask->ht_capabilities_info |= msk;
3855
3856 return 0;
3857}
3858
3859
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003860static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3861 struct ieee80211_ht_capabilities *htcaps,
3862 struct ieee80211_ht_capabilities *htcaps_mask,
3863 int disabled)
3864{
3865 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003866 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3867 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003868
3869 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3870
3871 if (disabled)
3872 htcaps->ht_capabilities_info &= ~msk;
3873 else
3874 htcaps->ht_capabilities_info |= msk;
3875
3876 htcaps_mask->ht_capabilities_info |= msk;
3877
3878 return 0;
3879}
3880
3881
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003882static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3883 struct ieee80211_ht_capabilities *htcaps,
3884 struct ieee80211_ht_capabilities *htcaps_mask,
3885 int disabled)
3886{
3887 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003888 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003889
3890 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3891
3892 if (disabled)
3893 htcaps->ht_capabilities_info &= ~msk;
3894 else
3895 htcaps->ht_capabilities_info |= msk;
3896
3897 htcaps_mask->ht_capabilities_info |= msk;
3898
3899 return 0;
3900}
3901
3902
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003903void wpa_supplicant_apply_ht_overrides(
3904 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3905 struct wpa_driver_associate_params *params)
3906{
3907 struct ieee80211_ht_capabilities *htcaps;
3908 struct ieee80211_ht_capabilities *htcaps_mask;
3909
3910 if (!ssid)
3911 return;
3912
3913 params->disable_ht = ssid->disable_ht;
3914 if (!params->htcaps || !params->htcaps_mask)
3915 return;
3916
3917 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3918 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3919 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3920 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3921 ssid->disable_max_amsdu);
3922 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3923 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3924 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003925 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003926 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003927
3928 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003929 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003930 htcaps->ht_capabilities_info |= bit;
3931 htcaps_mask->ht_capabilities_info |= bit;
3932 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003933}
3934
3935#endif /* CONFIG_HT_OVERRIDES */
3936
3937
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003938#ifdef CONFIG_VHT_OVERRIDES
3939void wpa_supplicant_apply_vht_overrides(
3940 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3941 struct wpa_driver_associate_params *params)
3942{
3943 struct ieee80211_vht_capabilities *vhtcaps;
3944 struct ieee80211_vht_capabilities *vhtcaps_mask;
3945
3946 if (!ssid)
3947 return;
3948
3949 params->disable_vht = ssid->disable_vht;
3950
3951 vhtcaps = (void *) params->vhtcaps;
3952 vhtcaps_mask = (void *) params->vhtcaps_mask;
3953
3954 if (!vhtcaps || !vhtcaps_mask)
3955 return;
3956
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003957 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
3958 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003959
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003960#ifdef CONFIG_HT_OVERRIDES
3961 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003962 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3963 int max_ampdu;
3964
3965 max_ampdu = (ssid->vht_capa &
3966 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3967 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003968
3969 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3970 wpa_set_ampdu_factor(wpa_s,
3971 (void *) params->htcaps,
3972 (void *) params->htcaps_mask,
3973 max_ampdu);
3974 }
3975#endif /* CONFIG_HT_OVERRIDES */
3976
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003977#define OVERRIDE_MCS(i) \
3978 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3979 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003980 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003981 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003982 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
3983 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003984 } \
3985 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3986 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003987 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003988 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003989 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
3990 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003991 }
3992
3993 OVERRIDE_MCS(1);
3994 OVERRIDE_MCS(2);
3995 OVERRIDE_MCS(3);
3996 OVERRIDE_MCS(4);
3997 OVERRIDE_MCS(5);
3998 OVERRIDE_MCS(6);
3999 OVERRIDE_MCS(7);
4000 OVERRIDE_MCS(8);
4001}
4002#endif /* CONFIG_VHT_OVERRIDES */
4003
4004
Dmitry Shmidt04949592012-07-19 12:16:46 -07004005static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4006{
4007#ifdef PCSC_FUNCS
4008 size_t len;
4009
4010 if (!wpa_s->conf->pcsc_reader)
4011 return 0;
4012
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004013 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004014 if (!wpa_s->scard)
4015 return 1;
4016
4017 if (wpa_s->conf->pcsc_pin &&
4018 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4019 scard_deinit(wpa_s->scard);
4020 wpa_s->scard = NULL;
4021 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4022 return -1;
4023 }
4024
4025 len = sizeof(wpa_s->imsi) - 1;
4026 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4027 scard_deinit(wpa_s->scard);
4028 wpa_s->scard = NULL;
4029 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4030 return -1;
4031 }
4032 wpa_s->imsi[len] = '\0';
4033
4034 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4035
4036 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4037 wpa_s->imsi, wpa_s->mnc_len);
4038
4039 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4040 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4041#endif /* PCSC_FUNCS */
4042
4043 return 0;
4044}
4045
4046
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004047int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4048{
4049 char *val, *pos;
4050
4051 ext_password_deinit(wpa_s->ext_pw);
4052 wpa_s->ext_pw = NULL;
4053 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4054
4055 if (!wpa_s->conf->ext_password_backend)
4056 return 0;
4057
4058 val = os_strdup(wpa_s->conf->ext_password_backend);
4059 if (val == NULL)
4060 return -1;
4061 pos = os_strchr(val, ':');
4062 if (pos)
4063 *pos++ = '\0';
4064
4065 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4066
4067 wpa_s->ext_pw = ext_password_init(val, pos);
4068 os_free(val);
4069 if (wpa_s->ext_pw == NULL) {
4070 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4071 return -1;
4072 }
4073 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4074
4075 return 0;
4076}
4077
4078
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004079#ifdef CONFIG_FST
4080
4081static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4082{
4083 struct wpa_supplicant *wpa_s = ctx;
4084
4085 return (is_zero_ether_addr(wpa_s->bssid) ||
4086 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4087}
4088
4089
4090static void wpas_fst_get_channel_info_cb(void *ctx,
4091 enum hostapd_hw_mode *hw_mode,
4092 u8 *channel)
4093{
4094 struct wpa_supplicant *wpa_s = ctx;
4095
4096 if (wpa_s->current_bss) {
4097 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4098 channel);
4099 } else if (wpa_s->hw.num_modes) {
4100 *hw_mode = wpa_s->hw.modes[0].mode;
4101 } else {
4102 WPA_ASSERT(0);
4103 *hw_mode = 0;
4104 }
4105}
4106
4107
4108static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4109{
4110 struct wpa_supplicant *wpa_s = ctx;
4111
4112 *modes = wpa_s->hw.modes;
4113 return wpa_s->hw.num_modes;
4114}
4115
4116
4117static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4118{
4119 struct wpa_supplicant *wpa_s = ctx;
4120
4121 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4122 wpa_s->fst_ies = fst_ies;
4123}
4124
4125
4126static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4127{
4128 struct wpa_supplicant *wpa_s = ctx;
4129
4130 WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
4131 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
4132 wpa_s->own_addr, wpa_s->bssid,
4133 wpabuf_head(data), wpabuf_len(data),
4134 0);
4135}
4136
4137
4138static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4139{
4140 struct wpa_supplicant *wpa_s = ctx;
4141
4142 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4143 return wpa_s->received_mb_ies;
4144}
4145
4146
4147static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4148 const u8 *buf, size_t size)
4149{
4150 struct wpa_supplicant *wpa_s = ctx;
4151 struct mb_ies_info info;
4152
4153 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4154
4155 if (!mb_ies_info_by_ies(&info, buf, size)) {
4156 wpabuf_free(wpa_s->received_mb_ies);
4157 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4158 }
4159}
4160
4161
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004162static const u8 * wpas_fst_get_peer_first(void *ctx,
4163 struct fst_get_peer_ctx **get_ctx,
4164 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004165{
4166 struct wpa_supplicant *wpa_s = ctx;
4167
4168 *get_ctx = NULL;
4169 if (!is_zero_ether_addr(wpa_s->bssid))
4170 return (wpa_s->received_mb_ies || !mb_only) ?
4171 wpa_s->bssid : NULL;
4172 return NULL;
4173}
4174
4175
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004176static const u8 * wpas_fst_get_peer_next(void *ctx,
4177 struct fst_get_peer_ctx **get_ctx,
4178 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004179{
4180 return NULL;
4181}
4182
4183void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4184 struct fst_wpa_obj *iface_obj)
4185{
4186 iface_obj->ctx = wpa_s;
4187 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4188 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4189 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4190 iface_obj->set_ies = wpas_fst_set_ies_cb;
4191 iface_obj->send_action = wpas_fst_send_action_cb;
4192 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4193 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4194 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4195 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4196}
4197#endif /* CONFIG_FST */
4198
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004199static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004200 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004201{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004202 struct wowlan_triggers *triggers;
4203 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004204
4205 if (!wpa_s->conf->wowlan_triggers)
4206 return 0;
4207
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004208 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4209 if (triggers) {
4210 ret = wpa_drv_wowlan(wpa_s, triggers);
4211 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004212 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004213 return ret;
4214}
4215
4216
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004217enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004218{
4219 if (freq < 3000)
4220 return BAND_2_4_GHZ;
4221 if (freq > 50000)
4222 return BAND_60_GHZ;
4223 return BAND_5_GHZ;
4224}
4225
4226
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004227unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004228{
4229 int i;
4230 unsigned int band = 0;
4231
4232 if (freqs) {
4233 /* freqs are specified for the radio work */
4234 for (i = 0; freqs[i]; i++)
4235 band |= wpas_freq_to_band(freqs[i]);
4236 } else {
4237 /*
4238 * freqs are not specified, implies all
4239 * the supported freqs by HW
4240 */
4241 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4242 if (wpa_s->hw.modes[i].num_channels != 0) {
4243 if (wpa_s->hw.modes[i].mode ==
4244 HOSTAPD_MODE_IEEE80211B ||
4245 wpa_s->hw.modes[i].mode ==
4246 HOSTAPD_MODE_IEEE80211G)
4247 band |= BAND_2_4_GHZ;
4248 else if (wpa_s->hw.modes[i].mode ==
4249 HOSTAPD_MODE_IEEE80211A)
4250 band |= BAND_5_GHZ;
4251 else if (wpa_s->hw.modes[i].mode ==
4252 HOSTAPD_MODE_IEEE80211AD)
4253 band |= BAND_60_GHZ;
4254 else if (wpa_s->hw.modes[i].mode ==
4255 HOSTAPD_MODE_IEEE80211ANY)
4256 band = BAND_2_4_GHZ | BAND_5_GHZ |
4257 BAND_60_GHZ;
4258 }
4259 }
4260 }
4261
4262 return band;
4263}
4264
4265
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004266static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4267 const char *rn)
4268{
4269 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4270 struct wpa_radio *radio;
4271
4272 while (rn && iface) {
4273 radio = iface->radio;
4274 if (radio && os_strcmp(rn, radio->name) == 0) {
4275 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4276 wpa_s->ifname, rn);
4277 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4278 return radio;
4279 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004280
4281 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004282 }
4283
4284 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4285 wpa_s->ifname, rn ? rn : "N/A");
4286 radio = os_zalloc(sizeof(*radio));
4287 if (radio == NULL)
4288 return NULL;
4289
4290 if (rn)
4291 os_strlcpy(radio->name, rn, sizeof(radio->name));
4292 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004293 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004294 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4295
4296 return radio;
4297}
4298
4299
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004300static void radio_work_free(struct wpa_radio_work *work)
4301{
4302 if (work->wpa_s->scan_work == work) {
4303 /* This should not really happen. */
4304 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4305 work->type, work, work->started);
4306 work->wpa_s->scan_work = NULL;
4307 }
4308
4309#ifdef CONFIG_P2P
4310 if (work->wpa_s->p2p_scan_work == work) {
4311 /* This should not really happen. */
4312 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4313 work->type, work, work->started);
4314 work->wpa_s->p2p_scan_work = NULL;
4315 }
4316#endif /* CONFIG_P2P */
4317
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004318 if (work->started) {
4319 work->wpa_s->radio->num_active_works--;
4320 wpa_dbg(work->wpa_s, MSG_DEBUG,
4321 "radio_work_free('%s'@%p: num_active_works --> %u",
4322 work->type, work,
4323 work->wpa_s->radio->num_active_works);
4324 }
4325
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004326 dl_list_del(&work->list);
4327 os_free(work);
4328}
4329
4330
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004331static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4332{
4333 struct wpa_radio_work *active_work = NULL;
4334 struct wpa_radio_work *tmp;
4335
4336 /* Get the active work to know the type and band. */
4337 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4338 if (tmp->started) {
4339 active_work = tmp;
4340 break;
4341 }
4342 }
4343
4344 if (!active_work) {
4345 /* No active work, start one */
4346 radio->num_active_works = 0;
4347 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4348 list) {
4349 if (os_strcmp(tmp->type, "scan") == 0 &&
4350 radio->external_scan_running &&
4351 (((struct wpa_driver_scan_params *)
4352 tmp->ctx)->only_new_results ||
4353 tmp->wpa_s->clear_driver_scan_cache))
4354 continue;
4355 return tmp;
4356 }
4357 return NULL;
4358 }
4359
4360 if (os_strcmp(active_work->type, "sme-connect") == 0 ||
4361 os_strcmp(active_work->type, "connect") == 0) {
4362 /*
4363 * If the active work is either connect or sme-connect,
4364 * do not parallelize them with other radio works.
4365 */
4366 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4367 "Do not parallelize radio work with %s",
4368 active_work->type);
4369 return NULL;
4370 }
4371
4372 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4373 if (tmp->started)
4374 continue;
4375
4376 /*
4377 * If connect or sme-connect are enqueued, parallelize only
4378 * those operations ahead of them in the queue.
4379 */
4380 if (os_strcmp(tmp->type, "connect") == 0 ||
4381 os_strcmp(tmp->type, "sme-connect") == 0)
4382 break;
4383
4384 /*
4385 * Check that the radio works are distinct and
4386 * on different bands.
4387 */
4388 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4389 (active_work->bands != tmp->bands)) {
4390 /*
4391 * If a scan has to be scheduled through nl80211 scan
4392 * interface and if an external scan is already running,
4393 * do not schedule the scan since it is likely to get
4394 * rejected by kernel.
4395 */
4396 if (os_strcmp(tmp->type, "scan") == 0 &&
4397 radio->external_scan_running &&
4398 (((struct wpa_driver_scan_params *)
4399 tmp->ctx)->only_new_results ||
4400 tmp->wpa_s->clear_driver_scan_cache))
4401 continue;
4402
4403 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4404 "active_work:%s new_work:%s",
4405 active_work->type, tmp->type);
4406 return tmp;
4407 }
4408 }
4409
4410 /* Did not find a radio work to schedule in parallel. */
4411 return NULL;
4412}
4413
4414
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004415static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4416{
4417 struct wpa_radio *radio = eloop_ctx;
4418 struct wpa_radio_work *work;
4419 struct os_reltime now, diff;
4420 struct wpa_supplicant *wpa_s;
4421
4422 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004423 if (work == NULL) {
4424 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004425 return;
4426 }
4427
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004428 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4429 radio_list);
4430
4431 if (!(wpa_s &&
4432 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4433 if (work->started)
4434 return; /* already started and still in progress */
4435
4436 if (wpa_s && wpa_s->radio->external_scan_running) {
4437 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4438 return;
4439 }
4440 } else {
4441 work = NULL;
4442 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4443 /* get the work to schedule next */
4444 work = radio_work_get_next_work(radio);
4445 }
4446 if (!work)
4447 return;
4448 }
4449
4450 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004451 os_get_reltime(&now);
4452 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004453 wpa_dbg(wpa_s, MSG_DEBUG,
4454 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004455 work->type, work, diff.sec, diff.usec);
4456 work->started = 1;
4457 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004458 radio->num_active_works++;
4459
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004460 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004461
4462 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4463 radio->num_active_works < MAX_ACTIVE_WORKS)
4464 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004465}
4466
4467
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004468/*
4469 * This function removes both started and pending radio works running on
4470 * the provided interface's radio.
4471 * Prior to the removal of the radio work, its callback (cb) is called with
4472 * deinit set to be 1. Each work's callback is responsible for clearing its
4473 * internal data and restoring to a correct state.
4474 * @wpa_s: wpa_supplicant data
4475 * @type: type of works to be removed
4476 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4477 * this interface's works.
4478 */
4479void radio_remove_works(struct wpa_supplicant *wpa_s,
4480 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004481{
4482 struct wpa_radio_work *work, *tmp;
4483 struct wpa_radio *radio = wpa_s->radio;
4484
4485 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4486 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004487 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004488 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004489
4490 /* skip other ifaces' works */
4491 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004492 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004493
4494 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4495 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004496 work->cb(work, 1);
4497 radio_work_free(work);
4498 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004499
4500 /* in case we removed the started work */
4501 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004502}
4503
4504
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004505static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4506{
4507 struct wpa_radio *radio = wpa_s->radio;
4508
4509 if (!radio)
4510 return;
4511
4512 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4513 wpa_s->ifname, radio->name);
4514 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004515 radio_remove_works(wpa_s, NULL, 0);
4516 wpa_s->radio = NULL;
4517 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004518 return; /* Interfaces remain for this radio */
4519
4520 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004521 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004522 os_free(radio);
4523}
4524
4525
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004526void radio_work_check_next(struct wpa_supplicant *wpa_s)
4527{
4528 struct wpa_radio *radio = wpa_s->radio;
4529
4530 if (dl_list_empty(&radio->work))
4531 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004532 if (wpa_s->ext_work_in_progress) {
4533 wpa_printf(MSG_DEBUG,
4534 "External radio work in progress - delay start of pending item");
4535 return;
4536 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004537 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4538 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4539}
4540
4541
4542/**
4543 * radio_add_work - Add a radio work item
4544 * @wpa_s: Pointer to wpa_supplicant data
4545 * @freq: Frequency of the offchannel operation in MHz or 0
4546 * @type: Unique identifier for each type of work
4547 * @next: Force as the next work to be executed
4548 * @cb: Callback function for indicating when radio is available
4549 * @ctx: Context pointer for the work (work->ctx in cb())
4550 * Returns: 0 on success, -1 on failure
4551 *
4552 * This function is used to request time for an operation that requires
4553 * exclusive radio control. Once the radio is available, the registered callback
4554 * function will be called. radio_work_done() must be called once the exclusive
4555 * radio operation has been completed, so that the radio is freed for other
4556 * operations. The special case of deinit=1 is used to free the context data
4557 * during interface removal. That does not allow the callback function to start
4558 * the radio operation, i.e., it must free any resources allocated for the radio
4559 * work and return.
4560 *
4561 * The @freq parameter can be used to indicate a single channel on which the
4562 * offchannel operation will occur. This may allow multiple radio work
4563 * operations to be performed in parallel if they apply for the same channel.
4564 * Setting this to 0 indicates that the work item may use multiple channels or
4565 * requires exclusive control of the radio.
4566 */
4567int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4568 const char *type, int next,
4569 void (*cb)(struct wpa_radio_work *work, int deinit),
4570 void *ctx)
4571{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004572 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004573 struct wpa_radio_work *work;
4574 int was_empty;
4575
4576 work = os_zalloc(sizeof(*work));
4577 if (work == NULL)
4578 return -1;
4579 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4580 os_get_reltime(&work->time);
4581 work->freq = freq;
4582 work->type = type;
4583 work->wpa_s = wpa_s;
4584 work->cb = cb;
4585 work->ctx = ctx;
4586
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004587 if (freq)
4588 work->bands = wpas_freq_to_band(freq);
4589 else if (os_strcmp(type, "scan") == 0 ||
4590 os_strcmp(type, "p2p-scan") == 0)
4591 work->bands = wpas_get_bands(wpa_s,
4592 ((struct wpa_driver_scan_params *)
4593 ctx)->freqs);
4594 else
4595 work->bands = wpas_get_bands(wpa_s, NULL);
4596
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004597 was_empty = dl_list_empty(&wpa_s->radio->work);
4598 if (next)
4599 dl_list_add(&wpa_s->radio->work, &work->list);
4600 else
4601 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4602 if (was_empty) {
4603 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4604 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004605 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4606 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4607 wpa_dbg(wpa_s, MSG_DEBUG,
4608 "Try to schedule a radio work (num_active_works=%u)",
4609 radio->num_active_works);
4610 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004611 }
4612
4613 return 0;
4614}
4615
4616
4617/**
4618 * radio_work_done - Indicate that a radio work item has been completed
4619 * @work: Completed work
4620 *
4621 * This function is called once the callback function registered with
4622 * radio_add_work() has completed its work.
4623 */
4624void radio_work_done(struct wpa_radio_work *work)
4625{
4626 struct wpa_supplicant *wpa_s = work->wpa_s;
4627 struct os_reltime now, diff;
4628 unsigned int started = work->started;
4629
4630 os_get_reltime(&now);
4631 os_reltime_sub(&now, &work->time, &diff);
4632 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4633 work->type, work, started ? "done" : "canceled",
4634 diff.sec, diff.usec);
4635 radio_work_free(work);
4636 if (started)
4637 radio_work_check_next(wpa_s);
4638}
4639
4640
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004641struct wpa_radio_work *
4642radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004643{
4644 struct wpa_radio_work *work;
4645 struct wpa_radio *radio = wpa_s->radio;
4646
4647 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4648 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004649 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004650 }
4651
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004652 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004653}
4654
4655
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004656static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4657 struct wpa_interface *iface)
4658{
4659 const char *ifname, *driver, *rn;
4660
4661 driver = iface->driver;
4662next_driver:
4663 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4664 return -1;
4665
4666 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4667 if (wpa_s->drv_priv == NULL) {
4668 const char *pos;
4669 pos = driver ? os_strchr(driver, ',') : NULL;
4670 if (pos) {
4671 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4672 "driver interface - try next driver wrapper");
4673 driver = pos + 1;
4674 goto next_driver;
4675 }
4676 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4677 "interface");
4678 return -1;
4679 }
4680 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4681 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4682 "driver_param '%s'", wpa_s->conf->driver_param);
4683 return -1;
4684 }
4685
4686 ifname = wpa_drv_get_ifname(wpa_s);
4687 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4688 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4689 "interface name with '%s'", ifname);
4690 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4691 }
4692
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004693 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004694 if (rn && rn[0] == '\0')
4695 rn = NULL;
4696
4697 wpa_s->radio = radio_add_interface(wpa_s, rn);
4698 if (wpa_s->radio == NULL)
4699 return -1;
4700
4701 return 0;
4702}
4703
4704
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004705static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4706 struct wpa_interface *iface)
4707{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004708 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004709 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004710
4711 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4712 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4713 iface->confname ? iface->confname : "N/A",
4714 iface->driver ? iface->driver : "default",
4715 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4716 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4717
4718 if (iface->confname) {
4719#ifdef CONFIG_BACKEND_FILE
4720 wpa_s->confname = os_rel2abs_path(iface->confname);
4721 if (wpa_s->confname == NULL) {
4722 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4723 "for configuration file '%s'.",
4724 iface->confname);
4725 return -1;
4726 }
4727 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4728 iface->confname, wpa_s->confname);
4729#else /* CONFIG_BACKEND_FILE */
4730 wpa_s->confname = os_strdup(iface->confname);
4731#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004732 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004733 if (wpa_s->conf == NULL) {
4734 wpa_printf(MSG_ERROR, "Failed to read or parse "
4735 "configuration '%s'.", wpa_s->confname);
4736 return -1;
4737 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004738 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4739 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004740
4741 /*
4742 * Override ctrl_interface and driver_param if set on command
4743 * line.
4744 */
4745 if (iface->ctrl_interface) {
4746 os_free(wpa_s->conf->ctrl_interface);
4747 wpa_s->conf->ctrl_interface =
4748 os_strdup(iface->ctrl_interface);
4749 }
4750
4751 if (iface->driver_param) {
4752 os_free(wpa_s->conf->driver_param);
4753 wpa_s->conf->driver_param =
4754 os_strdup(iface->driver_param);
4755 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004756
4757 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4758 os_free(wpa_s->conf->ctrl_interface);
4759 wpa_s->conf->ctrl_interface = NULL;
4760 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004761 } else
4762 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4763 iface->driver_param);
4764
4765 if (wpa_s->conf == NULL) {
4766 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4767 return -1;
4768 }
4769
4770 if (iface->ifname == NULL) {
4771 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4772 return -1;
4773 }
4774 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4775 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4776 iface->ifname);
4777 return -1;
4778 }
4779 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4780
4781 if (iface->bridge_ifname) {
4782 if (os_strlen(iface->bridge_ifname) >=
4783 sizeof(wpa_s->bridge_ifname)) {
4784 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4785 "name '%s'.", iface->bridge_ifname);
4786 return -1;
4787 }
4788 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4789 sizeof(wpa_s->bridge_ifname));
4790 }
4791
4792 /* RSNA Supplicant Key Management - INITIALIZE */
4793 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4794 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4795
4796 /* Initialize driver interface and register driver event handler before
4797 * L2 receive handler so that association events are processed before
4798 * EAPOL-Key packets if both become available for the same select()
4799 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004800 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004801 return -1;
4802
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004803 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4804 return -1;
4805
4806 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4807 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4808 NULL);
4809 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4810
4811 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4812 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4813 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4814 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4815 "dot11RSNAConfigPMKLifetime");
4816 return -1;
4817 }
4818
4819 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4820 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4821 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4822 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4823 "dot11RSNAConfigPMKReauthThreshold");
4824 return -1;
4825 }
4826
4827 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4828 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4829 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4830 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4831 "dot11RSNAConfigSATimeout");
4832 return -1;
4833 }
4834
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004835 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4836 &wpa_s->hw.num_modes,
4837 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004838 if (wpa_s->hw.modes) {
4839 u16 i;
4840
4841 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4842 if (wpa_s->hw.modes[i].vht_capab) {
4843 wpa_s->hw_capab = CAPAB_VHT;
4844 break;
4845 }
4846
4847 if (wpa_s->hw.modes[i].ht_capab &
4848 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4849 wpa_s->hw_capab = CAPAB_HT40;
4850 else if (wpa_s->hw.modes[i].ht_capab &&
4851 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4852 wpa_s->hw_capab = CAPAB_HT;
4853 }
4854 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004855
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004856 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4857 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004858 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004859 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004860 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004861 wpa_s->drv_smps_modes = capa.smps_modes;
4862 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004863 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004864 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004865 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004866 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
4867 wpa_s->max_sched_scan_plan_interval =
4868 capa.max_sched_scan_plan_interval;
4869 wpa_s->max_sched_scan_plan_iterations =
4870 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004871 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4872 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004873 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4874 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004875 wpa_s->extended_capa = capa.extended_capa;
4876 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4877 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004878 wpa_s->num_multichan_concurrent =
4879 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004880 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4881
4882 if (capa.mac_addr_rand_scan_supported)
4883 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4884 if (wpa_s->sched_scan_supported &&
4885 capa.mac_addr_rand_sched_scan_supported)
4886 wpa_s->mac_addr_rand_supported |=
4887 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004888 }
4889 if (wpa_s->max_remain_on_chan == 0)
4890 wpa_s->max_remain_on_chan = 1000;
4891
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004892 /*
4893 * Only take p2p_mgmt parameters when P2P Device is supported.
4894 * Doing it here as it determines whether l2_packet_init() will be done
4895 * during wpa_supplicant_driver_init().
4896 */
4897 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4898 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4899 else
4900 iface->p2p_mgmt = 1;
4901
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004902 if (wpa_s->num_multichan_concurrent == 0)
4903 wpa_s->num_multichan_concurrent = 1;
4904
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004905 if (wpa_supplicant_driver_init(wpa_s) < 0)
4906 return -1;
4907
4908#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004909 if ((!iface->p2p_mgmt ||
4910 !(wpa_s->drv_flags &
4911 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4912 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004913 return -1;
4914#endif /* CONFIG_TDLS */
4915
4916 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4917 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4918 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4919 return -1;
4920 }
4921
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004922#ifdef CONFIG_FST
4923 if (wpa_s->conf->fst_group_id) {
4924 struct fst_iface_cfg cfg;
4925 struct fst_wpa_obj iface_obj;
4926
4927 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4928 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4929 sizeof(cfg.group_id));
4930 cfg.priority = wpa_s->conf->fst_priority;
4931 cfg.llt = wpa_s->conf->fst_llt;
4932
4933 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4934 &iface_obj, &cfg);
4935 if (!wpa_s->fst) {
4936 wpa_msg(wpa_s, MSG_ERROR,
4937 "FST: Cannot attach iface %s to group %s",
4938 wpa_s->ifname, cfg.group_id);
4939 return -1;
4940 }
4941 }
4942#endif /* CONFIG_FST */
4943
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004944 if (wpas_wps_init(wpa_s))
4945 return -1;
4946
4947 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4948 return -1;
4949 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4950
4951 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4952 if (wpa_s->ctrl_iface == NULL) {
4953 wpa_printf(MSG_ERROR,
4954 "Failed to initialize control interface '%s'.\n"
4955 "You may have another wpa_supplicant process "
4956 "already running or the file was\n"
4957 "left by an unclean termination of wpa_supplicant "
4958 "in which case you will need\n"
4959 "to manually remove this file before starting "
4960 "wpa_supplicant again.\n",
4961 wpa_s->conf->ctrl_interface);
4962 return -1;
4963 }
4964
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004965 wpa_s->gas = gas_query_init(wpa_s);
4966 if (wpa_s->gas == NULL) {
4967 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4968 return -1;
4969 }
4970
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004971 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004972 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4973 return -1;
4974 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004975
4976 if (wpa_bss_init(wpa_s) < 0)
4977 return -1;
4978
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004979 /*
4980 * Set Wake-on-WLAN triggers, if configured.
4981 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4982 * have effect anyway when the interface is down).
4983 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004984 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004985 return -1;
4986
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004987#ifdef CONFIG_EAP_PROXY
4988{
4989 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004990 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4991 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004992 if (wpa_s->mnc_len > 0) {
4993 wpa_s->imsi[len] = '\0';
4994 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4995 wpa_s->imsi, wpa_s->mnc_len);
4996 } else {
4997 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4998 }
4999}
5000#endif /* CONFIG_EAP_PROXY */
5001
Dmitry Shmidt04949592012-07-19 12:16:46 -07005002 if (pcsc_reader_init(wpa_s) < 0)
5003 return -1;
5004
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005005 if (wpas_init_ext_pw(wpa_s) < 0)
5006 return -1;
5007
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005008 wpas_rrm_reset(wpa_s);
5009
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005010 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5011
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005012#ifdef CONFIG_HS20
5013 hs20_init(wpa_s);
5014#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005015#ifdef CONFIG_MBO
5016 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5017#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005018
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005019 wpa_supplicant_set_default_scan_ies(wpa_s);
5020
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005021 return 0;
5022}
5023
5024
5025static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005026 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005027{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005028 struct wpa_global *global = wpa_s->global;
5029 struct wpa_supplicant *iface, *prev;
5030
5031 if (wpa_s == wpa_s->parent)
5032 wpas_p2p_group_remove(wpa_s, "*");
5033
5034 iface = global->ifaces;
5035 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005036 if (iface->p2pdev == wpa_s)
5037 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005038 if (iface == wpa_s || iface->parent != wpa_s) {
5039 iface = iface->next;
5040 continue;
5041 }
5042 wpa_printf(MSG_DEBUG,
5043 "Remove remaining child interface %s from parent %s",
5044 iface->ifname, wpa_s->ifname);
5045 prev = iface;
5046 iface = iface->next;
5047 wpa_supplicant_remove_iface(global, prev, terminate);
5048 }
5049
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005050 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005051 if (wpa_s->drv_priv) {
5052 wpa_supplicant_deauthenticate(wpa_s,
5053 WLAN_REASON_DEAUTH_LEAVING);
5054
5055 wpa_drv_set_countermeasures(wpa_s, 0);
5056 wpa_clear_keys(wpa_s, NULL);
5057 }
5058
5059 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005060 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005061
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005062 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005063 radio_remove_interface(wpa_s);
5064
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005065#ifdef CONFIG_FST
5066 if (wpa_s->fst) {
5067 fst_detach(wpa_s->fst);
5068 wpa_s->fst = NULL;
5069 }
5070 if (wpa_s->received_mb_ies) {
5071 wpabuf_free(wpa_s->received_mb_ies);
5072 wpa_s->received_mb_ies = NULL;
5073 }
5074#endif /* CONFIG_FST */
5075
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005076 if (wpa_s->drv_priv)
5077 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005078
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005079 if (notify)
5080 wpas_notify_iface_removed(wpa_s);
5081
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005082 if (terminate)
5083 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005084
5085 if (wpa_s->ctrl_iface) {
5086 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5087 wpa_s->ctrl_iface = NULL;
5088 }
5089
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005090#ifdef CONFIG_MESH
5091 if (wpa_s->ifmsh) {
5092 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5093 wpa_s->ifmsh = NULL;
5094 }
5095#endif /* CONFIG_MESH */
5096
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005097 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005098 wpa_config_free(wpa_s->conf);
5099 wpa_s->conf = NULL;
5100 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005101
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005102 os_free(wpa_s->ssids_from_scan_req);
5103
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005104 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005105}
5106
5107
Dmitry Shmidte4663042016-04-04 10:07:49 -07005108#ifdef CONFIG_MATCH_IFACE
5109
5110/**
5111 * wpa_supplicant_match_iface - Match an interface description to a name
5112 * @global: Pointer to global data from wpa_supplicant_init()
5113 * @ifname: Name of the interface to match
5114 * Returns: Pointer to the created interface description or %NULL on failure
5115 */
5116struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5117 const char *ifname)
5118{
5119 int i;
5120 struct wpa_interface *iface, *miface;
5121
5122 for (i = 0; i < global->params.match_iface_count; i++) {
5123 miface = &global->params.match_ifaces[i];
5124 if (!miface->ifname ||
5125 fnmatch(miface->ifname, ifname, 0) == 0) {
5126 iface = os_zalloc(sizeof(*iface));
5127 if (!iface)
5128 return NULL;
5129 *iface = *miface;
5130 iface->ifname = ifname;
5131 return iface;
5132 }
5133 }
5134
5135 return NULL;
5136}
5137
5138
5139/**
5140 * wpa_supplicant_match_existing - Match existing interfaces
5141 * @global: Pointer to global data from wpa_supplicant_init()
5142 * Returns: 0 on success, -1 on failure
5143 */
5144static int wpa_supplicant_match_existing(struct wpa_global *global)
5145{
5146 struct if_nameindex *ifi, *ifp;
5147 struct wpa_supplicant *wpa_s;
5148 struct wpa_interface *iface;
5149
5150 ifp = if_nameindex();
5151 if (!ifp) {
5152 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5153 return -1;
5154 }
5155
5156 for (ifi = ifp; ifi->if_name; ifi++) {
5157 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5158 if (wpa_s)
5159 continue;
5160 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5161 if (iface) {
5162 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5163 os_free(iface);
5164 if (wpa_s)
5165 wpa_s->matched = 1;
5166 }
5167 }
5168
5169 if_freenameindex(ifp);
5170 return 0;
5171}
5172
5173#endif /* CONFIG_MATCH_IFACE */
5174
5175
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005176/**
5177 * wpa_supplicant_add_iface - Add a new network interface
5178 * @global: Pointer to global data from wpa_supplicant_init()
5179 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005180 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005181 * Returns: Pointer to the created interface or %NULL on failure
5182 *
5183 * This function is used to add new network interfaces for %wpa_supplicant.
5184 * This can be called before wpa_supplicant_run() to add interfaces before the
5185 * main event loop has been started. In addition, new interfaces can be added
5186 * dynamically while %wpa_supplicant is already running. This could happen,
5187 * e.g., when a hotplug network adapter is inserted.
5188 */
5189struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005190 struct wpa_interface *iface,
5191 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005192{
5193 struct wpa_supplicant *wpa_s;
5194 struct wpa_interface t_iface;
5195 struct wpa_ssid *ssid;
5196
5197 if (global == NULL || iface == NULL)
5198 return NULL;
5199
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005200 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005201 if (wpa_s == NULL)
5202 return NULL;
5203
5204 wpa_s->global = global;
5205
5206 t_iface = *iface;
5207 if (global->params.override_driver) {
5208 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5209 "('%s' -> '%s')",
5210 iface->driver, global->params.override_driver);
5211 t_iface.driver = global->params.override_driver;
5212 }
5213 if (global->params.override_ctrl_interface) {
5214 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5215 "ctrl_interface ('%s' -> '%s')",
5216 iface->ctrl_interface,
5217 global->params.override_ctrl_interface);
5218 t_iface.ctrl_interface =
5219 global->params.override_ctrl_interface;
5220 }
5221 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5222 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5223 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005224 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005225 return NULL;
5226 }
5227
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005228 if (iface->p2p_mgmt == 0) {
5229 /* 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
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005235 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5236 wpas_notify_network_added(wpa_s, ssid);
5237 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005238
5239 wpa_s->next = global->ifaces;
5240 global->ifaces = wpa_s;
5241
5242 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005243 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005244
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005245#ifdef CONFIG_P2P
5246 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005247 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005248 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005249 wpas_p2p_add_p2pdev_interface(
5250 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005251 wpa_printf(MSG_INFO,
5252 "P2P: Failed to enable P2P Device interface");
5253 /* Try to continue without. P2P will be disabled. */
5254 }
5255#endif /* CONFIG_P2P */
5256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005257 return wpa_s;
5258}
5259
5260
5261/**
5262 * wpa_supplicant_remove_iface - Remove a network interface
5263 * @global: Pointer to global data from wpa_supplicant_init()
5264 * @wpa_s: Pointer to the network interface to be removed
5265 * Returns: 0 if interface was removed, -1 if interface was not found
5266 *
5267 * This function can be used to dynamically remove network interfaces from
5268 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5269 * addition, this function is used to remove all remaining interfaces when
5270 * %wpa_supplicant is terminated.
5271 */
5272int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005273 struct wpa_supplicant *wpa_s,
5274 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005275{
5276 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005277#ifdef CONFIG_MESH
5278 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5279 char *ifname = NULL;
5280#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005281
5282 /* Remove interface from the global list of interfaces */
5283 prev = global->ifaces;
5284 if (prev == wpa_s) {
5285 global->ifaces = wpa_s->next;
5286 } else {
5287 while (prev && prev->next != wpa_s)
5288 prev = prev->next;
5289 if (prev == NULL)
5290 return -1;
5291 prev->next = wpa_s->next;
5292 }
5293
5294 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5295
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005296#ifdef CONFIG_MESH
5297 if (mesh_if_created) {
5298 ifname = os_strdup(wpa_s->ifname);
5299 if (ifname == NULL) {
5300 wpa_dbg(wpa_s, MSG_ERROR,
5301 "mesh: Failed to malloc ifname");
5302 return -1;
5303 }
5304 }
5305#endif /* CONFIG_MESH */
5306
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005307 if (global->p2p_group_formation == wpa_s)
5308 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005309 if (global->p2p_invite_group == wpa_s)
5310 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005311 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005312
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005313#ifdef CONFIG_MESH
5314 if (mesh_if_created) {
5315 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
5316 os_free(ifname);
5317 }
5318#endif /* CONFIG_MESH */
5319
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005320 return 0;
5321}
5322
5323
5324/**
5325 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5326 * @wpa_s: Pointer to the network interface
5327 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5328 */
5329const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5330{
5331 const char *eapol_method;
5332
5333 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5334 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5335 return "NO-EAP";
5336 }
5337
5338 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5339 if (eapol_method == NULL)
5340 return "UNKNOWN-EAP";
5341
5342 return eapol_method;
5343}
5344
5345
5346/**
5347 * wpa_supplicant_get_iface - Get a new network interface
5348 * @global: Pointer to global data from wpa_supplicant_init()
5349 * @ifname: Interface name
5350 * Returns: Pointer to the interface or %NULL if not found
5351 */
5352struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5353 const char *ifname)
5354{
5355 struct wpa_supplicant *wpa_s;
5356
5357 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5358 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5359 return wpa_s;
5360 }
5361 return NULL;
5362}
5363
5364
5365#ifndef CONFIG_NO_WPA_MSG
5366static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5367{
5368 struct wpa_supplicant *wpa_s = ctx;
5369 if (wpa_s == NULL)
5370 return NULL;
5371 return wpa_s->ifname;
5372}
5373#endif /* CONFIG_NO_WPA_MSG */
5374
5375
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005376#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5377#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5378#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5379
5380/* Periodic cleanup tasks */
5381static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5382{
5383 struct wpa_global *global = eloop_ctx;
5384 struct wpa_supplicant *wpa_s;
5385
5386 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5387 wpas_periodic, global, NULL);
5388
5389#ifdef CONFIG_P2P
5390 if (global->p2p)
5391 p2p_expire_peers(global->p2p);
5392#endif /* CONFIG_P2P */
5393
5394 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5395 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5396#ifdef CONFIG_AP
5397 ap_periodic(wpa_s);
5398#endif /* CONFIG_AP */
5399 }
5400}
5401
5402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005403/**
5404 * wpa_supplicant_init - Initialize %wpa_supplicant
5405 * @params: Parameters for %wpa_supplicant
5406 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5407 *
5408 * This function is used to initialize %wpa_supplicant. After successful
5409 * initialization, the returned data pointer can be used to add and remove
5410 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5411 */
5412struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5413{
5414 struct wpa_global *global;
5415 int ret, i;
5416
5417 if (params == NULL)
5418 return NULL;
5419
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005420#ifdef CONFIG_DRIVER_NDIS
5421 {
5422 void driver_ndis_init_ops(void);
5423 driver_ndis_init_ops();
5424 }
5425#endif /* CONFIG_DRIVER_NDIS */
5426
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005427#ifndef CONFIG_NO_WPA_MSG
5428 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5429#endif /* CONFIG_NO_WPA_MSG */
5430
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005431 if (params->wpa_debug_file_path)
5432 wpa_debug_open_file(params->wpa_debug_file_path);
5433 else
5434 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005435 if (params->wpa_debug_syslog)
5436 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005437 if (params->wpa_debug_tracing) {
5438 ret = wpa_debug_open_linux_tracing();
5439 if (ret) {
5440 wpa_printf(MSG_ERROR,
5441 "Failed to enable trace logging");
5442 return NULL;
5443 }
5444 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005445
5446 ret = eap_register_methods();
5447 if (ret) {
5448 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5449 if (ret == -2)
5450 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5451 "the same EAP type.");
5452 return NULL;
5453 }
5454
5455 global = os_zalloc(sizeof(*global));
5456 if (global == NULL)
5457 return NULL;
5458 dl_list_init(&global->p2p_srv_bonjour);
5459 dl_list_init(&global->p2p_srv_upnp);
5460 global->params.daemonize = params->daemonize;
5461 global->params.wait_for_monitor = params->wait_for_monitor;
5462 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5463 if (params->pid_file)
5464 global->params.pid_file = os_strdup(params->pid_file);
5465 if (params->ctrl_interface)
5466 global->params.ctrl_interface =
5467 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005468 if (params->ctrl_interface_group)
5469 global->params.ctrl_interface_group =
5470 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005471 if (params->override_driver)
5472 global->params.override_driver =
5473 os_strdup(params->override_driver);
5474 if (params->override_ctrl_interface)
5475 global->params.override_ctrl_interface =
5476 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005477#ifdef CONFIG_MATCH_IFACE
5478 global->params.match_iface_count = params->match_iface_count;
5479 if (params->match_iface_count) {
5480 global->params.match_ifaces =
5481 os_calloc(params->match_iface_count,
5482 sizeof(struct wpa_interface));
5483 os_memcpy(global->params.match_ifaces,
5484 params->match_ifaces,
5485 params->match_iface_count *
5486 sizeof(struct wpa_interface));
5487 }
5488#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005489#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005490 if (params->conf_p2p_dev)
5491 global->params.conf_p2p_dev =
5492 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005493#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005494 wpa_debug_level = global->params.wpa_debug_level =
5495 params->wpa_debug_level;
5496 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5497 params->wpa_debug_show_keys;
5498 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5499 params->wpa_debug_timestamp;
5500
5501 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5502
5503 if (eloop_init()) {
5504 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5505 wpa_supplicant_deinit(global);
5506 return NULL;
5507 }
5508
Jouni Malinen75ecf522011-06-27 15:19:46 -07005509 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005510
5511 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5512 if (global->ctrl_iface == NULL) {
5513 wpa_supplicant_deinit(global);
5514 return NULL;
5515 }
5516
5517 if (wpas_notify_supplicant_initialized(global)) {
5518 wpa_supplicant_deinit(global);
5519 return NULL;
5520 }
5521
5522 for (i = 0; wpa_drivers[i]; i++)
5523 global->drv_count++;
5524 if (global->drv_count == 0) {
5525 wpa_printf(MSG_ERROR, "No drivers enabled");
5526 wpa_supplicant_deinit(global);
5527 return NULL;
5528 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005529 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005530 if (global->drv_priv == NULL) {
5531 wpa_supplicant_deinit(global);
5532 return NULL;
5533 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005534
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005535#ifdef CONFIG_WIFI_DISPLAY
5536 if (wifi_display_init(global) < 0) {
5537 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5538 wpa_supplicant_deinit(global);
5539 return NULL;
5540 }
5541#endif /* CONFIG_WIFI_DISPLAY */
5542
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005543 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5544 wpas_periodic, global, NULL);
5545
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005546 return global;
5547}
5548
5549
5550/**
5551 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5552 * @global: Pointer to global data from wpa_supplicant_init()
5553 * Returns: 0 after successful event loop run, -1 on failure
5554 *
5555 * This function starts the main event loop and continues running as long as
5556 * there are any remaining events. In most cases, this function is running as
5557 * long as the %wpa_supplicant process in still in use.
5558 */
5559int wpa_supplicant_run(struct wpa_global *global)
5560{
5561 struct wpa_supplicant *wpa_s;
5562
5563 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005564 (wpa_supplicant_daemon(global->params.pid_file) ||
5565 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005566 return -1;
5567
Dmitry Shmidte4663042016-04-04 10:07:49 -07005568#ifdef CONFIG_MATCH_IFACE
5569 if (wpa_supplicant_match_existing(global))
5570 return -1;
5571#endif
5572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005573 if (global->params.wait_for_monitor) {
5574 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005575 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005576 wpa_supplicant_ctrl_iface_wait(
5577 wpa_s->ctrl_iface);
5578 }
5579
5580 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5581 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5582
5583 eloop_run();
5584
5585 return 0;
5586}
5587
5588
5589/**
5590 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5591 * @global: Pointer to global data from wpa_supplicant_init()
5592 *
5593 * This function is called to deinitialize %wpa_supplicant and to free all
5594 * allocated resources. Remaining network interfaces will also be removed.
5595 */
5596void wpa_supplicant_deinit(struct wpa_global *global)
5597{
5598 int i;
5599
5600 if (global == NULL)
5601 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005602
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005603 eloop_cancel_timeout(wpas_periodic, global, NULL);
5604
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005605#ifdef CONFIG_WIFI_DISPLAY
5606 wifi_display_deinit(global);
5607#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005608
5609 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005610 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005611
5612 if (global->ctrl_iface)
5613 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5614
5615 wpas_notify_supplicant_deinitialized(global);
5616
5617 eap_peer_unregister_methods();
5618#ifdef CONFIG_AP
5619 eap_server_unregister_methods();
5620#endif /* CONFIG_AP */
5621
5622 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5623 if (!global->drv_priv[i])
5624 continue;
5625 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5626 }
5627 os_free(global->drv_priv);
5628
5629 random_deinit();
5630
5631 eloop_destroy();
5632
5633 if (global->params.pid_file) {
5634 os_daemonize_terminate(global->params.pid_file);
5635 os_free(global->params.pid_file);
5636 }
5637 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005638 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005639 os_free(global->params.override_driver);
5640 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005641#ifdef CONFIG_MATCH_IFACE
5642 os_free(global->params.match_ifaces);
5643#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005644#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005645 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005646#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005647
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005648 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005649 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005650 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005651
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005652 os_free(global);
5653 wpa_debug_close_syslog();
5654 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005655 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005656}
5657
5658
5659void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5660{
5661 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5662 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5663 char country[3];
5664 country[0] = wpa_s->conf->country[0];
5665 country[1] = wpa_s->conf->country[1];
5666 country[2] = '\0';
5667 if (wpa_drv_set_country(wpa_s, country) < 0) {
5668 wpa_printf(MSG_ERROR, "Failed to set country code "
5669 "'%s'", country);
5670 }
5671 }
5672
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005673 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5674 wpas_init_ext_pw(wpa_s);
5675
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005676 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5677 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5678
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005679#ifdef CONFIG_WPS
5680 wpas_wps_update_config(wpa_s);
5681#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005682 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005683 wpa_s->conf->changed_parameters = 0;
5684}
5685
5686
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005687void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005688{
5689 int i;
5690
5691 for (i = 0; i < *num_freqs; i++) {
5692 if (freqs[i] == freq)
5693 return;
5694 }
5695
5696 freqs[*num_freqs] = freq;
5697 (*num_freqs)++;
5698}
5699
5700
5701static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5702{
5703 struct wpa_bss *bss, *cbss;
5704 const int max_freqs = 10;
5705 int *freqs;
5706 int num_freqs = 0;
5707
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005708 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005709 if (freqs == NULL)
5710 return NULL;
5711
5712 cbss = wpa_s->current_bss;
5713
5714 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5715 if (bss == cbss)
5716 continue;
5717 if (bss->ssid_len == cbss->ssid_len &&
5718 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5719 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5720 add_freq(freqs, &num_freqs, bss->freq);
5721 if (num_freqs == max_freqs)
5722 break;
5723 }
5724 }
5725
5726 if (num_freqs == 0) {
5727 os_free(freqs);
5728 freqs = NULL;
5729 }
5730
5731 return freqs;
5732}
5733
5734
5735void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5736{
5737 int timeout;
5738 int count;
5739 int *freqs = NULL;
5740
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005741 wpas_connect_work_done(wpa_s);
5742
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005743 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005744 * Remove possible authentication timeout since the connection failed.
5745 */
5746 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5747
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005748 /*
5749 * There is no point in blacklisting the AP if this event is
5750 * generated based on local request to disconnect.
5751 */
5752 if (wpa_s->own_disconnect_req) {
5753 wpa_s->own_disconnect_req = 0;
5754 wpa_dbg(wpa_s, MSG_DEBUG,
5755 "Ignore connection failure due to local request to disconnect");
5756 return;
5757 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005758 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005759 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5760 "indication since interface has been put into "
5761 "disconnected state");
5762 return;
5763 }
5764
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005765 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005766 * Add the failed BSSID into the blacklist and speed up next scan
5767 * attempt if there could be other APs that could accept association.
5768 * The current blacklist count indicates how many times we have tried
5769 * connecting to this AP and multiple attempts mean that other APs are
5770 * either not available or has already been tried, so that we can start
5771 * increasing the delay here to avoid constant scanning.
5772 */
5773 count = wpa_blacklist_add(wpa_s, bssid);
5774 if (count == 1 && wpa_s->current_bss) {
5775 /*
5776 * This BSS was not in the blacklist before. If there is
5777 * another BSS available for the same ESS, we should try that
5778 * next. Otherwise, we may as well try this one once more
5779 * before allowing other, likely worse, ESSes to be considered.
5780 */
5781 freqs = get_bss_freqs_in_ess(wpa_s);
5782 if (freqs) {
5783 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5784 "has been seen; try it next");
5785 wpa_blacklist_add(wpa_s, bssid);
5786 /*
5787 * On the next scan, go through only the known channels
5788 * used in this ESS based on previous scans to speed up
5789 * common load balancing use case.
5790 */
5791 os_free(wpa_s->next_scan_freqs);
5792 wpa_s->next_scan_freqs = freqs;
5793 }
5794 }
5795
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005796 /*
5797 * Add previous failure count in case the temporary blacklist was
5798 * cleared due to no other BSSes being available.
5799 */
5800 count += wpa_s->extra_blacklist_count;
5801
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005802 if (count > 3 && wpa_s->current_ssid) {
5803 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5804 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005805 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005806 }
5807
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005808 switch (count) {
5809 case 1:
5810 timeout = 100;
5811 break;
5812 case 2:
5813 timeout = 500;
5814 break;
5815 case 3:
5816 timeout = 1000;
5817 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005818 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005819 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005820 break;
5821 default:
5822 timeout = 10000;
5823 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005824 }
5825
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005826 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5827 "ms", count, timeout);
5828
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005829 /*
5830 * TODO: if more than one possible AP is available in scan results,
5831 * could try the other ones before requesting a new scan.
5832 */
5833 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5834 1000 * (timeout % 1000));
5835}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005836
5837
5838int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5839{
5840 return wpa_s->conf->ap_scan == 2 ||
5841 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5842}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005843
Dmitry Shmidt04949592012-07-19 12:16:46 -07005844
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005845#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005846int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5847 struct wpa_ssid *ssid,
5848 const char *field,
5849 const char *value)
5850{
5851#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005852 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005853
5854 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5855 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5856 (const u8 *) value, os_strlen(value));
5857
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005858 rtype = wpa_supplicant_ctrl_req_from_string(field);
5859 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
5860#else /* IEEE8021X_EAPOL */
5861 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5862 return -1;
5863#endif /* IEEE8021X_EAPOL */
5864}
5865
5866int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5867 struct wpa_ssid *ssid,
5868 enum wpa_ctrl_req_type rtype,
5869 const char *value)
5870{
5871#ifdef IEEE8021X_EAPOL
5872 struct eap_peer_config *eap = &ssid->eap;
5873
5874 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005875 case WPA_CTRL_REQ_EAP_IDENTITY:
5876 os_free(eap->identity);
5877 eap->identity = (u8 *) os_strdup(value);
5878 eap->identity_len = os_strlen(value);
5879 eap->pending_req_identity = 0;
5880 if (ssid == wpa_s->current_ssid)
5881 wpa_s->reassociate = 1;
5882 break;
5883 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005884 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005885 eap->password = (u8 *) os_strdup(value);
5886 eap->password_len = os_strlen(value);
5887 eap->pending_req_password = 0;
5888 if (ssid == wpa_s->current_ssid)
5889 wpa_s->reassociate = 1;
5890 break;
5891 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005892 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005893 eap->new_password = (u8 *) os_strdup(value);
5894 eap->new_password_len = os_strlen(value);
5895 eap->pending_req_new_password = 0;
5896 if (ssid == wpa_s->current_ssid)
5897 wpa_s->reassociate = 1;
5898 break;
5899 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005900 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005901 eap->pin = os_strdup(value);
5902 eap->pending_req_pin = 0;
5903 if (ssid == wpa_s->current_ssid)
5904 wpa_s->reassociate = 1;
5905 break;
5906 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005907 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005908 eap->otp = (u8 *) os_strdup(value);
5909 eap->otp_len = os_strlen(value);
5910 os_free(eap->pending_req_otp);
5911 eap->pending_req_otp = NULL;
5912 eap->pending_req_otp_len = 0;
5913 break;
5914 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005915 str_clear_free(eap->private_key_passwd);
5916 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005917 eap->pending_req_passphrase = 0;
5918 if (ssid == wpa_s->current_ssid)
5919 wpa_s->reassociate = 1;
5920 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005921 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005922 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005923 eap->external_sim_resp = os_strdup(value);
5924 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005925 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5926 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5927 return -1;
5928 ssid->mem_only_psk = 1;
5929 if (ssid->passphrase)
5930 wpa_config_update_psk(ssid);
5931 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5932 wpa_supplicant_req_scan(wpa_s, 0, 0);
5933 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005934 case WPA_CTRL_REQ_EXT_CERT_CHECK:
5935 if (eap->pending_ext_cert_check != PENDING_CHECK)
5936 return -1;
5937 if (os_strcmp(value, "good") == 0)
5938 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
5939 else if (os_strcmp(value, "bad") == 0)
5940 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
5941 else
5942 return -1;
5943 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005944 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005945 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005946 return -1;
5947 }
5948
5949 return 0;
5950#else /* IEEE8021X_EAPOL */
5951 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5952 return -1;
5953#endif /* IEEE8021X_EAPOL */
5954}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005955#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005956
5957
5958int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5959{
5960 int i;
5961 unsigned int drv_enc;
5962
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005963 if (wpa_s->p2p_mgmt)
5964 return 1; /* no normal network profiles on p2p_mgmt interface */
5965
Dmitry Shmidt04949592012-07-19 12:16:46 -07005966 if (ssid == NULL)
5967 return 1;
5968
5969 if (ssid->disabled)
5970 return 1;
5971
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005972 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005973 drv_enc = wpa_s->drv_enc;
5974 else
5975 drv_enc = (unsigned int) -1;
5976
5977 for (i = 0; i < NUM_WEP_KEYS; i++) {
5978 size_t len = ssid->wep_key_len[i];
5979 if (len == 0)
5980 continue;
5981 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5982 continue;
5983 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5984 continue;
5985 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5986 continue;
5987 return 1; /* invalid WEP key */
5988 }
5989
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005990 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005991 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5992 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005993 return 1;
5994
Dmitry Shmidt04949592012-07-19 12:16:46 -07005995 return 0;
5996}
5997
5998
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005999int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6000{
6001#ifdef CONFIG_IEEE80211W
6002 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6003 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6004 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6005 /*
6006 * Driver does not support BIP -- ignore pmf=1 default
6007 * since the connection with PMF would fail and the
6008 * configuration does not require PMF to be enabled.
6009 */
6010 return NO_MGMT_FRAME_PROTECTION;
6011 }
6012
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006013 if (ssid &&
6014 (ssid->key_mgmt &
6015 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6016 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6017 /*
6018 * Do not use the default PMF value for non-RSN networks
6019 * since PMF is available only with RSN and pmf=2
6020 * configuration would otherwise prevent connections to
6021 * all open networks.
6022 */
6023 return NO_MGMT_FRAME_PROTECTION;
6024 }
6025
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006026 return wpa_s->conf->pmf;
6027 }
6028
6029 return ssid->ieee80211w;
6030#else /* CONFIG_IEEE80211W */
6031 return NO_MGMT_FRAME_PROTECTION;
6032#endif /* CONFIG_IEEE80211W */
6033}
6034
6035
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006036int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006037{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006038 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006039 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006040 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006041 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006042 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006043}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006044
6045
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006046void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006047{
6048 struct wpa_ssid *ssid = wpa_s->current_ssid;
6049 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006050 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006051
6052 if (ssid == NULL) {
6053 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6054 "SSID block");
6055 return;
6056 }
6057
6058 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6059 return;
6060
6061 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006062
6063#ifdef CONFIG_P2P
6064 if (ssid->p2p_group &&
6065 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6066 /*
6067 * Skip the wait time since there is a short timeout on the
6068 * connection to a P2P group.
6069 */
6070 return;
6071 }
6072#endif /* CONFIG_P2P */
6073
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006074 if (ssid->auth_failures > 50)
6075 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006076 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006077 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006078 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006079 dur = 90;
6080 else if (ssid->auth_failures > 3)
6081 dur = 60;
6082 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006083 dur = 30;
6084 else if (ssid->auth_failures > 1)
6085 dur = 20;
6086 else
6087 dur = 10;
6088
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006089 if (ssid->auth_failures > 1 &&
6090 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6091 dur += os_random() % (ssid->auth_failures * 10);
6092
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006093 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006094 if (now.sec + dur <= ssid->disabled_until.sec)
6095 return;
6096
6097 ssid->disabled_until.sec = now.sec + dur;
6098
6099 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006100 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006101 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006102 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006103}
6104
6105
6106void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6107 struct wpa_ssid *ssid, int clear_failures)
6108{
6109 if (ssid == NULL)
6110 return;
6111
6112 if (ssid->disabled_until.sec) {
6113 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6114 "id=%d ssid=\"%s\"",
6115 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6116 }
6117 ssid->disabled_until.sec = 0;
6118 ssid->disabled_until.usec = 0;
6119 if (clear_failures)
6120 ssid->auth_failures = 0;
6121}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006122
6123
6124int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6125{
6126 size_t i;
6127
6128 if (wpa_s->disallow_aps_bssid == NULL)
6129 return 0;
6130
6131 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6132 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6133 bssid, ETH_ALEN) == 0)
6134 return 1;
6135 }
6136
6137 return 0;
6138}
6139
6140
6141int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6142 size_t ssid_len)
6143{
6144 size_t i;
6145
6146 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6147 return 0;
6148
6149 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6150 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6151 if (ssid_len == s->ssid_len &&
6152 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6153 return 1;
6154 }
6155
6156 return 0;
6157}
6158
6159
6160/**
6161 * wpas_request_connection - Request a new connection
6162 * @wpa_s: Pointer to the network interface
6163 *
6164 * This function is used to request a new connection to be found. It will mark
6165 * the interface to allow reassociation and request a new scan to find a
6166 * suitable network to connect to.
6167 */
6168void wpas_request_connection(struct wpa_supplicant *wpa_s)
6169{
6170 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006171 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006172 wpa_supplicant_reinit_autoscan(wpa_s);
6173 wpa_s->extra_blacklist_count = 0;
6174 wpa_s->disconnected = 0;
6175 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006176
6177 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6178 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006179 else
6180 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006181}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006182
Roshan Pius02242d72016-08-09 15:31:48 -07006183/**
6184 * wpas_request_disconnection - Request disconnection
6185 * @wpa_s: Pointer to the network interface
6186 *
6187 * This function is used to request disconnection from the currently connected
6188 * network. This will stop any ongoing scans and initiate deauthentication.
6189 */
6190void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6191{
6192#ifdef CONFIG_SME
6193 wpa_s->sme.prev_bssid_set = 0;
6194#endif /* CONFIG_SME */
6195 wpa_s->reassociate = 0;
6196 wpa_s->disconnected = 1;
6197 wpa_supplicant_cancel_sched_scan(wpa_s);
6198 wpa_supplicant_cancel_scan(wpa_s);
6199 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6200 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6201}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006202
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006203
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006204void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6205 struct wpa_used_freq_data *freqs_data,
6206 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006207{
6208 unsigned int i;
6209
6210 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6211 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006212 for (i = 0; i < len; i++) {
6213 struct wpa_used_freq_data *cur = &freqs_data[i];
6214 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6215 i, cur->freq, cur->flags);
6216 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006217}
6218
6219
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006220/*
6221 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006222 * are using the same radio as the current interface, and in addition, get
6223 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006224 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006225int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6226 struct wpa_used_freq_data *freqs_data,
6227 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006228{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006229 struct wpa_supplicant *ifs;
6230 u8 bssid[ETH_ALEN];
6231 int freq;
6232 unsigned int idx = 0, i;
6233
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006234 wpa_dbg(wpa_s, MSG_DEBUG,
6235 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006236 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006237
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006238 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6239 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006240 if (idx == len)
6241 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006242
6243 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6244 continue;
6245
6246 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006247 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6248 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006249 freq = ifs->current_ssid->frequency;
6250 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6251 freq = ifs->assoc_freq;
6252 else
6253 continue;
6254
6255 /* Hold only distinct freqs */
6256 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006257 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006258 break;
6259
6260 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006261 freqs_data[idx++].freq = freq;
6262
6263 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006264 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006265 WPA_FREQ_USED_BY_P2P_CLIENT :
6266 WPA_FREQ_USED_BY_INFRA_STATION;
6267 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006268 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006269
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006270 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006271 return idx;
6272}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006273
6274
6275/*
6276 * Find the operating frequencies of any of the virtual interfaces that
6277 * are using the same radio as the current interface.
6278 */
6279int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6280 int *freq_array, unsigned int len)
6281{
6282 struct wpa_used_freq_data *freqs_data;
6283 int num, i;
6284
6285 os_memset(freq_array, 0, sizeof(int) * len);
6286
6287 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6288 if (!freqs_data)
6289 return -1;
6290
6291 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6292 for (i = 0; i < num; i++)
6293 freq_array[i] = freqs_data[i].freq;
6294
6295 os_free(freqs_data);
6296
6297 return num;
6298}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006299
6300
6301static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
6302{
6303 struct rrm_data *rrm = data;
6304
6305 if (!rrm->notify_neighbor_rep) {
6306 wpa_printf(MSG_ERROR,
6307 "RRM: Unexpected neighbor report timeout");
6308 return;
6309 }
6310
6311 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
6312 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
6313
6314 rrm->notify_neighbor_rep = NULL;
6315 rrm->neighbor_rep_cb_ctx = NULL;
6316}
6317
6318
6319/*
6320 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
6321 * @wpa_s: Pointer to wpa_supplicant
6322 */
6323void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
6324{
6325 wpa_s->rrm.rrm_used = 0;
6326
6327 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6328 NULL);
6329 if (wpa_s->rrm.notify_neighbor_rep)
6330 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
6331 wpa_s->rrm.next_neighbor_rep_token = 1;
6332}
6333
6334
6335/*
6336 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
6337 * @wpa_s: Pointer to wpa_supplicant
6338 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
6339 * @report_len: Length of neighbor report buffer
6340 */
6341void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
6342 const u8 *report, size_t report_len)
6343{
6344 struct wpabuf *neighbor_rep;
6345
6346 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
6347 if (report_len < 1)
6348 return;
6349
6350 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
6351 wpa_printf(MSG_DEBUG,
6352 "RRM: Discarding neighbor report with token %d (expected %d)",
6353 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
6354 return;
6355 }
6356
6357 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6358 NULL);
6359
6360 if (!wpa_s->rrm.notify_neighbor_rep) {
6361 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
6362 return;
6363 }
6364
6365 /* skipping the first byte, which is only an id (dialog token) */
6366 neighbor_rep = wpabuf_alloc(report_len - 1);
6367 if (neighbor_rep == NULL)
6368 return;
6369 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
6370 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
6371 report[0]);
6372 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
6373 neighbor_rep);
6374 wpa_s->rrm.notify_neighbor_rep = NULL;
6375 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
6376}
6377
6378
Dmitry Shmidtff787d52015-01-12 13:01:47 -08006379#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
6380/* Workaround different, undefined for Windows, error codes used here */
6381#define ENOTCONN -1
6382#define EOPNOTSUPP -1
6383#define ECANCELED -1
6384#endif
6385
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006386/* Measurement Request element + Location Subject + Maximum Age subelement */
6387#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
6388/* Measurement Request element + Location Civic Request */
6389#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
6390
6391
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006392/**
6393 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
6394 * @wpa_s: Pointer to wpa_supplicant
6395 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
6396 * is sent in the request.
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006397 * @lci: if set, neighbor request will include LCI request
6398 * @civic: if set, neighbor request will include civic location request
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006399 * @cb: Callback function to be called once the requested report arrives, or
6400 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
6401 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
6402 * the requester's responsibility to free it.
6403 * In the latter case NULL will be sent in 'neighbor_rep'.
6404 * @cb_ctx: Context value to send the callback function
6405 * Returns: 0 in case of success, negative error code otherwise
6406 *
6407 * In case there is a previous request which has not been answered yet, the
6408 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
6409 * Request must contain a callback function.
6410 */
6411int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006412 const struct wpa_ssid_value *ssid,
6413 int lci, int civic,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006414 void (*cb)(void *ctx,
6415 struct wpabuf *neighbor_rep),
6416 void *cb_ctx)
6417{
6418 struct wpabuf *buf;
6419 const u8 *rrm_ie;
6420
6421 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
6422 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
6423 return -ENOTCONN;
6424 }
6425
6426 if (!wpa_s->rrm.rrm_used) {
6427 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
6428 return -EOPNOTSUPP;
6429 }
6430
6431 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
6432 WLAN_EID_RRM_ENABLED_CAPABILITIES);
6433 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
6434 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
6435 wpa_printf(MSG_DEBUG,
6436 "RRM: No network support for Neighbor Report.");
6437 return -EOPNOTSUPP;
6438 }
6439
6440 if (!cb) {
6441 wpa_printf(MSG_DEBUG,
6442 "RRM: Neighbor Report request must provide a callback.");
6443 return -EINVAL;
6444 }
6445
6446 /* Refuse if there's a live request */
6447 if (wpa_s->rrm.notify_neighbor_rep) {
6448 wpa_printf(MSG_DEBUG,
6449 "RRM: Currently handling previous Neighbor Report.");
6450 return -EBUSY;
6451 }
6452
6453 /* 3 = action category + action code + dialog token */
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006454 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
6455 (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
6456 (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006457 if (buf == NULL) {
6458 wpa_printf(MSG_DEBUG,
6459 "RRM: Failed to allocate Neighbor Report Request");
6460 return -ENOMEM;
6461 }
6462
6463 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
6464 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
6465 wpa_s->rrm.next_neighbor_rep_token);
6466
6467 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6468 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
6469 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
6470 if (ssid) {
6471 wpabuf_put_u8(buf, WLAN_EID_SSID);
6472 wpabuf_put_u8(buf, ssid->ssid_len);
6473 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
6474 }
6475
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006476 if (lci) {
6477 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6478 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6479 wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
6480
6481 /*
6482 * Measurement token; nonzero number that is unique among the
6483 * Measurement Request elements in a particular frame.
6484 */
6485 wpabuf_put_u8(buf, 1); /* Measurement Token */
6486
6487 /*
6488 * Parallel, Enable, Request, and Report bits are 0, Duration is
6489 * reserved.
6490 */
6491 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6492 wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
6493
6494 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
6495 /* Location Subject */
6496 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6497
6498 /* Optional Subelements */
6499 /*
6500 * IEEE P802.11-REVmc/D5.0 Figure 9-170
6501 * The Maximum Age subelement is required, otherwise the AP can
6502 * send only data that was determined after receiving the
6503 * request. Setting it here to unlimited age.
6504 */
6505 wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
6506 wpabuf_put_u8(buf, 2);
6507 wpabuf_put_le16(buf, 0xffff);
6508 }
6509
6510 if (civic) {
6511 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6512 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6513 wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
6514
6515 /*
6516 * Measurement token; nonzero number that is unique among the
6517 * Measurement Request elements in a particular frame.
6518 */
6519 wpabuf_put_u8(buf, 2); /* Measurement Token */
6520
6521 /*
6522 * Parallel, Enable, Request, and Report bits are 0, Duration is
6523 * reserved.
6524 */
6525 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6526 /* Measurement Type */
6527 wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
6528
6529 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
6530 * Location Civic request */
6531 /* Location Subject */
6532 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6533 wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
6534 /* Location Service Interval Units: Seconds */
6535 wpabuf_put_u8(buf, 0);
6536 /* Location Service Interval: 0 - Only one report is requested
6537 */
6538 wpabuf_put_le16(buf, 0);
6539 /* No optional subelements */
6540 }
6541
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006542 wpa_s->rrm.next_neighbor_rep_token++;
6543
6544 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
6545 wpa_s->own_addr, wpa_s->bssid,
6546 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
6547 wpa_printf(MSG_DEBUG,
6548 "RRM: Failed to send Neighbor Report Request");
6549 wpabuf_free(buf);
6550 return -ECANCELED;
6551 }
6552
6553 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
6554 wpa_s->rrm.notify_neighbor_rep = cb;
6555 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
6556 wpas_rrm_neighbor_rep_timeout_handler,
6557 &wpa_s->rrm, NULL);
6558
6559 wpabuf_free(buf);
6560 return 0;
6561}
6562
6563
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006564static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
6565 const u8 *request, size_t len,
6566 struct wpabuf *report)
6567{
6568 u8 token, type, subject;
6569 u16 max_age = 0;
6570 struct os_reltime t, diff;
6571 unsigned long diff_l;
6572 u8 *ptoken;
6573 const u8 *subelem;
6574
6575 if (!wpa_s->lci || len < 3 + 4)
6576 return report;
6577
6578 token = *request++;
6579 /* Measurement request mode isn't used */
6580 request++;
6581 type = *request++;
6582 subject = *request++;
6583
6584 wpa_printf(MSG_DEBUG,
6585 "Measurement request token %u type %u location subject %u",
6586 token, type, subject);
6587
6588 if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
6589 wpa_printf(MSG_INFO,
6590 "Not building LCI report - bad type or location subject");
6591 return report;
6592 }
6593
6594 /* Subelements are formatted exactly like elements */
6595 subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
6596 if (subelem && subelem[1] == 2)
6597 max_age = WPA_GET_LE16(subelem + 2);
6598
6599 if (os_get_reltime(&t))
6600 return report;
6601
6602 os_reltime_sub(&t, &wpa_s->lci_time, &diff);
6603 /* LCI age is calculated in 10th of a second units. */
6604 diff_l = diff.sec * 10 + diff.usec / 100000;
6605
6606 if (max_age != 0xffff && max_age < diff_l)
6607 return report;
6608
6609 if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
6610 return report;
6611
6612 wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
6613 wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
6614 /* We'll override user's measurement token */
6615 ptoken = wpabuf_put(report, 0);
6616 wpabuf_put_buf(report, wpa_s->lci);
6617 *ptoken = token;
6618
6619 return report;
6620}
6621
6622
6623void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
6624 const u8 *src,
6625 const u8 *frame, size_t len)
6626{
6627 struct wpabuf *buf, *report;
6628 u8 token;
6629 const u8 *ie, *end;
6630
6631 if (wpa_s->wpa_state != WPA_COMPLETED) {
6632 wpa_printf(MSG_INFO,
6633 "RRM: Ignoring radio measurement request: Not associated");
6634 return;
6635 }
6636
6637 if (!wpa_s->rrm.rrm_used) {
6638 wpa_printf(MSG_INFO,
6639 "RRM: Ignoring radio measurement request: Not RRM network");
6640 return;
6641 }
6642
6643 if (len < 3) {
6644 wpa_printf(MSG_INFO,
6645 "RRM: Ignoring too short radio measurement request");
6646 return;
6647 }
6648
6649 end = frame + len;
6650
6651 token = *frame++;
6652
6653 /* Ignore number of repetitions because it's not used in LCI request */
6654 frame += 2;
6655
6656 report = NULL;
6657 while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
6658 ie[1] >= 3) {
6659 u8 msmt_type;
6660
6661 msmt_type = ie[4];
6662 wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
6663
6664 switch (msmt_type) {
6665 case MEASURE_TYPE_LCI:
6666 report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
6667 report);
6668 break;
6669 default:
6670 wpa_printf(MSG_INFO,
6671 "RRM: Unsupported radio measurement request %d",
6672 msmt_type);
6673 break;
6674 }
6675
6676 frame = ie + ie[1] + 2;
6677 }
6678
6679 if (!report)
6680 return;
6681
6682 buf = wpabuf_alloc(3 + wpabuf_len(report));
6683 if (!buf) {
6684 wpabuf_free(report);
6685 return;
6686 }
6687
6688 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6689 wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
6690 wpabuf_put_u8(buf, token);
6691
6692 wpabuf_put_buf(buf, report);
6693 wpabuf_free(report);
6694
6695 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6696 wpa_s->own_addr, wpa_s->bssid,
6697 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6698 wpa_printf(MSG_ERROR,
6699 "RRM: Radio measurement report failed: Sending Action frame failed");
6700 }
6701 wpabuf_free(buf);
6702}
6703
6704
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006705void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
6706 const u8 *src,
6707 const u8 *frame, size_t len,
6708 int rssi)
6709{
6710 struct wpabuf *buf;
6711 const struct rrm_link_measurement_request *req;
6712 struct rrm_link_measurement_report report;
6713
6714 if (wpa_s->wpa_state != WPA_COMPLETED) {
6715 wpa_printf(MSG_INFO,
6716 "RRM: Ignoring link measurement request. Not associated");
6717 return;
6718 }
6719
6720 if (!wpa_s->rrm.rrm_used) {
6721 wpa_printf(MSG_INFO,
6722 "RRM: Ignoring link measurement request. Not RRM network");
6723 return;
6724 }
6725
6726 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
6727 wpa_printf(MSG_INFO,
6728 "RRM: Measurement report failed. TX power insertion not supported");
6729 return;
6730 }
6731
6732 req = (const struct rrm_link_measurement_request *) frame;
6733 if (len < sizeof(*req)) {
6734 wpa_printf(MSG_INFO,
6735 "RRM: Link measurement report failed. Request too short");
6736 return;
6737 }
6738
6739 os_memset(&report, 0, sizeof(report));
6740 report.tpc.eid = WLAN_EID_TPC_REPORT;
6741 report.tpc.len = 2;
6742 report.rsni = 255; /* 255 indicates that RSNI is not available */
6743 report.dialog_token = req->dialog_token;
6744
6745 /*
6746 * It's possible to estimate RCPI based on RSSI in dBm. This
6747 * calculation will not reflect the correct value for high rates,
6748 * but it's good enough for Action frames which are transmitted
6749 * with up to 24 Mbps rates.
6750 */
6751 if (!rssi)
6752 report.rcpi = 255; /* not available */
6753 else if (rssi < -110)
6754 report.rcpi = 0;
6755 else if (rssi > 0)
6756 report.rcpi = 220;
6757 else
6758 report.rcpi = (rssi + 110) * 2;
6759
6760 /* action_category + action_code */
6761 buf = wpabuf_alloc(2 + sizeof(report));
6762 if (buf == NULL) {
6763 wpa_printf(MSG_ERROR,
6764 "RRM: Link measurement report failed. Buffer allocation failed");
6765 return;
6766 }
6767
6768 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6769 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
6770 wpabuf_put_data(buf, &report, sizeof(report));
6771 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
6772 wpabuf_head(buf), wpabuf_len(buf));
6773
6774 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6775 wpa_s->own_addr, wpa_s->bssid,
6776 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6777 wpa_printf(MSG_ERROR,
6778 "RRM: Link measurement report failed. Send action failed");
6779 }
6780 wpabuf_free(buf);
6781}
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006782
6783
6784struct wpa_supplicant *
6785wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6786{
6787 switch (frame) {
6788#ifdef CONFIG_P2P
6789 case VENDOR_ELEM_PROBE_REQ_P2P:
6790 case VENDOR_ELEM_PROBE_RESP_P2P:
6791 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6792 case VENDOR_ELEM_BEACON_P2P_GO:
6793 case VENDOR_ELEM_P2P_PD_REQ:
6794 case VENDOR_ELEM_P2P_PD_RESP:
6795 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6796 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6797 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6798 case VENDOR_ELEM_P2P_INV_REQ:
6799 case VENDOR_ELEM_P2P_INV_RESP:
6800 case VENDOR_ELEM_P2P_ASSOC_REQ:
6801 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006802 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006803#endif /* CONFIG_P2P */
6804 default:
6805 return wpa_s;
6806 }
6807}
6808
6809
6810void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6811{
6812 unsigned int i;
6813 char buf[30];
6814
6815 wpa_printf(MSG_DEBUG, "Update vendor elements");
6816
6817 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6818 if (wpa_s->vendor_elem[i]) {
6819 int res;
6820
6821 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6822 if (!os_snprintf_error(sizeof(buf), res)) {
6823 wpa_hexdump_buf(MSG_DEBUG, buf,
6824 wpa_s->vendor_elem[i]);
6825 }
6826 }
6827 }
6828
6829#ifdef CONFIG_P2P
6830 if (wpa_s->parent == wpa_s &&
6831 wpa_s->global->p2p &&
6832 !wpa_s->global->p2p_disabled)
6833 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6834#endif /* CONFIG_P2P */
6835}
6836
6837
6838int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6839 const u8 *elem, size_t len)
6840{
6841 u8 *ie, *end;
6842
6843 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6844 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6845
6846 for (; ie + 1 < end; ie += 2 + ie[1]) {
6847 if (ie + len > end)
6848 break;
6849 if (os_memcmp(ie, elem, len) != 0)
6850 continue;
6851
6852 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6853 wpabuf_free(wpa_s->vendor_elem[frame]);
6854 wpa_s->vendor_elem[frame] = NULL;
6855 } else {
6856 os_memmove(ie, ie + len, end - (ie + len));
6857 wpa_s->vendor_elem[frame]->used -= len;
6858 }
6859 wpas_vendor_elem_update(wpa_s);
6860 return 0;
6861 }
6862
6863 return -1;
6864}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006865
6866
6867struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6868 u16 num_modes, enum hostapd_hw_mode mode)
6869{
6870 u16 i;
6871
6872 for (i = 0; i < num_modes; i++) {
6873 if (modes[i].mode == mode)
6874 return &modes[i];
6875 }
6876
6877 return NULL;
6878}
6879
6880
6881static struct
6882wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6883 const u8 *bssid)
6884{
6885 struct wpa_bss_tmp_disallowed *bss;
6886
6887 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6888 struct wpa_bss_tmp_disallowed, list) {
6889 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6890 return bss;
6891 }
6892
6893 return NULL;
6894}
6895
6896
6897void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6898 unsigned int sec)
6899{
6900 struct wpa_bss_tmp_disallowed *bss;
6901 struct os_reltime until;
6902
6903 os_get_reltime(&until);
6904 until.sec += sec;
6905
6906 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6907 if (bss) {
6908 bss->disallowed_until = until;
6909 return;
6910 }
6911
6912 bss = os_malloc(sizeof(*bss));
6913 if (!bss) {
6914 wpa_printf(MSG_DEBUG,
6915 "Failed to allocate memory for temp disallow BSS");
6916 return;
6917 }
6918
6919 bss->disallowed_until = until;
6920 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6921 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
6922}
6923
6924
6925int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6926{
6927 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
6928 struct os_reltime now, age;
6929
6930 os_get_reltime(&now);
6931
6932 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6933 struct wpa_bss_tmp_disallowed, list) {
6934 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
6935 /* This BSS is not disallowed anymore */
6936 dl_list_del(&tmp->list);
6937 os_free(tmp);
6938 continue;
6939 }
6940 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6941 bss = tmp;
6942 break;
6943 }
6944 }
6945 if (!bss)
6946 return 0;
6947
6948 os_reltime_sub(&bss->disallowed_until, &now, &age);
6949 wpa_printf(MSG_DEBUG,
6950 "BSS " MACSTR " disabled for %ld.%0ld seconds",
6951 MAC2STR(bss->bssid), age.sec, age.usec);
6952 return 1;
6953}