blob: 31b2d81af32820c64a31458d67f5bd444cb864a1 [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;
Roshan Pius38e96762017-01-23 14:52:00 -0800205 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700206
207 /*
208 * If we timed out, the AP or the local radio may be busy.
209 * So, wait a second until scanning again.
210 */
211 wpa_supplicant_req_scan(wpa_s, 1, 0);
212}
213
214
215/**
216 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
217 * @wpa_s: Pointer to wpa_supplicant data
218 * @sec: Number of seconds after which to time out authentication
219 * @usec: Number of microseconds after which to time out authentication
220 *
221 * This function is used to schedule a timeout for the current authentication
222 * attempt.
223 */
224void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
225 int sec, int usec)
226{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700227 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
229 return;
230
231 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
232 "%d usec", sec, usec);
233 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
234 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
235}
236
237
238/**
239 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
240 * @wpa_s: Pointer to wpa_supplicant data
241 *
242 * This function is used to cancel authentication timeout scheduled with
243 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
244 * been completed.
245 */
246void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
247{
248 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
249 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
250 wpa_blacklist_del(wpa_s, wpa_s->bssid);
251}
252
253
254/**
255 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
256 * @wpa_s: Pointer to wpa_supplicant data
257 *
258 * This function is used to configure EAPOL state machine based on the selected
259 * authentication mode.
260 */
261void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
262{
263#ifdef IEEE8021X_EAPOL
264 struct eapol_config eapol_conf;
265 struct wpa_ssid *ssid = wpa_s->current_ssid;
266
267#ifdef CONFIG_IBSS_RSN
268 if (ssid->mode == WPAS_MODE_IBSS &&
269 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
270 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
271 /*
272 * RSN IBSS authentication is per-STA and we can disable the
273 * per-BSSID EAPOL authentication.
274 */
275 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
276 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
277 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
278 return;
279 }
280#endif /* CONFIG_IBSS_RSN */
281
282 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
283 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
284
285 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
286 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
287 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
288 else
289 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
290
291 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
292 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
293 eapol_conf.accept_802_1x_keys = 1;
294 eapol_conf.required_keys = 0;
295 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
296 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
297 }
298 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
299 eapol_conf.required_keys |=
300 EAPOL_REQUIRE_KEY_BROADCAST;
301 }
302
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700303 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700304 eapol_conf.required_keys = 0;
305 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700306 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700307 eapol_conf.workaround = ssid->eap_workaround;
308 eapol_conf.eap_disabled =
309 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
310 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
311 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700312 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800313
314#ifdef CONFIG_WPS
315 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
316 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
317 if (wpa_s->current_bss) {
318 struct wpabuf *ie;
319 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
320 WPS_IE_VENDOR_TYPE);
321 if (ie) {
322 if (wps_is_20(ie))
323 eapol_conf.wps |=
324 EAPOL_PEER_IS_WPS20_AP;
325 wpabuf_free(ie);
326 }
327 }
328 }
329#endif /* CONFIG_WPS */
330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700331 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700332
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800333#ifdef CONFIG_MACSEC
334 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
335 ieee802_1x_create_preshared_mka(wpa_s, ssid);
336 else
337 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
338#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800339#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700340}
341
342
343/**
344 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
345 * @wpa_s: Pointer to wpa_supplicant data
346 * @ssid: Configuration data for the network
347 *
348 * This function is used to configure WPA state machine and related parameters
349 * to a mode where WPA is not enabled. This is called as part of the
350 * authentication configuration when the selected network does not use WPA.
351 */
352void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
353 struct wpa_ssid *ssid)
354{
355 int i;
356
357 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
358 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
359 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
360 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
361 else
362 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
363 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
364 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
365 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
366 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
367 wpa_s->group_cipher = WPA_CIPHER_NONE;
368 wpa_s->mgmt_group_cipher = 0;
369
370 for (i = 0; i < NUM_WEP_KEYS; i++) {
371 if (ssid->wep_key_len[i] > 5) {
372 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
373 wpa_s->group_cipher = WPA_CIPHER_WEP104;
374 break;
375 } else if (ssid->wep_key_len[i] > 0) {
376 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
377 wpa_s->group_cipher = WPA_CIPHER_WEP40;
378 break;
379 }
380 }
381
382 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
383 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
384 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
385 wpa_s->pairwise_cipher);
386 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
387#ifdef CONFIG_IEEE80211W
388 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
389 wpa_s->mgmt_group_cipher);
390#endif /* CONFIG_IEEE80211W */
391
392 pmksa_cache_clear_current(wpa_s->wpa);
393}
394
395
Dmitry Shmidt04949592012-07-19 12:16:46 -0700396void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800397{
398 int i;
399 if (wpa_s->hw.modes == NULL)
400 return;
401
402 for (i = 0; i < wpa_s->hw.num_modes; i++) {
403 os_free(wpa_s->hw.modes[i].channels);
404 os_free(wpa_s->hw.modes[i].rates);
405 }
406
407 os_free(wpa_s->hw.modes);
408 wpa_s->hw.modes = NULL;
409}
410
411
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800412static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
413{
414 struct wpa_bss_tmp_disallowed *bss, *prev;
415
416 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
417 struct wpa_bss_tmp_disallowed, list) {
418 dl_list_del(&bss->list);
419 os_free(bss);
420 }
421}
422
423
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
425{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700426 int i;
427
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700428 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700429 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700430 scard_deinit(wpa_s->scard);
431 wpa_s->scard = NULL;
432 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
433 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
434 l2_packet_deinit(wpa_s->l2);
435 wpa_s->l2 = NULL;
436 if (wpa_s->l2_br) {
437 l2_packet_deinit(wpa_s->l2_br);
438 wpa_s->l2_br = NULL;
439 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800440#ifdef CONFIG_TESTING_OPTIONS
441 l2_packet_deinit(wpa_s->l2_test);
442 wpa_s->l2_test = NULL;
443#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700445 if (wpa_s->conf != NULL) {
446 struct wpa_ssid *ssid;
447 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
448 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700449 }
450
451 os_free(wpa_s->confname);
452 wpa_s->confname = NULL;
453
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700454 os_free(wpa_s->confanother);
455 wpa_s->confanother = NULL;
456
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457 wpa_sm_set_eapol(wpa_s->wpa, NULL);
458 eapol_sm_deinit(wpa_s->eapol);
459 wpa_s->eapol = NULL;
460
461 rsn_preauth_deinit(wpa_s->wpa);
462
463#ifdef CONFIG_TDLS
464 wpa_tdls_deinit(wpa_s->wpa);
465#endif /* CONFIG_TDLS */
466
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800467 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700468 pmksa_candidate_free(wpa_s->wpa);
469 wpa_sm_deinit(wpa_s->wpa);
470 wpa_s->wpa = NULL;
471 wpa_blacklist_clear(wpa_s);
472
473 wpa_bss_deinit(wpa_s);
474
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700475 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700476 wpa_supplicant_cancel_scan(wpa_s);
477 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800478 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
479#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
480 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
481 wpa_s, NULL);
482#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700483
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700484 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
485
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700486 wpas_wps_deinit(wpa_s);
487
488 wpabuf_free(wpa_s->pending_eapol_rx);
489 wpa_s->pending_eapol_rx = NULL;
490
491#ifdef CONFIG_IBSS_RSN
492 ibss_rsn_deinit(wpa_s->ibss_rsn);
493 wpa_s->ibss_rsn = NULL;
494#endif /* CONFIG_IBSS_RSN */
495
496 sme_deinit(wpa_s);
497
498#ifdef CONFIG_AP
499 wpa_supplicant_ap_deinit(wpa_s);
500#endif /* CONFIG_AP */
501
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700503
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800504#ifdef CONFIG_OFFCHANNEL
505 offchannel_deinit(wpa_s);
506#endif /* CONFIG_OFFCHANNEL */
507
508 wpa_supplicant_cancel_sched_scan(wpa_s);
509
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700510 os_free(wpa_s->next_scan_freqs);
511 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800512
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800513 os_free(wpa_s->manual_scan_freqs);
514 wpa_s->manual_scan_freqs = NULL;
515
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700516 os_free(wpa_s->manual_sched_scan_freqs);
517 wpa_s->manual_sched_scan_freqs = NULL;
518
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800519 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
520
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700521 /*
522 * Need to remove any pending gas-query radio work before the
523 * gas_query_deinit() call because gas_query::work has not yet been set
524 * for works that have not been started. gas_query_free() will be unable
525 * to cancel such pending radio works and once the pending gas-query
526 * radio work eventually gets removed, the deinit notification call to
527 * gas_query_start_cb() would result in dereferencing freed memory.
528 */
529 if (wpa_s->radio)
530 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800531 gas_query_deinit(wpa_s->gas);
532 wpa_s->gas = NULL;
533
534 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700535
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700536 ieee802_1x_dealloc_kay_sm(wpa_s);
537
Dmitry Shmidt04949592012-07-19 12:16:46 -0700538 os_free(wpa_s->bssid_filter);
539 wpa_s->bssid_filter = NULL;
540
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800541 os_free(wpa_s->disallow_aps_bssid);
542 wpa_s->disallow_aps_bssid = NULL;
543 os_free(wpa_s->disallow_aps_ssid);
544 wpa_s->disallow_aps_ssid = NULL;
545
Dmitry Shmidt04949592012-07-19 12:16:46 -0700546 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700547#ifdef CONFIG_WNM
548 wnm_deallocate_memory(wpa_s);
549#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700550
551 ext_password_deinit(wpa_s->ext_pw);
552 wpa_s->ext_pw = NULL;
553
554 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800555 wpa_s->last_gas_resp = NULL;
556 wpabuf_free(wpa_s->prev_gas_resp);
557 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700558
559 os_free(wpa_s->last_scan_res);
560 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800561
562#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700563 if (wpa_s->drv_priv)
564 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700565 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800566#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700567
568 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
569 wpabuf_free(wpa_s->vendor_elem[i]);
570 wpa_s->vendor_elem[i] = NULL;
571 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800572
573 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800574
575 wpa_s->sched_scan_plans_num = 0;
576 os_free(wpa_s->sched_scan_plans);
577 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800578
579#ifdef CONFIG_MBO
580 wpa_s->non_pref_chan_num = 0;
581 os_free(wpa_s->non_pref_chan);
582 wpa_s->non_pref_chan = NULL;
583#endif /* CONFIG_MBO */
584
585 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700586
587 wpabuf_free(wpa_s->lci);
588 wpa_s->lci = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700589}
590
591
592/**
593 * wpa_clear_keys - Clear keys configured for the driver
594 * @wpa_s: Pointer to wpa_supplicant data
595 * @addr: Previously used BSSID or %NULL if not available
596 *
597 * This function clears the encryption keys that has been previously configured
598 * for the driver.
599 */
600void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
601{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800602 int i, max;
603
604#ifdef CONFIG_IEEE80211W
605 max = 6;
606#else /* CONFIG_IEEE80211W */
607 max = 4;
608#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700609
610 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800611 for (i = 0; i < max; i++) {
612 if (wpa_s->keys_cleared & BIT(i))
613 continue;
614 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
615 NULL, 0);
616 }
617 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
618 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700619 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
620 0);
621 /* MLME-SETPROTECTION.request(None) */
622 wpa_drv_mlme_setprotection(
623 wpa_s, addr,
624 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
625 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
626 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800627 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700628}
629
630
631/**
632 * wpa_supplicant_state_txt - Get the connection state name as a text string
633 * @state: State (wpa_state; WPA_*)
634 * Returns: The state name as a printable text string
635 */
636const char * wpa_supplicant_state_txt(enum wpa_states state)
637{
638 switch (state) {
639 case WPA_DISCONNECTED:
640 return "DISCONNECTED";
641 case WPA_INACTIVE:
642 return "INACTIVE";
643 case WPA_INTERFACE_DISABLED:
644 return "INTERFACE_DISABLED";
645 case WPA_SCANNING:
646 return "SCANNING";
647 case WPA_AUTHENTICATING:
648 return "AUTHENTICATING";
649 case WPA_ASSOCIATING:
650 return "ASSOCIATING";
651 case WPA_ASSOCIATED:
652 return "ASSOCIATED";
653 case WPA_4WAY_HANDSHAKE:
654 return "4WAY_HANDSHAKE";
655 case WPA_GROUP_HANDSHAKE:
656 return "GROUP_HANDSHAKE";
657 case WPA_COMPLETED:
658 return "COMPLETED";
659 default:
660 return "UNKNOWN";
661 }
662}
663
664
665#ifdef CONFIG_BGSCAN
666
667static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
668{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800669 const char *name;
670
671 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
672 name = wpa_s->current_ssid->bgscan;
673 else
674 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800675 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800676 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800677 if (wpas_driver_bss_selection(wpa_s))
678 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700679 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
680 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800681#ifdef CONFIG_P2P
682 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
683 return;
684#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685
686 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800687 if (wpa_s->current_ssid) {
688 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
690 "bgscan");
691 /*
692 * Live without bgscan; it is only used as a roaming
693 * optimization, so the initial connection is not
694 * affected.
695 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700696 } else {
697 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700698 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700699 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
700 0);
701 if (scan_res) {
702 bgscan_notify_scan(wpa_s, scan_res);
703 wpa_scan_results_free(scan_res);
704 }
705 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700706 } else
707 wpa_s->bgscan_ssid = NULL;
708}
709
710
711static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
712{
713 if (wpa_s->bgscan_ssid != NULL) {
714 bgscan_deinit(wpa_s);
715 wpa_s->bgscan_ssid = NULL;
716 }
717}
718
719#endif /* CONFIG_BGSCAN */
720
721
Dmitry Shmidt04949592012-07-19 12:16:46 -0700722static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
723{
724 if (autoscan_init(wpa_s, 0))
725 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
726}
727
728
729static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
730{
731 autoscan_deinit(wpa_s);
732}
733
734
735void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
736{
737 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
738 wpa_s->wpa_state == WPA_SCANNING) {
739 autoscan_deinit(wpa_s);
740 wpa_supplicant_start_autoscan(wpa_s);
741 }
742}
743
744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700745/**
746 * wpa_supplicant_set_state - Set current connection state
747 * @wpa_s: Pointer to wpa_supplicant data
748 * @state: The new connection state
749 *
750 * This function is called whenever the connection state changes, e.g.,
751 * association is completed for WPA/WPA2 4-Way Handshake is started.
752 */
753void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
754 enum wpa_states state)
755{
756 enum wpa_states old_state = wpa_s->wpa_state;
757
758 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
759 wpa_supplicant_state_txt(wpa_s->wpa_state),
760 wpa_supplicant_state_txt(state));
761
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800762 if (state == WPA_INTERFACE_DISABLED) {
763 /* Assure normal scan when interface is restored */
764 wpa_s->normal_scans = 0;
765 }
766
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700767 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800768 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700769 /* Reinitialize normal_scan counter */
770 wpa_s->normal_scans = 0;
771 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800772
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700773#ifdef CONFIG_P2P
774 /*
775 * P2PS client has to reply to Probe Request frames received on the
776 * group operating channel. Enable Probe Request frame reporting for
777 * P2P connected client in case p2p_cli_probe configuration property is
778 * set to 1.
779 */
780 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
781 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
782 wpa_s->current_ssid->p2p_group) {
783 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
784 wpa_dbg(wpa_s, MSG_DEBUG,
785 "P2P: Enable CLI Probe Request RX reporting");
786 wpa_s->p2p_cli_probe =
787 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
788 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
789 wpa_dbg(wpa_s, MSG_DEBUG,
790 "P2P: Disable CLI Probe Request RX reporting");
791 wpa_s->p2p_cli_probe = 0;
792 wpa_drv_probe_req_report(wpa_s, 0);
793 }
794 }
795#endif /* CONFIG_P2P */
796
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700797 if (state != WPA_SCANNING)
798 wpa_supplicant_notify_scanning(wpa_s, 0);
799
800 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700801 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700802#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700803 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800804 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800805 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700806 ssid ? ssid->id : -1,
807 ssid && ssid->id_str ? ssid->id_str : "");
808#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700809 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700810 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800811 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700812 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700813 wpa_drv_set_operstate(wpa_s, 1);
814#ifndef IEEE8021X_EAPOL
815 wpa_drv_set_supp_port(wpa_s, 1);
816#endif /* IEEE8021X_EAPOL */
817 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700818 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700820
821 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700822 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
823 state == WPA_ASSOCIATED) {
824 wpa_s->new_connection = 1;
825 wpa_drv_set_operstate(wpa_s, 0);
826#ifndef IEEE8021X_EAPOL
827 wpa_drv_set_supp_port(wpa_s, 0);
828#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700829 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700830 }
831 wpa_s->wpa_state = state;
832
833#ifdef CONFIG_BGSCAN
834 if (state == WPA_COMPLETED)
835 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800836 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700837 wpa_supplicant_stop_bgscan(wpa_s);
838#endif /* CONFIG_BGSCAN */
839
Dmitry Shmidt04949592012-07-19 12:16:46 -0700840 if (state == WPA_AUTHENTICATING)
841 wpa_supplicant_stop_autoscan(wpa_s);
842
843 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
844 wpa_supplicant_start_autoscan(wpa_s);
845
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800846 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
847 wmm_ac_notify_disassoc(wpa_s);
848
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849 if (wpa_s->wpa_state != old_state) {
850 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
851
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700852 /*
853 * Notify the P2P Device interface about a state change in one
854 * of the interfaces.
855 */
856 wpas_p2p_indicate_state_change(wpa_s);
857
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700858 if (wpa_s->wpa_state == WPA_COMPLETED ||
859 old_state == WPA_COMPLETED)
860 wpas_notify_auth_changed(wpa_s);
861 }
862}
863
864
865void wpa_supplicant_terminate_proc(struct wpa_global *global)
866{
867 int pending = 0;
868#ifdef CONFIG_WPS
869 struct wpa_supplicant *wpa_s = global->ifaces;
870 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800871 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700872 if (wpas_wps_terminate_pending(wpa_s) == 1)
873 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700874#ifdef CONFIG_P2P
875 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
876 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
877 wpas_p2p_disconnect(wpa_s);
878#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800879 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880 }
881#endif /* CONFIG_WPS */
882 if (pending)
883 return;
884 eloop_terminate();
885}
886
887
888static void wpa_supplicant_terminate(int sig, void *signal_ctx)
889{
890 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700891 wpa_supplicant_terminate_proc(global);
892}
893
894
895void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
896{
897 enum wpa_states old_state = wpa_s->wpa_state;
898
899 wpa_s->pairwise_cipher = 0;
900 wpa_s->group_cipher = 0;
901 wpa_s->mgmt_group_cipher = 0;
902 wpa_s->key_mgmt = 0;
903 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700904 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700905
906 if (wpa_s->wpa_state != old_state)
907 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
908}
909
910
911/**
912 * wpa_supplicant_reload_configuration - Reload configuration data
913 * @wpa_s: Pointer to wpa_supplicant data
914 * Returns: 0 on success or -1 if configuration parsing failed
915 *
916 * This function can be used to request that the configuration data is reloaded
917 * (e.g., after configuration file change). This function is reloading
918 * configuration only for one interface, so this may need to be called multiple
919 * times if %wpa_supplicant is controlling multiple interfaces and all
920 * interfaces need reconfiguration.
921 */
922int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
923{
924 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700925 int reconf_ctrl;
926 int old_ap_scan;
927
928 if (wpa_s->confname == NULL)
929 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700930 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700931 if (conf == NULL) {
932 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
933 "file '%s' - exiting", wpa_s->confname);
934 return -1;
935 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700936 wpa_config_read(wpa_s->confanother, conf);
937
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700938 conf->changed_parameters = (unsigned int) -1;
939
940 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
941 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
942 os_strcmp(conf->ctrl_interface,
943 wpa_s->conf->ctrl_interface) != 0);
944
945 if (reconf_ctrl && wpa_s->ctrl_iface) {
946 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
947 wpa_s->ctrl_iface = NULL;
948 }
949
950 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800951 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700952 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
953 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800954 wpa_supplicant_deauthenticate(wpa_s,
955 WLAN_REASON_DEAUTH_LEAVING);
956 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700957
958 /*
959 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800960 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700961 */
962 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
963 /*
964 * Clear forced success to clear EAP state for next
965 * authentication.
966 */
967 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
968 }
969 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
970 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800971 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700972 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
973 rsn_preauth_deinit(wpa_s->wpa);
974
975 old_ap_scan = wpa_s->conf->ap_scan;
976 wpa_config_free(wpa_s->conf);
977 wpa_s->conf = conf;
978 if (old_ap_scan != wpa_s->conf->ap_scan)
979 wpas_notify_ap_scan_changed(wpa_s);
980
981 if (reconf_ctrl)
982 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
983
984 wpa_supplicant_update_config(wpa_s);
985
986 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700987 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700988 wpa_s->reassociate = 1;
989 wpa_supplicant_req_scan(wpa_s, 0, 0);
990 }
991 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
992 return 0;
993}
994
995
996static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
997{
998 struct wpa_global *global = signal_ctx;
999 struct wpa_supplicant *wpa_s;
1000 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1001 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1002 sig);
1003 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1004 wpa_supplicant_terminate_proc(global);
1005 }
1006 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001007
1008 if (wpa_debug_reopen_file() < 0) {
1009 /* Ignore errors since we cannot really do much to fix this */
1010 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1011 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001012}
1013
1014
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001015static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1016 struct wpa_ssid *ssid,
1017 struct wpa_ie_data *ie)
1018{
1019 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1020 if (ret) {
1021 if (ret == -2) {
1022 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1023 "from association info");
1024 }
1025 return -1;
1026 }
1027
1028 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1029 "cipher suites");
1030 if (!(ie->group_cipher & ssid->group_cipher)) {
1031 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1032 "cipher 0x%x (mask 0x%x) - reject",
1033 ie->group_cipher, ssid->group_cipher);
1034 return -1;
1035 }
1036 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1037 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1038 "cipher 0x%x (mask 0x%x) - reject",
1039 ie->pairwise_cipher, ssid->pairwise_cipher);
1040 return -1;
1041 }
1042 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1043 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1044 "management 0x%x (mask 0x%x) - reject",
1045 ie->key_mgmt, ssid->key_mgmt);
1046 return -1;
1047 }
1048
1049#ifdef CONFIG_IEEE80211W
1050 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001051 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001052 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1053 "that does not support management frame protection - "
1054 "reject");
1055 return -1;
1056 }
1057#endif /* CONFIG_IEEE80211W */
1058
1059 return 0;
1060}
1061
1062
1063/**
1064 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1065 * @wpa_s: Pointer to wpa_supplicant data
1066 * @bss: Scan results for the selected BSS, or %NULL if not available
1067 * @ssid: Configuration data for the selected network
1068 * @wpa_ie: Buffer for the WPA/RSN IE
1069 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1070 * used buffer length in case the functions returns success.
1071 * Returns: 0 on success or -1 on failure
1072 *
1073 * This function is used to configure authentication and encryption parameters
1074 * based on the network configuration and scan result for the selected BSS (if
1075 * available).
1076 */
1077int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1078 struct wpa_bss *bss, struct wpa_ssid *ssid,
1079 u8 *wpa_ie, size_t *wpa_ie_len)
1080{
1081 struct wpa_ie_data ie;
1082 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001083 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001084
1085 if (bss) {
1086 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1087 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001088 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001090 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001091
1092 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1093 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1094 (ie.group_cipher & ssid->group_cipher) &&
1095 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1096 (ie.key_mgmt & ssid->key_mgmt)) {
1097 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1098 proto = WPA_PROTO_RSN;
1099 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001100 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001101 (ie.group_cipher & ssid->group_cipher) &&
1102 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1103 (ie.key_mgmt & ssid->key_mgmt)) {
1104 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1105 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001106#ifdef CONFIG_HS20
1107 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1108 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1109 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001110 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001111 ie.group_cipher = WPA_CIPHER_CCMP;
1112 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1113 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1114 proto = WPA_PROTO_OSEN;
1115#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001116 } else if (bss) {
1117 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001118 wpa_dbg(wpa_s, MSG_DEBUG,
1119 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1120 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1121 ssid->key_mgmt);
1122 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1123 MAC2STR(bss->bssid),
1124 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1125 bss_wpa ? " WPA" : "",
1126 bss_rsn ? " RSN" : "",
1127 bss_osen ? " OSEN" : "");
1128 if (bss_rsn) {
1129 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1130 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1131 wpa_dbg(wpa_s, MSG_DEBUG,
1132 "Could not parse RSN element");
1133 } else {
1134 wpa_dbg(wpa_s, MSG_DEBUG,
1135 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1136 ie.pairwise_cipher, ie.group_cipher,
1137 ie.key_mgmt);
1138 }
1139 }
1140 if (bss_wpa) {
1141 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1142 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1143 wpa_dbg(wpa_s, MSG_DEBUG,
1144 "Could not parse WPA element");
1145 } else {
1146 wpa_dbg(wpa_s, MSG_DEBUG,
1147 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1148 ie.pairwise_cipher, ie.group_cipher,
1149 ie.key_mgmt);
1150 }
1151 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152 return -1;
1153 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001154 if (ssid->proto & WPA_PROTO_OSEN)
1155 proto = WPA_PROTO_OSEN;
1156 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001157 proto = WPA_PROTO_RSN;
1158 else
1159 proto = WPA_PROTO_WPA;
1160 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1161 os_memset(&ie, 0, sizeof(ie));
1162 ie.group_cipher = ssid->group_cipher;
1163 ie.pairwise_cipher = ssid->pairwise_cipher;
1164 ie.key_mgmt = ssid->key_mgmt;
1165#ifdef CONFIG_IEEE80211W
1166 ie.mgmt_group_cipher =
1167 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1168 WPA_CIPHER_AES_128_CMAC : 0;
1169#endif /* CONFIG_IEEE80211W */
1170 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1171 "based on configuration");
1172 } else
1173 proto = ie.proto;
1174 }
1175
1176 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1177 "pairwise %d key_mgmt %d proto %d",
1178 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1179#ifdef CONFIG_IEEE80211W
1180 if (ssid->ieee80211w) {
1181 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1182 ie.mgmt_group_cipher);
1183 }
1184#endif /* CONFIG_IEEE80211W */
1185
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001186 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001187 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1188 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001189 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190
1191 if (bss || !wpa_s->ap_ies_from_associnfo) {
1192 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1193 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1194 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1195 bss_rsn ? 2 + bss_rsn[1] : 0))
1196 return -1;
1197 }
1198
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001199#ifdef CONFIG_NO_WPA
1200 wpa_s->group_cipher = WPA_CIPHER_NONE;
1201 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1202#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001203 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001204 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1205 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001206 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1207 "cipher");
1208 return -1;
1209 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001210 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1211 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001212
1213 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001214 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1215 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001216 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1217 "cipher");
1218 return -1;
1219 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001220 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1221 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001222#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001223
1224 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001225#ifdef CONFIG_SAE
1226 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1227 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1228#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001229 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001230#ifdef CONFIG_SUITEB192
1231 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1232 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1233 wpa_dbg(wpa_s, MSG_DEBUG,
1234 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1235#endif /* CONFIG_SUITEB192 */
1236#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001237 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1238 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1239 wpa_dbg(wpa_s, MSG_DEBUG,
1240 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001241#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001242#ifdef CONFIG_FILS
1243#ifdef CONFIG_IEEE80211R
1244 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1245 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1246 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1247 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1248 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1249 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1250#endif /* CONFIG_IEEE80211R */
1251 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1252 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1253 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1254 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1255 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1256 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1257#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001258#ifdef CONFIG_IEEE80211R
1259 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1260 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1261 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1262 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1263 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1264 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1265#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001266#ifdef CONFIG_SAE
1267 } else if (sel & WPA_KEY_MGMT_SAE) {
1268 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1269 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1270 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1271 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1272 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1273#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274#ifdef CONFIG_IEEE80211W
1275 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1276 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1277 wpa_dbg(wpa_s, MSG_DEBUG,
1278 "WPA: using KEY_MGMT 802.1X with SHA256");
1279 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1280 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1281 wpa_dbg(wpa_s, MSG_DEBUG,
1282 "WPA: using KEY_MGMT PSK with SHA256");
1283#endif /* CONFIG_IEEE80211W */
1284 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1285 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1286 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1287 } else if (sel & WPA_KEY_MGMT_PSK) {
1288 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1289 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1290 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1291 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1292 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001293#ifdef CONFIG_HS20
1294 } else if (sel & WPA_KEY_MGMT_OSEN) {
1295 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1296 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1297#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 } else {
1299 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1300 "authenticated key management type");
1301 return -1;
1302 }
1303
1304 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1305 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1306 wpa_s->pairwise_cipher);
1307 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1308
1309#ifdef CONFIG_IEEE80211W
1310 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001311 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001312 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1313 sel = 0;
1314 if (sel & WPA_CIPHER_AES_128_CMAC) {
1315 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1316 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1317 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001318 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1319 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1320 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1321 "BIP-GMAC-128");
1322 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1323 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1324 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1325 "BIP-GMAC-256");
1326 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1327 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1328 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1329 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 } else {
1331 wpa_s->mgmt_group_cipher = 0;
1332 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1333 }
1334 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1335 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001336 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001337 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001338#endif /* CONFIG_IEEE80211W */
1339
1340 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1341 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1342 return -1;
1343 }
1344
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001345 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001346 int psk_set = 0;
1347
1348 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001349 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1350 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001351 psk_set = 1;
1352 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001353#ifndef CONFIG_NO_PBKDF2
1354 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1355 ssid->passphrase) {
1356 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001357 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1358 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001359 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1360 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001361 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001362 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001363 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001364 }
1365#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001366#ifdef CONFIG_EXT_PASSWORD
1367 if (ssid->ext_psk) {
1368 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1369 ssid->ext_psk);
1370 char pw_str[64 + 1];
1371 u8 psk[PMK_LEN];
1372
1373 if (pw == NULL) {
1374 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1375 "found from external storage");
1376 return -1;
1377 }
1378
1379 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1380 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1381 "PSK length %d in external storage",
1382 (int) wpabuf_len(pw));
1383 ext_password_free(pw);
1384 return -1;
1385 }
1386
1387 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1388 pw_str[wpabuf_len(pw)] = '\0';
1389
1390#ifndef CONFIG_NO_PBKDF2
1391 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1392 {
1393 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1394 4096, psk, PMK_LEN);
1395 os_memset(pw_str, 0, sizeof(pw_str));
1396 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1397 "external passphrase)",
1398 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001399 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1400 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001401 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001402 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001403 } else
1404#endif /* CONFIG_NO_PBKDF2 */
1405 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1406 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1407 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1408 "Invalid PSK hex string");
1409 os_memset(pw_str, 0, sizeof(pw_str));
1410 ext_password_free(pw);
1411 return -1;
1412 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001413 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1414 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001415 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001416 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001417 } else {
1418 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1419 "PSK available");
1420 os_memset(pw_str, 0, sizeof(pw_str));
1421 ext_password_free(pw);
1422 return -1;
1423 }
1424
1425 os_memset(pw_str, 0, sizeof(pw_str));
1426 ext_password_free(pw);
1427 }
1428#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001429
1430 if (!psk_set) {
1431 wpa_msg(wpa_s, MSG_INFO,
1432 "No PSK available for association");
1433 return -1;
1434 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001435 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001436 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1437
1438 return 0;
1439}
1440
1441
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001442static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1443{
1444 *pos = 0x00;
1445
1446 switch (idx) {
1447 case 0: /* Bits 0-7 */
1448 break;
1449 case 1: /* Bits 8-15 */
1450 break;
1451 case 2: /* Bits 16-23 */
1452#ifdef CONFIG_WNM
1453 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1454 *pos |= 0x08; /* Bit 19 - BSS Transition */
1455#endif /* CONFIG_WNM */
1456 break;
1457 case 3: /* Bits 24-31 */
1458#ifdef CONFIG_WNM
1459 *pos |= 0x02; /* Bit 25 - SSID List */
1460#endif /* CONFIG_WNM */
1461#ifdef CONFIG_INTERWORKING
1462 if (wpa_s->conf->interworking)
1463 *pos |= 0x80; /* Bit 31 - Interworking */
1464#endif /* CONFIG_INTERWORKING */
1465 break;
1466 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001467#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001468 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1469 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001470#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001471 break;
1472 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001473#ifdef CONFIG_HS20
1474 if (wpa_s->conf->hs20)
1475 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1476#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001477#ifdef CONFIG_MBO
1478 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1479#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001480 break;
1481 case 6: /* Bits 48-55 */
1482 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001483 case 7: /* Bits 56-63 */
1484 break;
1485 case 8: /* Bits 64-71 */
1486 if (wpa_s->conf->ftm_responder)
1487 *pos |= 0x40; /* Bit 70 - FTM responder */
1488 if (wpa_s->conf->ftm_initiator)
1489 *pos |= 0x80; /* Bit 71 - FTM initiator */
1490 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001491 case 9: /* Bits 72-79 */
1492#ifdef CONFIG_FILS
1493 *pos |= 0x01;
1494#endif /* CONFIG_FILS */
1495 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001496 }
1497}
1498
1499
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001500int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001501{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001502 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001503 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001504
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001505 if (len < wpa_s->extended_capa_len)
1506 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001507 if (buflen < (size_t) len + 2) {
1508 wpa_printf(MSG_INFO,
1509 "Not enough room for building extended capabilities element");
1510 return -1;
1511 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001512
1513 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001514 *pos++ = len;
1515 for (i = 0; i < len; i++, pos++) {
1516 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001517
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001518 if (i < wpa_s->extended_capa_len) {
1519 *pos &= ~wpa_s->extended_capa_mask[i];
1520 *pos |= wpa_s->extended_capa[i];
1521 }
1522 }
1523
1524 while (len > 0 && buf[1 + len] == 0) {
1525 len--;
1526 buf[1] = len;
1527 }
1528 if (len == 0)
1529 return 0;
1530
1531 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001532}
1533
1534
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001535static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1536 struct wpa_bss *test_bss)
1537{
1538 struct wpa_bss *bss;
1539
1540 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1541 if (bss == test_bss)
1542 return 1;
1543 }
1544
1545 return 0;
1546}
1547
1548
1549static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1550 struct wpa_ssid *test_ssid)
1551{
1552 struct wpa_ssid *ssid;
1553
1554 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1555 if (ssid == test_ssid)
1556 return 1;
1557 }
1558
1559 return 0;
1560}
1561
1562
1563int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1564 struct wpa_ssid *test_ssid)
1565{
1566 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1567 return 0;
1568
1569 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1570}
1571
1572
1573void wpas_connect_work_free(struct wpa_connect_work *cwork)
1574{
1575 if (cwork == NULL)
1576 return;
1577 os_free(cwork);
1578}
1579
1580
1581void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1582{
1583 struct wpa_connect_work *cwork;
1584 struct wpa_radio_work *work = wpa_s->connect_work;
1585
1586 if (!work)
1587 return;
1588
1589 wpa_s->connect_work = NULL;
1590 cwork = work->ctx;
1591 work->ctx = NULL;
1592 wpas_connect_work_free(cwork);
1593 radio_work_done(work);
1594}
1595
1596
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001597int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1598{
1599 struct os_reltime now;
1600 u8 addr[ETH_ALEN];
1601
1602 os_get_reltime(&now);
1603 if (wpa_s->last_mac_addr_style == style &&
1604 wpa_s->last_mac_addr_change.sec != 0 &&
1605 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1606 wpa_s->conf->rand_addr_lifetime)) {
1607 wpa_msg(wpa_s, MSG_DEBUG,
1608 "Previously selected random MAC address has not yet expired");
1609 return 0;
1610 }
1611
1612 switch (style) {
1613 case 1:
1614 if (random_mac_addr(addr) < 0)
1615 return -1;
1616 break;
1617 case 2:
1618 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1619 if (random_mac_addr_keep_oui(addr) < 0)
1620 return -1;
1621 break;
1622 default:
1623 return -1;
1624 }
1625
1626 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1627 wpa_msg(wpa_s, MSG_INFO,
1628 "Failed to set random MAC address");
1629 return -1;
1630 }
1631
1632 os_get_reltime(&wpa_s->last_mac_addr_change);
1633 wpa_s->mac_addr_changed = 1;
1634 wpa_s->last_mac_addr_style = style;
1635
1636 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1637 wpa_msg(wpa_s, MSG_INFO,
1638 "Could not update MAC address information");
1639 return -1;
1640 }
1641
1642 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1643 MAC2STR(addr));
1644
1645 return 0;
1646}
1647
1648
1649int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1650{
1651 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1652 !wpa_s->conf->preassoc_mac_addr)
1653 return 0;
1654
1655 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1656}
1657
1658
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001659static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1660
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661/**
1662 * wpa_supplicant_associate - Request association
1663 * @wpa_s: Pointer to wpa_supplicant data
1664 * @bss: Scan results for the selected BSS, or %NULL if not available
1665 * @ssid: Configuration data for the selected network
1666 *
1667 * This function is used to request %wpa_supplicant to associate with a BSS.
1668 */
1669void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1670 struct wpa_bss *bss, struct wpa_ssid *ssid)
1671{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001672 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001673 int rand_style;
1674
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001675 wpa_s->own_disconnect_req = 0;
1676
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001677 /*
1678 * If we are starting a new connection, any previously pending EAPOL
1679 * RX cannot be valid anymore.
1680 */
1681 wpabuf_free(wpa_s->pending_eapol_rx);
1682 wpa_s->pending_eapol_rx = NULL;
1683
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001684 if (ssid->mac_addr == -1)
1685 rand_style = wpa_s->conf->mac_addr;
1686 else
1687 rand_style = ssid->mac_addr;
1688
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001689 wmm_ac_clear_saved_tspecs(wpa_s);
1690 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001691 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001692
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001693 if (wpa_s->last_ssid == ssid) {
1694 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001695 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001696 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1697 wmm_ac_save_tspecs(wpa_s);
1698 wpa_s->reassoc_same_bss = 1;
1699 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001700 }
1701
1702 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001703 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1704 return;
1705 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001706 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001707 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1708 wpa_msg(wpa_s, MSG_INFO,
1709 "Could not restore permanent MAC address");
1710 return;
1711 }
1712 wpa_s->mac_addr_changed = 0;
1713 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1714 wpa_msg(wpa_s, MSG_INFO,
1715 "Could not update MAC address information");
1716 return;
1717 }
1718 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1719 }
1720 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721
1722#ifdef CONFIG_IBSS_RSN
1723 ibss_rsn_deinit(wpa_s->ibss_rsn);
1724 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001725#else /* CONFIG_IBSS_RSN */
1726 if (ssid->mode == WPAS_MODE_IBSS &&
1727 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1728 wpa_msg(wpa_s, MSG_INFO,
1729 "IBSS RSN not supported in the build");
1730 return;
1731 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732#endif /* CONFIG_IBSS_RSN */
1733
1734 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1735 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1736#ifdef CONFIG_AP
1737 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1738 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1739 "mode");
1740 return;
1741 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001742 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1743 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001744 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1745 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001746 return;
1747 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001748 wpa_s->current_bss = bss;
1749#else /* CONFIG_AP */
1750 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1751 "the build");
1752#endif /* CONFIG_AP */
1753 return;
1754 }
1755
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001756 if (ssid->mode == WPAS_MODE_MESH) {
1757#ifdef CONFIG_MESH
1758 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1759 wpa_msg(wpa_s, MSG_INFO,
1760 "Driver does not support mesh mode");
1761 return;
1762 }
1763 if (bss)
1764 ssid->frequency = bss->freq;
1765 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1766 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1767 return;
1768 }
1769 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001770 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1771 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1772 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001773#else /* CONFIG_MESH */
1774 wpa_msg(wpa_s, MSG_ERROR,
1775 "mesh mode support not included in the build");
1776#endif /* CONFIG_MESH */
1777 return;
1778 }
1779
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780#ifdef CONFIG_TDLS
1781 if (bss)
1782 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1783 bss->ie_len);
1784#endif /* CONFIG_TDLS */
1785
1786 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1787 ssid->mode == IEEE80211_MODE_INFRA) {
1788 sme_authenticate(wpa_s, bss, ssid);
1789 return;
1790 }
1791
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001792 if (wpa_s->connect_work) {
1793 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1794 return;
1795 }
1796
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001797 if (radio_work_pending(wpa_s, "connect")) {
1798 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1799 return;
1800 }
1801
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001802 wpas_abort_ongoing_scan(wpa_s);
1803
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001804 cwork = os_zalloc(sizeof(*cwork));
1805 if (cwork == NULL)
1806 return;
1807
1808 cwork->bss = bss;
1809 cwork->ssid = ssid;
1810
1811 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1812 wpas_start_assoc_cb, cwork) < 0) {
1813 os_free(cwork);
1814 }
1815}
1816
1817
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001818static int bss_is_ibss(struct wpa_bss *bss)
1819{
1820 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1821 IEEE80211_CAP_IBSS;
1822}
1823
1824
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001825static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1826 const struct wpa_ssid *ssid)
1827{
1828 enum hostapd_hw_mode hw_mode;
1829 struct hostapd_hw_modes *mode = NULL;
1830 u8 channel;
1831 int i;
1832
1833#ifdef CONFIG_HT_OVERRIDES
1834 if (ssid->disable_ht)
1835 return 0;
1836#endif /* CONFIG_HT_OVERRIDES */
1837
1838 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1839 if (hw_mode == NUM_HOSTAPD_MODES)
1840 return 0;
1841 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1842 if (wpa_s->hw.modes[i].mode == hw_mode) {
1843 mode = &wpa_s->hw.modes[i];
1844 break;
1845 }
1846 }
1847
1848 if (!mode)
1849 return 0;
1850
1851 return mode->vht_capab != 0;
1852}
1853
1854
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001855void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1856 const struct wpa_ssid *ssid,
1857 struct hostapd_freq_params *freq)
1858{
1859 enum hostapd_hw_mode hw_mode;
1860 struct hostapd_hw_modes *mode = NULL;
1861 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1862 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001863 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001864 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1865 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001866 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001867 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001868 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001869 int chwidth, seg0, seg1;
1870 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001871
1872 freq->freq = ssid->frequency;
1873
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001874 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1875 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1876
1877 if (ssid->mode != WPAS_MODE_IBSS)
1878 break;
1879
1880 /* Don't adjust control freq in case of fixed_freq */
1881 if (ssid->fixed_freq)
1882 break;
1883
1884 if (!bss_is_ibss(bss))
1885 continue;
1886
1887 if (ssid->ssid_len == bss->ssid_len &&
1888 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1889 wpa_printf(MSG_DEBUG,
1890 "IBSS already found in scan results, adjust control freq: %d",
1891 bss->freq);
1892 freq->freq = bss->freq;
1893 obss_scan = 0;
1894 break;
1895 }
1896 }
1897
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001898 /* For IBSS check HT_IBSS flag */
1899 if (ssid->mode == WPAS_MODE_IBSS &&
1900 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1901 return;
1902
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001903 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1904 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1905 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1906 wpa_printf(MSG_DEBUG,
1907 "IBSS: WEP/TKIP detected, do not try to enable HT");
1908 return;
1909 }
1910
1911 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001912 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1913 if (wpa_s->hw.modes[i].mode == hw_mode) {
1914 mode = &wpa_s->hw.modes[i];
1915 break;
1916 }
1917 }
1918
1919 if (!mode)
1920 return;
1921
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001922#ifdef CONFIG_HT_OVERRIDES
1923 if (ssid->disable_ht) {
1924 freq->ht_enabled = 0;
1925 return;
1926 }
1927#endif /* CONFIG_HT_OVERRIDES */
1928
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001929 freq->ht_enabled = ht_supported(mode);
1930 if (!freq->ht_enabled)
1931 return;
1932
1933 /* Setup higher BW only for 5 GHz */
1934 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1935 return;
1936
1937 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1938 pri_chan = &mode->channels[chan_idx];
1939 if (pri_chan->chan == channel)
1940 break;
1941 pri_chan = NULL;
1942 }
1943 if (!pri_chan)
1944 return;
1945
1946 /* Check primary channel flags */
1947 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1948 return;
1949
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001950#ifdef CONFIG_HT_OVERRIDES
1951 if (ssid->disable_ht40)
1952 return;
1953#endif /* CONFIG_HT_OVERRIDES */
1954
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001955 /* Check/setup HT40+/HT40- */
1956 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1957 if (ht40plus[j] == channel) {
1958 ht40 = 1;
1959 break;
1960 }
1961 }
1962
1963 /* Find secondary channel */
1964 for (i = 0; i < mode->num_channels; i++) {
1965 sec_chan = &mode->channels[i];
1966 if (sec_chan->chan == channel + ht40 * 4)
1967 break;
1968 sec_chan = NULL;
1969 }
1970 if (!sec_chan)
1971 return;
1972
1973 /* Check secondary channel flags */
1974 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1975 return;
1976
1977 freq->channel = pri_chan->chan;
1978
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001979 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001980 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1981 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001982 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001983 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1984 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001985 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001986 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001987
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001988 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001989 struct wpa_scan_results *scan_res;
1990
1991 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1992 if (scan_res == NULL) {
1993 /* Back to HT20 */
1994 freq->sec_channel_offset = 0;
1995 return;
1996 }
1997
1998 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1999 sec_chan->chan);
2000 switch (res) {
2001 case 0:
2002 /* Back to HT20 */
2003 freq->sec_channel_offset = 0;
2004 break;
2005 case 1:
2006 /* Configuration allowed */
2007 break;
2008 case 2:
2009 /* Switch pri/sec channels */
2010 freq->freq = hw_get_freq(mode, sec_chan->chan);
2011 freq->sec_channel_offset = -freq->sec_channel_offset;
2012 freq->channel = sec_chan->chan;
2013 break;
2014 default:
2015 freq->sec_channel_offset = 0;
2016 break;
2017 }
2018
2019 wpa_scan_results_free(scan_res);
2020 }
2021
2022 wpa_printf(MSG_DEBUG,
2023 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2024 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002025
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002026 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002027 return;
2028
2029 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002030 if (ssid->mode == WPAS_MODE_IBSS &&
2031 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002032 return;
2033
2034 vht_freq = *freq;
2035
2036 vht_freq.vht_enabled = vht_supported(mode);
2037 if (!vht_freq.vht_enabled)
2038 return;
2039
2040 /* setup center_freq1, bandwidth */
2041 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2042 if (freq->channel >= vht80[j] &&
2043 freq->channel < vht80[j] + 16)
2044 break;
2045 }
2046
2047 if (j == ARRAY_SIZE(vht80))
2048 return;
2049
2050 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2051 struct hostapd_channel_data *chan;
2052
2053 chan = hw_get_channel_chan(mode, i, NULL);
2054 if (!chan)
2055 return;
2056
2057 /* Back to HT configuration if channel not usable */
2058 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2059 return;
2060 }
2061
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002062 chwidth = VHT_CHANWIDTH_80MHZ;
2063 seg0 = vht80[j] + 6;
2064 seg1 = 0;
2065
2066 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2067 /* setup center_freq2, bandwidth */
2068 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2069 /* Only accept 80 MHz segments separated by a gap */
2070 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2071 continue;
2072 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2073 struct hostapd_channel_data *chan;
2074
2075 chan = hw_get_channel_chan(mode, i, NULL);
2076 if (!chan)
2077 continue;
2078
2079 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2080 HOSTAPD_CHAN_NO_IR |
2081 HOSTAPD_CHAN_RADAR))
2082 continue;
2083
2084 /* Found a suitable second segment for 80+80 */
2085 chwidth = VHT_CHANWIDTH_80P80MHZ;
2086 vht_caps |=
2087 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2088 seg1 = vht80[k] + 6;
2089 }
2090
2091 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2092 break;
2093 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002094 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2095 if (freq->freq == 5180) {
2096 chwidth = VHT_CHANWIDTH_160MHZ;
2097 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2098 seg0 = 50;
2099 } else if (freq->freq == 5520) {
2100 chwidth = VHT_CHANWIDTH_160MHZ;
2101 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2102 seg0 = 114;
2103 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002104 }
2105
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002106 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2107 freq->channel, freq->ht_enabled,
2108 vht_freq.vht_enabled,
2109 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002110 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002111 return;
2112
2113 *freq = vht_freq;
2114
2115 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2116 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002117}
2118
2119
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002120static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2121{
2122 struct wpa_connect_work *cwork = work->ctx;
2123 struct wpa_bss *bss = cwork->bss;
2124 struct wpa_ssid *ssid = cwork->ssid;
2125 struct wpa_supplicant *wpa_s = work->wpa_s;
2126 u8 wpa_ie[200];
2127 size_t wpa_ie_len;
2128 int use_crypt, ret, i, bssid_changed;
2129 int algs = WPA_AUTH_ALG_OPEN;
2130 unsigned int cipher_pairwise, cipher_group;
2131 struct wpa_driver_associate_params params;
2132 int wep_keys_set = 0;
2133 int assoc_failed = 0;
2134 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002135 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002136#ifdef CONFIG_HT_OVERRIDES
2137 struct ieee80211_ht_capabilities htcaps;
2138 struct ieee80211_ht_capabilities htcaps_mask;
2139#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002140#ifdef CONFIG_VHT_OVERRIDES
2141 struct ieee80211_vht_capabilities vhtcaps;
2142 struct ieee80211_vht_capabilities vhtcaps_mask;
2143#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002144#ifdef CONFIG_MBO
2145 const u8 *mbo = NULL;
2146#endif /* CONFIG_MBO */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002147
2148 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002149 if (work->started) {
2150 wpa_s->connect_work = NULL;
2151
2152 /* cancel possible auth. timeout */
2153 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2154 NULL);
2155 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002156 wpas_connect_work_free(cwork);
2157 return;
2158 }
2159
2160 wpa_s->connect_work = work;
2161
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002162 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2163 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002164 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2165 wpas_connect_work_done(wpa_s);
2166 return;
2167 }
2168
Dmitry Shmidte4663042016-04-04 10:07:49 -07002169 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002170 os_memset(&params, 0, sizeof(params));
2171 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002172 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002173 if (bss &&
2174 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002175#ifdef CONFIG_IEEE80211R
2176 const u8 *ie, *md = NULL;
2177#endif /* CONFIG_IEEE80211R */
2178 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2179 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2180 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2181 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2182 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2183 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2184 if (bssid_changed)
2185 wpas_notify_bssid_changed(wpa_s);
2186#ifdef CONFIG_IEEE80211R
2187 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2188 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2189 md = ie + 2;
2190 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2191 if (md) {
2192 /* Prepare for the next transition */
2193 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2194 }
2195#endif /* CONFIG_IEEE80211R */
2196#ifdef CONFIG_WPS
2197 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2198 wpa_s->conf->ap_scan == 2 &&
2199 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2200 /* Use ap_scan==1 style network selection to find the network
2201 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002202 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002203 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002204 wpa_s->reassociate = 1;
2205 wpa_supplicant_req_scan(wpa_s, 0, 0);
2206 return;
2207#endif /* CONFIG_WPS */
2208 } else {
2209 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2210 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002211 if (bss)
2212 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2213 else
2214 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002215 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002216 if (!wpa_s->pno)
2217 wpa_supplicant_cancel_sched_scan(wpa_s);
2218
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002219 wpa_supplicant_cancel_scan(wpa_s);
2220
2221 /* Starting new association, so clear the possibly used WPA IE from the
2222 * previous association. */
2223 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2224
2225#ifdef IEEE8021X_EAPOL
2226 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2227 if (ssid->leap) {
2228 if (ssid->non_leap == 0)
2229 algs = WPA_AUTH_ALG_LEAP;
2230 else
2231 algs |= WPA_AUTH_ALG_LEAP;
2232 }
2233 }
2234#endif /* IEEE8021X_EAPOL */
2235 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2236 if (ssid->auth_alg) {
2237 algs = ssid->auth_alg;
2238 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2239 "0x%x", algs);
2240 }
2241
2242 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2243 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002244 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002245 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002246 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2247 wpa_s->conf->okc :
2248 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002249 (ssid->proto & WPA_PROTO_RSN);
2250 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002251 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002252 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002253 wpa_ie_len = sizeof(wpa_ie);
2254 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2255 wpa_ie, &wpa_ie_len)) {
2256 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2257 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002258 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259 return;
2260 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002261 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2262 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2263 /*
2264 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2265 * use non-WPA since the scan results did not indicate that the
2266 * AP is using WPA or WPA2.
2267 */
2268 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2269 wpa_ie_len = 0;
2270 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002271 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002272 wpa_ie_len = sizeof(wpa_ie);
2273 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2274 wpa_ie, &wpa_ie_len)) {
2275 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2276 "key management and encryption suites (no "
2277 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002278 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002279 return;
2280 }
2281#ifdef CONFIG_WPS
2282 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2283 struct wpabuf *wps_ie;
2284 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2285 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2286 wpa_ie_len = wpabuf_len(wps_ie);
2287 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2288 } else
2289 wpa_ie_len = 0;
2290 wpabuf_free(wps_ie);
2291 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2292 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2293 params.wps = WPS_MODE_PRIVACY;
2294 else
2295 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002296 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002297#endif /* CONFIG_WPS */
2298 } else {
2299 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2300 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002301 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002302 }
2303
2304#ifdef CONFIG_P2P
2305 if (wpa_s->global->p2p) {
2306 u8 *pos;
2307 size_t len;
2308 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002309 pos = wpa_ie + wpa_ie_len;
2310 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002311 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2312 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313 if (res >= 0)
2314 wpa_ie_len += res;
2315 }
2316
2317 wpa_s->cross_connect_disallowed = 0;
2318 if (bss) {
2319 struct wpabuf *p2p;
2320 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2321 if (p2p) {
2322 wpa_s->cross_connect_disallowed =
2323 p2p_get_cross_connect_disallowed(p2p);
2324 wpabuf_free(p2p);
2325 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2326 "connection",
2327 wpa_s->cross_connect_disallowed ?
2328 "disallows" : "allows");
2329 }
2330 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002331
2332 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333#endif /* CONFIG_P2P */
2334
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002335#ifdef CONFIG_MBO
2336 if (bss) {
2337 mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
2338 if (mbo) {
2339 int len;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002340
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002341 len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq,
2342 wpa_ie + wpa_ie_len,
2343 sizeof(wpa_ie) -
2344 wpa_ie_len);
2345 if (len > 0)
2346 wpa_ie_len += len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002347 }
2348 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002349#endif /* CONFIG_MBO */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002350
Dmitry Shmidt56052862013-10-04 10:23:25 -07002351 /*
2352 * Workaround: Add Extended Capabilities element only if the AP
2353 * included this element in Beacon/Probe Response frames. Some older
2354 * APs seem to have interoperability issues if this element is
2355 * included, so while the standard may require us to include the
2356 * element in all cases, it is justifiable to skip it to avoid
2357 * interoperability issues.
2358 */
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002359 if (ssid->p2p_group)
2360 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2361 else
2362 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2363
Dmitry Shmidt56052862013-10-04 10:23:25 -07002364 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002365 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002366 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002367 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2368 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002369 if (ext_capab_len > 0) {
2370 u8 *pos = wpa_ie;
2371 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2372 pos += 2 + pos[1];
2373 os_memmove(pos + ext_capab_len, pos,
2374 wpa_ie_len - (pos - wpa_ie));
2375 wpa_ie_len += ext_capab_len;
2376 os_memcpy(pos, ext_capab, ext_capab_len);
2377 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002378 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002379
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002380#ifdef CONFIG_HS20
2381 if (is_hs20_network(wpa_s, ssid, bss)) {
2382 struct wpabuf *hs20;
2383
2384 hs20 = wpabuf_alloc(20);
2385 if (hs20) {
2386 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2387 size_t len;
2388
2389 wpas_hs20_add_indication(hs20, pps_mo_id);
2390 len = sizeof(wpa_ie) - wpa_ie_len;
2391 if (wpabuf_len(hs20) <= len) {
2392 os_memcpy(wpa_ie + wpa_ie_len,
2393 wpabuf_head(hs20), wpabuf_len(hs20));
2394 wpa_ie_len += wpabuf_len(hs20);
2395 }
2396 wpabuf_free(hs20);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002397
2398 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002399 }
2400 }
2401#endif /* CONFIG_HS20 */
2402
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002403 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2404 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2405 size_t len;
2406
2407 len = sizeof(wpa_ie) - wpa_ie_len;
2408 if (wpabuf_len(buf) <= len) {
2409 os_memcpy(wpa_ie + wpa_ie_len,
2410 wpabuf_head(buf), wpabuf_len(buf));
2411 wpa_ie_len += wpabuf_len(buf);
2412 }
2413 }
2414
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002415#ifdef CONFIG_FST
2416 if (wpa_s->fst_ies) {
2417 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2418
2419 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2420 os_memcpy(wpa_ie + wpa_ie_len,
2421 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2422 wpa_ie_len += fst_ies_len;
2423 }
2424 }
2425#endif /* CONFIG_FST */
2426
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002427#ifdef CONFIG_MBO
2428 if (mbo) {
2429 int len;
2430
2431 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2432 sizeof(wpa_ie) - wpa_ie_len);
2433 if (len >= 0)
2434 wpa_ie_len += len;
2435 }
2436#endif /* CONFIG_MBO */
2437
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2439 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002440 cipher_pairwise = wpa_s->pairwise_cipher;
2441 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2443 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2444 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2445 use_crypt = 0;
2446 if (wpa_set_wep_keys(wpa_s, ssid)) {
2447 use_crypt = 1;
2448 wep_keys_set = 1;
2449 }
2450 }
2451 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2452 use_crypt = 0;
2453
2454#ifdef IEEE8021X_EAPOL
2455 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2456 if ((ssid->eapol_flags &
2457 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2458 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2459 !wep_keys_set) {
2460 use_crypt = 0;
2461 } else {
2462 /* Assume that dynamic WEP-104 keys will be used and
2463 * set cipher suites in order for drivers to expect
2464 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002465 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002466 }
2467 }
2468#endif /* IEEE8021X_EAPOL */
2469
2470 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2471 /* Set the key before (and later after) association */
2472 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2473 }
2474
2475 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2476 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002477 params.ssid = bss->ssid;
2478 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002479 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2480 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002481 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2482 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002483 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002484 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002485 ssid->bssid_set,
2486 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002487 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002488 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002489 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002490 params.bssid_hint = bss->bssid;
2491 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002492 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 } else {
2494 params.ssid = ssid->ssid;
2495 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002496 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002497 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002498
2499 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2500 wpa_s->conf->ap_scan == 2) {
2501 params.bssid = ssid->bssid;
2502 params.fixed_bssid = 1;
2503 }
2504
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002505 /* Initial frequency for IBSS/mesh */
2506 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002507 ssid->frequency > 0 && params.freq.freq == 0)
2508 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002509
2510 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002511 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002512 if (ssid->beacon_int)
2513 params.beacon_int = ssid->beacon_int;
2514 else
2515 params.beacon_int = wpa_s->conf->beacon_int;
2516 }
2517
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 params.wpa_ie = wpa_ie;
2519 params.wpa_ie_len = wpa_ie_len;
2520 params.pairwise_suite = cipher_pairwise;
2521 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002522 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002523 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524 params.auth_alg = algs;
2525 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002526 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 for (i = 0; i < NUM_WEP_KEYS; i++) {
2528 if (ssid->wep_key_len[i])
2529 params.wep_key[i] = ssid->wep_key[i];
2530 params.wep_key_len[i] = ssid->wep_key_len[i];
2531 }
2532 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2533
2534 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002535 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2536 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537 params.passphrase = ssid->passphrase;
2538 if (ssid->psk_set)
2539 params.psk = ssid->psk;
2540 }
2541
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002542 if (wpa_s->conf->key_mgmt_offload) {
2543 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2544 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002545 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2546 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002547 params.req_key_mgmt_offload =
2548 ssid->proactive_key_caching < 0 ?
2549 wpa_s->conf->okc : ssid->proactive_key_caching;
2550 else
2551 params.req_key_mgmt_offload = 1;
2552
2553 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2554 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2555 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2556 ssid->psk_set)
2557 params.psk = ssid->psk;
2558 }
2559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560 params.drop_unencrypted = use_crypt;
2561
2562#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002563 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002564 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2566 struct wpa_ie_data ie;
2567 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2568 ie.capabilities &
2569 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2570 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2571 "MFP: require MFP");
2572 params.mgmt_frame_protection =
2573 MGMT_FRAME_PROTECTION_REQUIRED;
2574 }
2575 }
2576#endif /* CONFIG_IEEE80211W */
2577
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002578 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002580 if (wpa_s->p2pdev->set_sta_uapsd)
2581 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002582 else
2583 params.uapsd = -1;
2584
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002585#ifdef CONFIG_HT_OVERRIDES
2586 os_memset(&htcaps, 0, sizeof(htcaps));
2587 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2588 params.htcaps = (u8 *) &htcaps;
2589 params.htcaps_mask = (u8 *) &htcaps_mask;
2590 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2591#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002592#ifdef CONFIG_VHT_OVERRIDES
2593 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2594 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2595 params.vhtcaps = &vhtcaps;
2596 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002597 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002598#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002599
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002600#ifdef CONFIG_P2P
2601 /*
2602 * If multi-channel concurrency is not supported, check for any
2603 * frequency conflict. In case of any frequency conflict, remove the
2604 * least prioritized connection.
2605 */
2606 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002607 int freq, num;
2608 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002609 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002610 wpa_printf(MSG_DEBUG,
2611 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002612 freq, params.freq.freq);
2613 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002614 wpa_s, params.freq.freq, ssid) < 0) {
2615 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002616 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002617 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002618 }
2619 }
2620#endif /* CONFIG_P2P */
2621
Dmitry Shmidte4663042016-04-04 10:07:49 -07002622 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2623 wpa_s->current_ssid)
2624 params.prev_bssid = prev_bssid;
2625
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002626 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002627 if (ret < 0) {
2628 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2629 "failed");
2630 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2631 /*
2632 * The driver is known to mean what is saying, so we
2633 * can stop right here; the association will not
2634 * succeed.
2635 */
2636 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002637 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2639 return;
2640 }
2641 /* try to continue anyway; new association will be tried again
2642 * after timeout */
2643 assoc_failed = 1;
2644 }
2645
2646 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2647 /* Set the key after the association just in case association
2648 * cleared the previously configured key. */
2649 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2650 /* No need to timeout authentication since there is no key
2651 * management. */
2652 wpa_supplicant_cancel_auth_timeout(wpa_s);
2653 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2654#ifdef CONFIG_IBSS_RSN
2655 } else if (ssid->mode == WPAS_MODE_IBSS &&
2656 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2657 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2658 /*
2659 * RSN IBSS authentication is per-STA and we can disable the
2660 * per-BSSID authentication.
2661 */
2662 wpa_supplicant_cancel_auth_timeout(wpa_s);
2663#endif /* CONFIG_IBSS_RSN */
2664 } else {
2665 /* Timeout for IEEE 802.11 authentication and association */
2666 int timeout = 60;
2667
2668 if (assoc_failed) {
2669 /* give IBSS a bit more time */
2670 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2671 } else if (wpa_s->conf->ap_scan == 1) {
2672 /* give IBSS a bit more time */
2673 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2674 }
2675 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2676 }
2677
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002678 if (wep_keys_set &&
2679 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 /* Set static WEP keys again */
2681 wpa_set_wep_keys(wpa_s, ssid);
2682 }
2683
2684 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2685 /*
2686 * Do not allow EAP session resumption between different
2687 * network configurations.
2688 */
2689 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2690 }
2691 old_ssid = wpa_s->current_ssid;
2692 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002693
2694 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002695 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002696#ifdef CONFIG_HS20
2697 hs20_configure_frame_filters(wpa_s);
2698#endif /* CONFIG_HS20 */
2699 }
2700
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2702 wpa_supplicant_initiate_eapol(wpa_s);
2703 if (old_ssid != wpa_s->current_ssid)
2704 wpas_notify_network_changed(wpa_s);
2705}
2706
2707
2708static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2709 const u8 *addr)
2710{
2711 struct wpa_ssid *old_ssid;
2712
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002713 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002715 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002716 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002717 wpa_sm_set_config(wpa_s->wpa, NULL);
2718 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2719 if (old_ssid != wpa_s->current_ssid)
2720 wpas_notify_network_changed(wpa_s);
2721 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2722}
2723
2724
2725/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002726 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2727 * @wpa_s: Pointer to wpa_supplicant data
2728 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2729 *
2730 * This function is used to request %wpa_supplicant to deauthenticate from the
2731 * current AP.
2732 */
2733void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2734 int reason_code)
2735{
2736 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002737 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002738 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002739
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002740 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2741 " pending_bssid=" MACSTR " reason=%d state=%s",
2742 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2743 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2744
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002745 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2746 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2747 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002748 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002749 else if (!is_zero_ether_addr(wpa_s->bssid))
2750 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002751 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2752 /*
2753 * When using driver-based BSS selection, we may not know the
2754 * BSSID with which we are currently trying to associate. We
2755 * need to notify the driver of this disconnection even in such
2756 * a case, so use the all zeros address here.
2757 */
2758 addr = wpa_s->bssid;
2759 zero_addr = 1;
2760 }
2761
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002762#ifdef CONFIG_TDLS
2763 wpa_tdls_teardown_peers(wpa_s->wpa);
2764#endif /* CONFIG_TDLS */
2765
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002766#ifdef CONFIG_MESH
2767 if (wpa_s->ifmsh) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002768 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2769 wpa_s->ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002770 wpa_supplicant_leave_mesh(wpa_s);
2771 }
2772#endif /* CONFIG_MESH */
2773
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002774 if (addr) {
2775 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002776 os_memset(&event, 0, sizeof(event));
2777 event.deauth_info.reason_code = (u16) reason_code;
2778 event.deauth_info.locally_generated = 1;
2779 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002780 if (zero_addr)
2781 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002782 }
2783
2784 wpa_supplicant_clear_connection(wpa_s, addr);
2785}
2786
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002787static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2788 struct wpa_ssid *ssid)
2789{
2790 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2791 return;
2792
2793 ssid->disabled = 0;
2794 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2795 wpas_notify_network_enabled_changed(wpa_s, ssid);
2796
2797 /*
2798 * Try to reassociate since there is no current configuration and a new
2799 * network was made available.
2800 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002801 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002802 wpa_s->reassociate = 1;
2803}
2804
Roshan Pius950bec92016-07-19 09:49:24 -07002805/**
2806 * wpa_supplicant_add_network - Add a new network.
2807 * @wpa_s: wpa_supplicant structure for a network interface
2808 * Returns: The new network configuration or %NULL if operation failed
2809 *
2810 * This function performs the following operations:
2811 * 1. Adds a new network.
2812 * 2. Send network addition notification.
2813 * 3. Marks the network disabled.
2814 * 4. Set network default parameters.
2815 */
2816struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2817{
2818 struct wpa_ssid *ssid;
2819
2820 ssid = wpa_config_add_network(wpa_s->conf);
2821 if (!ssid) {
2822 return NULL;
2823 }
2824 wpas_notify_network_added(wpa_s, ssid);
2825 ssid->disabled = 1;
2826 wpa_config_set_network_defaults(ssid);
2827
2828 return ssid;
2829}
2830
2831/**
2832 * wpa_supplicant_remove_network - Remove a configured network based on id
2833 * @wpa_s: wpa_supplicant structure for a network interface
2834 * @id: Unique network id to search for
2835 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2836 * could not be removed
2837 *
2838 * This function performs the following operations:
2839 * 1. Removes the network.
2840 * 2. Send network removal notification.
2841 * 3. Update internal state machines.
2842 * 4. Stop any running sched scans.
2843 */
2844int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2845{
2846 struct wpa_ssid *ssid;
2847 int was_disabled;
2848
2849 ssid = wpa_config_get_network(wpa_s->conf, id);
2850 if (ssid)
2851 wpas_notify_network_removed(wpa_s, ssid);
2852 if (ssid == NULL) {
2853 return -1;
2854 }
2855
2856 if (wpa_s->last_ssid == ssid)
2857 wpa_s->last_ssid = NULL;
2858
2859 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2860#ifdef CONFIG_SME
2861 wpa_s->sme.prev_bssid_set = 0;
2862#endif /* CONFIG_SME */
2863 /*
2864 * Invalidate the EAP session cache if the current or
2865 * previously used network is removed.
2866 */
2867 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2868 }
2869
2870 if (ssid == wpa_s->current_ssid) {
2871 wpa_sm_set_config(wpa_s->wpa, NULL);
2872 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2873
2874 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2875 wpa_s->own_disconnect_req = 1;
2876 wpa_supplicant_deauthenticate(wpa_s,
2877 WLAN_REASON_DEAUTH_LEAVING);
2878 }
2879
2880 was_disabled = ssid->disabled;
2881
2882 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2883 return -2;
2884 }
2885
2886 if (!was_disabled && wpa_s->sched_scanning) {
2887 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2888 "network from filters");
2889 wpa_supplicant_cancel_sched_scan(wpa_s);
2890 wpa_supplicant_req_scan(wpa_s, 0, 0);
2891 }
2892 return 0;
2893}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002894
2895/**
2896 * wpa_supplicant_enable_network - Mark a configured network as enabled
2897 * @wpa_s: wpa_supplicant structure for a network interface
2898 * @ssid: wpa_ssid structure for a configured network or %NULL
2899 *
2900 * Enables the specified network or all networks if no network specified.
2901 */
2902void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2903 struct wpa_ssid *ssid)
2904{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002905 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002906 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2907 wpa_supplicant_enable_one_network(wpa_s, ssid);
2908 } else
2909 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002910
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002911 if (wpa_s->reassociate && !wpa_s->disconnected &&
2912 (!wpa_s->current_ssid ||
2913 wpa_s->wpa_state == WPA_DISCONNECTED ||
2914 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002915 if (wpa_s->sched_scanning) {
2916 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2917 "new network to scan filters");
2918 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919 }
2920
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002921 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2922 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002923 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002924 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002925 }
2926}
2927
2928
2929/**
2930 * wpa_supplicant_disable_network - Mark a configured network as disabled
2931 * @wpa_s: wpa_supplicant structure for a network interface
2932 * @ssid: wpa_ssid structure for a configured network or %NULL
2933 *
2934 * Disables the specified network or all networks if no network specified.
2935 */
2936void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2937 struct wpa_ssid *ssid)
2938{
2939 struct wpa_ssid *other_ssid;
2940 int was_disabled;
2941
2942 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002943 if (wpa_s->sched_scanning)
2944 wpa_supplicant_cancel_sched_scan(wpa_s);
2945
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002946 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2947 other_ssid = other_ssid->next) {
2948 was_disabled = other_ssid->disabled;
2949 if (was_disabled == 2)
2950 continue; /* do not change persistent P2P group
2951 * data */
2952
2953 other_ssid->disabled = 1;
2954
2955 if (was_disabled != other_ssid->disabled)
2956 wpas_notify_network_enabled_changed(
2957 wpa_s, other_ssid);
2958 }
2959 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002960 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002961 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2962 } else if (ssid->disabled != 2) {
2963 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002964 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002965 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2966
2967 was_disabled = ssid->disabled;
2968
2969 ssid->disabled = 1;
2970
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002971 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002972 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002973 if (wpa_s->sched_scanning) {
2974 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2975 "to remove network from filters");
2976 wpa_supplicant_cancel_sched_scan(wpa_s);
2977 wpa_supplicant_req_scan(wpa_s, 0, 0);
2978 }
2979 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 }
2981}
2982
2983
2984/**
2985 * wpa_supplicant_select_network - Attempt association with a network
2986 * @wpa_s: wpa_supplicant structure for a network interface
2987 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2988 */
2989void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2990 struct wpa_ssid *ssid)
2991{
2992
2993 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002994 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002996 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002997 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2998 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002999 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003000 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003001 disconnected = 1;
3002 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003003
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003004 if (ssid)
3005 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3006
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007 /*
3008 * Mark all other networks disabled or mark all networks enabled if no
3009 * network specified.
3010 */
3011 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3012 other_ssid = other_ssid->next) {
3013 int was_disabled = other_ssid->disabled;
3014 if (was_disabled == 2)
3015 continue; /* do not change persistent P2P group data */
3016
3017 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003018 if (was_disabled && !other_ssid->disabled)
3019 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003020
3021 if (was_disabled != other_ssid->disabled)
3022 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3023 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003024
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003025 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3026 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003027 /* We are already associated with the selected network */
3028 wpa_printf(MSG_DEBUG, "Already associated with the "
3029 "selected network - do nothing");
3030 return;
3031 }
3032
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003033 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003034 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003035 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003036 wpa_s->connect_without_scan =
3037 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003038
3039 /*
3040 * Don't optimize next scan freqs since a new ESS has been
3041 * selected.
3042 */
3043 os_free(wpa_s->next_scan_freqs);
3044 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003045 } else {
3046 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003047 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003048
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003049 wpa_s->disconnected = 0;
3050 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003051
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003052 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003053 wpa_supplicant_fast_associate(wpa_s) != 1) {
3054 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003055 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003056 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003057 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058
3059 if (ssid)
3060 wpas_notify_network_selected(wpa_s, ssid);
3061}
3062
3063
3064/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003065 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3066 * @wpa_s: wpa_supplicant structure for a network interface
3067 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3068 * @pkcs11_module_path: PKCS #11 module path or NULL
3069 * Returns: 0 on success; -1 on failure
3070 *
3071 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3072 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3073 * module path fails the paths will be reset to the default value (NULL).
3074 */
3075int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3076 const char *pkcs11_engine_path,
3077 const char *pkcs11_module_path)
3078{
3079 char *pkcs11_engine_path_copy = NULL;
3080 char *pkcs11_module_path_copy = NULL;
3081
3082 if (pkcs11_engine_path != NULL) {
3083 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3084 if (pkcs11_engine_path_copy == NULL)
3085 return -1;
3086 }
3087 if (pkcs11_module_path != NULL) {
3088 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003089 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003090 os_free(pkcs11_engine_path_copy);
3091 return -1;
3092 }
3093 }
3094
3095 os_free(wpa_s->conf->pkcs11_engine_path);
3096 os_free(wpa_s->conf->pkcs11_module_path);
3097 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3098 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3099
3100 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3101 eapol_sm_deinit(wpa_s->eapol);
3102 wpa_s->eapol = NULL;
3103 if (wpa_supplicant_init_eapol(wpa_s)) {
3104 /* Error -> Reset paths to the default value (NULL) once. */
3105 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3106 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3107 NULL);
3108
3109 return -1;
3110 }
3111 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3112
3113 return 0;
3114}
3115
3116
3117/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003118 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3119 * @wpa_s: wpa_supplicant structure for a network interface
3120 * @ap_scan: AP scan mode
3121 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3122 *
3123 */
3124int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3125{
3126
3127 int old_ap_scan;
3128
3129 if (ap_scan < 0 || ap_scan > 2)
3130 return -1;
3131
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003132 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3133 wpa_printf(MSG_INFO,
3134 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3135 }
3136
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003137#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003138 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3139 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3140 wpa_s->wpa_state < WPA_COMPLETED) {
3141 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3142 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003143 return 0;
3144 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003145#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003146
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003147 old_ap_scan = wpa_s->conf->ap_scan;
3148 wpa_s->conf->ap_scan = ap_scan;
3149
3150 if (old_ap_scan != wpa_s->conf->ap_scan)
3151 wpas_notify_ap_scan_changed(wpa_s);
3152
3153 return 0;
3154}
3155
3156
3157/**
3158 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3159 * @wpa_s: wpa_supplicant structure for a network interface
3160 * @expire_age: Expiration age in seconds
3161 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3162 *
3163 */
3164int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3165 unsigned int bss_expire_age)
3166{
3167 if (bss_expire_age < 10) {
3168 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3169 bss_expire_age);
3170 return -1;
3171 }
3172 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3173 bss_expire_age);
3174 wpa_s->conf->bss_expiration_age = bss_expire_age;
3175
3176 return 0;
3177}
3178
3179
3180/**
3181 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3182 * @wpa_s: wpa_supplicant structure for a network interface
3183 * @expire_count: number of scans after which an unseen BSS is reclaimed
3184 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3185 *
3186 */
3187int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3188 unsigned int bss_expire_count)
3189{
3190 if (bss_expire_count < 1) {
3191 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3192 bss_expire_count);
3193 return -1;
3194 }
3195 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3196 bss_expire_count);
3197 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3198
3199 return 0;
3200}
3201
3202
3203/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003204 * wpa_supplicant_set_scan_interval - Set scan interval
3205 * @wpa_s: wpa_supplicant structure for a network interface
3206 * @scan_interval: scan interval in seconds
3207 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3208 *
3209 */
3210int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3211 int scan_interval)
3212{
3213 if (scan_interval < 0) {
3214 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3215 scan_interval);
3216 return -1;
3217 }
3218 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3219 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003220 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003221
3222 return 0;
3223}
3224
3225
3226/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003227 * wpa_supplicant_set_debug_params - Set global debug params
3228 * @global: wpa_global structure
3229 * @debug_level: debug level
3230 * @debug_timestamp: determines if show timestamp in debug data
3231 * @debug_show_keys: determines if show keys in debug data
3232 * Returns: 0 if succeed or -1 if debug_level has wrong value
3233 */
3234int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3235 int debug_timestamp, int debug_show_keys)
3236{
3237
3238 int old_level, old_timestamp, old_show_keys;
3239
3240 /* check for allowed debuglevels */
3241 if (debug_level != MSG_EXCESSIVE &&
3242 debug_level != MSG_MSGDUMP &&
3243 debug_level != MSG_DEBUG &&
3244 debug_level != MSG_INFO &&
3245 debug_level != MSG_WARNING &&
3246 debug_level != MSG_ERROR)
3247 return -1;
3248
3249 old_level = wpa_debug_level;
3250 old_timestamp = wpa_debug_timestamp;
3251 old_show_keys = wpa_debug_show_keys;
3252
3253 wpa_debug_level = debug_level;
3254 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3255 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3256
3257 if (wpa_debug_level != old_level)
3258 wpas_notify_debug_level_changed(global);
3259 if (wpa_debug_timestamp != old_timestamp)
3260 wpas_notify_debug_timestamp_changed(global);
3261 if (wpa_debug_show_keys != old_show_keys)
3262 wpas_notify_debug_show_keys_changed(global);
3263
3264 return 0;
3265}
3266
3267
3268/**
3269 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3270 * @wpa_s: Pointer to wpa_supplicant data
3271 * Returns: A pointer to the current network structure or %NULL on failure
3272 */
3273struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3274{
3275 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003276 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003277 int res;
3278 size_t ssid_len;
3279 u8 bssid[ETH_ALEN];
3280 int wired;
3281
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003282 res = wpa_drv_get_ssid(wpa_s, ssid);
3283 if (res < 0) {
3284 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3285 "driver");
3286 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003287 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003288 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003289
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003290 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003291 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3292 "driver");
3293 return NULL;
3294 }
3295
3296 wired = wpa_s->conf->ap_scan == 0 &&
3297 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3298
3299 entry = wpa_s->conf->ssid;
3300 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003301 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003302 ((ssid_len == entry->ssid_len &&
3303 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3304 (!entry->bssid_set ||
3305 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3306 return entry;
3307#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003308 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003309 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3310 (entry->ssid == NULL || entry->ssid_len == 0) &&
3311 (!entry->bssid_set ||
3312 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3313 return entry;
3314#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003315
Dmitry Shmidt04949592012-07-19 12:16:46 -07003316 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003317 entry->ssid_len == 0 &&
3318 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3319 return entry;
3320
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003321 entry = entry->next;
3322 }
3323
3324 return NULL;
3325}
3326
3327
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003328static int select_driver(struct wpa_supplicant *wpa_s, int i)
3329{
3330 struct wpa_global *global = wpa_s->global;
3331
3332 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003333 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003334 if (global->drv_priv[i] == NULL) {
3335 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3336 "'%s'", wpa_drivers[i]->name);
3337 return -1;
3338 }
3339 }
3340
3341 wpa_s->driver = wpa_drivers[i];
3342 wpa_s->global_drv_priv = global->drv_priv[i];
3343
3344 return 0;
3345}
3346
3347
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003348static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3349 const char *name)
3350{
3351 int i;
3352 size_t len;
3353 const char *pos, *driver = name;
3354
3355 if (wpa_s == NULL)
3356 return -1;
3357
3358 if (wpa_drivers[0] == NULL) {
3359 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3360 "wpa_supplicant");
3361 return -1;
3362 }
3363
3364 if (name == NULL) {
3365 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003366 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003367 }
3368
3369 do {
3370 pos = os_strchr(driver, ',');
3371 if (pos)
3372 len = pos - driver;
3373 else
3374 len = os_strlen(driver);
3375
3376 for (i = 0; wpa_drivers[i]; i++) {
3377 if (os_strlen(wpa_drivers[i]->name) == len &&
3378 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003379 0) {
3380 /* First driver that succeeds wins */
3381 if (select_driver(wpa_s, i) == 0)
3382 return 0;
3383 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003384 }
3385
3386 driver = pos + 1;
3387 } while (pos);
3388
3389 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3390 return -1;
3391}
3392
3393
3394/**
3395 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3396 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3397 * with struct wpa_driver_ops::init()
3398 * @src_addr: Source address of the EAPOL frame
3399 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3400 * @len: Length of the EAPOL data
3401 *
3402 * This function is called for each received EAPOL frame. Most driver
3403 * interfaces rely on more generic OS mechanism for receiving frames through
3404 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3405 * take care of received EAPOL frames and deliver them to the core supplicant
3406 * code by calling this function.
3407 */
3408void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3409 const u8 *buf, size_t len)
3410{
3411 struct wpa_supplicant *wpa_s = ctx;
3412
3413 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3414 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3415
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003416#ifdef CONFIG_TESTING_OPTIONS
3417 if (wpa_s->ignore_auth_resp) {
3418 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3419 return;
3420 }
3421#endif /* CONFIG_TESTING_OPTIONS */
3422
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003423#ifdef CONFIG_PEERKEY
3424 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3425 wpa_s->current_ssid->peerkey &&
3426 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3427 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3428 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3429 return;
3430 }
3431#endif /* CONFIG_PEERKEY */
3432
Jouni Malinena05074c2012-12-21 21:35:35 +02003433 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3434 (wpa_s->last_eapol_matches_bssid &&
3435#ifdef CONFIG_AP
3436 !wpa_s->ap_iface &&
3437#endif /* CONFIG_AP */
3438 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003439 /*
3440 * There is possible race condition between receiving the
3441 * association event and the EAPOL frame since they are coming
3442 * through different paths from the driver. In order to avoid
3443 * issues in trying to process the EAPOL frame before receiving
3444 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003445 * the association event is received. This may also be needed in
3446 * driver-based roaming case, so also use src_addr != BSSID as a
3447 * trigger if we have previously confirmed that the
3448 * Authenticator uses BSSID as the src_addr (which is not the
3449 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003450 */
3451 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003452 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3453 wpa_supplicant_state_txt(wpa_s->wpa_state),
3454 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003455 wpabuf_free(wpa_s->pending_eapol_rx);
3456 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3457 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003458 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003459 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3460 ETH_ALEN);
3461 }
3462 return;
3463 }
3464
Jouni Malinena05074c2012-12-21 21:35:35 +02003465 wpa_s->last_eapol_matches_bssid =
3466 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3467
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468#ifdef CONFIG_AP
3469 if (wpa_s->ap_iface) {
3470 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3471 return;
3472 }
3473#endif /* CONFIG_AP */
3474
3475 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3476 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3477 "no key management is configured");
3478 return;
3479 }
3480
3481 if (wpa_s->eapol_received == 0 &&
3482 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3483 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3484 wpa_s->wpa_state != WPA_COMPLETED) &&
3485 (wpa_s->current_ssid == NULL ||
3486 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3487 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003488 int timeout = 10;
3489
3490 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3491 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3492 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3493 /* Use longer timeout for IEEE 802.1X/EAP */
3494 timeout = 70;
3495 }
3496
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003497#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003498 if (wpa_s->current_ssid && wpa_s->current_bss &&
3499 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3500 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3501 /*
3502 * Use shorter timeout if going through WPS AP iteration
3503 * for PIN config method with an AP that does not
3504 * advertise Selected Registrar.
3505 */
3506 struct wpabuf *wps_ie;
3507
3508 wps_ie = wpa_bss_get_vendor_ie_multi(
3509 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3510 if (wps_ie &&
3511 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3512 timeout = 10;
3513 wpabuf_free(wps_ie);
3514 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003515#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003516
3517 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518 }
3519 wpa_s->eapol_received++;
3520
3521 if (wpa_s->countermeasures) {
3522 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3523 "EAPOL packet");
3524 return;
3525 }
3526
3527#ifdef CONFIG_IBSS_RSN
3528 if (wpa_s->current_ssid &&
3529 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3530 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3531 return;
3532 }
3533#endif /* CONFIG_IBSS_RSN */
3534
3535 /* Source address of the incoming EAPOL frame could be compared to the
3536 * current BSSID. However, it is possible that a centralized
3537 * Authenticator could be using another MAC address than the BSSID of
3538 * an AP, so just allow any address to be used for now. The replies are
3539 * still sent to the current BSSID (if available), though. */
3540
3541 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3542 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3543 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3544 return;
3545 wpa_drv_poll(wpa_s);
3546 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3547 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3548 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3549 /*
3550 * Set portValid = TRUE here since we are going to skip 4-way
3551 * handshake processing which would normally set portValid. We
3552 * need this to allow the EAPOL state machines to be completed
3553 * without going through EAPOL-Key handshake.
3554 */
3555 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3556 }
3557}
3558
3559
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003560int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003561{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003562 if ((!wpa_s->p2p_mgmt ||
3563 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3564 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003565 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003566 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3567 wpa_drv_get_mac_addr(wpa_s),
3568 ETH_P_EAPOL,
3569 wpa_supplicant_rx_eapol, wpa_s, 0);
3570 if (wpa_s->l2 == NULL)
3571 return -1;
3572 } else {
3573 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3574 if (addr)
3575 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3576 }
3577
3578 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3579 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3580 return -1;
3581 }
3582
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003583 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3584
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003585 return 0;
3586}
3587
3588
Dmitry Shmidt04949592012-07-19 12:16:46 -07003589static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3590 const u8 *buf, size_t len)
3591{
3592 struct wpa_supplicant *wpa_s = ctx;
3593 const struct l2_ethhdr *eth;
3594
3595 if (len < sizeof(*eth))
3596 return;
3597 eth = (const struct l2_ethhdr *) buf;
3598
3599 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3600 !(eth->h_dest[0] & 0x01)) {
3601 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3602 " (bridge - not for this interface - ignore)",
3603 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3604 return;
3605 }
3606
3607 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3608 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3609 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3610 len - sizeof(*eth));
3611}
3612
3613
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003614/**
3615 * wpa_supplicant_driver_init - Initialize driver interface parameters
3616 * @wpa_s: Pointer to wpa_supplicant data
3617 * Returns: 0 on success, -1 on failure
3618 *
3619 * This function is called to initialize driver interface parameters.
3620 * wpa_drv_init() must have been called before this function to initialize the
3621 * driver interface.
3622 */
3623int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3624{
3625 static int interface_count = 0;
3626
3627 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3628 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003630 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3631 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003632 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003633 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3634
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003635 if (wpa_s->bridge_ifname[0]) {
3636 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3637 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003638 wpa_s->l2_br = l2_packet_init_bridge(
3639 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3640 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003641 if (wpa_s->l2_br == NULL) {
3642 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3643 "connection for the bridge interface '%s'",
3644 wpa_s->bridge_ifname);
3645 return -1;
3646 }
3647 }
3648
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003649 if (wpa_s->conf->ap_scan == 2 &&
3650 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3651 wpa_printf(MSG_INFO,
3652 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3653 }
3654
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003655 wpa_clear_keys(wpa_s, NULL);
3656
3657 /* Make sure that TKIP countermeasures are not left enabled (could
3658 * happen if wpa_supplicant is killed during countermeasures. */
3659 wpa_drv_set_countermeasures(wpa_s, 0);
3660
3661 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3662 wpa_drv_flush_pmkid(wpa_s);
3663
3664 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003665 wpa_s->prev_scan_wildcard = 0;
3666
Dmitry Shmidt04949592012-07-19 12:16:46 -07003667 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003668 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3669 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3670 interface_count = 0;
3671 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003672#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003673 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003674 wpa_supplicant_delayed_sched_scan(wpa_s,
3675 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003676 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003677 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003678 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003679#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003680 interface_count++;
3681 } else
3682 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3683
3684 return 0;
3685}
3686
3687
3688static int wpa_supplicant_daemon(const char *pid_file)
3689{
3690 wpa_printf(MSG_DEBUG, "Daemonize..");
3691 return os_daemonize(pid_file);
3692}
3693
3694
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003695static struct wpa_supplicant *
3696wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003697{
3698 struct wpa_supplicant *wpa_s;
3699
3700 wpa_s = os_zalloc(sizeof(*wpa_s));
3701 if (wpa_s == NULL)
3702 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003703 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003704 wpa_s->scan_interval = 5;
3705 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003706 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003707 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003708 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003709
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003710 dl_list_init(&wpa_s->bss_tmp_disallowed);
3711
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003712 return wpa_s;
3713}
3714
3715
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003716#ifdef CONFIG_HT_OVERRIDES
3717
3718static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3719 struct ieee80211_ht_capabilities *htcaps,
3720 struct ieee80211_ht_capabilities *htcaps_mask,
3721 const char *ht_mcs)
3722{
3723 /* parse ht_mcs into hex array */
3724 int i;
3725 const char *tmp = ht_mcs;
3726 char *end = NULL;
3727
3728 /* If ht_mcs is null, do not set anything */
3729 if (!ht_mcs)
3730 return 0;
3731
3732 /* This is what we are setting in the kernel */
3733 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3734
3735 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3736
3737 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3738 errno = 0;
3739 long v = strtol(tmp, &end, 16);
3740 if (errno == 0) {
3741 wpa_msg(wpa_s, MSG_DEBUG,
3742 "htcap value[%i]: %ld end: %p tmp: %p",
3743 i, v, end, tmp);
3744 if (end == tmp)
3745 break;
3746
3747 htcaps->supported_mcs_set[i] = v;
3748 tmp = end;
3749 } else {
3750 wpa_msg(wpa_s, MSG_ERROR,
3751 "Failed to parse ht-mcs: %s, error: %s\n",
3752 ht_mcs, strerror(errno));
3753 return -1;
3754 }
3755 }
3756
3757 /*
3758 * If we were able to parse any values, then set mask for the MCS set.
3759 */
3760 if (i) {
3761 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3762 IEEE80211_HT_MCS_MASK_LEN - 1);
3763 /* skip the 3 reserved bits */
3764 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3765 0x1f;
3766 }
3767
3768 return 0;
3769}
3770
3771
3772static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3773 struct ieee80211_ht_capabilities *htcaps,
3774 struct ieee80211_ht_capabilities *htcaps_mask,
3775 int disabled)
3776{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003777 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003778
3779 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3780
3781 if (disabled == -1)
3782 return 0;
3783
3784 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3785 htcaps_mask->ht_capabilities_info |= msk;
3786 if (disabled)
3787 htcaps->ht_capabilities_info &= msk;
3788 else
3789 htcaps->ht_capabilities_info |= msk;
3790
3791 return 0;
3792}
3793
3794
3795static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3796 struct ieee80211_ht_capabilities *htcaps,
3797 struct ieee80211_ht_capabilities *htcaps_mask,
3798 int factor)
3799{
3800 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3801
3802 if (factor == -1)
3803 return 0;
3804
3805 if (factor < 0 || factor > 3) {
3806 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3807 "Must be 0-3 or -1", factor);
3808 return -EINVAL;
3809 }
3810
3811 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3812 htcaps->a_mpdu_params &= ~0x3;
3813 htcaps->a_mpdu_params |= factor & 0x3;
3814
3815 return 0;
3816}
3817
3818
3819static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3820 struct ieee80211_ht_capabilities *htcaps,
3821 struct ieee80211_ht_capabilities *htcaps_mask,
3822 int density)
3823{
3824 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3825
3826 if (density == -1)
3827 return 0;
3828
3829 if (density < 0 || density > 7) {
3830 wpa_msg(wpa_s, MSG_ERROR,
3831 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3832 density);
3833 return -EINVAL;
3834 }
3835
3836 htcaps_mask->a_mpdu_params |= 0x1C;
3837 htcaps->a_mpdu_params &= ~(0x1C);
3838 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3839
3840 return 0;
3841}
3842
3843
3844static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3845 struct ieee80211_ht_capabilities *htcaps,
3846 struct ieee80211_ht_capabilities *htcaps_mask,
3847 int disabled)
3848{
3849 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003850 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3851 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003852
3853 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3854
3855 if (disabled)
3856 htcaps->ht_capabilities_info &= ~msk;
3857 else
3858 htcaps->ht_capabilities_info |= msk;
3859
3860 htcaps_mask->ht_capabilities_info |= msk;
3861
3862 return 0;
3863}
3864
3865
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003866static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3867 struct ieee80211_ht_capabilities *htcaps,
3868 struct ieee80211_ht_capabilities *htcaps_mask,
3869 int disabled)
3870{
3871 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003872 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3873 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003874
3875 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3876
3877 if (disabled)
3878 htcaps->ht_capabilities_info &= ~msk;
3879 else
3880 htcaps->ht_capabilities_info |= msk;
3881
3882 htcaps_mask->ht_capabilities_info |= msk;
3883
3884 return 0;
3885}
3886
3887
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003888static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3889 struct ieee80211_ht_capabilities *htcaps,
3890 struct ieee80211_ht_capabilities *htcaps_mask,
3891 int disabled)
3892{
3893 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003894 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003895
3896 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3897
3898 if (disabled)
3899 htcaps->ht_capabilities_info &= ~msk;
3900 else
3901 htcaps->ht_capabilities_info |= msk;
3902
3903 htcaps_mask->ht_capabilities_info |= msk;
3904
3905 return 0;
3906}
3907
3908
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003909void wpa_supplicant_apply_ht_overrides(
3910 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3911 struct wpa_driver_associate_params *params)
3912{
3913 struct ieee80211_ht_capabilities *htcaps;
3914 struct ieee80211_ht_capabilities *htcaps_mask;
3915
3916 if (!ssid)
3917 return;
3918
3919 params->disable_ht = ssid->disable_ht;
3920 if (!params->htcaps || !params->htcaps_mask)
3921 return;
3922
3923 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3924 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3925 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3926 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3927 ssid->disable_max_amsdu);
3928 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3929 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3930 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003931 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003932 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003933
3934 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003935 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003936 htcaps->ht_capabilities_info |= bit;
3937 htcaps_mask->ht_capabilities_info |= bit;
3938 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003939}
3940
3941#endif /* CONFIG_HT_OVERRIDES */
3942
3943
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003944#ifdef CONFIG_VHT_OVERRIDES
3945void wpa_supplicant_apply_vht_overrides(
3946 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3947 struct wpa_driver_associate_params *params)
3948{
3949 struct ieee80211_vht_capabilities *vhtcaps;
3950 struct ieee80211_vht_capabilities *vhtcaps_mask;
3951
3952 if (!ssid)
3953 return;
3954
3955 params->disable_vht = ssid->disable_vht;
3956
3957 vhtcaps = (void *) params->vhtcaps;
3958 vhtcaps_mask = (void *) params->vhtcaps_mask;
3959
3960 if (!vhtcaps || !vhtcaps_mask)
3961 return;
3962
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003963 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
3964 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003965
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003966#ifdef CONFIG_HT_OVERRIDES
3967 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003968 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3969 int max_ampdu;
3970
3971 max_ampdu = (ssid->vht_capa &
3972 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3973 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003974
3975 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3976 wpa_set_ampdu_factor(wpa_s,
3977 (void *) params->htcaps,
3978 (void *) params->htcaps_mask,
3979 max_ampdu);
3980 }
3981#endif /* CONFIG_HT_OVERRIDES */
3982
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003983#define OVERRIDE_MCS(i) \
3984 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3985 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003986 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003987 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003988 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
3989 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003990 } \
3991 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3992 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003993 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003994 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003995 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
3996 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003997 }
3998
3999 OVERRIDE_MCS(1);
4000 OVERRIDE_MCS(2);
4001 OVERRIDE_MCS(3);
4002 OVERRIDE_MCS(4);
4003 OVERRIDE_MCS(5);
4004 OVERRIDE_MCS(6);
4005 OVERRIDE_MCS(7);
4006 OVERRIDE_MCS(8);
4007}
4008#endif /* CONFIG_VHT_OVERRIDES */
4009
4010
Dmitry Shmidt04949592012-07-19 12:16:46 -07004011static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4012{
4013#ifdef PCSC_FUNCS
4014 size_t len;
4015
4016 if (!wpa_s->conf->pcsc_reader)
4017 return 0;
4018
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004019 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004020 if (!wpa_s->scard)
4021 return 1;
4022
4023 if (wpa_s->conf->pcsc_pin &&
4024 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4025 scard_deinit(wpa_s->scard);
4026 wpa_s->scard = NULL;
4027 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4028 return -1;
4029 }
4030
4031 len = sizeof(wpa_s->imsi) - 1;
4032 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4033 scard_deinit(wpa_s->scard);
4034 wpa_s->scard = NULL;
4035 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4036 return -1;
4037 }
4038 wpa_s->imsi[len] = '\0';
4039
4040 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4041
4042 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4043 wpa_s->imsi, wpa_s->mnc_len);
4044
4045 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4046 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4047#endif /* PCSC_FUNCS */
4048
4049 return 0;
4050}
4051
4052
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004053int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4054{
4055 char *val, *pos;
4056
4057 ext_password_deinit(wpa_s->ext_pw);
4058 wpa_s->ext_pw = NULL;
4059 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4060
4061 if (!wpa_s->conf->ext_password_backend)
4062 return 0;
4063
4064 val = os_strdup(wpa_s->conf->ext_password_backend);
4065 if (val == NULL)
4066 return -1;
4067 pos = os_strchr(val, ':');
4068 if (pos)
4069 *pos++ = '\0';
4070
4071 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4072
4073 wpa_s->ext_pw = ext_password_init(val, pos);
4074 os_free(val);
4075 if (wpa_s->ext_pw == NULL) {
4076 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4077 return -1;
4078 }
4079 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4080
4081 return 0;
4082}
4083
4084
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004085#ifdef CONFIG_FST
4086
4087static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4088{
4089 struct wpa_supplicant *wpa_s = ctx;
4090
4091 return (is_zero_ether_addr(wpa_s->bssid) ||
4092 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4093}
4094
4095
4096static void wpas_fst_get_channel_info_cb(void *ctx,
4097 enum hostapd_hw_mode *hw_mode,
4098 u8 *channel)
4099{
4100 struct wpa_supplicant *wpa_s = ctx;
4101
4102 if (wpa_s->current_bss) {
4103 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4104 channel);
4105 } else if (wpa_s->hw.num_modes) {
4106 *hw_mode = wpa_s->hw.modes[0].mode;
4107 } else {
4108 WPA_ASSERT(0);
4109 *hw_mode = 0;
4110 }
4111}
4112
4113
4114static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4115{
4116 struct wpa_supplicant *wpa_s = ctx;
4117
4118 *modes = wpa_s->hw.modes;
4119 return wpa_s->hw.num_modes;
4120}
4121
4122
4123static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4124{
4125 struct wpa_supplicant *wpa_s = ctx;
4126
4127 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4128 wpa_s->fst_ies = fst_ies;
4129}
4130
4131
4132static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4133{
4134 struct wpa_supplicant *wpa_s = ctx;
4135
4136 WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
4137 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
4138 wpa_s->own_addr, wpa_s->bssid,
4139 wpabuf_head(data), wpabuf_len(data),
4140 0);
4141}
4142
4143
4144static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4145{
4146 struct wpa_supplicant *wpa_s = ctx;
4147
4148 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4149 return wpa_s->received_mb_ies;
4150}
4151
4152
4153static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4154 const u8 *buf, size_t size)
4155{
4156 struct wpa_supplicant *wpa_s = ctx;
4157 struct mb_ies_info info;
4158
4159 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4160
4161 if (!mb_ies_info_by_ies(&info, buf, size)) {
4162 wpabuf_free(wpa_s->received_mb_ies);
4163 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4164 }
4165}
4166
4167
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004168static const u8 * wpas_fst_get_peer_first(void *ctx,
4169 struct fst_get_peer_ctx **get_ctx,
4170 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004171{
4172 struct wpa_supplicant *wpa_s = ctx;
4173
4174 *get_ctx = NULL;
4175 if (!is_zero_ether_addr(wpa_s->bssid))
4176 return (wpa_s->received_mb_ies || !mb_only) ?
4177 wpa_s->bssid : NULL;
4178 return NULL;
4179}
4180
4181
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004182static const u8 * wpas_fst_get_peer_next(void *ctx,
4183 struct fst_get_peer_ctx **get_ctx,
4184 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004185{
4186 return NULL;
4187}
4188
4189void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4190 struct fst_wpa_obj *iface_obj)
4191{
4192 iface_obj->ctx = wpa_s;
4193 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4194 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4195 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4196 iface_obj->set_ies = wpas_fst_set_ies_cb;
4197 iface_obj->send_action = wpas_fst_send_action_cb;
4198 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4199 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4200 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4201 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4202}
4203#endif /* CONFIG_FST */
4204
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004205static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004206 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004207{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004208 struct wowlan_triggers *triggers;
4209 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004210
4211 if (!wpa_s->conf->wowlan_triggers)
4212 return 0;
4213
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004214 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4215 if (triggers) {
4216 ret = wpa_drv_wowlan(wpa_s, triggers);
4217 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004218 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004219 return ret;
4220}
4221
4222
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004223enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004224{
4225 if (freq < 3000)
4226 return BAND_2_4_GHZ;
4227 if (freq > 50000)
4228 return BAND_60_GHZ;
4229 return BAND_5_GHZ;
4230}
4231
4232
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004233unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004234{
4235 int i;
4236 unsigned int band = 0;
4237
4238 if (freqs) {
4239 /* freqs are specified for the radio work */
4240 for (i = 0; freqs[i]; i++)
4241 band |= wpas_freq_to_band(freqs[i]);
4242 } else {
4243 /*
4244 * freqs are not specified, implies all
4245 * the supported freqs by HW
4246 */
4247 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4248 if (wpa_s->hw.modes[i].num_channels != 0) {
4249 if (wpa_s->hw.modes[i].mode ==
4250 HOSTAPD_MODE_IEEE80211B ||
4251 wpa_s->hw.modes[i].mode ==
4252 HOSTAPD_MODE_IEEE80211G)
4253 band |= BAND_2_4_GHZ;
4254 else if (wpa_s->hw.modes[i].mode ==
4255 HOSTAPD_MODE_IEEE80211A)
4256 band |= BAND_5_GHZ;
4257 else if (wpa_s->hw.modes[i].mode ==
4258 HOSTAPD_MODE_IEEE80211AD)
4259 band |= BAND_60_GHZ;
4260 else if (wpa_s->hw.modes[i].mode ==
4261 HOSTAPD_MODE_IEEE80211ANY)
4262 band = BAND_2_4_GHZ | BAND_5_GHZ |
4263 BAND_60_GHZ;
4264 }
4265 }
4266 }
4267
4268 return band;
4269}
4270
4271
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004272static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4273 const char *rn)
4274{
4275 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4276 struct wpa_radio *radio;
4277
4278 while (rn && iface) {
4279 radio = iface->radio;
4280 if (radio && os_strcmp(rn, radio->name) == 0) {
4281 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4282 wpa_s->ifname, rn);
4283 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4284 return radio;
4285 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004286
4287 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004288 }
4289
4290 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4291 wpa_s->ifname, rn ? rn : "N/A");
4292 radio = os_zalloc(sizeof(*radio));
4293 if (radio == NULL)
4294 return NULL;
4295
4296 if (rn)
4297 os_strlcpy(radio->name, rn, sizeof(radio->name));
4298 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004299 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004300 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4301
4302 return radio;
4303}
4304
4305
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004306static void radio_work_free(struct wpa_radio_work *work)
4307{
4308 if (work->wpa_s->scan_work == work) {
4309 /* This should not really happen. */
4310 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4311 work->type, work, work->started);
4312 work->wpa_s->scan_work = NULL;
4313 }
4314
4315#ifdef CONFIG_P2P
4316 if (work->wpa_s->p2p_scan_work == work) {
4317 /* This should not really happen. */
4318 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4319 work->type, work, work->started);
4320 work->wpa_s->p2p_scan_work = NULL;
4321 }
4322#endif /* CONFIG_P2P */
4323
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004324 if (work->started) {
4325 work->wpa_s->radio->num_active_works--;
4326 wpa_dbg(work->wpa_s, MSG_DEBUG,
4327 "radio_work_free('%s'@%p: num_active_works --> %u",
4328 work->type, work,
4329 work->wpa_s->radio->num_active_works);
4330 }
4331
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004332 dl_list_del(&work->list);
4333 os_free(work);
4334}
4335
4336
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004337static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4338{
4339 struct wpa_radio_work *active_work = NULL;
4340 struct wpa_radio_work *tmp;
4341
4342 /* Get the active work to know the type and band. */
4343 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4344 if (tmp->started) {
4345 active_work = tmp;
4346 break;
4347 }
4348 }
4349
4350 if (!active_work) {
4351 /* No active work, start one */
4352 radio->num_active_works = 0;
4353 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4354 list) {
4355 if (os_strcmp(tmp->type, "scan") == 0 &&
4356 radio->external_scan_running &&
4357 (((struct wpa_driver_scan_params *)
4358 tmp->ctx)->only_new_results ||
4359 tmp->wpa_s->clear_driver_scan_cache))
4360 continue;
4361 return tmp;
4362 }
4363 return NULL;
4364 }
4365
4366 if (os_strcmp(active_work->type, "sme-connect") == 0 ||
4367 os_strcmp(active_work->type, "connect") == 0) {
4368 /*
4369 * If the active work is either connect or sme-connect,
4370 * do not parallelize them with other radio works.
4371 */
4372 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4373 "Do not parallelize radio work with %s",
4374 active_work->type);
4375 return NULL;
4376 }
4377
4378 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4379 if (tmp->started)
4380 continue;
4381
4382 /*
4383 * If connect or sme-connect are enqueued, parallelize only
4384 * those operations ahead of them in the queue.
4385 */
4386 if (os_strcmp(tmp->type, "connect") == 0 ||
4387 os_strcmp(tmp->type, "sme-connect") == 0)
4388 break;
4389
4390 /*
4391 * Check that the radio works are distinct and
4392 * on different bands.
4393 */
4394 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4395 (active_work->bands != tmp->bands)) {
4396 /*
4397 * If a scan has to be scheduled through nl80211 scan
4398 * interface and if an external scan is already running,
4399 * do not schedule the scan since it is likely to get
4400 * rejected by kernel.
4401 */
4402 if (os_strcmp(tmp->type, "scan") == 0 &&
4403 radio->external_scan_running &&
4404 (((struct wpa_driver_scan_params *)
4405 tmp->ctx)->only_new_results ||
4406 tmp->wpa_s->clear_driver_scan_cache))
4407 continue;
4408
4409 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4410 "active_work:%s new_work:%s",
4411 active_work->type, tmp->type);
4412 return tmp;
4413 }
4414 }
4415
4416 /* Did not find a radio work to schedule in parallel. */
4417 return NULL;
4418}
4419
4420
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004421static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4422{
4423 struct wpa_radio *radio = eloop_ctx;
4424 struct wpa_radio_work *work;
4425 struct os_reltime now, diff;
4426 struct wpa_supplicant *wpa_s;
4427
4428 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004429 if (work == NULL) {
4430 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004431 return;
4432 }
4433
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004434 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4435 radio_list);
4436
4437 if (!(wpa_s &&
4438 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4439 if (work->started)
4440 return; /* already started and still in progress */
4441
4442 if (wpa_s && wpa_s->radio->external_scan_running) {
4443 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4444 return;
4445 }
4446 } else {
4447 work = NULL;
4448 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4449 /* get the work to schedule next */
4450 work = radio_work_get_next_work(radio);
4451 }
4452 if (!work)
4453 return;
4454 }
4455
4456 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004457 os_get_reltime(&now);
4458 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004459 wpa_dbg(wpa_s, MSG_DEBUG,
4460 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004461 work->type, work, diff.sec, diff.usec);
4462 work->started = 1;
4463 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004464 radio->num_active_works++;
4465
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004466 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004467
4468 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4469 radio->num_active_works < MAX_ACTIVE_WORKS)
4470 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004471}
4472
4473
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004474/*
4475 * This function removes both started and pending radio works running on
4476 * the provided interface's radio.
4477 * Prior to the removal of the radio work, its callback (cb) is called with
4478 * deinit set to be 1. Each work's callback is responsible for clearing its
4479 * internal data and restoring to a correct state.
4480 * @wpa_s: wpa_supplicant data
4481 * @type: type of works to be removed
4482 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4483 * this interface's works.
4484 */
4485void radio_remove_works(struct wpa_supplicant *wpa_s,
4486 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004487{
4488 struct wpa_radio_work *work, *tmp;
4489 struct wpa_radio *radio = wpa_s->radio;
4490
4491 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4492 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004493 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004494 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004495
4496 /* skip other ifaces' works */
4497 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004498 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004499
4500 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4501 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004502 work->cb(work, 1);
4503 radio_work_free(work);
4504 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004505
4506 /* in case we removed the started work */
4507 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004508}
4509
4510
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004511static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4512{
4513 struct wpa_radio *radio = wpa_s->radio;
4514
4515 if (!radio)
4516 return;
4517
4518 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4519 wpa_s->ifname, radio->name);
4520 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004521 radio_remove_works(wpa_s, NULL, 0);
4522 wpa_s->radio = NULL;
4523 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004524 return; /* Interfaces remain for this radio */
4525
4526 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004527 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004528 os_free(radio);
4529}
4530
4531
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004532void radio_work_check_next(struct wpa_supplicant *wpa_s)
4533{
4534 struct wpa_radio *radio = wpa_s->radio;
4535
4536 if (dl_list_empty(&radio->work))
4537 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004538 if (wpa_s->ext_work_in_progress) {
4539 wpa_printf(MSG_DEBUG,
4540 "External radio work in progress - delay start of pending item");
4541 return;
4542 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004543 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4544 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4545}
4546
4547
4548/**
4549 * radio_add_work - Add a radio work item
4550 * @wpa_s: Pointer to wpa_supplicant data
4551 * @freq: Frequency of the offchannel operation in MHz or 0
4552 * @type: Unique identifier for each type of work
4553 * @next: Force as the next work to be executed
4554 * @cb: Callback function for indicating when radio is available
4555 * @ctx: Context pointer for the work (work->ctx in cb())
4556 * Returns: 0 on success, -1 on failure
4557 *
4558 * This function is used to request time for an operation that requires
4559 * exclusive radio control. Once the radio is available, the registered callback
4560 * function will be called. radio_work_done() must be called once the exclusive
4561 * radio operation has been completed, so that the radio is freed for other
4562 * operations. The special case of deinit=1 is used to free the context data
4563 * during interface removal. That does not allow the callback function to start
4564 * the radio operation, i.e., it must free any resources allocated for the radio
4565 * work and return.
4566 *
4567 * The @freq parameter can be used to indicate a single channel on which the
4568 * offchannel operation will occur. This may allow multiple radio work
4569 * operations to be performed in parallel if they apply for the same channel.
4570 * Setting this to 0 indicates that the work item may use multiple channels or
4571 * requires exclusive control of the radio.
4572 */
4573int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4574 const char *type, int next,
4575 void (*cb)(struct wpa_radio_work *work, int deinit),
4576 void *ctx)
4577{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004578 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004579 struct wpa_radio_work *work;
4580 int was_empty;
4581
4582 work = os_zalloc(sizeof(*work));
4583 if (work == NULL)
4584 return -1;
4585 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4586 os_get_reltime(&work->time);
4587 work->freq = freq;
4588 work->type = type;
4589 work->wpa_s = wpa_s;
4590 work->cb = cb;
4591 work->ctx = ctx;
4592
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004593 if (freq)
4594 work->bands = wpas_freq_to_band(freq);
4595 else if (os_strcmp(type, "scan") == 0 ||
4596 os_strcmp(type, "p2p-scan") == 0)
4597 work->bands = wpas_get_bands(wpa_s,
4598 ((struct wpa_driver_scan_params *)
4599 ctx)->freqs);
4600 else
4601 work->bands = wpas_get_bands(wpa_s, NULL);
4602
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004603 was_empty = dl_list_empty(&wpa_s->radio->work);
4604 if (next)
4605 dl_list_add(&wpa_s->radio->work, &work->list);
4606 else
4607 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4608 if (was_empty) {
4609 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4610 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004611 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4612 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4613 wpa_dbg(wpa_s, MSG_DEBUG,
4614 "Try to schedule a radio work (num_active_works=%u)",
4615 radio->num_active_works);
4616 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004617 }
4618
4619 return 0;
4620}
4621
4622
4623/**
4624 * radio_work_done - Indicate that a radio work item has been completed
4625 * @work: Completed work
4626 *
4627 * This function is called once the callback function registered with
4628 * radio_add_work() has completed its work.
4629 */
4630void radio_work_done(struct wpa_radio_work *work)
4631{
4632 struct wpa_supplicant *wpa_s = work->wpa_s;
4633 struct os_reltime now, diff;
4634 unsigned int started = work->started;
4635
4636 os_get_reltime(&now);
4637 os_reltime_sub(&now, &work->time, &diff);
4638 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4639 work->type, work, started ? "done" : "canceled",
4640 diff.sec, diff.usec);
4641 radio_work_free(work);
4642 if (started)
4643 radio_work_check_next(wpa_s);
4644}
4645
4646
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004647struct wpa_radio_work *
4648radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004649{
4650 struct wpa_radio_work *work;
4651 struct wpa_radio *radio = wpa_s->radio;
4652
4653 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4654 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004655 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004656 }
4657
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004658 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004659}
4660
4661
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004662static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4663 struct wpa_interface *iface)
4664{
4665 const char *ifname, *driver, *rn;
4666
4667 driver = iface->driver;
4668next_driver:
4669 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4670 return -1;
4671
4672 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4673 if (wpa_s->drv_priv == NULL) {
4674 const char *pos;
4675 pos = driver ? os_strchr(driver, ',') : NULL;
4676 if (pos) {
4677 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4678 "driver interface - try next driver wrapper");
4679 driver = pos + 1;
4680 goto next_driver;
4681 }
4682 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4683 "interface");
4684 return -1;
4685 }
4686 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4687 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4688 "driver_param '%s'", wpa_s->conf->driver_param);
4689 return -1;
4690 }
4691
4692 ifname = wpa_drv_get_ifname(wpa_s);
4693 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4694 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4695 "interface name with '%s'", ifname);
4696 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4697 }
4698
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004699 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004700 if (rn && rn[0] == '\0')
4701 rn = NULL;
4702
4703 wpa_s->radio = radio_add_interface(wpa_s, rn);
4704 if (wpa_s->radio == NULL)
4705 return -1;
4706
4707 return 0;
4708}
4709
4710
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004711static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4712 struct wpa_interface *iface)
4713{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004714 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004715 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004716
4717 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4718 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4719 iface->confname ? iface->confname : "N/A",
4720 iface->driver ? iface->driver : "default",
4721 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4722 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4723
4724 if (iface->confname) {
4725#ifdef CONFIG_BACKEND_FILE
4726 wpa_s->confname = os_rel2abs_path(iface->confname);
4727 if (wpa_s->confname == NULL) {
4728 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4729 "for configuration file '%s'.",
4730 iface->confname);
4731 return -1;
4732 }
4733 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4734 iface->confname, wpa_s->confname);
4735#else /* CONFIG_BACKEND_FILE */
4736 wpa_s->confname = os_strdup(iface->confname);
4737#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004738 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004739 if (wpa_s->conf == NULL) {
4740 wpa_printf(MSG_ERROR, "Failed to read or parse "
4741 "configuration '%s'.", wpa_s->confname);
4742 return -1;
4743 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004744 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4745 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004746
4747 /*
4748 * Override ctrl_interface and driver_param if set on command
4749 * line.
4750 */
4751 if (iface->ctrl_interface) {
4752 os_free(wpa_s->conf->ctrl_interface);
4753 wpa_s->conf->ctrl_interface =
4754 os_strdup(iface->ctrl_interface);
4755 }
4756
4757 if (iface->driver_param) {
4758 os_free(wpa_s->conf->driver_param);
4759 wpa_s->conf->driver_param =
4760 os_strdup(iface->driver_param);
4761 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004762
4763 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4764 os_free(wpa_s->conf->ctrl_interface);
4765 wpa_s->conf->ctrl_interface = NULL;
4766 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004767 } else
4768 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4769 iface->driver_param);
4770
4771 if (wpa_s->conf == NULL) {
4772 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4773 return -1;
4774 }
4775
4776 if (iface->ifname == NULL) {
4777 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4778 return -1;
4779 }
4780 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4781 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4782 iface->ifname);
4783 return -1;
4784 }
4785 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4786
4787 if (iface->bridge_ifname) {
4788 if (os_strlen(iface->bridge_ifname) >=
4789 sizeof(wpa_s->bridge_ifname)) {
4790 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4791 "name '%s'.", iface->bridge_ifname);
4792 return -1;
4793 }
4794 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4795 sizeof(wpa_s->bridge_ifname));
4796 }
4797
4798 /* RSNA Supplicant Key Management - INITIALIZE */
4799 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4800 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4801
4802 /* Initialize driver interface and register driver event handler before
4803 * L2 receive handler so that association events are processed before
4804 * EAPOL-Key packets if both become available for the same select()
4805 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004806 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004807 return -1;
4808
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004809 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4810 return -1;
4811
4812 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4813 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4814 NULL);
4815 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4816
4817 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4818 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4819 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4820 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4821 "dot11RSNAConfigPMKLifetime");
4822 return -1;
4823 }
4824
4825 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4826 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4827 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4828 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4829 "dot11RSNAConfigPMKReauthThreshold");
4830 return -1;
4831 }
4832
4833 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4834 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4835 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4836 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4837 "dot11RSNAConfigSATimeout");
4838 return -1;
4839 }
4840
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004841 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4842 &wpa_s->hw.num_modes,
4843 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004844 if (wpa_s->hw.modes) {
4845 u16 i;
4846
4847 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4848 if (wpa_s->hw.modes[i].vht_capab) {
4849 wpa_s->hw_capab = CAPAB_VHT;
4850 break;
4851 }
4852
4853 if (wpa_s->hw.modes[i].ht_capab &
4854 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4855 wpa_s->hw_capab = CAPAB_HT40;
4856 else if (wpa_s->hw.modes[i].ht_capab &&
4857 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4858 wpa_s->hw_capab = CAPAB_HT;
4859 }
4860 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004861
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004862 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4863 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004864 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004865 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004866 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004867 wpa_s->drv_smps_modes = capa.smps_modes;
4868 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004869 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004870 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004871 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004872 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
4873 wpa_s->max_sched_scan_plan_interval =
4874 capa.max_sched_scan_plan_interval;
4875 wpa_s->max_sched_scan_plan_iterations =
4876 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004877 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4878 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004879 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4880 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004881 wpa_s->extended_capa = capa.extended_capa;
4882 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4883 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004884 wpa_s->num_multichan_concurrent =
4885 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004886 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4887
4888 if (capa.mac_addr_rand_scan_supported)
4889 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4890 if (wpa_s->sched_scan_supported &&
4891 capa.mac_addr_rand_sched_scan_supported)
4892 wpa_s->mac_addr_rand_supported |=
4893 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004894 }
4895 if (wpa_s->max_remain_on_chan == 0)
4896 wpa_s->max_remain_on_chan = 1000;
4897
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004898 /*
4899 * Only take p2p_mgmt parameters when P2P Device is supported.
4900 * Doing it here as it determines whether l2_packet_init() will be done
4901 * during wpa_supplicant_driver_init().
4902 */
4903 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4904 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4905 else
4906 iface->p2p_mgmt = 1;
4907
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004908 if (wpa_s->num_multichan_concurrent == 0)
4909 wpa_s->num_multichan_concurrent = 1;
4910
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004911 if (wpa_supplicant_driver_init(wpa_s) < 0)
4912 return -1;
4913
4914#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004915 if ((!iface->p2p_mgmt ||
4916 !(wpa_s->drv_flags &
4917 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4918 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004919 return -1;
4920#endif /* CONFIG_TDLS */
4921
4922 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4923 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4924 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4925 return -1;
4926 }
4927
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004928#ifdef CONFIG_FST
4929 if (wpa_s->conf->fst_group_id) {
4930 struct fst_iface_cfg cfg;
4931 struct fst_wpa_obj iface_obj;
4932
4933 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4934 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4935 sizeof(cfg.group_id));
4936 cfg.priority = wpa_s->conf->fst_priority;
4937 cfg.llt = wpa_s->conf->fst_llt;
4938
4939 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4940 &iface_obj, &cfg);
4941 if (!wpa_s->fst) {
4942 wpa_msg(wpa_s, MSG_ERROR,
4943 "FST: Cannot attach iface %s to group %s",
4944 wpa_s->ifname, cfg.group_id);
4945 return -1;
4946 }
4947 }
4948#endif /* CONFIG_FST */
4949
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004950 if (wpas_wps_init(wpa_s))
4951 return -1;
4952
4953 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4954 return -1;
4955 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4956
4957 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4958 if (wpa_s->ctrl_iface == NULL) {
4959 wpa_printf(MSG_ERROR,
4960 "Failed to initialize control interface '%s'.\n"
4961 "You may have another wpa_supplicant process "
4962 "already running or the file was\n"
4963 "left by an unclean termination of wpa_supplicant "
4964 "in which case you will need\n"
4965 "to manually remove this file before starting "
4966 "wpa_supplicant again.\n",
4967 wpa_s->conf->ctrl_interface);
4968 return -1;
4969 }
4970
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004971 wpa_s->gas = gas_query_init(wpa_s);
4972 if (wpa_s->gas == NULL) {
4973 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4974 return -1;
4975 }
4976
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004977 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004978 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4979 return -1;
4980 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004981
4982 if (wpa_bss_init(wpa_s) < 0)
4983 return -1;
4984
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004985 /*
4986 * Set Wake-on-WLAN triggers, if configured.
4987 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4988 * have effect anyway when the interface is down).
4989 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004990 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004991 return -1;
4992
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004993#ifdef CONFIG_EAP_PROXY
4994{
4995 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004996 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4997 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004998 if (wpa_s->mnc_len > 0) {
4999 wpa_s->imsi[len] = '\0';
5000 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5001 wpa_s->imsi, wpa_s->mnc_len);
5002 } else {
5003 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5004 }
5005}
5006#endif /* CONFIG_EAP_PROXY */
5007
Dmitry Shmidt04949592012-07-19 12:16:46 -07005008 if (pcsc_reader_init(wpa_s) < 0)
5009 return -1;
5010
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005011 if (wpas_init_ext_pw(wpa_s) < 0)
5012 return -1;
5013
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005014 wpas_rrm_reset(wpa_s);
5015
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005016 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5017
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005018#ifdef CONFIG_HS20
5019 hs20_init(wpa_s);
5020#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005021#ifdef CONFIG_MBO
5022 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5023#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005024
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005025 wpa_supplicant_set_default_scan_ies(wpa_s);
5026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005027 return 0;
5028}
5029
5030
5031static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005032 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005033{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005034 struct wpa_global *global = wpa_s->global;
5035 struct wpa_supplicant *iface, *prev;
5036
5037 if (wpa_s == wpa_s->parent)
5038 wpas_p2p_group_remove(wpa_s, "*");
5039
5040 iface = global->ifaces;
5041 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005042 if (iface->p2pdev == wpa_s)
5043 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005044 if (iface == wpa_s || iface->parent != wpa_s) {
5045 iface = iface->next;
5046 continue;
5047 }
5048 wpa_printf(MSG_DEBUG,
5049 "Remove remaining child interface %s from parent %s",
5050 iface->ifname, wpa_s->ifname);
5051 prev = iface;
5052 iface = iface->next;
5053 wpa_supplicant_remove_iface(global, prev, terminate);
5054 }
5055
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005056 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005057 if (wpa_s->drv_priv) {
5058 wpa_supplicant_deauthenticate(wpa_s,
5059 WLAN_REASON_DEAUTH_LEAVING);
5060
5061 wpa_drv_set_countermeasures(wpa_s, 0);
5062 wpa_clear_keys(wpa_s, NULL);
5063 }
5064
5065 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005066 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005067
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005068 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005069 radio_remove_interface(wpa_s);
5070
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005071#ifdef CONFIG_FST
5072 if (wpa_s->fst) {
5073 fst_detach(wpa_s->fst);
5074 wpa_s->fst = NULL;
5075 }
5076 if (wpa_s->received_mb_ies) {
5077 wpabuf_free(wpa_s->received_mb_ies);
5078 wpa_s->received_mb_ies = NULL;
5079 }
5080#endif /* CONFIG_FST */
5081
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005082 if (wpa_s->drv_priv)
5083 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005084
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005085 if (notify)
5086 wpas_notify_iface_removed(wpa_s);
5087
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005088 if (terminate)
5089 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005090
5091 if (wpa_s->ctrl_iface) {
5092 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5093 wpa_s->ctrl_iface = NULL;
5094 }
5095
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005096#ifdef CONFIG_MESH
5097 if (wpa_s->ifmsh) {
5098 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5099 wpa_s->ifmsh = NULL;
5100 }
5101#endif /* CONFIG_MESH */
5102
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005103 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005104 wpa_config_free(wpa_s->conf);
5105 wpa_s->conf = NULL;
5106 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005107
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005108 os_free(wpa_s->ssids_from_scan_req);
5109
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005110 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005111}
5112
5113
Dmitry Shmidte4663042016-04-04 10:07:49 -07005114#ifdef CONFIG_MATCH_IFACE
5115
5116/**
5117 * wpa_supplicant_match_iface - Match an interface description to a name
5118 * @global: Pointer to global data from wpa_supplicant_init()
5119 * @ifname: Name of the interface to match
5120 * Returns: Pointer to the created interface description or %NULL on failure
5121 */
5122struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5123 const char *ifname)
5124{
5125 int i;
5126 struct wpa_interface *iface, *miface;
5127
5128 for (i = 0; i < global->params.match_iface_count; i++) {
5129 miface = &global->params.match_ifaces[i];
5130 if (!miface->ifname ||
5131 fnmatch(miface->ifname, ifname, 0) == 0) {
5132 iface = os_zalloc(sizeof(*iface));
5133 if (!iface)
5134 return NULL;
5135 *iface = *miface;
5136 iface->ifname = ifname;
5137 return iface;
5138 }
5139 }
5140
5141 return NULL;
5142}
5143
5144
5145/**
5146 * wpa_supplicant_match_existing - Match existing interfaces
5147 * @global: Pointer to global data from wpa_supplicant_init()
5148 * Returns: 0 on success, -1 on failure
5149 */
5150static int wpa_supplicant_match_existing(struct wpa_global *global)
5151{
5152 struct if_nameindex *ifi, *ifp;
5153 struct wpa_supplicant *wpa_s;
5154 struct wpa_interface *iface;
5155
5156 ifp = if_nameindex();
5157 if (!ifp) {
5158 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5159 return -1;
5160 }
5161
5162 for (ifi = ifp; ifi->if_name; ifi++) {
5163 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5164 if (wpa_s)
5165 continue;
5166 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5167 if (iface) {
5168 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5169 os_free(iface);
5170 if (wpa_s)
5171 wpa_s->matched = 1;
5172 }
5173 }
5174
5175 if_freenameindex(ifp);
5176 return 0;
5177}
5178
5179#endif /* CONFIG_MATCH_IFACE */
5180
5181
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005182/**
5183 * wpa_supplicant_add_iface - Add a new network interface
5184 * @global: Pointer to global data from wpa_supplicant_init()
5185 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005186 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005187 * Returns: Pointer to the created interface or %NULL on failure
5188 *
5189 * This function is used to add new network interfaces for %wpa_supplicant.
5190 * This can be called before wpa_supplicant_run() to add interfaces before the
5191 * main event loop has been started. In addition, new interfaces can be added
5192 * dynamically while %wpa_supplicant is already running. This could happen,
5193 * e.g., when a hotplug network adapter is inserted.
5194 */
5195struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005196 struct wpa_interface *iface,
5197 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005198{
5199 struct wpa_supplicant *wpa_s;
5200 struct wpa_interface t_iface;
5201 struct wpa_ssid *ssid;
5202
5203 if (global == NULL || iface == NULL)
5204 return NULL;
5205
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005206 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005207 if (wpa_s == NULL)
5208 return NULL;
5209
5210 wpa_s->global = global;
5211
5212 t_iface = *iface;
5213 if (global->params.override_driver) {
5214 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5215 "('%s' -> '%s')",
5216 iface->driver, global->params.override_driver);
5217 t_iface.driver = global->params.override_driver;
5218 }
5219 if (global->params.override_ctrl_interface) {
5220 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5221 "ctrl_interface ('%s' -> '%s')",
5222 iface->ctrl_interface,
5223 global->params.override_ctrl_interface);
5224 t_iface.ctrl_interface =
5225 global->params.override_ctrl_interface;
5226 }
5227 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5228 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5229 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005230 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005231 return NULL;
5232 }
5233
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005234 /* Notify the control interfaces about new iface */
5235 if (wpas_notify_iface_added(wpa_s)) {
5236 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5237 return NULL;
5238 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005239
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005240 /* Notify the control interfaces about new networks for non p2p mgmt
5241 * ifaces. */
5242 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005243 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5244 wpas_notify_network_added(wpa_s, ssid);
5245 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005246
5247 wpa_s->next = global->ifaces;
5248 global->ifaces = wpa_s;
5249
5250 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005251 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005252
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005253#ifdef CONFIG_P2P
5254 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005255 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005256 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005257 wpas_p2p_add_p2pdev_interface(
5258 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005259 wpa_printf(MSG_INFO,
5260 "P2P: Failed to enable P2P Device interface");
5261 /* Try to continue without. P2P will be disabled. */
5262 }
5263#endif /* CONFIG_P2P */
5264
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005265 return wpa_s;
5266}
5267
5268
5269/**
5270 * wpa_supplicant_remove_iface - Remove a network interface
5271 * @global: Pointer to global data from wpa_supplicant_init()
5272 * @wpa_s: Pointer to the network interface to be removed
5273 * Returns: 0 if interface was removed, -1 if interface was not found
5274 *
5275 * This function can be used to dynamically remove network interfaces from
5276 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5277 * addition, this function is used to remove all remaining interfaces when
5278 * %wpa_supplicant is terminated.
5279 */
5280int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005281 struct wpa_supplicant *wpa_s,
5282 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005283{
5284 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005285#ifdef CONFIG_MESH
5286 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5287 char *ifname = NULL;
5288#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005289
5290 /* Remove interface from the global list of interfaces */
5291 prev = global->ifaces;
5292 if (prev == wpa_s) {
5293 global->ifaces = wpa_s->next;
5294 } else {
5295 while (prev && prev->next != wpa_s)
5296 prev = prev->next;
5297 if (prev == NULL)
5298 return -1;
5299 prev->next = wpa_s->next;
5300 }
5301
5302 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5303
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005304#ifdef CONFIG_MESH
5305 if (mesh_if_created) {
5306 ifname = os_strdup(wpa_s->ifname);
5307 if (ifname == NULL) {
5308 wpa_dbg(wpa_s, MSG_ERROR,
5309 "mesh: Failed to malloc ifname");
5310 return -1;
5311 }
5312 }
5313#endif /* CONFIG_MESH */
5314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005315 if (global->p2p_group_formation == wpa_s)
5316 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005317 if (global->p2p_invite_group == wpa_s)
5318 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005319 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005320
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005321#ifdef CONFIG_MESH
5322 if (mesh_if_created) {
5323 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
5324 os_free(ifname);
5325 }
5326#endif /* CONFIG_MESH */
5327
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005328 return 0;
5329}
5330
5331
5332/**
5333 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5334 * @wpa_s: Pointer to the network interface
5335 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5336 */
5337const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5338{
5339 const char *eapol_method;
5340
5341 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5342 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5343 return "NO-EAP";
5344 }
5345
5346 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5347 if (eapol_method == NULL)
5348 return "UNKNOWN-EAP";
5349
5350 return eapol_method;
5351}
5352
5353
5354/**
5355 * wpa_supplicant_get_iface - Get a new network interface
5356 * @global: Pointer to global data from wpa_supplicant_init()
5357 * @ifname: Interface name
5358 * Returns: Pointer to the interface or %NULL if not found
5359 */
5360struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5361 const char *ifname)
5362{
5363 struct wpa_supplicant *wpa_s;
5364
5365 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5366 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5367 return wpa_s;
5368 }
5369 return NULL;
5370}
5371
5372
5373#ifndef CONFIG_NO_WPA_MSG
5374static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5375{
5376 struct wpa_supplicant *wpa_s = ctx;
5377 if (wpa_s == NULL)
5378 return NULL;
5379 return wpa_s->ifname;
5380}
5381#endif /* CONFIG_NO_WPA_MSG */
5382
5383
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005384#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5385#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5386#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5387
5388/* Periodic cleanup tasks */
5389static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5390{
5391 struct wpa_global *global = eloop_ctx;
5392 struct wpa_supplicant *wpa_s;
5393
5394 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5395 wpas_periodic, global, NULL);
5396
5397#ifdef CONFIG_P2P
5398 if (global->p2p)
5399 p2p_expire_peers(global->p2p);
5400#endif /* CONFIG_P2P */
5401
5402 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5403 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5404#ifdef CONFIG_AP
5405 ap_periodic(wpa_s);
5406#endif /* CONFIG_AP */
5407 }
5408}
5409
5410
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005411/**
5412 * wpa_supplicant_init - Initialize %wpa_supplicant
5413 * @params: Parameters for %wpa_supplicant
5414 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5415 *
5416 * This function is used to initialize %wpa_supplicant. After successful
5417 * initialization, the returned data pointer can be used to add and remove
5418 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5419 */
5420struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5421{
5422 struct wpa_global *global;
5423 int ret, i;
5424
5425 if (params == NULL)
5426 return NULL;
5427
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005428#ifdef CONFIG_DRIVER_NDIS
5429 {
5430 void driver_ndis_init_ops(void);
5431 driver_ndis_init_ops();
5432 }
5433#endif /* CONFIG_DRIVER_NDIS */
5434
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005435#ifndef CONFIG_NO_WPA_MSG
5436 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5437#endif /* CONFIG_NO_WPA_MSG */
5438
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005439 if (params->wpa_debug_file_path)
5440 wpa_debug_open_file(params->wpa_debug_file_path);
5441 else
5442 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005443 if (params->wpa_debug_syslog)
5444 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005445 if (params->wpa_debug_tracing) {
5446 ret = wpa_debug_open_linux_tracing();
5447 if (ret) {
5448 wpa_printf(MSG_ERROR,
5449 "Failed to enable trace logging");
5450 return NULL;
5451 }
5452 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005453
5454 ret = eap_register_methods();
5455 if (ret) {
5456 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5457 if (ret == -2)
5458 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5459 "the same EAP type.");
5460 return NULL;
5461 }
5462
5463 global = os_zalloc(sizeof(*global));
5464 if (global == NULL)
5465 return NULL;
5466 dl_list_init(&global->p2p_srv_bonjour);
5467 dl_list_init(&global->p2p_srv_upnp);
5468 global->params.daemonize = params->daemonize;
5469 global->params.wait_for_monitor = params->wait_for_monitor;
5470 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5471 if (params->pid_file)
5472 global->params.pid_file = os_strdup(params->pid_file);
5473 if (params->ctrl_interface)
5474 global->params.ctrl_interface =
5475 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005476 if (params->ctrl_interface_group)
5477 global->params.ctrl_interface_group =
5478 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005479 if (params->override_driver)
5480 global->params.override_driver =
5481 os_strdup(params->override_driver);
5482 if (params->override_ctrl_interface)
5483 global->params.override_ctrl_interface =
5484 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005485#ifdef CONFIG_MATCH_IFACE
5486 global->params.match_iface_count = params->match_iface_count;
5487 if (params->match_iface_count) {
5488 global->params.match_ifaces =
5489 os_calloc(params->match_iface_count,
5490 sizeof(struct wpa_interface));
5491 os_memcpy(global->params.match_ifaces,
5492 params->match_ifaces,
5493 params->match_iface_count *
5494 sizeof(struct wpa_interface));
5495 }
5496#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005497#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005498 if (params->conf_p2p_dev)
5499 global->params.conf_p2p_dev =
5500 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005501#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005502 wpa_debug_level = global->params.wpa_debug_level =
5503 params->wpa_debug_level;
5504 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5505 params->wpa_debug_show_keys;
5506 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5507 params->wpa_debug_timestamp;
5508
5509 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5510
5511 if (eloop_init()) {
5512 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5513 wpa_supplicant_deinit(global);
5514 return NULL;
5515 }
5516
Jouni Malinen75ecf522011-06-27 15:19:46 -07005517 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005518
5519 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5520 if (global->ctrl_iface == NULL) {
5521 wpa_supplicant_deinit(global);
5522 return NULL;
5523 }
5524
5525 if (wpas_notify_supplicant_initialized(global)) {
5526 wpa_supplicant_deinit(global);
5527 return NULL;
5528 }
5529
5530 for (i = 0; wpa_drivers[i]; i++)
5531 global->drv_count++;
5532 if (global->drv_count == 0) {
5533 wpa_printf(MSG_ERROR, "No drivers enabled");
5534 wpa_supplicant_deinit(global);
5535 return NULL;
5536 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005537 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005538 if (global->drv_priv == NULL) {
5539 wpa_supplicant_deinit(global);
5540 return NULL;
5541 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005542
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005543#ifdef CONFIG_WIFI_DISPLAY
5544 if (wifi_display_init(global) < 0) {
5545 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5546 wpa_supplicant_deinit(global);
5547 return NULL;
5548 }
5549#endif /* CONFIG_WIFI_DISPLAY */
5550
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005551 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5552 wpas_periodic, global, NULL);
5553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005554 return global;
5555}
5556
5557
5558/**
5559 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5560 * @global: Pointer to global data from wpa_supplicant_init()
5561 * Returns: 0 after successful event loop run, -1 on failure
5562 *
5563 * This function starts the main event loop and continues running as long as
5564 * there are any remaining events. In most cases, this function is running as
5565 * long as the %wpa_supplicant process in still in use.
5566 */
5567int wpa_supplicant_run(struct wpa_global *global)
5568{
5569 struct wpa_supplicant *wpa_s;
5570
5571 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005572 (wpa_supplicant_daemon(global->params.pid_file) ||
5573 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005574 return -1;
5575
Dmitry Shmidte4663042016-04-04 10:07:49 -07005576#ifdef CONFIG_MATCH_IFACE
5577 if (wpa_supplicant_match_existing(global))
5578 return -1;
5579#endif
5580
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005581 if (global->params.wait_for_monitor) {
5582 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005583 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005584 wpa_supplicant_ctrl_iface_wait(
5585 wpa_s->ctrl_iface);
5586 }
5587
5588 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5589 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5590
5591 eloop_run();
5592
5593 return 0;
5594}
5595
5596
5597/**
5598 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5599 * @global: Pointer to global data from wpa_supplicant_init()
5600 *
5601 * This function is called to deinitialize %wpa_supplicant and to free all
5602 * allocated resources. Remaining network interfaces will also be removed.
5603 */
5604void wpa_supplicant_deinit(struct wpa_global *global)
5605{
5606 int i;
5607
5608 if (global == NULL)
5609 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005610
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005611 eloop_cancel_timeout(wpas_periodic, global, NULL);
5612
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005613#ifdef CONFIG_WIFI_DISPLAY
5614 wifi_display_deinit(global);
5615#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005616
5617 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005618 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005619
5620 if (global->ctrl_iface)
5621 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5622
5623 wpas_notify_supplicant_deinitialized(global);
5624
5625 eap_peer_unregister_methods();
5626#ifdef CONFIG_AP
5627 eap_server_unregister_methods();
5628#endif /* CONFIG_AP */
5629
5630 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5631 if (!global->drv_priv[i])
5632 continue;
5633 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5634 }
5635 os_free(global->drv_priv);
5636
5637 random_deinit();
5638
5639 eloop_destroy();
5640
5641 if (global->params.pid_file) {
5642 os_daemonize_terminate(global->params.pid_file);
5643 os_free(global->params.pid_file);
5644 }
5645 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005646 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005647 os_free(global->params.override_driver);
5648 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005649#ifdef CONFIG_MATCH_IFACE
5650 os_free(global->params.match_ifaces);
5651#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005652#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005653 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005654#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005655
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005656 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005657 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005658 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005659
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005660 os_free(global);
5661 wpa_debug_close_syslog();
5662 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005663 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005664}
5665
5666
5667void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5668{
5669 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5670 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5671 char country[3];
5672 country[0] = wpa_s->conf->country[0];
5673 country[1] = wpa_s->conf->country[1];
5674 country[2] = '\0';
5675 if (wpa_drv_set_country(wpa_s, country) < 0) {
5676 wpa_printf(MSG_ERROR, "Failed to set country code "
5677 "'%s'", country);
5678 }
5679 }
5680
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005681 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5682 wpas_init_ext_pw(wpa_s);
5683
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005684 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5685 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5686
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005687#ifdef CONFIG_WPS
5688 wpas_wps_update_config(wpa_s);
5689#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005690 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005691 wpa_s->conf->changed_parameters = 0;
5692}
5693
5694
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005695void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005696{
5697 int i;
5698
5699 for (i = 0; i < *num_freqs; i++) {
5700 if (freqs[i] == freq)
5701 return;
5702 }
5703
5704 freqs[*num_freqs] = freq;
5705 (*num_freqs)++;
5706}
5707
5708
5709static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5710{
5711 struct wpa_bss *bss, *cbss;
5712 const int max_freqs = 10;
5713 int *freqs;
5714 int num_freqs = 0;
5715
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005716 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005717 if (freqs == NULL)
5718 return NULL;
5719
5720 cbss = wpa_s->current_bss;
5721
5722 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5723 if (bss == cbss)
5724 continue;
5725 if (bss->ssid_len == cbss->ssid_len &&
5726 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5727 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5728 add_freq(freqs, &num_freqs, bss->freq);
5729 if (num_freqs == max_freqs)
5730 break;
5731 }
5732 }
5733
5734 if (num_freqs == 0) {
5735 os_free(freqs);
5736 freqs = NULL;
5737 }
5738
5739 return freqs;
5740}
5741
5742
5743void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5744{
5745 int timeout;
5746 int count;
5747 int *freqs = NULL;
5748
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005749 wpas_connect_work_done(wpa_s);
5750
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005751 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005752 * Remove possible authentication timeout since the connection failed.
5753 */
5754 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5755
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005756 /*
5757 * There is no point in blacklisting the AP if this event is
5758 * generated based on local request to disconnect.
5759 */
5760 if (wpa_s->own_disconnect_req) {
5761 wpa_s->own_disconnect_req = 0;
5762 wpa_dbg(wpa_s, MSG_DEBUG,
5763 "Ignore connection failure due to local request to disconnect");
5764 return;
5765 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005766 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005767 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5768 "indication since interface has been put into "
5769 "disconnected state");
5770 return;
5771 }
5772
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005773 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005774 * Add the failed BSSID into the blacklist and speed up next scan
5775 * attempt if there could be other APs that could accept association.
5776 * The current blacklist count indicates how many times we have tried
5777 * connecting to this AP and multiple attempts mean that other APs are
5778 * either not available or has already been tried, so that we can start
5779 * increasing the delay here to avoid constant scanning.
5780 */
5781 count = wpa_blacklist_add(wpa_s, bssid);
5782 if (count == 1 && wpa_s->current_bss) {
5783 /*
5784 * This BSS was not in the blacklist before. If there is
5785 * another BSS available for the same ESS, we should try that
5786 * next. Otherwise, we may as well try this one once more
5787 * before allowing other, likely worse, ESSes to be considered.
5788 */
5789 freqs = get_bss_freqs_in_ess(wpa_s);
5790 if (freqs) {
5791 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5792 "has been seen; try it next");
5793 wpa_blacklist_add(wpa_s, bssid);
5794 /*
5795 * On the next scan, go through only the known channels
5796 * used in this ESS based on previous scans to speed up
5797 * common load balancing use case.
5798 */
5799 os_free(wpa_s->next_scan_freqs);
5800 wpa_s->next_scan_freqs = freqs;
5801 }
5802 }
5803
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005804 /*
5805 * Add previous failure count in case the temporary blacklist was
5806 * cleared due to no other BSSes being available.
5807 */
5808 count += wpa_s->extra_blacklist_count;
5809
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005810 if (count > 3 && wpa_s->current_ssid) {
5811 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5812 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005813 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005814 }
5815
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005816 switch (count) {
5817 case 1:
5818 timeout = 100;
5819 break;
5820 case 2:
5821 timeout = 500;
5822 break;
5823 case 3:
5824 timeout = 1000;
5825 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005826 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005827 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005828 break;
5829 default:
5830 timeout = 10000;
5831 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005832 }
5833
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005834 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5835 "ms", count, timeout);
5836
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005837 /*
5838 * TODO: if more than one possible AP is available in scan results,
5839 * could try the other ones before requesting a new scan.
5840 */
5841 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5842 1000 * (timeout % 1000));
5843}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005844
5845
5846int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5847{
5848 return wpa_s->conf->ap_scan == 2 ||
5849 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5850}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005851
Dmitry Shmidt04949592012-07-19 12:16:46 -07005852
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005853#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005854int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5855 struct wpa_ssid *ssid,
5856 const char *field,
5857 const char *value)
5858{
5859#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005860 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005861
5862 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5863 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5864 (const u8 *) value, os_strlen(value));
5865
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005866 rtype = wpa_supplicant_ctrl_req_from_string(field);
5867 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
5868#else /* IEEE8021X_EAPOL */
5869 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5870 return -1;
5871#endif /* IEEE8021X_EAPOL */
5872}
5873
5874int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5875 struct wpa_ssid *ssid,
5876 enum wpa_ctrl_req_type rtype,
5877 const char *value)
5878{
5879#ifdef IEEE8021X_EAPOL
5880 struct eap_peer_config *eap = &ssid->eap;
5881
5882 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005883 case WPA_CTRL_REQ_EAP_IDENTITY:
5884 os_free(eap->identity);
5885 eap->identity = (u8 *) os_strdup(value);
5886 eap->identity_len = os_strlen(value);
5887 eap->pending_req_identity = 0;
5888 if (ssid == wpa_s->current_ssid)
5889 wpa_s->reassociate = 1;
5890 break;
5891 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005892 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005893 eap->password = (u8 *) os_strdup(value);
5894 eap->password_len = os_strlen(value);
5895 eap->pending_req_password = 0;
5896 if (ssid == wpa_s->current_ssid)
5897 wpa_s->reassociate = 1;
5898 break;
5899 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005900 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005901 eap->new_password = (u8 *) os_strdup(value);
5902 eap->new_password_len = os_strlen(value);
5903 eap->pending_req_new_password = 0;
5904 if (ssid == wpa_s->current_ssid)
5905 wpa_s->reassociate = 1;
5906 break;
5907 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005908 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005909 eap->pin = os_strdup(value);
5910 eap->pending_req_pin = 0;
5911 if (ssid == wpa_s->current_ssid)
5912 wpa_s->reassociate = 1;
5913 break;
5914 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005915 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005916 eap->otp = (u8 *) os_strdup(value);
5917 eap->otp_len = os_strlen(value);
5918 os_free(eap->pending_req_otp);
5919 eap->pending_req_otp = NULL;
5920 eap->pending_req_otp_len = 0;
5921 break;
5922 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005923 str_clear_free(eap->private_key_passwd);
5924 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005925 eap->pending_req_passphrase = 0;
5926 if (ssid == wpa_s->current_ssid)
5927 wpa_s->reassociate = 1;
5928 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005929 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005930 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005931 eap->external_sim_resp = os_strdup(value);
5932 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005933 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5934 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5935 return -1;
5936 ssid->mem_only_psk = 1;
5937 if (ssid->passphrase)
5938 wpa_config_update_psk(ssid);
5939 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5940 wpa_supplicant_req_scan(wpa_s, 0, 0);
5941 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005942 case WPA_CTRL_REQ_EXT_CERT_CHECK:
5943 if (eap->pending_ext_cert_check != PENDING_CHECK)
5944 return -1;
5945 if (os_strcmp(value, "good") == 0)
5946 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
5947 else if (os_strcmp(value, "bad") == 0)
5948 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
5949 else
5950 return -1;
5951 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005952 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005953 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005954 return -1;
5955 }
5956
5957 return 0;
5958#else /* IEEE8021X_EAPOL */
5959 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5960 return -1;
5961#endif /* IEEE8021X_EAPOL */
5962}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005963#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005964
5965
5966int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5967{
5968 int i;
5969 unsigned int drv_enc;
5970
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005971 if (wpa_s->p2p_mgmt)
5972 return 1; /* no normal network profiles on p2p_mgmt interface */
5973
Dmitry Shmidt04949592012-07-19 12:16:46 -07005974 if (ssid == NULL)
5975 return 1;
5976
5977 if (ssid->disabled)
5978 return 1;
5979
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005980 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005981 drv_enc = wpa_s->drv_enc;
5982 else
5983 drv_enc = (unsigned int) -1;
5984
5985 for (i = 0; i < NUM_WEP_KEYS; i++) {
5986 size_t len = ssid->wep_key_len[i];
5987 if (len == 0)
5988 continue;
5989 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5990 continue;
5991 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5992 continue;
5993 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5994 continue;
5995 return 1; /* invalid WEP key */
5996 }
5997
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005998 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005999 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
6000 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006001 return 1;
6002
Dmitry Shmidt04949592012-07-19 12:16:46 -07006003 return 0;
6004}
6005
6006
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006007int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6008{
6009#ifdef CONFIG_IEEE80211W
6010 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6011 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6012 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6013 /*
6014 * Driver does not support BIP -- ignore pmf=1 default
6015 * since the connection with PMF would fail and the
6016 * configuration does not require PMF to be enabled.
6017 */
6018 return NO_MGMT_FRAME_PROTECTION;
6019 }
6020
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006021 if (ssid &&
6022 (ssid->key_mgmt &
6023 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6024 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6025 /*
6026 * Do not use the default PMF value for non-RSN networks
6027 * since PMF is available only with RSN and pmf=2
6028 * configuration would otherwise prevent connections to
6029 * all open networks.
6030 */
6031 return NO_MGMT_FRAME_PROTECTION;
6032 }
6033
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006034 return wpa_s->conf->pmf;
6035 }
6036
6037 return ssid->ieee80211w;
6038#else /* CONFIG_IEEE80211W */
6039 return NO_MGMT_FRAME_PROTECTION;
6040#endif /* CONFIG_IEEE80211W */
6041}
6042
6043
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006044int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006045{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006046 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006047 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006048 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006049 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006050 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006051}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006052
6053
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006054void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006055{
6056 struct wpa_ssid *ssid = wpa_s->current_ssid;
6057 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006058 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006059
6060 if (ssid == NULL) {
6061 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6062 "SSID block");
6063 return;
6064 }
6065
6066 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6067 return;
6068
6069 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006070
6071#ifdef CONFIG_P2P
6072 if (ssid->p2p_group &&
6073 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6074 /*
6075 * Skip the wait time since there is a short timeout on the
6076 * connection to a P2P group.
6077 */
6078 return;
6079 }
6080#endif /* CONFIG_P2P */
6081
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006082 if (ssid->auth_failures > 50)
6083 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006084 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006085 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006086 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006087 dur = 90;
6088 else if (ssid->auth_failures > 3)
6089 dur = 60;
6090 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006091 dur = 30;
6092 else if (ssid->auth_failures > 1)
6093 dur = 20;
6094 else
6095 dur = 10;
6096
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006097 if (ssid->auth_failures > 1 &&
6098 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6099 dur += os_random() % (ssid->auth_failures * 10);
6100
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006101 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006102 if (now.sec + dur <= ssid->disabled_until.sec)
6103 return;
6104
6105 ssid->disabled_until.sec = now.sec + dur;
6106
6107 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006108 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006109 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006110 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006111}
6112
6113
6114void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6115 struct wpa_ssid *ssid, int clear_failures)
6116{
6117 if (ssid == NULL)
6118 return;
6119
6120 if (ssid->disabled_until.sec) {
6121 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6122 "id=%d ssid=\"%s\"",
6123 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6124 }
6125 ssid->disabled_until.sec = 0;
6126 ssid->disabled_until.usec = 0;
6127 if (clear_failures)
6128 ssid->auth_failures = 0;
6129}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006130
6131
6132int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6133{
6134 size_t i;
6135
6136 if (wpa_s->disallow_aps_bssid == NULL)
6137 return 0;
6138
6139 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6140 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6141 bssid, ETH_ALEN) == 0)
6142 return 1;
6143 }
6144
6145 return 0;
6146}
6147
6148
6149int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6150 size_t ssid_len)
6151{
6152 size_t i;
6153
6154 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6155 return 0;
6156
6157 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6158 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6159 if (ssid_len == s->ssid_len &&
6160 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6161 return 1;
6162 }
6163
6164 return 0;
6165}
6166
6167
6168/**
6169 * wpas_request_connection - Request a new connection
6170 * @wpa_s: Pointer to the network interface
6171 *
6172 * This function is used to request a new connection to be found. It will mark
6173 * the interface to allow reassociation and request a new scan to find a
6174 * suitable network to connect to.
6175 */
6176void wpas_request_connection(struct wpa_supplicant *wpa_s)
6177{
6178 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006179 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006180 wpa_supplicant_reinit_autoscan(wpa_s);
6181 wpa_s->extra_blacklist_count = 0;
6182 wpa_s->disconnected = 0;
6183 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006184
6185 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6186 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006187 else
6188 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006189}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006190
Roshan Pius02242d72016-08-09 15:31:48 -07006191/**
6192 * wpas_request_disconnection - Request disconnection
6193 * @wpa_s: Pointer to the network interface
6194 *
6195 * This function is used to request disconnection from the currently connected
6196 * network. This will stop any ongoing scans and initiate deauthentication.
6197 */
6198void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6199{
6200#ifdef CONFIG_SME
6201 wpa_s->sme.prev_bssid_set = 0;
6202#endif /* CONFIG_SME */
6203 wpa_s->reassociate = 0;
6204 wpa_s->disconnected = 1;
6205 wpa_supplicant_cancel_sched_scan(wpa_s);
6206 wpa_supplicant_cancel_scan(wpa_s);
6207 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6208 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6209}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006210
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006211
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006212void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6213 struct wpa_used_freq_data *freqs_data,
6214 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006215{
6216 unsigned int i;
6217
6218 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6219 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006220 for (i = 0; i < len; i++) {
6221 struct wpa_used_freq_data *cur = &freqs_data[i];
6222 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6223 i, cur->freq, cur->flags);
6224 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006225}
6226
6227
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006228/*
6229 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006230 * are using the same radio as the current interface, and in addition, get
6231 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006232 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006233int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6234 struct wpa_used_freq_data *freqs_data,
6235 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006236{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006237 struct wpa_supplicant *ifs;
6238 u8 bssid[ETH_ALEN];
6239 int freq;
6240 unsigned int idx = 0, i;
6241
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006242 wpa_dbg(wpa_s, MSG_DEBUG,
6243 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006244 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006245
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006246 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6247 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006248 if (idx == len)
6249 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006250
6251 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6252 continue;
6253
6254 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006255 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6256 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006257 freq = ifs->current_ssid->frequency;
6258 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6259 freq = ifs->assoc_freq;
6260 else
6261 continue;
6262
6263 /* Hold only distinct freqs */
6264 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006265 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006266 break;
6267
6268 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006269 freqs_data[idx++].freq = freq;
6270
6271 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006272 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006273 WPA_FREQ_USED_BY_P2P_CLIENT :
6274 WPA_FREQ_USED_BY_INFRA_STATION;
6275 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006276 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006277
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006278 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006279 return idx;
6280}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006281
6282
6283/*
6284 * Find the operating frequencies of any of the virtual interfaces that
6285 * are using the same radio as the current interface.
6286 */
6287int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6288 int *freq_array, unsigned int len)
6289{
6290 struct wpa_used_freq_data *freqs_data;
6291 int num, i;
6292
6293 os_memset(freq_array, 0, sizeof(int) * len);
6294
6295 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6296 if (!freqs_data)
6297 return -1;
6298
6299 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6300 for (i = 0; i < num; i++)
6301 freq_array[i] = freqs_data[i].freq;
6302
6303 os_free(freqs_data);
6304
6305 return num;
6306}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006307
6308
6309static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
6310{
6311 struct rrm_data *rrm = data;
6312
6313 if (!rrm->notify_neighbor_rep) {
6314 wpa_printf(MSG_ERROR,
6315 "RRM: Unexpected neighbor report timeout");
6316 return;
6317 }
6318
6319 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
6320 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
6321
6322 rrm->notify_neighbor_rep = NULL;
6323 rrm->neighbor_rep_cb_ctx = NULL;
6324}
6325
6326
6327/*
6328 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
6329 * @wpa_s: Pointer to wpa_supplicant
6330 */
6331void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
6332{
6333 wpa_s->rrm.rrm_used = 0;
6334
6335 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6336 NULL);
6337 if (wpa_s->rrm.notify_neighbor_rep)
6338 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
6339 wpa_s->rrm.next_neighbor_rep_token = 1;
6340}
6341
6342
6343/*
6344 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
6345 * @wpa_s: Pointer to wpa_supplicant
6346 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
6347 * @report_len: Length of neighbor report buffer
6348 */
6349void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
6350 const u8 *report, size_t report_len)
6351{
6352 struct wpabuf *neighbor_rep;
6353
6354 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
6355 if (report_len < 1)
6356 return;
6357
6358 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
6359 wpa_printf(MSG_DEBUG,
6360 "RRM: Discarding neighbor report with token %d (expected %d)",
6361 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
6362 return;
6363 }
6364
6365 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6366 NULL);
6367
6368 if (!wpa_s->rrm.notify_neighbor_rep) {
6369 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
6370 return;
6371 }
6372
6373 /* skipping the first byte, which is only an id (dialog token) */
6374 neighbor_rep = wpabuf_alloc(report_len - 1);
6375 if (neighbor_rep == NULL)
6376 return;
6377 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
6378 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
6379 report[0]);
6380 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
6381 neighbor_rep);
6382 wpa_s->rrm.notify_neighbor_rep = NULL;
6383 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
6384}
6385
6386
Dmitry Shmidtff787d52015-01-12 13:01:47 -08006387#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
6388/* Workaround different, undefined for Windows, error codes used here */
6389#define ENOTCONN -1
6390#define EOPNOTSUPP -1
6391#define ECANCELED -1
6392#endif
6393
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006394/* Measurement Request element + Location Subject + Maximum Age subelement */
6395#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
6396/* Measurement Request element + Location Civic Request */
6397#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
6398
6399
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006400/**
6401 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
6402 * @wpa_s: Pointer to wpa_supplicant
6403 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
6404 * is sent in the request.
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006405 * @lci: if set, neighbor request will include LCI request
6406 * @civic: if set, neighbor request will include civic location request
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006407 * @cb: Callback function to be called once the requested report arrives, or
6408 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
6409 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
6410 * the requester's responsibility to free it.
6411 * In the latter case NULL will be sent in 'neighbor_rep'.
6412 * @cb_ctx: Context value to send the callback function
6413 * Returns: 0 in case of success, negative error code otherwise
6414 *
6415 * In case there is a previous request which has not been answered yet, the
6416 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
6417 * Request must contain a callback function.
6418 */
6419int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006420 const struct wpa_ssid_value *ssid,
6421 int lci, int civic,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006422 void (*cb)(void *ctx,
6423 struct wpabuf *neighbor_rep),
6424 void *cb_ctx)
6425{
6426 struct wpabuf *buf;
6427 const u8 *rrm_ie;
6428
6429 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
6430 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
6431 return -ENOTCONN;
6432 }
6433
6434 if (!wpa_s->rrm.rrm_used) {
6435 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
6436 return -EOPNOTSUPP;
6437 }
6438
6439 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
6440 WLAN_EID_RRM_ENABLED_CAPABILITIES);
6441 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
6442 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
6443 wpa_printf(MSG_DEBUG,
6444 "RRM: No network support for Neighbor Report.");
6445 return -EOPNOTSUPP;
6446 }
6447
6448 if (!cb) {
6449 wpa_printf(MSG_DEBUG,
6450 "RRM: Neighbor Report request must provide a callback.");
6451 return -EINVAL;
6452 }
6453
6454 /* Refuse if there's a live request */
6455 if (wpa_s->rrm.notify_neighbor_rep) {
6456 wpa_printf(MSG_DEBUG,
6457 "RRM: Currently handling previous Neighbor Report.");
6458 return -EBUSY;
6459 }
6460
6461 /* 3 = action category + action code + dialog token */
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006462 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
6463 (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
6464 (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006465 if (buf == NULL) {
6466 wpa_printf(MSG_DEBUG,
6467 "RRM: Failed to allocate Neighbor Report Request");
6468 return -ENOMEM;
6469 }
6470
6471 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
6472 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
6473 wpa_s->rrm.next_neighbor_rep_token);
6474
6475 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6476 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
6477 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
6478 if (ssid) {
6479 wpabuf_put_u8(buf, WLAN_EID_SSID);
6480 wpabuf_put_u8(buf, ssid->ssid_len);
6481 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
6482 }
6483
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006484 if (lci) {
6485 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6486 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6487 wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
6488
6489 /*
6490 * Measurement token; nonzero number that is unique among the
6491 * Measurement Request elements in a particular frame.
6492 */
6493 wpabuf_put_u8(buf, 1); /* Measurement Token */
6494
6495 /*
6496 * Parallel, Enable, Request, and Report bits are 0, Duration is
6497 * reserved.
6498 */
6499 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6500 wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
6501
6502 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
6503 /* Location Subject */
6504 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6505
6506 /* Optional Subelements */
6507 /*
6508 * IEEE P802.11-REVmc/D5.0 Figure 9-170
6509 * The Maximum Age subelement is required, otherwise the AP can
6510 * send only data that was determined after receiving the
6511 * request. Setting it here to unlimited age.
6512 */
6513 wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
6514 wpabuf_put_u8(buf, 2);
6515 wpabuf_put_le16(buf, 0xffff);
6516 }
6517
6518 if (civic) {
6519 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6520 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6521 wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
6522
6523 /*
6524 * Measurement token; nonzero number that is unique among the
6525 * Measurement Request elements in a particular frame.
6526 */
6527 wpabuf_put_u8(buf, 2); /* Measurement Token */
6528
6529 /*
6530 * Parallel, Enable, Request, and Report bits are 0, Duration is
6531 * reserved.
6532 */
6533 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6534 /* Measurement Type */
6535 wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
6536
6537 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
6538 * Location Civic request */
6539 /* Location Subject */
6540 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6541 wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
6542 /* Location Service Interval Units: Seconds */
6543 wpabuf_put_u8(buf, 0);
6544 /* Location Service Interval: 0 - Only one report is requested
6545 */
6546 wpabuf_put_le16(buf, 0);
6547 /* No optional subelements */
6548 }
6549
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006550 wpa_s->rrm.next_neighbor_rep_token++;
6551
6552 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
6553 wpa_s->own_addr, wpa_s->bssid,
6554 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
6555 wpa_printf(MSG_DEBUG,
6556 "RRM: Failed to send Neighbor Report Request");
6557 wpabuf_free(buf);
6558 return -ECANCELED;
6559 }
6560
6561 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
6562 wpa_s->rrm.notify_neighbor_rep = cb;
6563 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
6564 wpas_rrm_neighbor_rep_timeout_handler,
6565 &wpa_s->rrm, NULL);
6566
6567 wpabuf_free(buf);
6568 return 0;
6569}
6570
6571
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006572static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
6573 const u8 *request, size_t len,
6574 struct wpabuf *report)
6575{
6576 u8 token, type, subject;
6577 u16 max_age = 0;
6578 struct os_reltime t, diff;
6579 unsigned long diff_l;
6580 u8 *ptoken;
6581 const u8 *subelem;
6582
6583 if (!wpa_s->lci || len < 3 + 4)
6584 return report;
6585
6586 token = *request++;
6587 /* Measurement request mode isn't used */
6588 request++;
6589 type = *request++;
6590 subject = *request++;
6591
6592 wpa_printf(MSG_DEBUG,
6593 "Measurement request token %u type %u location subject %u",
6594 token, type, subject);
6595
6596 if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
6597 wpa_printf(MSG_INFO,
6598 "Not building LCI report - bad type or location subject");
6599 return report;
6600 }
6601
6602 /* Subelements are formatted exactly like elements */
6603 subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
6604 if (subelem && subelem[1] == 2)
6605 max_age = WPA_GET_LE16(subelem + 2);
6606
6607 if (os_get_reltime(&t))
6608 return report;
6609
6610 os_reltime_sub(&t, &wpa_s->lci_time, &diff);
6611 /* LCI age is calculated in 10th of a second units. */
6612 diff_l = diff.sec * 10 + diff.usec / 100000;
6613
6614 if (max_age != 0xffff && max_age < diff_l)
6615 return report;
6616
6617 if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
6618 return report;
6619
6620 wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
6621 wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
6622 /* We'll override user's measurement token */
6623 ptoken = wpabuf_put(report, 0);
6624 wpabuf_put_buf(report, wpa_s->lci);
6625 *ptoken = token;
6626
6627 return report;
6628}
6629
6630
6631void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
6632 const u8 *src,
6633 const u8 *frame, size_t len)
6634{
6635 struct wpabuf *buf, *report;
6636 u8 token;
6637 const u8 *ie, *end;
6638
6639 if (wpa_s->wpa_state != WPA_COMPLETED) {
6640 wpa_printf(MSG_INFO,
6641 "RRM: Ignoring radio measurement request: Not associated");
6642 return;
6643 }
6644
6645 if (!wpa_s->rrm.rrm_used) {
6646 wpa_printf(MSG_INFO,
6647 "RRM: Ignoring radio measurement request: Not RRM network");
6648 return;
6649 }
6650
6651 if (len < 3) {
6652 wpa_printf(MSG_INFO,
6653 "RRM: Ignoring too short radio measurement request");
6654 return;
6655 }
6656
6657 end = frame + len;
6658
6659 token = *frame++;
6660
6661 /* Ignore number of repetitions because it's not used in LCI request */
6662 frame += 2;
6663
6664 report = NULL;
6665 while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
6666 ie[1] >= 3) {
6667 u8 msmt_type;
6668
6669 msmt_type = ie[4];
6670 wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
6671
6672 switch (msmt_type) {
6673 case MEASURE_TYPE_LCI:
6674 report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
6675 report);
6676 break;
6677 default:
6678 wpa_printf(MSG_INFO,
6679 "RRM: Unsupported radio measurement request %d",
6680 msmt_type);
6681 break;
6682 }
6683
6684 frame = ie + ie[1] + 2;
6685 }
6686
6687 if (!report)
6688 return;
6689
6690 buf = wpabuf_alloc(3 + wpabuf_len(report));
6691 if (!buf) {
6692 wpabuf_free(report);
6693 return;
6694 }
6695
6696 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6697 wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
6698 wpabuf_put_u8(buf, token);
6699
6700 wpabuf_put_buf(buf, report);
6701 wpabuf_free(report);
6702
6703 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6704 wpa_s->own_addr, wpa_s->bssid,
6705 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6706 wpa_printf(MSG_ERROR,
6707 "RRM: Radio measurement report failed: Sending Action frame failed");
6708 }
6709 wpabuf_free(buf);
6710}
6711
6712
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006713void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
6714 const u8 *src,
6715 const u8 *frame, size_t len,
6716 int rssi)
6717{
6718 struct wpabuf *buf;
6719 const struct rrm_link_measurement_request *req;
6720 struct rrm_link_measurement_report report;
6721
6722 if (wpa_s->wpa_state != WPA_COMPLETED) {
6723 wpa_printf(MSG_INFO,
6724 "RRM: Ignoring link measurement request. Not associated");
6725 return;
6726 }
6727
6728 if (!wpa_s->rrm.rrm_used) {
6729 wpa_printf(MSG_INFO,
6730 "RRM: Ignoring link measurement request. Not RRM network");
6731 return;
6732 }
6733
6734 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
6735 wpa_printf(MSG_INFO,
6736 "RRM: Measurement report failed. TX power insertion not supported");
6737 return;
6738 }
6739
6740 req = (const struct rrm_link_measurement_request *) frame;
6741 if (len < sizeof(*req)) {
6742 wpa_printf(MSG_INFO,
6743 "RRM: Link measurement report failed. Request too short");
6744 return;
6745 }
6746
6747 os_memset(&report, 0, sizeof(report));
6748 report.tpc.eid = WLAN_EID_TPC_REPORT;
6749 report.tpc.len = 2;
6750 report.rsni = 255; /* 255 indicates that RSNI is not available */
6751 report.dialog_token = req->dialog_token;
6752
6753 /*
6754 * It's possible to estimate RCPI based on RSSI in dBm. This
6755 * calculation will not reflect the correct value for high rates,
6756 * but it's good enough for Action frames which are transmitted
6757 * with up to 24 Mbps rates.
6758 */
6759 if (!rssi)
6760 report.rcpi = 255; /* not available */
6761 else if (rssi < -110)
6762 report.rcpi = 0;
6763 else if (rssi > 0)
6764 report.rcpi = 220;
6765 else
6766 report.rcpi = (rssi + 110) * 2;
6767
6768 /* action_category + action_code */
6769 buf = wpabuf_alloc(2 + sizeof(report));
6770 if (buf == NULL) {
6771 wpa_printf(MSG_ERROR,
6772 "RRM: Link measurement report failed. Buffer allocation failed");
6773 return;
6774 }
6775
6776 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6777 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
6778 wpabuf_put_data(buf, &report, sizeof(report));
6779 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
6780 wpabuf_head(buf), wpabuf_len(buf));
6781
6782 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6783 wpa_s->own_addr, wpa_s->bssid,
6784 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6785 wpa_printf(MSG_ERROR,
6786 "RRM: Link measurement report failed. Send action failed");
6787 }
6788 wpabuf_free(buf);
6789}
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006790
6791
6792struct wpa_supplicant *
6793wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6794{
6795 switch (frame) {
6796#ifdef CONFIG_P2P
6797 case VENDOR_ELEM_PROBE_REQ_P2P:
6798 case VENDOR_ELEM_PROBE_RESP_P2P:
6799 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6800 case VENDOR_ELEM_BEACON_P2P_GO:
6801 case VENDOR_ELEM_P2P_PD_REQ:
6802 case VENDOR_ELEM_P2P_PD_RESP:
6803 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6804 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6805 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6806 case VENDOR_ELEM_P2P_INV_REQ:
6807 case VENDOR_ELEM_P2P_INV_RESP:
6808 case VENDOR_ELEM_P2P_ASSOC_REQ:
6809 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006810 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006811#endif /* CONFIG_P2P */
6812 default:
6813 return wpa_s;
6814 }
6815}
6816
6817
6818void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6819{
6820 unsigned int i;
6821 char buf[30];
6822
6823 wpa_printf(MSG_DEBUG, "Update vendor elements");
6824
6825 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6826 if (wpa_s->vendor_elem[i]) {
6827 int res;
6828
6829 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6830 if (!os_snprintf_error(sizeof(buf), res)) {
6831 wpa_hexdump_buf(MSG_DEBUG, buf,
6832 wpa_s->vendor_elem[i]);
6833 }
6834 }
6835 }
6836
6837#ifdef CONFIG_P2P
6838 if (wpa_s->parent == wpa_s &&
6839 wpa_s->global->p2p &&
6840 !wpa_s->global->p2p_disabled)
6841 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6842#endif /* CONFIG_P2P */
6843}
6844
6845
6846int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6847 const u8 *elem, size_t len)
6848{
6849 u8 *ie, *end;
6850
6851 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6852 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6853
6854 for (; ie + 1 < end; ie += 2 + ie[1]) {
6855 if (ie + len > end)
6856 break;
6857 if (os_memcmp(ie, elem, len) != 0)
6858 continue;
6859
6860 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6861 wpabuf_free(wpa_s->vendor_elem[frame]);
6862 wpa_s->vendor_elem[frame] = NULL;
6863 } else {
6864 os_memmove(ie, ie + len, end - (ie + len));
6865 wpa_s->vendor_elem[frame]->used -= len;
6866 }
6867 wpas_vendor_elem_update(wpa_s);
6868 return 0;
6869 }
6870
6871 return -1;
6872}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006873
6874
6875struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6876 u16 num_modes, enum hostapd_hw_mode mode)
6877{
6878 u16 i;
6879
6880 for (i = 0; i < num_modes; i++) {
6881 if (modes[i].mode == mode)
6882 return &modes[i];
6883 }
6884
6885 return NULL;
6886}
6887
6888
6889static struct
6890wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6891 const u8 *bssid)
6892{
6893 struct wpa_bss_tmp_disallowed *bss;
6894
6895 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6896 struct wpa_bss_tmp_disallowed, list) {
6897 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6898 return bss;
6899 }
6900
6901 return NULL;
6902}
6903
6904
6905void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6906 unsigned int sec)
6907{
6908 struct wpa_bss_tmp_disallowed *bss;
6909 struct os_reltime until;
6910
6911 os_get_reltime(&until);
6912 until.sec += sec;
6913
6914 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6915 if (bss) {
6916 bss->disallowed_until = until;
6917 return;
6918 }
6919
6920 bss = os_malloc(sizeof(*bss));
6921 if (!bss) {
6922 wpa_printf(MSG_DEBUG,
6923 "Failed to allocate memory for temp disallow BSS");
6924 return;
6925 }
6926
6927 bss->disallowed_until = until;
6928 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6929 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
6930}
6931
6932
6933int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6934{
6935 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
6936 struct os_reltime now, age;
6937
6938 os_get_reltime(&now);
6939
6940 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6941 struct wpa_bss_tmp_disallowed, list) {
6942 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
6943 /* This BSS is not disallowed anymore */
6944 dl_list_del(&tmp->list);
6945 os_free(tmp);
6946 continue;
6947 }
6948 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6949 bss = tmp;
6950 break;
6951 }
6952 }
6953 if (!bss)
6954 return 0;
6955
6956 os_reltime_sub(&bss->disallowed_until, &now, &age);
6957 wpa_printf(MSG_DEBUG,
6958 "BSS " MACSTR " disabled for %ld.%0ld seconds",
6959 MAC2STR(bss->bssid), age.sec, age.usec);
6960 return 1;
6961}