blob: 8cfb48887c04431be036155a1859940250143e6d [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
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005228 /* Notify the control interfaces about new iface */
5229 if (wpas_notify_iface_added(wpa_s)) {
5230 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5231 return NULL;
5232 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005233
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005234 /* Notify the control interfaces about new networks for non p2p mgmt
5235 * ifaces. */
5236 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005237 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5238 wpas_notify_network_added(wpa_s, ssid);
5239 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005240
5241 wpa_s->next = global->ifaces;
5242 global->ifaces = wpa_s;
5243
5244 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005245 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005246
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005247#ifdef CONFIG_P2P
5248 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005249 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005250 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005251 wpas_p2p_add_p2pdev_interface(
5252 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005253 wpa_printf(MSG_INFO,
5254 "P2P: Failed to enable P2P Device interface");
5255 /* Try to continue without. P2P will be disabled. */
5256 }
5257#endif /* CONFIG_P2P */
5258
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005259 return wpa_s;
5260}
5261
5262
5263/**
5264 * wpa_supplicant_remove_iface - Remove a network interface
5265 * @global: Pointer to global data from wpa_supplicant_init()
5266 * @wpa_s: Pointer to the network interface to be removed
5267 * Returns: 0 if interface was removed, -1 if interface was not found
5268 *
5269 * This function can be used to dynamically remove network interfaces from
5270 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5271 * addition, this function is used to remove all remaining interfaces when
5272 * %wpa_supplicant is terminated.
5273 */
5274int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005275 struct wpa_supplicant *wpa_s,
5276 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005277{
5278 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005279#ifdef CONFIG_MESH
5280 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5281 char *ifname = NULL;
5282#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005283
5284 /* Remove interface from the global list of interfaces */
5285 prev = global->ifaces;
5286 if (prev == wpa_s) {
5287 global->ifaces = wpa_s->next;
5288 } else {
5289 while (prev && prev->next != wpa_s)
5290 prev = prev->next;
5291 if (prev == NULL)
5292 return -1;
5293 prev->next = wpa_s->next;
5294 }
5295
5296 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5297
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005298#ifdef CONFIG_MESH
5299 if (mesh_if_created) {
5300 ifname = os_strdup(wpa_s->ifname);
5301 if (ifname == NULL) {
5302 wpa_dbg(wpa_s, MSG_ERROR,
5303 "mesh: Failed to malloc ifname");
5304 return -1;
5305 }
5306 }
5307#endif /* CONFIG_MESH */
5308
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005309 if (global->p2p_group_formation == wpa_s)
5310 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005311 if (global->p2p_invite_group == wpa_s)
5312 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005313 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005314
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005315#ifdef CONFIG_MESH
5316 if (mesh_if_created) {
5317 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
5318 os_free(ifname);
5319 }
5320#endif /* CONFIG_MESH */
5321
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005322 return 0;
5323}
5324
5325
5326/**
5327 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5328 * @wpa_s: Pointer to the network interface
5329 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5330 */
5331const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5332{
5333 const char *eapol_method;
5334
5335 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5336 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5337 return "NO-EAP";
5338 }
5339
5340 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5341 if (eapol_method == NULL)
5342 return "UNKNOWN-EAP";
5343
5344 return eapol_method;
5345}
5346
5347
5348/**
5349 * wpa_supplicant_get_iface - Get a new network interface
5350 * @global: Pointer to global data from wpa_supplicant_init()
5351 * @ifname: Interface name
5352 * Returns: Pointer to the interface or %NULL if not found
5353 */
5354struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5355 const char *ifname)
5356{
5357 struct wpa_supplicant *wpa_s;
5358
5359 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5360 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5361 return wpa_s;
5362 }
5363 return NULL;
5364}
5365
5366
5367#ifndef CONFIG_NO_WPA_MSG
5368static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5369{
5370 struct wpa_supplicant *wpa_s = ctx;
5371 if (wpa_s == NULL)
5372 return NULL;
5373 return wpa_s->ifname;
5374}
5375#endif /* CONFIG_NO_WPA_MSG */
5376
5377
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005378#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5379#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5380#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5381
5382/* Periodic cleanup tasks */
5383static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5384{
5385 struct wpa_global *global = eloop_ctx;
5386 struct wpa_supplicant *wpa_s;
5387
5388 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5389 wpas_periodic, global, NULL);
5390
5391#ifdef CONFIG_P2P
5392 if (global->p2p)
5393 p2p_expire_peers(global->p2p);
5394#endif /* CONFIG_P2P */
5395
5396 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5397 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5398#ifdef CONFIG_AP
5399 ap_periodic(wpa_s);
5400#endif /* CONFIG_AP */
5401 }
5402}
5403
5404
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005405/**
5406 * wpa_supplicant_init - Initialize %wpa_supplicant
5407 * @params: Parameters for %wpa_supplicant
5408 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5409 *
5410 * This function is used to initialize %wpa_supplicant. After successful
5411 * initialization, the returned data pointer can be used to add and remove
5412 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5413 */
5414struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5415{
5416 struct wpa_global *global;
5417 int ret, i;
5418
5419 if (params == NULL)
5420 return NULL;
5421
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005422#ifdef CONFIG_DRIVER_NDIS
5423 {
5424 void driver_ndis_init_ops(void);
5425 driver_ndis_init_ops();
5426 }
5427#endif /* CONFIG_DRIVER_NDIS */
5428
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005429#ifndef CONFIG_NO_WPA_MSG
5430 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5431#endif /* CONFIG_NO_WPA_MSG */
5432
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005433 if (params->wpa_debug_file_path)
5434 wpa_debug_open_file(params->wpa_debug_file_path);
5435 else
5436 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005437 if (params->wpa_debug_syslog)
5438 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005439 if (params->wpa_debug_tracing) {
5440 ret = wpa_debug_open_linux_tracing();
5441 if (ret) {
5442 wpa_printf(MSG_ERROR,
5443 "Failed to enable trace logging");
5444 return NULL;
5445 }
5446 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005447
5448 ret = eap_register_methods();
5449 if (ret) {
5450 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5451 if (ret == -2)
5452 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5453 "the same EAP type.");
5454 return NULL;
5455 }
5456
5457 global = os_zalloc(sizeof(*global));
5458 if (global == NULL)
5459 return NULL;
5460 dl_list_init(&global->p2p_srv_bonjour);
5461 dl_list_init(&global->p2p_srv_upnp);
5462 global->params.daemonize = params->daemonize;
5463 global->params.wait_for_monitor = params->wait_for_monitor;
5464 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5465 if (params->pid_file)
5466 global->params.pid_file = os_strdup(params->pid_file);
5467 if (params->ctrl_interface)
5468 global->params.ctrl_interface =
5469 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005470 if (params->ctrl_interface_group)
5471 global->params.ctrl_interface_group =
5472 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005473 if (params->override_driver)
5474 global->params.override_driver =
5475 os_strdup(params->override_driver);
5476 if (params->override_ctrl_interface)
5477 global->params.override_ctrl_interface =
5478 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005479#ifdef CONFIG_MATCH_IFACE
5480 global->params.match_iface_count = params->match_iface_count;
5481 if (params->match_iface_count) {
5482 global->params.match_ifaces =
5483 os_calloc(params->match_iface_count,
5484 sizeof(struct wpa_interface));
5485 os_memcpy(global->params.match_ifaces,
5486 params->match_ifaces,
5487 params->match_iface_count *
5488 sizeof(struct wpa_interface));
5489 }
5490#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005491#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005492 if (params->conf_p2p_dev)
5493 global->params.conf_p2p_dev =
5494 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005495#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005496 wpa_debug_level = global->params.wpa_debug_level =
5497 params->wpa_debug_level;
5498 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5499 params->wpa_debug_show_keys;
5500 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5501 params->wpa_debug_timestamp;
5502
5503 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5504
5505 if (eloop_init()) {
5506 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5507 wpa_supplicant_deinit(global);
5508 return NULL;
5509 }
5510
Jouni Malinen75ecf522011-06-27 15:19:46 -07005511 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005512
5513 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5514 if (global->ctrl_iface == NULL) {
5515 wpa_supplicant_deinit(global);
5516 return NULL;
5517 }
5518
5519 if (wpas_notify_supplicant_initialized(global)) {
5520 wpa_supplicant_deinit(global);
5521 return NULL;
5522 }
5523
5524 for (i = 0; wpa_drivers[i]; i++)
5525 global->drv_count++;
5526 if (global->drv_count == 0) {
5527 wpa_printf(MSG_ERROR, "No drivers enabled");
5528 wpa_supplicant_deinit(global);
5529 return NULL;
5530 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005531 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005532 if (global->drv_priv == NULL) {
5533 wpa_supplicant_deinit(global);
5534 return NULL;
5535 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005536
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005537#ifdef CONFIG_WIFI_DISPLAY
5538 if (wifi_display_init(global) < 0) {
5539 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5540 wpa_supplicant_deinit(global);
5541 return NULL;
5542 }
5543#endif /* CONFIG_WIFI_DISPLAY */
5544
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005545 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5546 wpas_periodic, global, NULL);
5547
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005548 return global;
5549}
5550
5551
5552/**
5553 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5554 * @global: Pointer to global data from wpa_supplicant_init()
5555 * Returns: 0 after successful event loop run, -1 on failure
5556 *
5557 * This function starts the main event loop and continues running as long as
5558 * there are any remaining events. In most cases, this function is running as
5559 * long as the %wpa_supplicant process in still in use.
5560 */
5561int wpa_supplicant_run(struct wpa_global *global)
5562{
5563 struct wpa_supplicant *wpa_s;
5564
5565 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005566 (wpa_supplicant_daemon(global->params.pid_file) ||
5567 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005568 return -1;
5569
Dmitry Shmidte4663042016-04-04 10:07:49 -07005570#ifdef CONFIG_MATCH_IFACE
5571 if (wpa_supplicant_match_existing(global))
5572 return -1;
5573#endif
5574
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005575 if (global->params.wait_for_monitor) {
5576 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005577 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005578 wpa_supplicant_ctrl_iface_wait(
5579 wpa_s->ctrl_iface);
5580 }
5581
5582 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5583 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5584
5585 eloop_run();
5586
5587 return 0;
5588}
5589
5590
5591/**
5592 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5593 * @global: Pointer to global data from wpa_supplicant_init()
5594 *
5595 * This function is called to deinitialize %wpa_supplicant and to free all
5596 * allocated resources. Remaining network interfaces will also be removed.
5597 */
5598void wpa_supplicant_deinit(struct wpa_global *global)
5599{
5600 int i;
5601
5602 if (global == NULL)
5603 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005604
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005605 eloop_cancel_timeout(wpas_periodic, global, NULL);
5606
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005607#ifdef CONFIG_WIFI_DISPLAY
5608 wifi_display_deinit(global);
5609#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005610
5611 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005612 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005613
5614 if (global->ctrl_iface)
5615 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5616
5617 wpas_notify_supplicant_deinitialized(global);
5618
5619 eap_peer_unregister_methods();
5620#ifdef CONFIG_AP
5621 eap_server_unregister_methods();
5622#endif /* CONFIG_AP */
5623
5624 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5625 if (!global->drv_priv[i])
5626 continue;
5627 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5628 }
5629 os_free(global->drv_priv);
5630
5631 random_deinit();
5632
5633 eloop_destroy();
5634
5635 if (global->params.pid_file) {
5636 os_daemonize_terminate(global->params.pid_file);
5637 os_free(global->params.pid_file);
5638 }
5639 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005640 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005641 os_free(global->params.override_driver);
5642 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005643#ifdef CONFIG_MATCH_IFACE
5644 os_free(global->params.match_ifaces);
5645#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005646#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005647 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005648#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005649
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005650 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005651 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005652 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005653
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005654 os_free(global);
5655 wpa_debug_close_syslog();
5656 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005657 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005658}
5659
5660
5661void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5662{
5663 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5664 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5665 char country[3];
5666 country[0] = wpa_s->conf->country[0];
5667 country[1] = wpa_s->conf->country[1];
5668 country[2] = '\0';
5669 if (wpa_drv_set_country(wpa_s, country) < 0) {
5670 wpa_printf(MSG_ERROR, "Failed to set country code "
5671 "'%s'", country);
5672 }
5673 }
5674
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005675 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5676 wpas_init_ext_pw(wpa_s);
5677
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005678 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5679 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5680
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005681#ifdef CONFIG_WPS
5682 wpas_wps_update_config(wpa_s);
5683#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005684 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005685 wpa_s->conf->changed_parameters = 0;
5686}
5687
5688
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005689void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005690{
5691 int i;
5692
5693 for (i = 0; i < *num_freqs; i++) {
5694 if (freqs[i] == freq)
5695 return;
5696 }
5697
5698 freqs[*num_freqs] = freq;
5699 (*num_freqs)++;
5700}
5701
5702
5703static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5704{
5705 struct wpa_bss *bss, *cbss;
5706 const int max_freqs = 10;
5707 int *freqs;
5708 int num_freqs = 0;
5709
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005710 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005711 if (freqs == NULL)
5712 return NULL;
5713
5714 cbss = wpa_s->current_bss;
5715
5716 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5717 if (bss == cbss)
5718 continue;
5719 if (bss->ssid_len == cbss->ssid_len &&
5720 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5721 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5722 add_freq(freqs, &num_freqs, bss->freq);
5723 if (num_freqs == max_freqs)
5724 break;
5725 }
5726 }
5727
5728 if (num_freqs == 0) {
5729 os_free(freqs);
5730 freqs = NULL;
5731 }
5732
5733 return freqs;
5734}
5735
5736
5737void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5738{
5739 int timeout;
5740 int count;
5741 int *freqs = NULL;
5742
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005743 wpas_connect_work_done(wpa_s);
5744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005745 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005746 * Remove possible authentication timeout since the connection failed.
5747 */
5748 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5749
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005750 /*
5751 * There is no point in blacklisting the AP if this event is
5752 * generated based on local request to disconnect.
5753 */
5754 if (wpa_s->own_disconnect_req) {
5755 wpa_s->own_disconnect_req = 0;
5756 wpa_dbg(wpa_s, MSG_DEBUG,
5757 "Ignore connection failure due to local request to disconnect");
5758 return;
5759 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005760 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005761 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5762 "indication since interface has been put into "
5763 "disconnected state");
5764 return;
5765 }
5766
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005767 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005768 * Add the failed BSSID into the blacklist and speed up next scan
5769 * attempt if there could be other APs that could accept association.
5770 * The current blacklist count indicates how many times we have tried
5771 * connecting to this AP and multiple attempts mean that other APs are
5772 * either not available or has already been tried, so that we can start
5773 * increasing the delay here to avoid constant scanning.
5774 */
5775 count = wpa_blacklist_add(wpa_s, bssid);
5776 if (count == 1 && wpa_s->current_bss) {
5777 /*
5778 * This BSS was not in the blacklist before. If there is
5779 * another BSS available for the same ESS, we should try that
5780 * next. Otherwise, we may as well try this one once more
5781 * before allowing other, likely worse, ESSes to be considered.
5782 */
5783 freqs = get_bss_freqs_in_ess(wpa_s);
5784 if (freqs) {
5785 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5786 "has been seen; try it next");
5787 wpa_blacklist_add(wpa_s, bssid);
5788 /*
5789 * On the next scan, go through only the known channels
5790 * used in this ESS based on previous scans to speed up
5791 * common load balancing use case.
5792 */
5793 os_free(wpa_s->next_scan_freqs);
5794 wpa_s->next_scan_freqs = freqs;
5795 }
5796 }
5797
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005798 /*
5799 * Add previous failure count in case the temporary blacklist was
5800 * cleared due to no other BSSes being available.
5801 */
5802 count += wpa_s->extra_blacklist_count;
5803
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005804 if (count > 3 && wpa_s->current_ssid) {
5805 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5806 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005807 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005808 }
5809
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005810 switch (count) {
5811 case 1:
5812 timeout = 100;
5813 break;
5814 case 2:
5815 timeout = 500;
5816 break;
5817 case 3:
5818 timeout = 1000;
5819 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005820 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005821 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005822 break;
5823 default:
5824 timeout = 10000;
5825 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005826 }
5827
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005828 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5829 "ms", count, timeout);
5830
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005831 /*
5832 * TODO: if more than one possible AP is available in scan results,
5833 * could try the other ones before requesting a new scan.
5834 */
5835 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5836 1000 * (timeout % 1000));
5837}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005838
5839
5840int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5841{
5842 return wpa_s->conf->ap_scan == 2 ||
5843 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5844}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005845
Dmitry Shmidt04949592012-07-19 12:16:46 -07005846
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005847#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005848int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5849 struct wpa_ssid *ssid,
5850 const char *field,
5851 const char *value)
5852{
5853#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005854 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005855
5856 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5857 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5858 (const u8 *) value, os_strlen(value));
5859
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005860 rtype = wpa_supplicant_ctrl_req_from_string(field);
5861 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
5862#else /* IEEE8021X_EAPOL */
5863 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5864 return -1;
5865#endif /* IEEE8021X_EAPOL */
5866}
5867
5868int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5869 struct wpa_ssid *ssid,
5870 enum wpa_ctrl_req_type rtype,
5871 const char *value)
5872{
5873#ifdef IEEE8021X_EAPOL
5874 struct eap_peer_config *eap = &ssid->eap;
5875
5876 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005877 case WPA_CTRL_REQ_EAP_IDENTITY:
5878 os_free(eap->identity);
5879 eap->identity = (u8 *) os_strdup(value);
5880 eap->identity_len = os_strlen(value);
5881 eap->pending_req_identity = 0;
5882 if (ssid == wpa_s->current_ssid)
5883 wpa_s->reassociate = 1;
5884 break;
5885 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005886 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005887 eap->password = (u8 *) os_strdup(value);
5888 eap->password_len = os_strlen(value);
5889 eap->pending_req_password = 0;
5890 if (ssid == wpa_s->current_ssid)
5891 wpa_s->reassociate = 1;
5892 break;
5893 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005894 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005895 eap->new_password = (u8 *) os_strdup(value);
5896 eap->new_password_len = os_strlen(value);
5897 eap->pending_req_new_password = 0;
5898 if (ssid == wpa_s->current_ssid)
5899 wpa_s->reassociate = 1;
5900 break;
5901 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005902 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005903 eap->pin = os_strdup(value);
5904 eap->pending_req_pin = 0;
5905 if (ssid == wpa_s->current_ssid)
5906 wpa_s->reassociate = 1;
5907 break;
5908 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005909 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005910 eap->otp = (u8 *) os_strdup(value);
5911 eap->otp_len = os_strlen(value);
5912 os_free(eap->pending_req_otp);
5913 eap->pending_req_otp = NULL;
5914 eap->pending_req_otp_len = 0;
5915 break;
5916 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005917 str_clear_free(eap->private_key_passwd);
5918 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005919 eap->pending_req_passphrase = 0;
5920 if (ssid == wpa_s->current_ssid)
5921 wpa_s->reassociate = 1;
5922 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005923 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005924 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005925 eap->external_sim_resp = os_strdup(value);
5926 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005927 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5928 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5929 return -1;
5930 ssid->mem_only_psk = 1;
5931 if (ssid->passphrase)
5932 wpa_config_update_psk(ssid);
5933 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5934 wpa_supplicant_req_scan(wpa_s, 0, 0);
5935 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005936 case WPA_CTRL_REQ_EXT_CERT_CHECK:
5937 if (eap->pending_ext_cert_check != PENDING_CHECK)
5938 return -1;
5939 if (os_strcmp(value, "good") == 0)
5940 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
5941 else if (os_strcmp(value, "bad") == 0)
5942 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
5943 else
5944 return -1;
5945 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005946 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005947 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005948 return -1;
5949 }
5950
5951 return 0;
5952#else /* IEEE8021X_EAPOL */
5953 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5954 return -1;
5955#endif /* IEEE8021X_EAPOL */
5956}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005957#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005958
5959
5960int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5961{
5962 int i;
5963 unsigned int drv_enc;
5964
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005965 if (wpa_s->p2p_mgmt)
5966 return 1; /* no normal network profiles on p2p_mgmt interface */
5967
Dmitry Shmidt04949592012-07-19 12:16:46 -07005968 if (ssid == NULL)
5969 return 1;
5970
5971 if (ssid->disabled)
5972 return 1;
5973
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005974 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005975 drv_enc = wpa_s->drv_enc;
5976 else
5977 drv_enc = (unsigned int) -1;
5978
5979 for (i = 0; i < NUM_WEP_KEYS; i++) {
5980 size_t len = ssid->wep_key_len[i];
5981 if (len == 0)
5982 continue;
5983 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5984 continue;
5985 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5986 continue;
5987 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5988 continue;
5989 return 1; /* invalid WEP key */
5990 }
5991
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005992 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005993 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5994 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005995 return 1;
5996
Dmitry Shmidt04949592012-07-19 12:16:46 -07005997 return 0;
5998}
5999
6000
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006001int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6002{
6003#ifdef CONFIG_IEEE80211W
6004 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6005 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6006 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6007 /*
6008 * Driver does not support BIP -- ignore pmf=1 default
6009 * since the connection with PMF would fail and the
6010 * configuration does not require PMF to be enabled.
6011 */
6012 return NO_MGMT_FRAME_PROTECTION;
6013 }
6014
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006015 if (ssid &&
6016 (ssid->key_mgmt &
6017 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6018 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6019 /*
6020 * Do not use the default PMF value for non-RSN networks
6021 * since PMF is available only with RSN and pmf=2
6022 * configuration would otherwise prevent connections to
6023 * all open networks.
6024 */
6025 return NO_MGMT_FRAME_PROTECTION;
6026 }
6027
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006028 return wpa_s->conf->pmf;
6029 }
6030
6031 return ssid->ieee80211w;
6032#else /* CONFIG_IEEE80211W */
6033 return NO_MGMT_FRAME_PROTECTION;
6034#endif /* CONFIG_IEEE80211W */
6035}
6036
6037
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006038int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006039{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006040 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006041 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006042 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006043 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006044 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006045}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006046
6047
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006048void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006049{
6050 struct wpa_ssid *ssid = wpa_s->current_ssid;
6051 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006052 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006053
6054 if (ssid == NULL) {
6055 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6056 "SSID block");
6057 return;
6058 }
6059
6060 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6061 return;
6062
6063 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006064
6065#ifdef CONFIG_P2P
6066 if (ssid->p2p_group &&
6067 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6068 /*
6069 * Skip the wait time since there is a short timeout on the
6070 * connection to a P2P group.
6071 */
6072 return;
6073 }
6074#endif /* CONFIG_P2P */
6075
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006076 if (ssid->auth_failures > 50)
6077 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006078 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006079 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006080 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006081 dur = 90;
6082 else if (ssid->auth_failures > 3)
6083 dur = 60;
6084 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006085 dur = 30;
6086 else if (ssid->auth_failures > 1)
6087 dur = 20;
6088 else
6089 dur = 10;
6090
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006091 if (ssid->auth_failures > 1 &&
6092 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6093 dur += os_random() % (ssid->auth_failures * 10);
6094
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006095 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006096 if (now.sec + dur <= ssid->disabled_until.sec)
6097 return;
6098
6099 ssid->disabled_until.sec = now.sec + dur;
6100
6101 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006102 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006103 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006104 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006105}
6106
6107
6108void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6109 struct wpa_ssid *ssid, int clear_failures)
6110{
6111 if (ssid == NULL)
6112 return;
6113
6114 if (ssid->disabled_until.sec) {
6115 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6116 "id=%d ssid=\"%s\"",
6117 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6118 }
6119 ssid->disabled_until.sec = 0;
6120 ssid->disabled_until.usec = 0;
6121 if (clear_failures)
6122 ssid->auth_failures = 0;
6123}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006124
6125
6126int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6127{
6128 size_t i;
6129
6130 if (wpa_s->disallow_aps_bssid == NULL)
6131 return 0;
6132
6133 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6134 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6135 bssid, ETH_ALEN) == 0)
6136 return 1;
6137 }
6138
6139 return 0;
6140}
6141
6142
6143int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6144 size_t ssid_len)
6145{
6146 size_t i;
6147
6148 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6149 return 0;
6150
6151 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6152 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6153 if (ssid_len == s->ssid_len &&
6154 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6155 return 1;
6156 }
6157
6158 return 0;
6159}
6160
6161
6162/**
6163 * wpas_request_connection - Request a new connection
6164 * @wpa_s: Pointer to the network interface
6165 *
6166 * This function is used to request a new connection to be found. It will mark
6167 * the interface to allow reassociation and request a new scan to find a
6168 * suitable network to connect to.
6169 */
6170void wpas_request_connection(struct wpa_supplicant *wpa_s)
6171{
6172 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006173 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006174 wpa_supplicant_reinit_autoscan(wpa_s);
6175 wpa_s->extra_blacklist_count = 0;
6176 wpa_s->disconnected = 0;
6177 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006178
6179 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6180 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006181 else
6182 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006183}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006184
Roshan Pius02242d72016-08-09 15:31:48 -07006185/**
6186 * wpas_request_disconnection - Request disconnection
6187 * @wpa_s: Pointer to the network interface
6188 *
6189 * This function is used to request disconnection from the currently connected
6190 * network. This will stop any ongoing scans and initiate deauthentication.
6191 */
6192void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6193{
6194#ifdef CONFIG_SME
6195 wpa_s->sme.prev_bssid_set = 0;
6196#endif /* CONFIG_SME */
6197 wpa_s->reassociate = 0;
6198 wpa_s->disconnected = 1;
6199 wpa_supplicant_cancel_sched_scan(wpa_s);
6200 wpa_supplicant_cancel_scan(wpa_s);
6201 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6202 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6203}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006204
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006205
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006206void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6207 struct wpa_used_freq_data *freqs_data,
6208 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006209{
6210 unsigned int i;
6211
6212 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6213 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006214 for (i = 0; i < len; i++) {
6215 struct wpa_used_freq_data *cur = &freqs_data[i];
6216 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6217 i, cur->freq, cur->flags);
6218 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006219}
6220
6221
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006222/*
6223 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006224 * are using the same radio as the current interface, and in addition, get
6225 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006226 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006227int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6228 struct wpa_used_freq_data *freqs_data,
6229 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006230{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006231 struct wpa_supplicant *ifs;
6232 u8 bssid[ETH_ALEN];
6233 int freq;
6234 unsigned int idx = 0, i;
6235
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006236 wpa_dbg(wpa_s, MSG_DEBUG,
6237 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006238 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006239
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006240 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6241 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006242 if (idx == len)
6243 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006244
6245 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6246 continue;
6247
6248 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006249 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6250 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006251 freq = ifs->current_ssid->frequency;
6252 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6253 freq = ifs->assoc_freq;
6254 else
6255 continue;
6256
6257 /* Hold only distinct freqs */
6258 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006259 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006260 break;
6261
6262 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006263 freqs_data[idx++].freq = freq;
6264
6265 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006266 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006267 WPA_FREQ_USED_BY_P2P_CLIENT :
6268 WPA_FREQ_USED_BY_INFRA_STATION;
6269 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006270 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006271
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006272 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006273 return idx;
6274}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006275
6276
6277/*
6278 * Find the operating frequencies of any of the virtual interfaces that
6279 * are using the same radio as the current interface.
6280 */
6281int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6282 int *freq_array, unsigned int len)
6283{
6284 struct wpa_used_freq_data *freqs_data;
6285 int num, i;
6286
6287 os_memset(freq_array, 0, sizeof(int) * len);
6288
6289 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6290 if (!freqs_data)
6291 return -1;
6292
6293 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6294 for (i = 0; i < num; i++)
6295 freq_array[i] = freqs_data[i].freq;
6296
6297 os_free(freqs_data);
6298
6299 return num;
6300}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006301
6302
6303static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
6304{
6305 struct rrm_data *rrm = data;
6306
6307 if (!rrm->notify_neighbor_rep) {
6308 wpa_printf(MSG_ERROR,
6309 "RRM: Unexpected neighbor report timeout");
6310 return;
6311 }
6312
6313 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
6314 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
6315
6316 rrm->notify_neighbor_rep = NULL;
6317 rrm->neighbor_rep_cb_ctx = NULL;
6318}
6319
6320
6321/*
6322 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
6323 * @wpa_s: Pointer to wpa_supplicant
6324 */
6325void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
6326{
6327 wpa_s->rrm.rrm_used = 0;
6328
6329 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6330 NULL);
6331 if (wpa_s->rrm.notify_neighbor_rep)
6332 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
6333 wpa_s->rrm.next_neighbor_rep_token = 1;
6334}
6335
6336
6337/*
6338 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
6339 * @wpa_s: Pointer to wpa_supplicant
6340 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
6341 * @report_len: Length of neighbor report buffer
6342 */
6343void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
6344 const u8 *report, size_t report_len)
6345{
6346 struct wpabuf *neighbor_rep;
6347
6348 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
6349 if (report_len < 1)
6350 return;
6351
6352 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
6353 wpa_printf(MSG_DEBUG,
6354 "RRM: Discarding neighbor report with token %d (expected %d)",
6355 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
6356 return;
6357 }
6358
6359 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6360 NULL);
6361
6362 if (!wpa_s->rrm.notify_neighbor_rep) {
6363 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
6364 return;
6365 }
6366
6367 /* skipping the first byte, which is only an id (dialog token) */
6368 neighbor_rep = wpabuf_alloc(report_len - 1);
6369 if (neighbor_rep == NULL)
6370 return;
6371 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
6372 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
6373 report[0]);
6374 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
6375 neighbor_rep);
6376 wpa_s->rrm.notify_neighbor_rep = NULL;
6377 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
6378}
6379
6380
Dmitry Shmidtff787d52015-01-12 13:01:47 -08006381#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
6382/* Workaround different, undefined for Windows, error codes used here */
6383#define ENOTCONN -1
6384#define EOPNOTSUPP -1
6385#define ECANCELED -1
6386#endif
6387
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006388/* Measurement Request element + Location Subject + Maximum Age subelement */
6389#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
6390/* Measurement Request element + Location Civic Request */
6391#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
6392
6393
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006394/**
6395 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
6396 * @wpa_s: Pointer to wpa_supplicant
6397 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
6398 * is sent in the request.
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006399 * @lci: if set, neighbor request will include LCI request
6400 * @civic: if set, neighbor request will include civic location request
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006401 * @cb: Callback function to be called once the requested report arrives, or
6402 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
6403 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
6404 * the requester's responsibility to free it.
6405 * In the latter case NULL will be sent in 'neighbor_rep'.
6406 * @cb_ctx: Context value to send the callback function
6407 * Returns: 0 in case of success, negative error code otherwise
6408 *
6409 * In case there is a previous request which has not been answered yet, the
6410 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
6411 * Request must contain a callback function.
6412 */
6413int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006414 const struct wpa_ssid_value *ssid,
6415 int lci, int civic,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006416 void (*cb)(void *ctx,
6417 struct wpabuf *neighbor_rep),
6418 void *cb_ctx)
6419{
6420 struct wpabuf *buf;
6421 const u8 *rrm_ie;
6422
6423 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
6424 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
6425 return -ENOTCONN;
6426 }
6427
6428 if (!wpa_s->rrm.rrm_used) {
6429 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
6430 return -EOPNOTSUPP;
6431 }
6432
6433 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
6434 WLAN_EID_RRM_ENABLED_CAPABILITIES);
6435 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
6436 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
6437 wpa_printf(MSG_DEBUG,
6438 "RRM: No network support for Neighbor Report.");
6439 return -EOPNOTSUPP;
6440 }
6441
6442 if (!cb) {
6443 wpa_printf(MSG_DEBUG,
6444 "RRM: Neighbor Report request must provide a callback.");
6445 return -EINVAL;
6446 }
6447
6448 /* Refuse if there's a live request */
6449 if (wpa_s->rrm.notify_neighbor_rep) {
6450 wpa_printf(MSG_DEBUG,
6451 "RRM: Currently handling previous Neighbor Report.");
6452 return -EBUSY;
6453 }
6454
6455 /* 3 = action category + action code + dialog token */
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006456 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
6457 (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
6458 (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006459 if (buf == NULL) {
6460 wpa_printf(MSG_DEBUG,
6461 "RRM: Failed to allocate Neighbor Report Request");
6462 return -ENOMEM;
6463 }
6464
6465 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
6466 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
6467 wpa_s->rrm.next_neighbor_rep_token);
6468
6469 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6470 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
6471 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
6472 if (ssid) {
6473 wpabuf_put_u8(buf, WLAN_EID_SSID);
6474 wpabuf_put_u8(buf, ssid->ssid_len);
6475 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
6476 }
6477
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006478 if (lci) {
6479 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6480 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6481 wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
6482
6483 /*
6484 * Measurement token; nonzero number that is unique among the
6485 * Measurement Request elements in a particular frame.
6486 */
6487 wpabuf_put_u8(buf, 1); /* Measurement Token */
6488
6489 /*
6490 * Parallel, Enable, Request, and Report bits are 0, Duration is
6491 * reserved.
6492 */
6493 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6494 wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
6495
6496 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
6497 /* Location Subject */
6498 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6499
6500 /* Optional Subelements */
6501 /*
6502 * IEEE P802.11-REVmc/D5.0 Figure 9-170
6503 * The Maximum Age subelement is required, otherwise the AP can
6504 * send only data that was determined after receiving the
6505 * request. Setting it here to unlimited age.
6506 */
6507 wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
6508 wpabuf_put_u8(buf, 2);
6509 wpabuf_put_le16(buf, 0xffff);
6510 }
6511
6512 if (civic) {
6513 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6514 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6515 wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
6516
6517 /*
6518 * Measurement token; nonzero number that is unique among the
6519 * Measurement Request elements in a particular frame.
6520 */
6521 wpabuf_put_u8(buf, 2); /* Measurement Token */
6522
6523 /*
6524 * Parallel, Enable, Request, and Report bits are 0, Duration is
6525 * reserved.
6526 */
6527 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6528 /* Measurement Type */
6529 wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
6530
6531 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
6532 * Location Civic request */
6533 /* Location Subject */
6534 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6535 wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
6536 /* Location Service Interval Units: Seconds */
6537 wpabuf_put_u8(buf, 0);
6538 /* Location Service Interval: 0 - Only one report is requested
6539 */
6540 wpabuf_put_le16(buf, 0);
6541 /* No optional subelements */
6542 }
6543
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006544 wpa_s->rrm.next_neighbor_rep_token++;
6545
6546 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
6547 wpa_s->own_addr, wpa_s->bssid,
6548 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
6549 wpa_printf(MSG_DEBUG,
6550 "RRM: Failed to send Neighbor Report Request");
6551 wpabuf_free(buf);
6552 return -ECANCELED;
6553 }
6554
6555 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
6556 wpa_s->rrm.notify_neighbor_rep = cb;
6557 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
6558 wpas_rrm_neighbor_rep_timeout_handler,
6559 &wpa_s->rrm, NULL);
6560
6561 wpabuf_free(buf);
6562 return 0;
6563}
6564
6565
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006566static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
6567 const u8 *request, size_t len,
6568 struct wpabuf *report)
6569{
6570 u8 token, type, subject;
6571 u16 max_age = 0;
6572 struct os_reltime t, diff;
6573 unsigned long diff_l;
6574 u8 *ptoken;
6575 const u8 *subelem;
6576
6577 if (!wpa_s->lci || len < 3 + 4)
6578 return report;
6579
6580 token = *request++;
6581 /* Measurement request mode isn't used */
6582 request++;
6583 type = *request++;
6584 subject = *request++;
6585
6586 wpa_printf(MSG_DEBUG,
6587 "Measurement request token %u type %u location subject %u",
6588 token, type, subject);
6589
6590 if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
6591 wpa_printf(MSG_INFO,
6592 "Not building LCI report - bad type or location subject");
6593 return report;
6594 }
6595
6596 /* Subelements are formatted exactly like elements */
6597 subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
6598 if (subelem && subelem[1] == 2)
6599 max_age = WPA_GET_LE16(subelem + 2);
6600
6601 if (os_get_reltime(&t))
6602 return report;
6603
6604 os_reltime_sub(&t, &wpa_s->lci_time, &diff);
6605 /* LCI age is calculated in 10th of a second units. */
6606 diff_l = diff.sec * 10 + diff.usec / 100000;
6607
6608 if (max_age != 0xffff && max_age < diff_l)
6609 return report;
6610
6611 if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
6612 return report;
6613
6614 wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
6615 wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
6616 /* We'll override user's measurement token */
6617 ptoken = wpabuf_put(report, 0);
6618 wpabuf_put_buf(report, wpa_s->lci);
6619 *ptoken = token;
6620
6621 return report;
6622}
6623
6624
6625void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
6626 const u8 *src,
6627 const u8 *frame, size_t len)
6628{
6629 struct wpabuf *buf, *report;
6630 u8 token;
6631 const u8 *ie, *end;
6632
6633 if (wpa_s->wpa_state != WPA_COMPLETED) {
6634 wpa_printf(MSG_INFO,
6635 "RRM: Ignoring radio measurement request: Not associated");
6636 return;
6637 }
6638
6639 if (!wpa_s->rrm.rrm_used) {
6640 wpa_printf(MSG_INFO,
6641 "RRM: Ignoring radio measurement request: Not RRM network");
6642 return;
6643 }
6644
6645 if (len < 3) {
6646 wpa_printf(MSG_INFO,
6647 "RRM: Ignoring too short radio measurement request");
6648 return;
6649 }
6650
6651 end = frame + len;
6652
6653 token = *frame++;
6654
6655 /* Ignore number of repetitions because it's not used in LCI request */
6656 frame += 2;
6657
6658 report = NULL;
6659 while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
6660 ie[1] >= 3) {
6661 u8 msmt_type;
6662
6663 msmt_type = ie[4];
6664 wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
6665
6666 switch (msmt_type) {
6667 case MEASURE_TYPE_LCI:
6668 report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
6669 report);
6670 break;
6671 default:
6672 wpa_printf(MSG_INFO,
6673 "RRM: Unsupported radio measurement request %d",
6674 msmt_type);
6675 break;
6676 }
6677
6678 frame = ie + ie[1] + 2;
6679 }
6680
6681 if (!report)
6682 return;
6683
6684 buf = wpabuf_alloc(3 + wpabuf_len(report));
6685 if (!buf) {
6686 wpabuf_free(report);
6687 return;
6688 }
6689
6690 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6691 wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
6692 wpabuf_put_u8(buf, token);
6693
6694 wpabuf_put_buf(buf, report);
6695 wpabuf_free(report);
6696
6697 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6698 wpa_s->own_addr, wpa_s->bssid,
6699 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6700 wpa_printf(MSG_ERROR,
6701 "RRM: Radio measurement report failed: Sending Action frame failed");
6702 }
6703 wpabuf_free(buf);
6704}
6705
6706
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006707void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
6708 const u8 *src,
6709 const u8 *frame, size_t len,
6710 int rssi)
6711{
6712 struct wpabuf *buf;
6713 const struct rrm_link_measurement_request *req;
6714 struct rrm_link_measurement_report report;
6715
6716 if (wpa_s->wpa_state != WPA_COMPLETED) {
6717 wpa_printf(MSG_INFO,
6718 "RRM: Ignoring link measurement request. Not associated");
6719 return;
6720 }
6721
6722 if (!wpa_s->rrm.rrm_used) {
6723 wpa_printf(MSG_INFO,
6724 "RRM: Ignoring link measurement request. Not RRM network");
6725 return;
6726 }
6727
6728 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
6729 wpa_printf(MSG_INFO,
6730 "RRM: Measurement report failed. TX power insertion not supported");
6731 return;
6732 }
6733
6734 req = (const struct rrm_link_measurement_request *) frame;
6735 if (len < sizeof(*req)) {
6736 wpa_printf(MSG_INFO,
6737 "RRM: Link measurement report failed. Request too short");
6738 return;
6739 }
6740
6741 os_memset(&report, 0, sizeof(report));
6742 report.tpc.eid = WLAN_EID_TPC_REPORT;
6743 report.tpc.len = 2;
6744 report.rsni = 255; /* 255 indicates that RSNI is not available */
6745 report.dialog_token = req->dialog_token;
6746
6747 /*
6748 * It's possible to estimate RCPI based on RSSI in dBm. This
6749 * calculation will not reflect the correct value for high rates,
6750 * but it's good enough for Action frames which are transmitted
6751 * with up to 24 Mbps rates.
6752 */
6753 if (!rssi)
6754 report.rcpi = 255; /* not available */
6755 else if (rssi < -110)
6756 report.rcpi = 0;
6757 else if (rssi > 0)
6758 report.rcpi = 220;
6759 else
6760 report.rcpi = (rssi + 110) * 2;
6761
6762 /* action_category + action_code */
6763 buf = wpabuf_alloc(2 + sizeof(report));
6764 if (buf == NULL) {
6765 wpa_printf(MSG_ERROR,
6766 "RRM: Link measurement report failed. Buffer allocation failed");
6767 return;
6768 }
6769
6770 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6771 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
6772 wpabuf_put_data(buf, &report, sizeof(report));
6773 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
6774 wpabuf_head(buf), wpabuf_len(buf));
6775
6776 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6777 wpa_s->own_addr, wpa_s->bssid,
6778 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6779 wpa_printf(MSG_ERROR,
6780 "RRM: Link measurement report failed. Send action failed");
6781 }
6782 wpabuf_free(buf);
6783}
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006784
6785
6786struct wpa_supplicant *
6787wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6788{
6789 switch (frame) {
6790#ifdef CONFIG_P2P
6791 case VENDOR_ELEM_PROBE_REQ_P2P:
6792 case VENDOR_ELEM_PROBE_RESP_P2P:
6793 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6794 case VENDOR_ELEM_BEACON_P2P_GO:
6795 case VENDOR_ELEM_P2P_PD_REQ:
6796 case VENDOR_ELEM_P2P_PD_RESP:
6797 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6798 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6799 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6800 case VENDOR_ELEM_P2P_INV_REQ:
6801 case VENDOR_ELEM_P2P_INV_RESP:
6802 case VENDOR_ELEM_P2P_ASSOC_REQ:
6803 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006804 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006805#endif /* CONFIG_P2P */
6806 default:
6807 return wpa_s;
6808 }
6809}
6810
6811
6812void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6813{
6814 unsigned int i;
6815 char buf[30];
6816
6817 wpa_printf(MSG_DEBUG, "Update vendor elements");
6818
6819 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6820 if (wpa_s->vendor_elem[i]) {
6821 int res;
6822
6823 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6824 if (!os_snprintf_error(sizeof(buf), res)) {
6825 wpa_hexdump_buf(MSG_DEBUG, buf,
6826 wpa_s->vendor_elem[i]);
6827 }
6828 }
6829 }
6830
6831#ifdef CONFIG_P2P
6832 if (wpa_s->parent == wpa_s &&
6833 wpa_s->global->p2p &&
6834 !wpa_s->global->p2p_disabled)
6835 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6836#endif /* CONFIG_P2P */
6837}
6838
6839
6840int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6841 const u8 *elem, size_t len)
6842{
6843 u8 *ie, *end;
6844
6845 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6846 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6847
6848 for (; ie + 1 < end; ie += 2 + ie[1]) {
6849 if (ie + len > end)
6850 break;
6851 if (os_memcmp(ie, elem, len) != 0)
6852 continue;
6853
6854 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6855 wpabuf_free(wpa_s->vendor_elem[frame]);
6856 wpa_s->vendor_elem[frame] = NULL;
6857 } else {
6858 os_memmove(ie, ie + len, end - (ie + len));
6859 wpa_s->vendor_elem[frame]->used -= len;
6860 }
6861 wpas_vendor_elem_update(wpa_s);
6862 return 0;
6863 }
6864
6865 return -1;
6866}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006867
6868
6869struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6870 u16 num_modes, enum hostapd_hw_mode mode)
6871{
6872 u16 i;
6873
6874 for (i = 0; i < num_modes; i++) {
6875 if (modes[i].mode == mode)
6876 return &modes[i];
6877 }
6878
6879 return NULL;
6880}
6881
6882
6883static struct
6884wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6885 const u8 *bssid)
6886{
6887 struct wpa_bss_tmp_disallowed *bss;
6888
6889 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6890 struct wpa_bss_tmp_disallowed, list) {
6891 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6892 return bss;
6893 }
6894
6895 return NULL;
6896}
6897
6898
6899void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6900 unsigned int sec)
6901{
6902 struct wpa_bss_tmp_disallowed *bss;
6903 struct os_reltime until;
6904
6905 os_get_reltime(&until);
6906 until.sec += sec;
6907
6908 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6909 if (bss) {
6910 bss->disallowed_until = until;
6911 return;
6912 }
6913
6914 bss = os_malloc(sizeof(*bss));
6915 if (!bss) {
6916 wpa_printf(MSG_DEBUG,
6917 "Failed to allocate memory for temp disallow BSS");
6918 return;
6919 }
6920
6921 bss->disallowed_until = until;
6922 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6923 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
6924}
6925
6926
6927int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6928{
6929 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
6930 struct os_reltime now, age;
6931
6932 os_get_reltime(&now);
6933
6934 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6935 struct wpa_bss_tmp_disallowed, list) {
6936 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
6937 /* This BSS is not disallowed anymore */
6938 dl_list_del(&tmp->list);
6939 os_free(tmp);
6940 continue;
6941 }
6942 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6943 bss = tmp;
6944 break;
6945 }
6946 }
6947 if (!bss)
6948 return 0;
6949
6950 os_reltime_sub(&bss->disallowed_until, &now, &age);
6951 wpa_printf(MSG_DEBUG,
6952 "BSS " MACSTR " disabled for %ld.%0ld seconds",
6953 MAC2STR(bss->bssid), age.sec, age.usec);
6954 return 1;
6955}