blob: 531004f2f236c6ece51745d4d161d3bdd12e2b5e [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003 * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
20#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "eapol_supp/eapol_supp_sm.h"
23#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070024#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "eap_server/eap_methods.h"
26#include "rsn_supp/wpa.h"
27#include "eloop.h"
28#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070029#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "l2_packet/l2_packet.h"
31#include "wpa_supplicant_i.h"
32#include "driver_i.h"
33#include "ctrl_iface.h"
34#include "pcsc_funcs.h"
35#include "common/version.h"
36#include "rsn_supp/preauth.h"
37#include "rsn_supp/pmksa_cache.h"
38#include "common/wpa_ctrl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070039#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080040#include "common/hw_features_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080042#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043#include "blacklist.h"
44#include "wpas_glue.h"
45#include "wps_supplicant.h"
46#include "ibss_rsn.h"
47#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080048#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "ap.h"
50#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070051#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070052#include "notify.h"
53#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070054#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070055#include "bss.h"
56#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080057#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070058#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070059#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070060#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080061#include "mesh.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070062
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070063const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070064"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidtde47be72016-01-07 12:52:55 -080065"Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070066
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070067const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080068"This software may be distributed under the terms of the BSD license.\n"
69"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070#ifdef EAP_TLS_OPENSSL
71"\nThis product includes software developed by the OpenSSL Project\n"
72"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
73#endif /* EAP_TLS_OPENSSL */
74;
75
76#ifndef CONFIG_NO_STDOUT_DEBUG
77/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070078const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080079"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070080const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080081"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082"\n"
83"Redistribution and use in source and binary forms, with or without\n"
84"modification, are permitted provided that the following conditions are\n"
85"met:\n"
86"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070087const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088"1. Redistributions of source code must retain the above copyright\n"
89" notice, this list of conditions and the following disclaimer.\n"
90"\n"
91"2. Redistributions in binary form must reproduce the above copyright\n"
92" notice, this list of conditions and the following disclaimer in the\n"
93" documentation and/or other materials provided with the distribution.\n"
94"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070095const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
97" names of its contributors may be used to endorse or promote products\n"
98" derived from this software without specific prior written permission.\n"
99"\n"
100"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
101"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
102"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
103"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700104const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
106"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
107"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
108"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
109"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
110"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
111"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
112"\n";
113#endif /* CONFIG_NO_STDOUT_DEBUG */
114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700115/* Configure default/group WEP keys for static WEP */
116int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
117{
118 int i, set = 0;
119
120 for (i = 0; i < NUM_WEP_KEYS; i++) {
121 if (ssid->wep_key_len[i] == 0)
122 continue;
123
124 set = 1;
125 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
126 i, i == ssid->wep_tx_keyidx, NULL, 0,
127 ssid->wep_key[i], ssid->wep_key_len[i]);
128 }
129
130 return set;
131}
132
133
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700134int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
135 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136{
137 u8 key[32];
138 size_t keylen;
139 enum wpa_alg alg;
140 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800141 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700142
143 /* IBSS/WPA-None uses only one key (Group) for both receiving and
144 * sending unicast and multicast packets. */
145
146 if (ssid->mode != WPAS_MODE_IBSS) {
147 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
148 "IBSS/ad-hoc) for WPA-None", ssid->mode);
149 return -1;
150 }
151
152 if (!ssid->psk_set) {
153 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
154 "WPA-None");
155 return -1;
156 }
157
158 switch (wpa_s->group_cipher) {
159 case WPA_CIPHER_CCMP:
160 os_memcpy(key, ssid->psk, 16);
161 keylen = 16;
162 alg = WPA_ALG_CCMP;
163 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700164 case WPA_CIPHER_GCMP:
165 os_memcpy(key, ssid->psk, 16);
166 keylen = 16;
167 alg = WPA_ALG_GCMP;
168 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700169 case WPA_CIPHER_TKIP:
170 /* WPA-None uses the same Michael MIC key for both TX and RX */
171 os_memcpy(key, ssid->psk, 16 + 8);
172 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
173 keylen = 32;
174 alg = WPA_ALG_TKIP;
175 break;
176 default:
177 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
178 "WPA-None", wpa_s->group_cipher);
179 return -1;
180 }
181
182 /* TODO: should actually remember the previously used seq#, both for TX
183 * and RX from each STA.. */
184
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800185 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
186 os_memset(key, 0, sizeof(key));
187 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700188}
189
190
191static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
192{
193 struct wpa_supplicant *wpa_s = eloop_ctx;
194 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700195 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
196 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
197 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700198 bssid = wpa_s->pending_bssid;
199 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
200 MAC2STR(bssid));
201 wpa_blacklist_add(wpa_s, bssid);
202 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800203 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700204 wpa_s->reassociate = 1;
205
206 /*
207 * If we timed out, the AP or the local radio may be busy.
208 * So, wait a second until scanning again.
209 */
210 wpa_supplicant_req_scan(wpa_s, 1, 0);
211}
212
213
214/**
215 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
216 * @wpa_s: Pointer to wpa_supplicant data
217 * @sec: Number of seconds after which to time out authentication
218 * @usec: Number of microseconds after which to time out authentication
219 *
220 * This function is used to schedule a timeout for the current authentication
221 * attempt.
222 */
223void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
224 int sec, int usec)
225{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700226 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700227 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
228 return;
229
230 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
231 "%d usec", sec, usec);
232 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
233 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
234}
235
236
237/**
238 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
239 * @wpa_s: Pointer to wpa_supplicant data
240 *
241 * This function is used to cancel authentication timeout scheduled with
242 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
243 * been completed.
244 */
245void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
246{
247 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
248 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
249 wpa_blacklist_del(wpa_s, wpa_s->bssid);
250}
251
252
253/**
254 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
255 * @wpa_s: Pointer to wpa_supplicant data
256 *
257 * This function is used to configure EAPOL state machine based on the selected
258 * authentication mode.
259 */
260void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
261{
262#ifdef IEEE8021X_EAPOL
263 struct eapol_config eapol_conf;
264 struct wpa_ssid *ssid = wpa_s->current_ssid;
265
266#ifdef CONFIG_IBSS_RSN
267 if (ssid->mode == WPAS_MODE_IBSS &&
268 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
269 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
270 /*
271 * RSN IBSS authentication is per-STA and we can disable the
272 * per-BSSID EAPOL authentication.
273 */
274 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
275 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
276 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
277 return;
278 }
279#endif /* CONFIG_IBSS_RSN */
280
281 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
282 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
283
284 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
285 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
286 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
287 else
288 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
289
290 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
291 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
292 eapol_conf.accept_802_1x_keys = 1;
293 eapol_conf.required_keys = 0;
294 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
295 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
296 }
297 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
298 eapol_conf.required_keys |=
299 EAPOL_REQUIRE_KEY_BROADCAST;
300 }
301
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700302 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303 eapol_conf.required_keys = 0;
304 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700305 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700306 eapol_conf.workaround = ssid->eap_workaround;
307 eapol_conf.eap_disabled =
308 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
309 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
310 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700311 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800312
313#ifdef CONFIG_WPS
314 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
315 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
316 if (wpa_s->current_bss) {
317 struct wpabuf *ie;
318 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
319 WPS_IE_VENDOR_TYPE);
320 if (ie) {
321 if (wps_is_20(ie))
322 eapol_conf.wps |=
323 EAPOL_PEER_IS_WPS20_AP;
324 wpabuf_free(ie);
325 }
326 }
327 }
328#endif /* CONFIG_WPS */
329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700330 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700331
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800332#ifdef CONFIG_MACSEC
333 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
334 ieee802_1x_create_preshared_mka(wpa_s, ssid);
335 else
336 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
337#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800338#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700339}
340
341
342/**
343 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
344 * @wpa_s: Pointer to wpa_supplicant data
345 * @ssid: Configuration data for the network
346 *
347 * This function is used to configure WPA state machine and related parameters
348 * to a mode where WPA is not enabled. This is called as part of the
349 * authentication configuration when the selected network does not use WPA.
350 */
351void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
352 struct wpa_ssid *ssid)
353{
354 int i;
355
356 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
357 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
358 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
359 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
360 else
361 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
362 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
363 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
364 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
365 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
366 wpa_s->group_cipher = WPA_CIPHER_NONE;
367 wpa_s->mgmt_group_cipher = 0;
368
369 for (i = 0; i < NUM_WEP_KEYS; i++) {
370 if (ssid->wep_key_len[i] > 5) {
371 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
372 wpa_s->group_cipher = WPA_CIPHER_WEP104;
373 break;
374 } else if (ssid->wep_key_len[i] > 0) {
375 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
376 wpa_s->group_cipher = WPA_CIPHER_WEP40;
377 break;
378 }
379 }
380
381 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
382 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
383 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
384 wpa_s->pairwise_cipher);
385 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
386#ifdef CONFIG_IEEE80211W
387 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
388 wpa_s->mgmt_group_cipher);
389#endif /* CONFIG_IEEE80211W */
390
391 pmksa_cache_clear_current(wpa_s->wpa);
392}
393
394
Dmitry Shmidt04949592012-07-19 12:16:46 -0700395void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800396{
397 int i;
398 if (wpa_s->hw.modes == NULL)
399 return;
400
401 for (i = 0; i < wpa_s->hw.num_modes; i++) {
402 os_free(wpa_s->hw.modes[i].channels);
403 os_free(wpa_s->hw.modes[i].rates);
404 }
405
406 os_free(wpa_s->hw.modes);
407 wpa_s->hw.modes = NULL;
408}
409
410
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800411static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
412{
413 struct wpa_bss_tmp_disallowed *bss, *prev;
414
415 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
416 struct wpa_bss_tmp_disallowed, list) {
417 dl_list_del(&bss->list);
418 os_free(bss);
419 }
420}
421
422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700423static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
424{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700425 int i;
426
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700427 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700428 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700429 scard_deinit(wpa_s->scard);
430 wpa_s->scard = NULL;
431 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
432 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
433 l2_packet_deinit(wpa_s->l2);
434 wpa_s->l2 = NULL;
435 if (wpa_s->l2_br) {
436 l2_packet_deinit(wpa_s->l2_br);
437 wpa_s->l2_br = NULL;
438 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800439#ifdef CONFIG_TESTING_OPTIONS
440 l2_packet_deinit(wpa_s->l2_test);
441 wpa_s->l2_test = NULL;
442#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444 if (wpa_s->conf != NULL) {
445 struct wpa_ssid *ssid;
446 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
447 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700448 }
449
450 os_free(wpa_s->confname);
451 wpa_s->confname = NULL;
452
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700453 os_free(wpa_s->confanother);
454 wpa_s->confanother = NULL;
455
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700456 wpa_sm_set_eapol(wpa_s->wpa, NULL);
457 eapol_sm_deinit(wpa_s->eapol);
458 wpa_s->eapol = NULL;
459
460 rsn_preauth_deinit(wpa_s->wpa);
461
462#ifdef CONFIG_TDLS
463 wpa_tdls_deinit(wpa_s->wpa);
464#endif /* CONFIG_TDLS */
465
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800466 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700467 pmksa_candidate_free(wpa_s->wpa);
468 wpa_sm_deinit(wpa_s->wpa);
469 wpa_s->wpa = NULL;
470 wpa_blacklist_clear(wpa_s);
471
472 wpa_bss_deinit(wpa_s);
473
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700474 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700475 wpa_supplicant_cancel_scan(wpa_s);
476 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800477 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
478#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
479 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
480 wpa_s, NULL);
481#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700482
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700483 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700485 wpas_wps_deinit(wpa_s);
486
487 wpabuf_free(wpa_s->pending_eapol_rx);
488 wpa_s->pending_eapol_rx = NULL;
489
490#ifdef CONFIG_IBSS_RSN
491 ibss_rsn_deinit(wpa_s->ibss_rsn);
492 wpa_s->ibss_rsn = NULL;
493#endif /* CONFIG_IBSS_RSN */
494
495 sme_deinit(wpa_s);
496
497#ifdef CONFIG_AP
498 wpa_supplicant_ap_deinit(wpa_s);
499#endif /* CONFIG_AP */
500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700501 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800503#ifdef CONFIG_OFFCHANNEL
504 offchannel_deinit(wpa_s);
505#endif /* CONFIG_OFFCHANNEL */
506
507 wpa_supplicant_cancel_sched_scan(wpa_s);
508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700509 os_free(wpa_s->next_scan_freqs);
510 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800511
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800512 os_free(wpa_s->manual_scan_freqs);
513 wpa_s->manual_scan_freqs = NULL;
514
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700515 os_free(wpa_s->manual_sched_scan_freqs);
516 wpa_s->manual_sched_scan_freqs = NULL;
517
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800518 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
519
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700520 /*
521 * Need to remove any pending gas-query radio work before the
522 * gas_query_deinit() call because gas_query::work has not yet been set
523 * for works that have not been started. gas_query_free() will be unable
524 * to cancel such pending radio works and once the pending gas-query
525 * radio work eventually gets removed, the deinit notification call to
526 * gas_query_start_cb() would result in dereferencing freed memory.
527 */
528 if (wpa_s->radio)
529 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800530 gas_query_deinit(wpa_s->gas);
531 wpa_s->gas = NULL;
532
533 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700534
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700535 ieee802_1x_dealloc_kay_sm(wpa_s);
536
Dmitry Shmidt04949592012-07-19 12:16:46 -0700537 os_free(wpa_s->bssid_filter);
538 wpa_s->bssid_filter = NULL;
539
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800540 os_free(wpa_s->disallow_aps_bssid);
541 wpa_s->disallow_aps_bssid = NULL;
542 os_free(wpa_s->disallow_aps_ssid);
543 wpa_s->disallow_aps_ssid = NULL;
544
Dmitry Shmidt04949592012-07-19 12:16:46 -0700545 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700546#ifdef CONFIG_WNM
547 wnm_deallocate_memory(wpa_s);
548#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700549
550 ext_password_deinit(wpa_s->ext_pw);
551 wpa_s->ext_pw = NULL;
552
553 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800554 wpa_s->last_gas_resp = NULL;
555 wpabuf_free(wpa_s->prev_gas_resp);
556 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700557
558 os_free(wpa_s->last_scan_res);
559 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800560
561#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700562 if (wpa_s->drv_priv)
563 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700564 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800565#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700566
567 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
568 wpabuf_free(wpa_s->vendor_elem[i]);
569 wpa_s->vendor_elem[i] = NULL;
570 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800571
572 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800573
574 wpa_s->sched_scan_plans_num = 0;
575 os_free(wpa_s->sched_scan_plans);
576 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800577
578#ifdef CONFIG_MBO
579 wpa_s->non_pref_chan_num = 0;
580 os_free(wpa_s->non_pref_chan);
581 wpa_s->non_pref_chan = NULL;
582#endif /* CONFIG_MBO */
583
584 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700585
586 wpabuf_free(wpa_s->lci);
587 wpa_s->lci = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700588}
589
590
591/**
592 * wpa_clear_keys - Clear keys configured for the driver
593 * @wpa_s: Pointer to wpa_supplicant data
594 * @addr: Previously used BSSID or %NULL if not available
595 *
596 * This function clears the encryption keys that has been previously configured
597 * for the driver.
598 */
599void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
600{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800601 int i, max;
602
603#ifdef CONFIG_IEEE80211W
604 max = 6;
605#else /* CONFIG_IEEE80211W */
606 max = 4;
607#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700608
609 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800610 for (i = 0; i < max; i++) {
611 if (wpa_s->keys_cleared & BIT(i))
612 continue;
613 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
614 NULL, 0);
615 }
616 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
617 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700618 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
619 0);
620 /* MLME-SETPROTECTION.request(None) */
621 wpa_drv_mlme_setprotection(
622 wpa_s, addr,
623 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
624 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
625 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800626 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700627}
628
629
630/**
631 * wpa_supplicant_state_txt - Get the connection state name as a text string
632 * @state: State (wpa_state; WPA_*)
633 * Returns: The state name as a printable text string
634 */
635const char * wpa_supplicant_state_txt(enum wpa_states state)
636{
637 switch (state) {
638 case WPA_DISCONNECTED:
639 return "DISCONNECTED";
640 case WPA_INACTIVE:
641 return "INACTIVE";
642 case WPA_INTERFACE_DISABLED:
643 return "INTERFACE_DISABLED";
644 case WPA_SCANNING:
645 return "SCANNING";
646 case WPA_AUTHENTICATING:
647 return "AUTHENTICATING";
648 case WPA_ASSOCIATING:
649 return "ASSOCIATING";
650 case WPA_ASSOCIATED:
651 return "ASSOCIATED";
652 case WPA_4WAY_HANDSHAKE:
653 return "4WAY_HANDSHAKE";
654 case WPA_GROUP_HANDSHAKE:
655 return "GROUP_HANDSHAKE";
656 case WPA_COMPLETED:
657 return "COMPLETED";
658 default:
659 return "UNKNOWN";
660 }
661}
662
663
664#ifdef CONFIG_BGSCAN
665
666static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
667{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800668 const char *name;
669
670 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
671 name = wpa_s->current_ssid->bgscan;
672 else
673 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800674 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800675 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800676 if (wpas_driver_bss_selection(wpa_s))
677 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700678 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
679 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800680#ifdef CONFIG_P2P
681 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
682 return;
683#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684
685 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800686 if (wpa_s->current_ssid) {
687 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700688 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
689 "bgscan");
690 /*
691 * Live without bgscan; it is only used as a roaming
692 * optimization, so the initial connection is not
693 * affected.
694 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700695 } else {
696 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700698 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
699 0);
700 if (scan_res) {
701 bgscan_notify_scan(wpa_s, scan_res);
702 wpa_scan_results_free(scan_res);
703 }
704 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705 } else
706 wpa_s->bgscan_ssid = NULL;
707}
708
709
710static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
711{
712 if (wpa_s->bgscan_ssid != NULL) {
713 bgscan_deinit(wpa_s);
714 wpa_s->bgscan_ssid = NULL;
715 }
716}
717
718#endif /* CONFIG_BGSCAN */
719
720
Dmitry Shmidt04949592012-07-19 12:16:46 -0700721static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
722{
723 if (autoscan_init(wpa_s, 0))
724 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
725}
726
727
728static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
729{
730 autoscan_deinit(wpa_s);
731}
732
733
734void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
735{
736 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
737 wpa_s->wpa_state == WPA_SCANNING) {
738 autoscan_deinit(wpa_s);
739 wpa_supplicant_start_autoscan(wpa_s);
740 }
741}
742
743
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744/**
745 * wpa_supplicant_set_state - Set current connection state
746 * @wpa_s: Pointer to wpa_supplicant data
747 * @state: The new connection state
748 *
749 * This function is called whenever the connection state changes, e.g.,
750 * association is completed for WPA/WPA2 4-Way Handshake is started.
751 */
752void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
753 enum wpa_states state)
754{
755 enum wpa_states old_state = wpa_s->wpa_state;
756
757 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
758 wpa_supplicant_state_txt(wpa_s->wpa_state),
759 wpa_supplicant_state_txt(state));
760
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800761 if (state == WPA_INTERFACE_DISABLED) {
762 /* Assure normal scan when interface is restored */
763 wpa_s->normal_scans = 0;
764 }
765
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700766 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800767 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700768 /* Reinitialize normal_scan counter */
769 wpa_s->normal_scans = 0;
770 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800771
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700772#ifdef CONFIG_P2P
773 /*
774 * P2PS client has to reply to Probe Request frames received on the
775 * group operating channel. Enable Probe Request frame reporting for
776 * P2P connected client in case p2p_cli_probe configuration property is
777 * set to 1.
778 */
779 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
780 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
781 wpa_s->current_ssid->p2p_group) {
782 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
783 wpa_dbg(wpa_s, MSG_DEBUG,
784 "P2P: Enable CLI Probe Request RX reporting");
785 wpa_s->p2p_cli_probe =
786 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
787 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
788 wpa_dbg(wpa_s, MSG_DEBUG,
789 "P2P: Disable CLI Probe Request RX reporting");
790 wpa_s->p2p_cli_probe = 0;
791 wpa_drv_probe_req_report(wpa_s, 0);
792 }
793 }
794#endif /* CONFIG_P2P */
795
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796 if (state != WPA_SCANNING)
797 wpa_supplicant_notify_scanning(wpa_s, 0);
798
799 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700800 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700801#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700802 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800803 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800804 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700805 ssid ? ssid->id : -1,
806 ssid && ssid->id_str ? ssid->id_str : "");
807#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700808 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700809 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800810 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700811 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700812 wpa_drv_set_operstate(wpa_s, 1);
813#ifndef IEEE8021X_EAPOL
814 wpa_drv_set_supp_port(wpa_s, 1);
815#endif /* IEEE8021X_EAPOL */
816 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700817 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700818 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700819
820 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700821 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
822 state == WPA_ASSOCIATED) {
823 wpa_s->new_connection = 1;
824 wpa_drv_set_operstate(wpa_s, 0);
825#ifndef IEEE8021X_EAPOL
826 wpa_drv_set_supp_port(wpa_s, 0);
827#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700828 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700829 }
830 wpa_s->wpa_state = state;
831
832#ifdef CONFIG_BGSCAN
833 if (state == WPA_COMPLETED)
834 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800835 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700836 wpa_supplicant_stop_bgscan(wpa_s);
837#endif /* CONFIG_BGSCAN */
838
Dmitry Shmidt04949592012-07-19 12:16:46 -0700839 if (state == WPA_AUTHENTICATING)
840 wpa_supplicant_stop_autoscan(wpa_s);
841
842 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
843 wpa_supplicant_start_autoscan(wpa_s);
844
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800845 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
846 wmm_ac_notify_disassoc(wpa_s);
847
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700848 if (wpa_s->wpa_state != old_state) {
849 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
850
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700851 /*
852 * Notify the P2P Device interface about a state change in one
853 * of the interfaces.
854 */
855 wpas_p2p_indicate_state_change(wpa_s);
856
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700857 if (wpa_s->wpa_state == WPA_COMPLETED ||
858 old_state == WPA_COMPLETED)
859 wpas_notify_auth_changed(wpa_s);
860 }
861}
862
863
864void wpa_supplicant_terminate_proc(struct wpa_global *global)
865{
866 int pending = 0;
867#ifdef CONFIG_WPS
868 struct wpa_supplicant *wpa_s = global->ifaces;
869 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800870 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700871 if (wpas_wps_terminate_pending(wpa_s) == 1)
872 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700873#ifdef CONFIG_P2P
874 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
875 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
876 wpas_p2p_disconnect(wpa_s);
877#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800878 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700879 }
880#endif /* CONFIG_WPS */
881 if (pending)
882 return;
883 eloop_terminate();
884}
885
886
887static void wpa_supplicant_terminate(int sig, void *signal_ctx)
888{
889 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700890 wpa_supplicant_terminate_proc(global);
891}
892
893
894void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
895{
896 enum wpa_states old_state = wpa_s->wpa_state;
897
898 wpa_s->pairwise_cipher = 0;
899 wpa_s->group_cipher = 0;
900 wpa_s->mgmt_group_cipher = 0;
901 wpa_s->key_mgmt = 0;
902 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700903 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700904
905 if (wpa_s->wpa_state != old_state)
906 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
907}
908
909
910/**
911 * wpa_supplicant_reload_configuration - Reload configuration data
912 * @wpa_s: Pointer to wpa_supplicant data
913 * Returns: 0 on success or -1 if configuration parsing failed
914 *
915 * This function can be used to request that the configuration data is reloaded
916 * (e.g., after configuration file change). This function is reloading
917 * configuration only for one interface, so this may need to be called multiple
918 * times if %wpa_supplicant is controlling multiple interfaces and all
919 * interfaces need reconfiguration.
920 */
921int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
922{
923 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700924 int reconf_ctrl;
925 int old_ap_scan;
926
927 if (wpa_s->confname == NULL)
928 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700929 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930 if (conf == NULL) {
931 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
932 "file '%s' - exiting", wpa_s->confname);
933 return -1;
934 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700935 wpa_config_read(wpa_s->confanother, conf);
936
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700937 conf->changed_parameters = (unsigned int) -1;
938
939 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
940 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
941 os_strcmp(conf->ctrl_interface,
942 wpa_s->conf->ctrl_interface) != 0);
943
944 if (reconf_ctrl && wpa_s->ctrl_iface) {
945 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
946 wpa_s->ctrl_iface = NULL;
947 }
948
949 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800950 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700951 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
952 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800953 wpa_supplicant_deauthenticate(wpa_s,
954 WLAN_REASON_DEAUTH_LEAVING);
955 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956
957 /*
958 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800959 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700960 */
961 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
962 /*
963 * Clear forced success to clear EAP state for next
964 * authentication.
965 */
966 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
967 }
968 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
969 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800970 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700971 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
972 rsn_preauth_deinit(wpa_s->wpa);
973
974 old_ap_scan = wpa_s->conf->ap_scan;
975 wpa_config_free(wpa_s->conf);
976 wpa_s->conf = conf;
977 if (old_ap_scan != wpa_s->conf->ap_scan)
978 wpas_notify_ap_scan_changed(wpa_s);
979
980 if (reconf_ctrl)
981 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
982
983 wpa_supplicant_update_config(wpa_s);
984
985 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700986 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987 wpa_s->reassociate = 1;
988 wpa_supplicant_req_scan(wpa_s, 0, 0);
989 }
990 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
991 return 0;
992}
993
994
995static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
996{
997 struct wpa_global *global = signal_ctx;
998 struct wpa_supplicant *wpa_s;
999 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1000 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1001 sig);
1002 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1003 wpa_supplicant_terminate_proc(global);
1004 }
1005 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001006
1007 if (wpa_debug_reopen_file() < 0) {
1008 /* Ignore errors since we cannot really do much to fix this */
1009 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1010 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001011}
1012
1013
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001014static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1015 struct wpa_ssid *ssid,
1016 struct wpa_ie_data *ie)
1017{
1018 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1019 if (ret) {
1020 if (ret == -2) {
1021 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1022 "from association info");
1023 }
1024 return -1;
1025 }
1026
1027 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1028 "cipher suites");
1029 if (!(ie->group_cipher & ssid->group_cipher)) {
1030 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1031 "cipher 0x%x (mask 0x%x) - reject",
1032 ie->group_cipher, ssid->group_cipher);
1033 return -1;
1034 }
1035 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1036 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1037 "cipher 0x%x (mask 0x%x) - reject",
1038 ie->pairwise_cipher, ssid->pairwise_cipher);
1039 return -1;
1040 }
1041 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1042 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1043 "management 0x%x (mask 0x%x) - reject",
1044 ie->key_mgmt, ssid->key_mgmt);
1045 return -1;
1046 }
1047
1048#ifdef CONFIG_IEEE80211W
1049 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001050 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001051 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1052 "that does not support management frame protection - "
1053 "reject");
1054 return -1;
1055 }
1056#endif /* CONFIG_IEEE80211W */
1057
1058 return 0;
1059}
1060
1061
1062/**
1063 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1064 * @wpa_s: Pointer to wpa_supplicant data
1065 * @bss: Scan results for the selected BSS, or %NULL if not available
1066 * @ssid: Configuration data for the selected network
1067 * @wpa_ie: Buffer for the WPA/RSN IE
1068 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1069 * used buffer length in case the functions returns success.
1070 * Returns: 0 on success or -1 on failure
1071 *
1072 * This function is used to configure authentication and encryption parameters
1073 * based on the network configuration and scan result for the selected BSS (if
1074 * available).
1075 */
1076int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1077 struct wpa_bss *bss, struct wpa_ssid *ssid,
1078 u8 *wpa_ie, size_t *wpa_ie_len)
1079{
1080 struct wpa_ie_data ie;
1081 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001082 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001083
1084 if (bss) {
1085 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1086 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001087 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001089 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090
1091 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1092 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1093 (ie.group_cipher & ssid->group_cipher) &&
1094 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1095 (ie.key_mgmt & ssid->key_mgmt)) {
1096 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1097 proto = WPA_PROTO_RSN;
1098 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001099 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001100 (ie.group_cipher & ssid->group_cipher) &&
1101 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1102 (ie.key_mgmt & ssid->key_mgmt)) {
1103 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1104 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001105#ifdef CONFIG_HS20
1106 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1107 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1108 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001109 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001110 ie.group_cipher = WPA_CIPHER_CCMP;
1111 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1112 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1113 proto = WPA_PROTO_OSEN;
1114#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001115 } else if (bss) {
1116 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001117 wpa_dbg(wpa_s, MSG_DEBUG,
1118 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1119 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1120 ssid->key_mgmt);
1121 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1122 MAC2STR(bss->bssid),
1123 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1124 bss_wpa ? " WPA" : "",
1125 bss_rsn ? " RSN" : "",
1126 bss_osen ? " OSEN" : "");
1127 if (bss_rsn) {
1128 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1129 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1130 wpa_dbg(wpa_s, MSG_DEBUG,
1131 "Could not parse RSN element");
1132 } else {
1133 wpa_dbg(wpa_s, MSG_DEBUG,
1134 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1135 ie.pairwise_cipher, ie.group_cipher,
1136 ie.key_mgmt);
1137 }
1138 }
1139 if (bss_wpa) {
1140 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1141 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1142 wpa_dbg(wpa_s, MSG_DEBUG,
1143 "Could not parse WPA element");
1144 } else {
1145 wpa_dbg(wpa_s, MSG_DEBUG,
1146 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1147 ie.pairwise_cipher, ie.group_cipher,
1148 ie.key_mgmt);
1149 }
1150 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001151 return -1;
1152 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001153 if (ssid->proto & WPA_PROTO_OSEN)
1154 proto = WPA_PROTO_OSEN;
1155 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001156 proto = WPA_PROTO_RSN;
1157 else
1158 proto = WPA_PROTO_WPA;
1159 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1160 os_memset(&ie, 0, sizeof(ie));
1161 ie.group_cipher = ssid->group_cipher;
1162 ie.pairwise_cipher = ssid->pairwise_cipher;
1163 ie.key_mgmt = ssid->key_mgmt;
1164#ifdef CONFIG_IEEE80211W
1165 ie.mgmt_group_cipher =
1166 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1167 WPA_CIPHER_AES_128_CMAC : 0;
1168#endif /* CONFIG_IEEE80211W */
1169 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1170 "based on configuration");
1171 } else
1172 proto = ie.proto;
1173 }
1174
1175 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1176 "pairwise %d key_mgmt %d proto %d",
1177 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1178#ifdef CONFIG_IEEE80211W
1179 if (ssid->ieee80211w) {
1180 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1181 ie.mgmt_group_cipher);
1182 }
1183#endif /* CONFIG_IEEE80211W */
1184
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001185 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001186 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1187 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001188 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001189
1190 if (bss || !wpa_s->ap_ies_from_associnfo) {
1191 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1192 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1193 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1194 bss_rsn ? 2 + bss_rsn[1] : 0))
1195 return -1;
1196 }
1197
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001198#ifdef CONFIG_NO_WPA
1199 wpa_s->group_cipher = WPA_CIPHER_NONE;
1200 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1201#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001202 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001203 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1204 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001205 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1206 "cipher");
1207 return -1;
1208 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001209 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1210 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001211
1212 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001213 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1214 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001215 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1216 "cipher");
1217 return -1;
1218 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001219 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1220 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001221#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001222
1223 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001224#ifdef CONFIG_SAE
1225 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1226 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1227#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001228 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001229#ifdef CONFIG_SUITEB192
1230 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1231 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1232 wpa_dbg(wpa_s, MSG_DEBUG,
1233 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1234#endif /* CONFIG_SUITEB192 */
1235#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001236 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1237 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1238 wpa_dbg(wpa_s, MSG_DEBUG,
1239 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001240#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001241#ifdef CONFIG_FILS
1242#ifdef CONFIG_IEEE80211R
1243 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1244 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1245 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1246 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1247 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1248 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1249#endif /* CONFIG_IEEE80211R */
1250 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1251 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1252 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1253 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1254 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1255 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1256#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001257#ifdef CONFIG_IEEE80211R
1258 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1259 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1260 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1261 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1262 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1263 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1264#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001265#ifdef CONFIG_SAE
1266 } else if (sel & WPA_KEY_MGMT_SAE) {
1267 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1268 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1269 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1270 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1271 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1272#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001273#ifdef CONFIG_IEEE80211W
1274 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1275 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1276 wpa_dbg(wpa_s, MSG_DEBUG,
1277 "WPA: using KEY_MGMT 802.1X with SHA256");
1278 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1279 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1280 wpa_dbg(wpa_s, MSG_DEBUG,
1281 "WPA: using KEY_MGMT PSK with SHA256");
1282#endif /* CONFIG_IEEE80211W */
1283 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1284 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1285 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1286 } else if (sel & WPA_KEY_MGMT_PSK) {
1287 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1288 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1289 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1290 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1291 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001292#ifdef CONFIG_HS20
1293 } else if (sel & WPA_KEY_MGMT_OSEN) {
1294 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1295 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1296#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001297 } else {
1298 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1299 "authenticated key management type");
1300 return -1;
1301 }
1302
1303 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1304 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1305 wpa_s->pairwise_cipher);
1306 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1307
1308#ifdef CONFIG_IEEE80211W
1309 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001310 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001311 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1312 sel = 0;
1313 if (sel & WPA_CIPHER_AES_128_CMAC) {
1314 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1315 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1316 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001317 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1318 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1319 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1320 "BIP-GMAC-128");
1321 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1322 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1323 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1324 "BIP-GMAC-256");
1325 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1326 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1327 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1328 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001329 } else {
1330 wpa_s->mgmt_group_cipher = 0;
1331 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1332 }
1333 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1334 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001335 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001336 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001337#endif /* CONFIG_IEEE80211W */
1338
1339 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1340 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1341 return -1;
1342 }
1343
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001344 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001345 int psk_set = 0;
1346
1347 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001348 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1349 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001350 psk_set = 1;
1351 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001352#ifndef CONFIG_NO_PBKDF2
1353 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1354 ssid->passphrase) {
1355 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001356 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1357 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001358 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1359 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001360 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001361 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001362 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001363 }
1364#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001365#ifdef CONFIG_EXT_PASSWORD
1366 if (ssid->ext_psk) {
1367 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1368 ssid->ext_psk);
1369 char pw_str[64 + 1];
1370 u8 psk[PMK_LEN];
1371
1372 if (pw == NULL) {
1373 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1374 "found from external storage");
1375 return -1;
1376 }
1377
1378 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1379 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1380 "PSK length %d in external storage",
1381 (int) wpabuf_len(pw));
1382 ext_password_free(pw);
1383 return -1;
1384 }
1385
1386 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1387 pw_str[wpabuf_len(pw)] = '\0';
1388
1389#ifndef CONFIG_NO_PBKDF2
1390 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1391 {
1392 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1393 4096, psk, PMK_LEN);
1394 os_memset(pw_str, 0, sizeof(pw_str));
1395 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1396 "external passphrase)",
1397 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001398 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1399 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001400 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001401 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001402 } else
1403#endif /* CONFIG_NO_PBKDF2 */
1404 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1405 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1406 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1407 "Invalid PSK hex string");
1408 os_memset(pw_str, 0, sizeof(pw_str));
1409 ext_password_free(pw);
1410 return -1;
1411 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001412 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1413 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001414 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001415 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001416 } else {
1417 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1418 "PSK available");
1419 os_memset(pw_str, 0, sizeof(pw_str));
1420 ext_password_free(pw);
1421 return -1;
1422 }
1423
1424 os_memset(pw_str, 0, sizeof(pw_str));
1425 ext_password_free(pw);
1426 }
1427#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001428
1429 if (!psk_set) {
1430 wpa_msg(wpa_s, MSG_INFO,
1431 "No PSK available for association");
1432 return -1;
1433 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001434 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001435 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1436
1437 return 0;
1438}
1439
1440
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001441static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1442{
1443 *pos = 0x00;
1444
1445 switch (idx) {
1446 case 0: /* Bits 0-7 */
1447 break;
1448 case 1: /* Bits 8-15 */
1449 break;
1450 case 2: /* Bits 16-23 */
1451#ifdef CONFIG_WNM
1452 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1453 *pos |= 0x08; /* Bit 19 - BSS Transition */
1454#endif /* CONFIG_WNM */
1455 break;
1456 case 3: /* Bits 24-31 */
1457#ifdef CONFIG_WNM
1458 *pos |= 0x02; /* Bit 25 - SSID List */
1459#endif /* CONFIG_WNM */
1460#ifdef CONFIG_INTERWORKING
1461 if (wpa_s->conf->interworking)
1462 *pos |= 0x80; /* Bit 31 - Interworking */
1463#endif /* CONFIG_INTERWORKING */
1464 break;
1465 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001466#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001467 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1468 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001469#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001470 break;
1471 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001472#ifdef CONFIG_HS20
1473 if (wpa_s->conf->hs20)
1474 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1475#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001476#ifdef CONFIG_MBO
1477 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1478#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001479 break;
1480 case 6: /* Bits 48-55 */
1481 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001482 case 7: /* Bits 56-63 */
1483 break;
1484 case 8: /* Bits 64-71 */
1485 if (wpa_s->conf->ftm_responder)
1486 *pos |= 0x40; /* Bit 70 - FTM responder */
1487 if (wpa_s->conf->ftm_initiator)
1488 *pos |= 0x80; /* Bit 71 - FTM initiator */
1489 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001490 case 9: /* Bits 72-79 */
1491#ifdef CONFIG_FILS
1492 *pos |= 0x01;
1493#endif /* CONFIG_FILS */
1494 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001495 }
1496}
1497
1498
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001499int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001500{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001501 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001502 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001503
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001504 if (len < wpa_s->extended_capa_len)
1505 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001506 if (buflen < (size_t) len + 2) {
1507 wpa_printf(MSG_INFO,
1508 "Not enough room for building extended capabilities element");
1509 return -1;
1510 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001511
1512 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001513 *pos++ = len;
1514 for (i = 0; i < len; i++, pos++) {
1515 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001516
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001517 if (i < wpa_s->extended_capa_len) {
1518 *pos &= ~wpa_s->extended_capa_mask[i];
1519 *pos |= wpa_s->extended_capa[i];
1520 }
1521 }
1522
1523 while (len > 0 && buf[1 + len] == 0) {
1524 len--;
1525 buf[1] = len;
1526 }
1527 if (len == 0)
1528 return 0;
1529
1530 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001531}
1532
1533
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001534static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1535 struct wpa_bss *test_bss)
1536{
1537 struct wpa_bss *bss;
1538
1539 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1540 if (bss == test_bss)
1541 return 1;
1542 }
1543
1544 return 0;
1545}
1546
1547
1548static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1549 struct wpa_ssid *test_ssid)
1550{
1551 struct wpa_ssid *ssid;
1552
1553 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1554 if (ssid == test_ssid)
1555 return 1;
1556 }
1557
1558 return 0;
1559}
1560
1561
1562int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1563 struct wpa_ssid *test_ssid)
1564{
1565 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1566 return 0;
1567
1568 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1569}
1570
1571
1572void wpas_connect_work_free(struct wpa_connect_work *cwork)
1573{
1574 if (cwork == NULL)
1575 return;
1576 os_free(cwork);
1577}
1578
1579
1580void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1581{
1582 struct wpa_connect_work *cwork;
1583 struct wpa_radio_work *work = wpa_s->connect_work;
1584
1585 if (!work)
1586 return;
1587
1588 wpa_s->connect_work = NULL;
1589 cwork = work->ctx;
1590 work->ctx = NULL;
1591 wpas_connect_work_free(cwork);
1592 radio_work_done(work);
1593}
1594
1595
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001596int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1597{
1598 struct os_reltime now;
1599 u8 addr[ETH_ALEN];
1600
1601 os_get_reltime(&now);
1602 if (wpa_s->last_mac_addr_style == style &&
1603 wpa_s->last_mac_addr_change.sec != 0 &&
1604 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1605 wpa_s->conf->rand_addr_lifetime)) {
1606 wpa_msg(wpa_s, MSG_DEBUG,
1607 "Previously selected random MAC address has not yet expired");
1608 return 0;
1609 }
1610
1611 switch (style) {
1612 case 1:
1613 if (random_mac_addr(addr) < 0)
1614 return -1;
1615 break;
1616 case 2:
1617 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1618 if (random_mac_addr_keep_oui(addr) < 0)
1619 return -1;
1620 break;
1621 default:
1622 return -1;
1623 }
1624
1625 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1626 wpa_msg(wpa_s, MSG_INFO,
1627 "Failed to set random MAC address");
1628 return -1;
1629 }
1630
1631 os_get_reltime(&wpa_s->last_mac_addr_change);
1632 wpa_s->mac_addr_changed = 1;
1633 wpa_s->last_mac_addr_style = style;
1634
1635 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1636 wpa_msg(wpa_s, MSG_INFO,
1637 "Could not update MAC address information");
1638 return -1;
1639 }
1640
1641 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1642 MAC2STR(addr));
1643
1644 return 0;
1645}
1646
1647
1648int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1649{
1650 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1651 !wpa_s->conf->preassoc_mac_addr)
1652 return 0;
1653
1654 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1655}
1656
1657
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001658static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1659
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001660/**
1661 * wpa_supplicant_associate - Request association
1662 * @wpa_s: Pointer to wpa_supplicant data
1663 * @bss: Scan results for the selected BSS, or %NULL if not available
1664 * @ssid: Configuration data for the selected network
1665 *
1666 * This function is used to request %wpa_supplicant to associate with a BSS.
1667 */
1668void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1669 struct wpa_bss *bss, struct wpa_ssid *ssid)
1670{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001671 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001672 int rand_style;
1673
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001674 wpa_s->own_disconnect_req = 0;
1675
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001676 /*
1677 * If we are starting a new connection, any previously pending EAPOL
1678 * RX cannot be valid anymore.
1679 */
1680 wpabuf_free(wpa_s->pending_eapol_rx);
1681 wpa_s->pending_eapol_rx = NULL;
1682
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001683 if (ssid->mac_addr == -1)
1684 rand_style = wpa_s->conf->mac_addr;
1685 else
1686 rand_style = ssid->mac_addr;
1687
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001688 wmm_ac_clear_saved_tspecs(wpa_s);
1689 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001690 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001691
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001692 if (wpa_s->last_ssid == ssid) {
1693 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001694 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001695 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1696 wmm_ac_save_tspecs(wpa_s);
1697 wpa_s->reassoc_same_bss = 1;
1698 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001699 }
1700
1701 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001702 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1703 return;
1704 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001705 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001706 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1707 wpa_msg(wpa_s, MSG_INFO,
1708 "Could not restore permanent MAC address");
1709 return;
1710 }
1711 wpa_s->mac_addr_changed = 0;
1712 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1713 wpa_msg(wpa_s, MSG_INFO,
1714 "Could not update MAC address information");
1715 return;
1716 }
1717 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1718 }
1719 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720
1721#ifdef CONFIG_IBSS_RSN
1722 ibss_rsn_deinit(wpa_s->ibss_rsn);
1723 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001724#else /* CONFIG_IBSS_RSN */
1725 if (ssid->mode == WPAS_MODE_IBSS &&
1726 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1727 wpa_msg(wpa_s, MSG_INFO,
1728 "IBSS RSN not supported in the build");
1729 return;
1730 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001731#endif /* CONFIG_IBSS_RSN */
1732
1733 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1734 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1735#ifdef CONFIG_AP
1736 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1737 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1738 "mode");
1739 return;
1740 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001741 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1742 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001743 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1744 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001745 return;
1746 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001747 wpa_s->current_bss = bss;
1748#else /* CONFIG_AP */
1749 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1750 "the build");
1751#endif /* CONFIG_AP */
1752 return;
1753 }
1754
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001755 if (ssid->mode == WPAS_MODE_MESH) {
1756#ifdef CONFIG_MESH
1757 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1758 wpa_msg(wpa_s, MSG_INFO,
1759 "Driver does not support mesh mode");
1760 return;
1761 }
1762 if (bss)
1763 ssid->frequency = bss->freq;
1764 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1765 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1766 return;
1767 }
1768 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001769 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1770 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1771 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001772#else /* CONFIG_MESH */
1773 wpa_msg(wpa_s, MSG_ERROR,
1774 "mesh mode support not included in the build");
1775#endif /* CONFIG_MESH */
1776 return;
1777 }
1778
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001779#ifdef CONFIG_TDLS
1780 if (bss)
1781 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1782 bss->ie_len);
1783#endif /* CONFIG_TDLS */
1784
1785 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1786 ssid->mode == IEEE80211_MODE_INFRA) {
1787 sme_authenticate(wpa_s, bss, ssid);
1788 return;
1789 }
1790
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001791 if (wpa_s->connect_work) {
1792 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1793 return;
1794 }
1795
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001796 if (radio_work_pending(wpa_s, "connect")) {
1797 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1798 return;
1799 }
1800
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001801 wpas_abort_ongoing_scan(wpa_s);
1802
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001803 cwork = os_zalloc(sizeof(*cwork));
1804 if (cwork == NULL)
1805 return;
1806
1807 cwork->bss = bss;
1808 cwork->ssid = ssid;
1809
1810 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1811 wpas_start_assoc_cb, cwork) < 0) {
1812 os_free(cwork);
1813 }
1814}
1815
1816
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001817static int bss_is_ibss(struct wpa_bss *bss)
1818{
1819 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1820 IEEE80211_CAP_IBSS;
1821}
1822
1823
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001824static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1825 const struct wpa_ssid *ssid)
1826{
1827 enum hostapd_hw_mode hw_mode;
1828 struct hostapd_hw_modes *mode = NULL;
1829 u8 channel;
1830 int i;
1831
1832#ifdef CONFIG_HT_OVERRIDES
1833 if (ssid->disable_ht)
1834 return 0;
1835#endif /* CONFIG_HT_OVERRIDES */
1836
1837 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1838 if (hw_mode == NUM_HOSTAPD_MODES)
1839 return 0;
1840 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1841 if (wpa_s->hw.modes[i].mode == hw_mode) {
1842 mode = &wpa_s->hw.modes[i];
1843 break;
1844 }
1845 }
1846
1847 if (!mode)
1848 return 0;
1849
1850 return mode->vht_capab != 0;
1851}
1852
1853
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001854void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1855 const struct wpa_ssid *ssid,
1856 struct hostapd_freq_params *freq)
1857{
1858 enum hostapd_hw_mode hw_mode;
1859 struct hostapd_hw_modes *mode = NULL;
1860 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1861 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001862 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001863 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1864 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001865 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001866 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001867 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001868 int chwidth, seg0, seg1;
1869 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001870
1871 freq->freq = ssid->frequency;
1872
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001873 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1874 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1875
1876 if (ssid->mode != WPAS_MODE_IBSS)
1877 break;
1878
1879 /* Don't adjust control freq in case of fixed_freq */
1880 if (ssid->fixed_freq)
1881 break;
1882
1883 if (!bss_is_ibss(bss))
1884 continue;
1885
1886 if (ssid->ssid_len == bss->ssid_len &&
1887 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1888 wpa_printf(MSG_DEBUG,
1889 "IBSS already found in scan results, adjust control freq: %d",
1890 bss->freq);
1891 freq->freq = bss->freq;
1892 obss_scan = 0;
1893 break;
1894 }
1895 }
1896
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001897 /* For IBSS check HT_IBSS flag */
1898 if (ssid->mode == WPAS_MODE_IBSS &&
1899 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1900 return;
1901
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001902 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1903 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1904 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1905 wpa_printf(MSG_DEBUG,
1906 "IBSS: WEP/TKIP detected, do not try to enable HT");
1907 return;
1908 }
1909
1910 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001911 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1912 if (wpa_s->hw.modes[i].mode == hw_mode) {
1913 mode = &wpa_s->hw.modes[i];
1914 break;
1915 }
1916 }
1917
1918 if (!mode)
1919 return;
1920
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001921#ifdef CONFIG_HT_OVERRIDES
1922 if (ssid->disable_ht) {
1923 freq->ht_enabled = 0;
1924 return;
1925 }
1926#endif /* CONFIG_HT_OVERRIDES */
1927
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001928 freq->ht_enabled = ht_supported(mode);
1929 if (!freq->ht_enabled)
1930 return;
1931
1932 /* Setup higher BW only for 5 GHz */
1933 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1934 return;
1935
1936 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1937 pri_chan = &mode->channels[chan_idx];
1938 if (pri_chan->chan == channel)
1939 break;
1940 pri_chan = NULL;
1941 }
1942 if (!pri_chan)
1943 return;
1944
1945 /* Check primary channel flags */
1946 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1947 return;
1948
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001949#ifdef CONFIG_HT_OVERRIDES
1950 if (ssid->disable_ht40)
1951 return;
1952#endif /* CONFIG_HT_OVERRIDES */
1953
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001954 /* Check/setup HT40+/HT40- */
1955 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1956 if (ht40plus[j] == channel) {
1957 ht40 = 1;
1958 break;
1959 }
1960 }
1961
1962 /* Find secondary channel */
1963 for (i = 0; i < mode->num_channels; i++) {
1964 sec_chan = &mode->channels[i];
1965 if (sec_chan->chan == channel + ht40 * 4)
1966 break;
1967 sec_chan = NULL;
1968 }
1969 if (!sec_chan)
1970 return;
1971
1972 /* Check secondary channel flags */
1973 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1974 return;
1975
1976 freq->channel = pri_chan->chan;
1977
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001978 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001979 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1980 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001981 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001982 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1983 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001984 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001985 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001986
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001987 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001988 struct wpa_scan_results *scan_res;
1989
1990 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1991 if (scan_res == NULL) {
1992 /* Back to HT20 */
1993 freq->sec_channel_offset = 0;
1994 return;
1995 }
1996
1997 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1998 sec_chan->chan);
1999 switch (res) {
2000 case 0:
2001 /* Back to HT20 */
2002 freq->sec_channel_offset = 0;
2003 break;
2004 case 1:
2005 /* Configuration allowed */
2006 break;
2007 case 2:
2008 /* Switch pri/sec channels */
2009 freq->freq = hw_get_freq(mode, sec_chan->chan);
2010 freq->sec_channel_offset = -freq->sec_channel_offset;
2011 freq->channel = sec_chan->chan;
2012 break;
2013 default:
2014 freq->sec_channel_offset = 0;
2015 break;
2016 }
2017
2018 wpa_scan_results_free(scan_res);
2019 }
2020
2021 wpa_printf(MSG_DEBUG,
2022 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2023 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002024
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002025 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002026 return;
2027
2028 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002029 if (ssid->mode == WPAS_MODE_IBSS &&
2030 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002031 return;
2032
2033 vht_freq = *freq;
2034
2035 vht_freq.vht_enabled = vht_supported(mode);
2036 if (!vht_freq.vht_enabled)
2037 return;
2038
2039 /* setup center_freq1, bandwidth */
2040 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2041 if (freq->channel >= vht80[j] &&
2042 freq->channel < vht80[j] + 16)
2043 break;
2044 }
2045
2046 if (j == ARRAY_SIZE(vht80))
2047 return;
2048
2049 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2050 struct hostapd_channel_data *chan;
2051
2052 chan = hw_get_channel_chan(mode, i, NULL);
2053 if (!chan)
2054 return;
2055
2056 /* Back to HT configuration if channel not usable */
2057 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2058 return;
2059 }
2060
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002061 chwidth = VHT_CHANWIDTH_80MHZ;
2062 seg0 = vht80[j] + 6;
2063 seg1 = 0;
2064
2065 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2066 /* setup center_freq2, bandwidth */
2067 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2068 /* Only accept 80 MHz segments separated by a gap */
2069 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2070 continue;
2071 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2072 struct hostapd_channel_data *chan;
2073
2074 chan = hw_get_channel_chan(mode, i, NULL);
2075 if (!chan)
2076 continue;
2077
2078 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2079 HOSTAPD_CHAN_NO_IR |
2080 HOSTAPD_CHAN_RADAR))
2081 continue;
2082
2083 /* Found a suitable second segment for 80+80 */
2084 chwidth = VHT_CHANWIDTH_80P80MHZ;
2085 vht_caps |=
2086 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2087 seg1 = vht80[k] + 6;
2088 }
2089
2090 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2091 break;
2092 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002093 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2094 if (freq->freq == 5180) {
2095 chwidth = VHT_CHANWIDTH_160MHZ;
2096 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2097 seg0 = 50;
2098 } else if (freq->freq == 5520) {
2099 chwidth = VHT_CHANWIDTH_160MHZ;
2100 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2101 seg0 = 114;
2102 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002103 }
2104
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002105 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2106 freq->channel, freq->ht_enabled,
2107 vht_freq.vht_enabled,
2108 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002109 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002110 return;
2111
2112 *freq = vht_freq;
2113
2114 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2115 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002116}
2117
2118
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002119static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2120{
2121 struct wpa_connect_work *cwork = work->ctx;
2122 struct wpa_bss *bss = cwork->bss;
2123 struct wpa_ssid *ssid = cwork->ssid;
2124 struct wpa_supplicant *wpa_s = work->wpa_s;
2125 u8 wpa_ie[200];
2126 size_t wpa_ie_len;
2127 int use_crypt, ret, i, bssid_changed;
2128 int algs = WPA_AUTH_ALG_OPEN;
2129 unsigned int cipher_pairwise, cipher_group;
2130 struct wpa_driver_associate_params params;
2131 int wep_keys_set = 0;
2132 int assoc_failed = 0;
2133 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002134 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002135#ifdef CONFIG_HT_OVERRIDES
2136 struct ieee80211_ht_capabilities htcaps;
2137 struct ieee80211_ht_capabilities htcaps_mask;
2138#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002139#ifdef CONFIG_VHT_OVERRIDES
2140 struct ieee80211_vht_capabilities vhtcaps;
2141 struct ieee80211_vht_capabilities vhtcaps_mask;
2142#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002143#ifdef CONFIG_MBO
2144 const u8 *mbo = NULL;
2145#endif /* CONFIG_MBO */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002146
2147 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002148 if (work->started) {
2149 wpa_s->connect_work = NULL;
2150
2151 /* cancel possible auth. timeout */
2152 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2153 NULL);
2154 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002155 wpas_connect_work_free(cwork);
2156 return;
2157 }
2158
2159 wpa_s->connect_work = work;
2160
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002161 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2162 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002163 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2164 wpas_connect_work_done(wpa_s);
2165 return;
2166 }
2167
Dmitry Shmidte4663042016-04-04 10:07:49 -07002168 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169 os_memset(&params, 0, sizeof(params));
2170 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002171 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002172 if (bss &&
2173 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002174#ifdef CONFIG_IEEE80211R
2175 const u8 *ie, *md = NULL;
2176#endif /* CONFIG_IEEE80211R */
2177 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2178 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2179 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2180 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2181 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2182 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2183 if (bssid_changed)
2184 wpas_notify_bssid_changed(wpa_s);
2185#ifdef CONFIG_IEEE80211R
2186 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2187 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2188 md = ie + 2;
2189 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2190 if (md) {
2191 /* Prepare for the next transition */
2192 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2193 }
2194#endif /* CONFIG_IEEE80211R */
2195#ifdef CONFIG_WPS
2196 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2197 wpa_s->conf->ap_scan == 2 &&
2198 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2199 /* Use ap_scan==1 style network selection to find the network
2200 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002201 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002202 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002203 wpa_s->reassociate = 1;
2204 wpa_supplicant_req_scan(wpa_s, 0, 0);
2205 return;
2206#endif /* CONFIG_WPS */
2207 } else {
2208 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2209 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002210 if (bss)
2211 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2212 else
2213 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002214 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002215 if (!wpa_s->pno)
2216 wpa_supplicant_cancel_sched_scan(wpa_s);
2217
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002218 wpa_supplicant_cancel_scan(wpa_s);
2219
2220 /* Starting new association, so clear the possibly used WPA IE from the
2221 * previous association. */
2222 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2223
2224#ifdef IEEE8021X_EAPOL
2225 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2226 if (ssid->leap) {
2227 if (ssid->non_leap == 0)
2228 algs = WPA_AUTH_ALG_LEAP;
2229 else
2230 algs |= WPA_AUTH_ALG_LEAP;
2231 }
2232 }
2233#endif /* IEEE8021X_EAPOL */
2234 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2235 if (ssid->auth_alg) {
2236 algs = ssid->auth_alg;
2237 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2238 "0x%x", algs);
2239 }
2240
2241 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2242 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002243 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002244 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002245 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2246 wpa_s->conf->okc :
2247 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002248 (ssid->proto & WPA_PROTO_RSN);
2249 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002250 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002251 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002252 wpa_ie_len = sizeof(wpa_ie);
2253 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2254 wpa_ie, &wpa_ie_len)) {
2255 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2256 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002257 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 return;
2259 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002260 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2261 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2262 /*
2263 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2264 * use non-WPA since the scan results did not indicate that the
2265 * AP is using WPA or WPA2.
2266 */
2267 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2268 wpa_ie_len = 0;
2269 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002270 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002271 wpa_ie_len = sizeof(wpa_ie);
2272 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2273 wpa_ie, &wpa_ie_len)) {
2274 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2275 "key management and encryption suites (no "
2276 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002277 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002278 return;
2279 }
2280#ifdef CONFIG_WPS
2281 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2282 struct wpabuf *wps_ie;
2283 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2284 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2285 wpa_ie_len = wpabuf_len(wps_ie);
2286 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2287 } else
2288 wpa_ie_len = 0;
2289 wpabuf_free(wps_ie);
2290 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2291 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2292 params.wps = WPS_MODE_PRIVACY;
2293 else
2294 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002295 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296#endif /* CONFIG_WPS */
2297 } else {
2298 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2299 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002300 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301 }
2302
2303#ifdef CONFIG_P2P
2304 if (wpa_s->global->p2p) {
2305 u8 *pos;
2306 size_t len;
2307 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002308 pos = wpa_ie + wpa_ie_len;
2309 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002310 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2311 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002312 if (res >= 0)
2313 wpa_ie_len += res;
2314 }
2315
2316 wpa_s->cross_connect_disallowed = 0;
2317 if (bss) {
2318 struct wpabuf *p2p;
2319 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2320 if (p2p) {
2321 wpa_s->cross_connect_disallowed =
2322 p2p_get_cross_connect_disallowed(p2p);
2323 wpabuf_free(p2p);
2324 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2325 "connection",
2326 wpa_s->cross_connect_disallowed ?
2327 "disallows" : "allows");
2328 }
2329 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002330
2331 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002332#endif /* CONFIG_P2P */
2333
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002334#ifdef CONFIG_MBO
2335 if (bss) {
2336 mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
2337 if (mbo) {
2338 int len;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002339
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002340 len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq,
2341 wpa_ie + wpa_ie_len,
2342 sizeof(wpa_ie) -
2343 wpa_ie_len);
2344 if (len > 0)
2345 wpa_ie_len += len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002346 }
2347 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002348#endif /* CONFIG_MBO */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002349
Dmitry Shmidt56052862013-10-04 10:23:25 -07002350 /*
2351 * Workaround: Add Extended Capabilities element only if the AP
2352 * included this element in Beacon/Probe Response frames. Some older
2353 * APs seem to have interoperability issues if this element is
2354 * included, so while the standard may require us to include the
2355 * element in all cases, it is justifiable to skip it to avoid
2356 * interoperability issues.
2357 */
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002358 if (ssid->p2p_group)
2359 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2360 else
2361 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2362
Dmitry Shmidt56052862013-10-04 10:23:25 -07002363 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002364 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002365 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002366 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2367 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002368 if (ext_capab_len > 0) {
2369 u8 *pos = wpa_ie;
2370 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2371 pos += 2 + pos[1];
2372 os_memmove(pos + ext_capab_len, pos,
2373 wpa_ie_len - (pos - wpa_ie));
2374 wpa_ie_len += ext_capab_len;
2375 os_memcpy(pos, ext_capab, ext_capab_len);
2376 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002377 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002378
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002379#ifdef CONFIG_HS20
2380 if (is_hs20_network(wpa_s, ssid, bss)) {
2381 struct wpabuf *hs20;
2382
2383 hs20 = wpabuf_alloc(20);
2384 if (hs20) {
2385 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2386 size_t len;
2387
2388 wpas_hs20_add_indication(hs20, pps_mo_id);
2389 len = sizeof(wpa_ie) - wpa_ie_len;
2390 if (wpabuf_len(hs20) <= len) {
2391 os_memcpy(wpa_ie + wpa_ie_len,
2392 wpabuf_head(hs20), wpabuf_len(hs20));
2393 wpa_ie_len += wpabuf_len(hs20);
2394 }
2395 wpabuf_free(hs20);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002396
2397 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002398 }
2399 }
2400#endif /* CONFIG_HS20 */
2401
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002402 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2403 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2404 size_t len;
2405
2406 len = sizeof(wpa_ie) - wpa_ie_len;
2407 if (wpabuf_len(buf) <= len) {
2408 os_memcpy(wpa_ie + wpa_ie_len,
2409 wpabuf_head(buf), wpabuf_len(buf));
2410 wpa_ie_len += wpabuf_len(buf);
2411 }
2412 }
2413
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002414#ifdef CONFIG_FST
2415 if (wpa_s->fst_ies) {
2416 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2417
2418 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2419 os_memcpy(wpa_ie + wpa_ie_len,
2420 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2421 wpa_ie_len += fst_ies_len;
2422 }
2423 }
2424#endif /* CONFIG_FST */
2425
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002426#ifdef CONFIG_MBO
2427 if (mbo) {
2428 int len;
2429
2430 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2431 sizeof(wpa_ie) - wpa_ie_len);
2432 if (len >= 0)
2433 wpa_ie_len += len;
2434 }
2435#endif /* CONFIG_MBO */
2436
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002437 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2438 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002439 cipher_pairwise = wpa_s->pairwise_cipher;
2440 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2442 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2443 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2444 use_crypt = 0;
2445 if (wpa_set_wep_keys(wpa_s, ssid)) {
2446 use_crypt = 1;
2447 wep_keys_set = 1;
2448 }
2449 }
2450 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2451 use_crypt = 0;
2452
2453#ifdef IEEE8021X_EAPOL
2454 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2455 if ((ssid->eapol_flags &
2456 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2457 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2458 !wep_keys_set) {
2459 use_crypt = 0;
2460 } else {
2461 /* Assume that dynamic WEP-104 keys will be used and
2462 * set cipher suites in order for drivers to expect
2463 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002464 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465 }
2466 }
2467#endif /* IEEE8021X_EAPOL */
2468
2469 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2470 /* Set the key before (and later after) association */
2471 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2472 }
2473
2474 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2475 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 params.ssid = bss->ssid;
2477 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002478 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2479 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002480 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2481 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002482 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002483 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002484 ssid->bssid_set,
2485 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002486 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002487 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002488 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002489 params.bssid_hint = bss->bssid;
2490 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002491 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 } else {
2493 params.ssid = ssid->ssid;
2494 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002495 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002497
2498 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2499 wpa_s->conf->ap_scan == 2) {
2500 params.bssid = ssid->bssid;
2501 params.fixed_bssid = 1;
2502 }
2503
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002504 /* Initial frequency for IBSS/mesh */
2505 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002506 ssid->frequency > 0 && params.freq.freq == 0)
2507 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002508
2509 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002510 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002511 if (ssid->beacon_int)
2512 params.beacon_int = ssid->beacon_int;
2513 else
2514 params.beacon_int = wpa_s->conf->beacon_int;
2515 }
2516
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 params.wpa_ie = wpa_ie;
2518 params.wpa_ie_len = wpa_ie_len;
2519 params.pairwise_suite = cipher_pairwise;
2520 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002521 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002522 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 params.auth_alg = algs;
2524 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002525 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 for (i = 0; i < NUM_WEP_KEYS; i++) {
2527 if (ssid->wep_key_len[i])
2528 params.wep_key[i] = ssid->wep_key[i];
2529 params.wep_key_len[i] = ssid->wep_key_len[i];
2530 }
2531 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2532
2533 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002534 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2535 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002536 params.passphrase = ssid->passphrase;
2537 if (ssid->psk_set)
2538 params.psk = ssid->psk;
2539 }
2540
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002541 if (wpa_s->conf->key_mgmt_offload) {
2542 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2543 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002544 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2545 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002546 params.req_key_mgmt_offload =
2547 ssid->proactive_key_caching < 0 ?
2548 wpa_s->conf->okc : ssid->proactive_key_caching;
2549 else
2550 params.req_key_mgmt_offload = 1;
2551
2552 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2553 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2554 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2555 ssid->psk_set)
2556 params.psk = ssid->psk;
2557 }
2558
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559 params.drop_unencrypted = use_crypt;
2560
2561#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002562 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002563 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2565 struct wpa_ie_data ie;
2566 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2567 ie.capabilities &
2568 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2569 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2570 "MFP: require MFP");
2571 params.mgmt_frame_protection =
2572 MGMT_FRAME_PROTECTION_REQUIRED;
2573 }
2574 }
2575#endif /* CONFIG_IEEE80211W */
2576
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002577 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002579 if (wpa_s->p2pdev->set_sta_uapsd)
2580 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 else
2582 params.uapsd = -1;
2583
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002584#ifdef CONFIG_HT_OVERRIDES
2585 os_memset(&htcaps, 0, sizeof(htcaps));
2586 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2587 params.htcaps = (u8 *) &htcaps;
2588 params.htcaps_mask = (u8 *) &htcaps_mask;
2589 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2590#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002591#ifdef CONFIG_VHT_OVERRIDES
2592 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2593 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2594 params.vhtcaps = &vhtcaps;
2595 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002596 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002597#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002598
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002599#ifdef CONFIG_P2P
2600 /*
2601 * If multi-channel concurrency is not supported, check for any
2602 * frequency conflict. In case of any frequency conflict, remove the
2603 * least prioritized connection.
2604 */
2605 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002606 int freq, num;
2607 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002608 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002609 wpa_printf(MSG_DEBUG,
2610 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002611 freq, params.freq.freq);
2612 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002613 wpa_s, params.freq.freq, ssid) < 0) {
2614 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002615 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002616 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002617 }
2618 }
2619#endif /* CONFIG_P2P */
2620
Dmitry Shmidte4663042016-04-04 10:07:49 -07002621 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2622 wpa_s->current_ssid)
2623 params.prev_bssid = prev_bssid;
2624
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002625 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626 if (ret < 0) {
2627 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2628 "failed");
2629 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2630 /*
2631 * The driver is known to mean what is saying, so we
2632 * can stop right here; the association will not
2633 * succeed.
2634 */
2635 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002636 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002637 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2638 return;
2639 }
2640 /* try to continue anyway; new association will be tried again
2641 * after timeout */
2642 assoc_failed = 1;
2643 }
2644
2645 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2646 /* Set the key after the association just in case association
2647 * cleared the previously configured key. */
2648 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2649 /* No need to timeout authentication since there is no key
2650 * management. */
2651 wpa_supplicant_cancel_auth_timeout(wpa_s);
2652 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2653#ifdef CONFIG_IBSS_RSN
2654 } else if (ssid->mode == WPAS_MODE_IBSS &&
2655 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2656 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2657 /*
2658 * RSN IBSS authentication is per-STA and we can disable the
2659 * per-BSSID authentication.
2660 */
2661 wpa_supplicant_cancel_auth_timeout(wpa_s);
2662#endif /* CONFIG_IBSS_RSN */
2663 } else {
2664 /* Timeout for IEEE 802.11 authentication and association */
2665 int timeout = 60;
2666
2667 if (assoc_failed) {
2668 /* give IBSS a bit more time */
2669 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2670 } else if (wpa_s->conf->ap_scan == 1) {
2671 /* give IBSS a bit more time */
2672 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2673 }
2674 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2675 }
2676
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002677 if (wep_keys_set &&
2678 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002679 /* Set static WEP keys again */
2680 wpa_set_wep_keys(wpa_s, ssid);
2681 }
2682
2683 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2684 /*
2685 * Do not allow EAP session resumption between different
2686 * network configurations.
2687 */
2688 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2689 }
2690 old_ssid = wpa_s->current_ssid;
2691 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002692
2693 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002694 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002695#ifdef CONFIG_HS20
2696 hs20_configure_frame_filters(wpa_s);
2697#endif /* CONFIG_HS20 */
2698 }
2699
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002700 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2701 wpa_supplicant_initiate_eapol(wpa_s);
2702 if (old_ssid != wpa_s->current_ssid)
2703 wpas_notify_network_changed(wpa_s);
2704}
2705
2706
2707static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2708 const u8 *addr)
2709{
2710 struct wpa_ssid *old_ssid;
2711
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002712 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002715 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002716 wpa_sm_set_config(wpa_s->wpa, NULL);
2717 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2718 if (old_ssid != wpa_s->current_ssid)
2719 wpas_notify_network_changed(wpa_s);
2720 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2721}
2722
2723
2724/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002725 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2726 * @wpa_s: Pointer to wpa_supplicant data
2727 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2728 *
2729 * This function is used to request %wpa_supplicant to deauthenticate from the
2730 * current AP.
2731 */
2732void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2733 int reason_code)
2734{
2735 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002736 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002737 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002739 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2740 " pending_bssid=" MACSTR " reason=%d state=%s",
2741 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2742 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2743
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002744 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2745 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2746 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002747 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002748 else if (!is_zero_ether_addr(wpa_s->bssid))
2749 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002750 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2751 /*
2752 * When using driver-based BSS selection, we may not know the
2753 * BSSID with which we are currently trying to associate. We
2754 * need to notify the driver of this disconnection even in such
2755 * a case, so use the all zeros address here.
2756 */
2757 addr = wpa_s->bssid;
2758 zero_addr = 1;
2759 }
2760
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002761#ifdef CONFIG_TDLS
2762 wpa_tdls_teardown_peers(wpa_s->wpa);
2763#endif /* CONFIG_TDLS */
2764
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002765#ifdef CONFIG_MESH
2766 if (wpa_s->ifmsh) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002767 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2768 wpa_s->ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002769 wpa_supplicant_leave_mesh(wpa_s);
2770 }
2771#endif /* CONFIG_MESH */
2772
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002773 if (addr) {
2774 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002775 os_memset(&event, 0, sizeof(event));
2776 event.deauth_info.reason_code = (u16) reason_code;
2777 event.deauth_info.locally_generated = 1;
2778 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002779 if (zero_addr)
2780 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002781 }
2782
2783 wpa_supplicant_clear_connection(wpa_s, addr);
2784}
2785
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002786static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2787 struct wpa_ssid *ssid)
2788{
2789 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2790 return;
2791
2792 ssid->disabled = 0;
2793 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2794 wpas_notify_network_enabled_changed(wpa_s, ssid);
2795
2796 /*
2797 * Try to reassociate since there is no current configuration and a new
2798 * network was made available.
2799 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002800 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002801 wpa_s->reassociate = 1;
2802}
2803
Roshan Pius950bec92016-07-19 09:49:24 -07002804/**
2805 * wpa_supplicant_add_network - Add a new network.
2806 * @wpa_s: wpa_supplicant structure for a network interface
2807 * Returns: The new network configuration or %NULL if operation failed
2808 *
2809 * This function performs the following operations:
2810 * 1. Adds a new network.
2811 * 2. Send network addition notification.
2812 * 3. Marks the network disabled.
2813 * 4. Set network default parameters.
2814 */
2815struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2816{
2817 struct wpa_ssid *ssid;
2818
2819 ssid = wpa_config_add_network(wpa_s->conf);
2820 if (!ssid) {
2821 return NULL;
2822 }
2823 wpas_notify_network_added(wpa_s, ssid);
2824 ssid->disabled = 1;
2825 wpa_config_set_network_defaults(ssid);
2826
2827 return ssid;
2828}
2829
2830/**
2831 * wpa_supplicant_remove_network - Remove a configured network based on id
2832 * @wpa_s: wpa_supplicant structure for a network interface
2833 * @id: Unique network id to search for
2834 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2835 * could not be removed
2836 *
2837 * This function performs the following operations:
2838 * 1. Removes the network.
2839 * 2. Send network removal notification.
2840 * 3. Update internal state machines.
2841 * 4. Stop any running sched scans.
2842 */
2843int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2844{
2845 struct wpa_ssid *ssid;
2846 int was_disabled;
2847
2848 ssid = wpa_config_get_network(wpa_s->conf, id);
2849 if (ssid)
2850 wpas_notify_network_removed(wpa_s, ssid);
2851 if (ssid == NULL) {
2852 return -1;
2853 }
2854
2855 if (wpa_s->last_ssid == ssid)
2856 wpa_s->last_ssid = NULL;
2857
2858 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2859#ifdef CONFIG_SME
2860 wpa_s->sme.prev_bssid_set = 0;
2861#endif /* CONFIG_SME */
2862 /*
2863 * Invalidate the EAP session cache if the current or
2864 * previously used network is removed.
2865 */
2866 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2867 }
2868
2869 if (ssid == wpa_s->current_ssid) {
2870 wpa_sm_set_config(wpa_s->wpa, NULL);
2871 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2872
2873 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2874 wpa_s->own_disconnect_req = 1;
2875 wpa_supplicant_deauthenticate(wpa_s,
2876 WLAN_REASON_DEAUTH_LEAVING);
2877 }
2878
2879 was_disabled = ssid->disabled;
2880
2881 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2882 return -2;
2883 }
2884
2885 if (!was_disabled && wpa_s->sched_scanning) {
2886 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2887 "network from filters");
2888 wpa_supplicant_cancel_sched_scan(wpa_s);
2889 wpa_supplicant_req_scan(wpa_s, 0, 0);
2890 }
2891 return 0;
2892}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002893
2894/**
2895 * wpa_supplicant_enable_network - Mark a configured network as enabled
2896 * @wpa_s: wpa_supplicant structure for a network interface
2897 * @ssid: wpa_ssid structure for a configured network or %NULL
2898 *
2899 * Enables the specified network or all networks if no network specified.
2900 */
2901void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2902 struct wpa_ssid *ssid)
2903{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002905 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2906 wpa_supplicant_enable_one_network(wpa_s, ssid);
2907 } else
2908 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002909
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002910 if (wpa_s->reassociate && !wpa_s->disconnected &&
2911 (!wpa_s->current_ssid ||
2912 wpa_s->wpa_state == WPA_DISCONNECTED ||
2913 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002914 if (wpa_s->sched_scanning) {
2915 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2916 "new network to scan filters");
2917 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002918 }
2919
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002920 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2921 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002922 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002923 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 }
2925}
2926
2927
2928/**
2929 * wpa_supplicant_disable_network - Mark a configured network as disabled
2930 * @wpa_s: wpa_supplicant structure for a network interface
2931 * @ssid: wpa_ssid structure for a configured network or %NULL
2932 *
2933 * Disables the specified network or all networks if no network specified.
2934 */
2935void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2936 struct wpa_ssid *ssid)
2937{
2938 struct wpa_ssid *other_ssid;
2939 int was_disabled;
2940
2941 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002942 if (wpa_s->sched_scanning)
2943 wpa_supplicant_cancel_sched_scan(wpa_s);
2944
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002945 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2946 other_ssid = other_ssid->next) {
2947 was_disabled = other_ssid->disabled;
2948 if (was_disabled == 2)
2949 continue; /* do not change persistent P2P group
2950 * data */
2951
2952 other_ssid->disabled = 1;
2953
2954 if (was_disabled != other_ssid->disabled)
2955 wpas_notify_network_enabled_changed(
2956 wpa_s, other_ssid);
2957 }
2958 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002959 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002960 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2961 } else if (ssid->disabled != 2) {
2962 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002963 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2965
2966 was_disabled = ssid->disabled;
2967
2968 ssid->disabled = 1;
2969
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002970 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002971 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002972 if (wpa_s->sched_scanning) {
2973 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2974 "to remove network from filters");
2975 wpa_supplicant_cancel_sched_scan(wpa_s);
2976 wpa_supplicant_req_scan(wpa_s, 0, 0);
2977 }
2978 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002979 }
2980}
2981
2982
2983/**
2984 * wpa_supplicant_select_network - Attempt association with a network
2985 * @wpa_s: wpa_supplicant structure for a network interface
2986 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2987 */
2988void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2989 struct wpa_ssid *ssid)
2990{
2991
2992 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002993 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002994
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002995 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002996 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2997 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002998 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002999 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003000 disconnected = 1;
3001 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003002
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003003 if (ssid)
3004 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3005
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003006 /*
3007 * Mark all other networks disabled or mark all networks enabled if no
3008 * network specified.
3009 */
3010 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3011 other_ssid = other_ssid->next) {
3012 int was_disabled = other_ssid->disabled;
3013 if (was_disabled == 2)
3014 continue; /* do not change persistent P2P group data */
3015
3016 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003017 if (was_disabled && !other_ssid->disabled)
3018 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003019
3020 if (was_disabled != other_ssid->disabled)
3021 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3022 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003023
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003024 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3025 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003026 /* We are already associated with the selected network */
3027 wpa_printf(MSG_DEBUG, "Already associated with the "
3028 "selected network - do nothing");
3029 return;
3030 }
3031
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003032 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003033 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003034 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003035 wpa_s->connect_without_scan =
3036 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003037
3038 /*
3039 * Don't optimize next scan freqs since a new ESS has been
3040 * selected.
3041 */
3042 os_free(wpa_s->next_scan_freqs);
3043 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003044 } else {
3045 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003046 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003047
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003048 wpa_s->disconnected = 0;
3049 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003050
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003051 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003052 wpa_supplicant_fast_associate(wpa_s) != 1) {
3053 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003054 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003055 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003056 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003057
3058 if (ssid)
3059 wpas_notify_network_selected(wpa_s, ssid);
3060}
3061
3062
3063/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003064 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3065 * @wpa_s: wpa_supplicant structure for a network interface
3066 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3067 * @pkcs11_module_path: PKCS #11 module path or NULL
3068 * Returns: 0 on success; -1 on failure
3069 *
3070 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3071 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3072 * module path fails the paths will be reset to the default value (NULL).
3073 */
3074int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3075 const char *pkcs11_engine_path,
3076 const char *pkcs11_module_path)
3077{
3078 char *pkcs11_engine_path_copy = NULL;
3079 char *pkcs11_module_path_copy = NULL;
3080
3081 if (pkcs11_engine_path != NULL) {
3082 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3083 if (pkcs11_engine_path_copy == NULL)
3084 return -1;
3085 }
3086 if (pkcs11_module_path != NULL) {
3087 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003088 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003089 os_free(pkcs11_engine_path_copy);
3090 return -1;
3091 }
3092 }
3093
3094 os_free(wpa_s->conf->pkcs11_engine_path);
3095 os_free(wpa_s->conf->pkcs11_module_path);
3096 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3097 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3098
3099 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3100 eapol_sm_deinit(wpa_s->eapol);
3101 wpa_s->eapol = NULL;
3102 if (wpa_supplicant_init_eapol(wpa_s)) {
3103 /* Error -> Reset paths to the default value (NULL) once. */
3104 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3105 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3106 NULL);
3107
3108 return -1;
3109 }
3110 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3111
3112 return 0;
3113}
3114
3115
3116/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003117 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3118 * @wpa_s: wpa_supplicant structure for a network interface
3119 * @ap_scan: AP scan mode
3120 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3121 *
3122 */
3123int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3124{
3125
3126 int old_ap_scan;
3127
3128 if (ap_scan < 0 || ap_scan > 2)
3129 return -1;
3130
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003131 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3132 wpa_printf(MSG_INFO,
3133 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3134 }
3135
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003136#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003137 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3138 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3139 wpa_s->wpa_state < WPA_COMPLETED) {
3140 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3141 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003142 return 0;
3143 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003144#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003145
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003146 old_ap_scan = wpa_s->conf->ap_scan;
3147 wpa_s->conf->ap_scan = ap_scan;
3148
3149 if (old_ap_scan != wpa_s->conf->ap_scan)
3150 wpas_notify_ap_scan_changed(wpa_s);
3151
3152 return 0;
3153}
3154
3155
3156/**
3157 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3158 * @wpa_s: wpa_supplicant structure for a network interface
3159 * @expire_age: Expiration age in seconds
3160 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3161 *
3162 */
3163int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3164 unsigned int bss_expire_age)
3165{
3166 if (bss_expire_age < 10) {
3167 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3168 bss_expire_age);
3169 return -1;
3170 }
3171 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3172 bss_expire_age);
3173 wpa_s->conf->bss_expiration_age = bss_expire_age;
3174
3175 return 0;
3176}
3177
3178
3179/**
3180 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3181 * @wpa_s: wpa_supplicant structure for a network interface
3182 * @expire_count: number of scans after which an unseen BSS is reclaimed
3183 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3184 *
3185 */
3186int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3187 unsigned int bss_expire_count)
3188{
3189 if (bss_expire_count < 1) {
3190 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3191 bss_expire_count);
3192 return -1;
3193 }
3194 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3195 bss_expire_count);
3196 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3197
3198 return 0;
3199}
3200
3201
3202/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003203 * wpa_supplicant_set_scan_interval - Set scan interval
3204 * @wpa_s: wpa_supplicant structure for a network interface
3205 * @scan_interval: scan interval in seconds
3206 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3207 *
3208 */
3209int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3210 int scan_interval)
3211{
3212 if (scan_interval < 0) {
3213 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3214 scan_interval);
3215 return -1;
3216 }
3217 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3218 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003219 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003220
3221 return 0;
3222}
3223
3224
3225/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003226 * wpa_supplicant_set_debug_params - Set global debug params
3227 * @global: wpa_global structure
3228 * @debug_level: debug level
3229 * @debug_timestamp: determines if show timestamp in debug data
3230 * @debug_show_keys: determines if show keys in debug data
3231 * Returns: 0 if succeed or -1 if debug_level has wrong value
3232 */
3233int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3234 int debug_timestamp, int debug_show_keys)
3235{
3236
3237 int old_level, old_timestamp, old_show_keys;
3238
3239 /* check for allowed debuglevels */
3240 if (debug_level != MSG_EXCESSIVE &&
3241 debug_level != MSG_MSGDUMP &&
3242 debug_level != MSG_DEBUG &&
3243 debug_level != MSG_INFO &&
3244 debug_level != MSG_WARNING &&
3245 debug_level != MSG_ERROR)
3246 return -1;
3247
3248 old_level = wpa_debug_level;
3249 old_timestamp = wpa_debug_timestamp;
3250 old_show_keys = wpa_debug_show_keys;
3251
3252 wpa_debug_level = debug_level;
3253 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3254 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3255
3256 if (wpa_debug_level != old_level)
3257 wpas_notify_debug_level_changed(global);
3258 if (wpa_debug_timestamp != old_timestamp)
3259 wpas_notify_debug_timestamp_changed(global);
3260 if (wpa_debug_show_keys != old_show_keys)
3261 wpas_notify_debug_show_keys_changed(global);
3262
3263 return 0;
3264}
3265
3266
3267/**
3268 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3269 * @wpa_s: Pointer to wpa_supplicant data
3270 * Returns: A pointer to the current network structure or %NULL on failure
3271 */
3272struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3273{
3274 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003275 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003276 int res;
3277 size_t ssid_len;
3278 u8 bssid[ETH_ALEN];
3279 int wired;
3280
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003281 res = wpa_drv_get_ssid(wpa_s, ssid);
3282 if (res < 0) {
3283 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3284 "driver");
3285 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003286 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003287 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003288
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003289 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003290 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3291 "driver");
3292 return NULL;
3293 }
3294
3295 wired = wpa_s->conf->ap_scan == 0 &&
3296 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3297
3298 entry = wpa_s->conf->ssid;
3299 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003300 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003301 ((ssid_len == entry->ssid_len &&
3302 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3303 (!entry->bssid_set ||
3304 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3305 return entry;
3306#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003307 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003308 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3309 (entry->ssid == NULL || entry->ssid_len == 0) &&
3310 (!entry->bssid_set ||
3311 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3312 return entry;
3313#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003314
Dmitry Shmidt04949592012-07-19 12:16:46 -07003315 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003316 entry->ssid_len == 0 &&
3317 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3318 return entry;
3319
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003320 entry = entry->next;
3321 }
3322
3323 return NULL;
3324}
3325
3326
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003327static int select_driver(struct wpa_supplicant *wpa_s, int i)
3328{
3329 struct wpa_global *global = wpa_s->global;
3330
3331 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003332 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003333 if (global->drv_priv[i] == NULL) {
3334 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3335 "'%s'", wpa_drivers[i]->name);
3336 return -1;
3337 }
3338 }
3339
3340 wpa_s->driver = wpa_drivers[i];
3341 wpa_s->global_drv_priv = global->drv_priv[i];
3342
3343 return 0;
3344}
3345
3346
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003347static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3348 const char *name)
3349{
3350 int i;
3351 size_t len;
3352 const char *pos, *driver = name;
3353
3354 if (wpa_s == NULL)
3355 return -1;
3356
3357 if (wpa_drivers[0] == NULL) {
3358 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3359 "wpa_supplicant");
3360 return -1;
3361 }
3362
3363 if (name == NULL) {
3364 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003365 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003366 }
3367
3368 do {
3369 pos = os_strchr(driver, ',');
3370 if (pos)
3371 len = pos - driver;
3372 else
3373 len = os_strlen(driver);
3374
3375 for (i = 0; wpa_drivers[i]; i++) {
3376 if (os_strlen(wpa_drivers[i]->name) == len &&
3377 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003378 0) {
3379 /* First driver that succeeds wins */
3380 if (select_driver(wpa_s, i) == 0)
3381 return 0;
3382 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003383 }
3384
3385 driver = pos + 1;
3386 } while (pos);
3387
3388 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3389 return -1;
3390}
3391
3392
3393/**
3394 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3395 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3396 * with struct wpa_driver_ops::init()
3397 * @src_addr: Source address of the EAPOL frame
3398 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3399 * @len: Length of the EAPOL data
3400 *
3401 * This function is called for each received EAPOL frame. Most driver
3402 * interfaces rely on more generic OS mechanism for receiving frames through
3403 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3404 * take care of received EAPOL frames and deliver them to the core supplicant
3405 * code by calling this function.
3406 */
3407void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3408 const u8 *buf, size_t len)
3409{
3410 struct wpa_supplicant *wpa_s = ctx;
3411
3412 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3413 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3414
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003415#ifdef CONFIG_TESTING_OPTIONS
3416 if (wpa_s->ignore_auth_resp) {
3417 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3418 return;
3419 }
3420#endif /* CONFIG_TESTING_OPTIONS */
3421
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003422#ifdef CONFIG_PEERKEY
3423 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3424 wpa_s->current_ssid->peerkey &&
3425 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3426 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3427 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3428 return;
3429 }
3430#endif /* CONFIG_PEERKEY */
3431
Jouni Malinena05074c2012-12-21 21:35:35 +02003432 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3433 (wpa_s->last_eapol_matches_bssid &&
3434#ifdef CONFIG_AP
3435 !wpa_s->ap_iface &&
3436#endif /* CONFIG_AP */
3437 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003438 /*
3439 * There is possible race condition between receiving the
3440 * association event and the EAPOL frame since they are coming
3441 * through different paths from the driver. In order to avoid
3442 * issues in trying to process the EAPOL frame before receiving
3443 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003444 * the association event is received. This may also be needed in
3445 * driver-based roaming case, so also use src_addr != BSSID as a
3446 * trigger if we have previously confirmed that the
3447 * Authenticator uses BSSID as the src_addr (which is not the
3448 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003449 */
3450 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003451 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3452 wpa_supplicant_state_txt(wpa_s->wpa_state),
3453 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003454 wpabuf_free(wpa_s->pending_eapol_rx);
3455 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3456 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003457 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003458 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3459 ETH_ALEN);
3460 }
3461 return;
3462 }
3463
Jouni Malinena05074c2012-12-21 21:35:35 +02003464 wpa_s->last_eapol_matches_bssid =
3465 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3466
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003467#ifdef CONFIG_AP
3468 if (wpa_s->ap_iface) {
3469 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3470 return;
3471 }
3472#endif /* CONFIG_AP */
3473
3474 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3475 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3476 "no key management is configured");
3477 return;
3478 }
3479
3480 if (wpa_s->eapol_received == 0 &&
3481 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3482 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3483 wpa_s->wpa_state != WPA_COMPLETED) &&
3484 (wpa_s->current_ssid == NULL ||
3485 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3486 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003487 int timeout = 10;
3488
3489 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3490 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3491 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3492 /* Use longer timeout for IEEE 802.1X/EAP */
3493 timeout = 70;
3494 }
3495
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003496#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003497 if (wpa_s->current_ssid && wpa_s->current_bss &&
3498 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3499 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3500 /*
3501 * Use shorter timeout if going through WPS AP iteration
3502 * for PIN config method with an AP that does not
3503 * advertise Selected Registrar.
3504 */
3505 struct wpabuf *wps_ie;
3506
3507 wps_ie = wpa_bss_get_vendor_ie_multi(
3508 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3509 if (wps_ie &&
3510 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3511 timeout = 10;
3512 wpabuf_free(wps_ie);
3513 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003514#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003515
3516 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003517 }
3518 wpa_s->eapol_received++;
3519
3520 if (wpa_s->countermeasures) {
3521 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3522 "EAPOL packet");
3523 return;
3524 }
3525
3526#ifdef CONFIG_IBSS_RSN
3527 if (wpa_s->current_ssid &&
3528 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3529 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3530 return;
3531 }
3532#endif /* CONFIG_IBSS_RSN */
3533
3534 /* Source address of the incoming EAPOL frame could be compared to the
3535 * current BSSID. However, it is possible that a centralized
3536 * Authenticator could be using another MAC address than the BSSID of
3537 * an AP, so just allow any address to be used for now. The replies are
3538 * still sent to the current BSSID (if available), though. */
3539
3540 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3541 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3542 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3543 return;
3544 wpa_drv_poll(wpa_s);
3545 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3546 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3547 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3548 /*
3549 * Set portValid = TRUE here since we are going to skip 4-way
3550 * handshake processing which would normally set portValid. We
3551 * need this to allow the EAPOL state machines to be completed
3552 * without going through EAPOL-Key handshake.
3553 */
3554 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3555 }
3556}
3557
3558
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003559int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003560{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003561 if ((!wpa_s->p2p_mgmt ||
3562 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3563 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003564 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003565 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3566 wpa_drv_get_mac_addr(wpa_s),
3567 ETH_P_EAPOL,
3568 wpa_supplicant_rx_eapol, wpa_s, 0);
3569 if (wpa_s->l2 == NULL)
3570 return -1;
3571 } else {
3572 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3573 if (addr)
3574 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3575 }
3576
3577 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3578 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3579 return -1;
3580 }
3581
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003582 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3583
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003584 return 0;
3585}
3586
3587
Dmitry Shmidt04949592012-07-19 12:16:46 -07003588static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3589 const u8 *buf, size_t len)
3590{
3591 struct wpa_supplicant *wpa_s = ctx;
3592 const struct l2_ethhdr *eth;
3593
3594 if (len < sizeof(*eth))
3595 return;
3596 eth = (const struct l2_ethhdr *) buf;
3597
3598 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3599 !(eth->h_dest[0] & 0x01)) {
3600 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3601 " (bridge - not for this interface - ignore)",
3602 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3603 return;
3604 }
3605
3606 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3607 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3608 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3609 len - sizeof(*eth));
3610}
3611
3612
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003613/**
3614 * wpa_supplicant_driver_init - Initialize driver interface parameters
3615 * @wpa_s: Pointer to wpa_supplicant data
3616 * Returns: 0 on success, -1 on failure
3617 *
3618 * This function is called to initialize driver interface parameters.
3619 * wpa_drv_init() must have been called before this function to initialize the
3620 * driver interface.
3621 */
3622int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3623{
3624 static int interface_count = 0;
3625
3626 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3627 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003628
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003629 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3630 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003631 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003632 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3633
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003634 if (wpa_s->bridge_ifname[0]) {
3635 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3636 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003637 wpa_s->l2_br = l2_packet_init_bridge(
3638 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3639 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003640 if (wpa_s->l2_br == NULL) {
3641 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3642 "connection for the bridge interface '%s'",
3643 wpa_s->bridge_ifname);
3644 return -1;
3645 }
3646 }
3647
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003648 if (wpa_s->conf->ap_scan == 2 &&
3649 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3650 wpa_printf(MSG_INFO,
3651 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3652 }
3653
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003654 wpa_clear_keys(wpa_s, NULL);
3655
3656 /* Make sure that TKIP countermeasures are not left enabled (could
3657 * happen if wpa_supplicant is killed during countermeasures. */
3658 wpa_drv_set_countermeasures(wpa_s, 0);
3659
3660 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3661 wpa_drv_flush_pmkid(wpa_s);
3662
3663 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003664 wpa_s->prev_scan_wildcard = 0;
3665
Dmitry Shmidt04949592012-07-19 12:16:46 -07003666 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003667 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3668 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3669 interface_count = 0;
3670 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003671#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003672 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003673 wpa_supplicant_delayed_sched_scan(wpa_s,
3674 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003675 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003676 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003677 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003678#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003679 interface_count++;
3680 } else
3681 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3682
3683 return 0;
3684}
3685
3686
3687static int wpa_supplicant_daemon(const char *pid_file)
3688{
3689 wpa_printf(MSG_DEBUG, "Daemonize..");
3690 return os_daemonize(pid_file);
3691}
3692
3693
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003694static struct wpa_supplicant *
3695wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003696{
3697 struct wpa_supplicant *wpa_s;
3698
3699 wpa_s = os_zalloc(sizeof(*wpa_s));
3700 if (wpa_s == NULL)
3701 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003702 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003703 wpa_s->scan_interval = 5;
3704 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003705 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003706 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003707 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003709 dl_list_init(&wpa_s->bss_tmp_disallowed);
3710
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003711 return wpa_s;
3712}
3713
3714
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003715#ifdef CONFIG_HT_OVERRIDES
3716
3717static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3718 struct ieee80211_ht_capabilities *htcaps,
3719 struct ieee80211_ht_capabilities *htcaps_mask,
3720 const char *ht_mcs)
3721{
3722 /* parse ht_mcs into hex array */
3723 int i;
3724 const char *tmp = ht_mcs;
3725 char *end = NULL;
3726
3727 /* If ht_mcs is null, do not set anything */
3728 if (!ht_mcs)
3729 return 0;
3730
3731 /* This is what we are setting in the kernel */
3732 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3733
3734 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3735
3736 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3737 errno = 0;
3738 long v = strtol(tmp, &end, 16);
3739 if (errno == 0) {
3740 wpa_msg(wpa_s, MSG_DEBUG,
3741 "htcap value[%i]: %ld end: %p tmp: %p",
3742 i, v, end, tmp);
3743 if (end == tmp)
3744 break;
3745
3746 htcaps->supported_mcs_set[i] = v;
3747 tmp = end;
3748 } else {
3749 wpa_msg(wpa_s, MSG_ERROR,
3750 "Failed to parse ht-mcs: %s, error: %s\n",
3751 ht_mcs, strerror(errno));
3752 return -1;
3753 }
3754 }
3755
3756 /*
3757 * If we were able to parse any values, then set mask for the MCS set.
3758 */
3759 if (i) {
3760 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3761 IEEE80211_HT_MCS_MASK_LEN - 1);
3762 /* skip the 3 reserved bits */
3763 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3764 0x1f;
3765 }
3766
3767 return 0;
3768}
3769
3770
3771static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3772 struct ieee80211_ht_capabilities *htcaps,
3773 struct ieee80211_ht_capabilities *htcaps_mask,
3774 int disabled)
3775{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003776 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003777
3778 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3779
3780 if (disabled == -1)
3781 return 0;
3782
3783 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3784 htcaps_mask->ht_capabilities_info |= msk;
3785 if (disabled)
3786 htcaps->ht_capabilities_info &= msk;
3787 else
3788 htcaps->ht_capabilities_info |= msk;
3789
3790 return 0;
3791}
3792
3793
3794static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3795 struct ieee80211_ht_capabilities *htcaps,
3796 struct ieee80211_ht_capabilities *htcaps_mask,
3797 int factor)
3798{
3799 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3800
3801 if (factor == -1)
3802 return 0;
3803
3804 if (factor < 0 || factor > 3) {
3805 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3806 "Must be 0-3 or -1", factor);
3807 return -EINVAL;
3808 }
3809
3810 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3811 htcaps->a_mpdu_params &= ~0x3;
3812 htcaps->a_mpdu_params |= factor & 0x3;
3813
3814 return 0;
3815}
3816
3817
3818static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3819 struct ieee80211_ht_capabilities *htcaps,
3820 struct ieee80211_ht_capabilities *htcaps_mask,
3821 int density)
3822{
3823 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3824
3825 if (density == -1)
3826 return 0;
3827
3828 if (density < 0 || density > 7) {
3829 wpa_msg(wpa_s, MSG_ERROR,
3830 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3831 density);
3832 return -EINVAL;
3833 }
3834
3835 htcaps_mask->a_mpdu_params |= 0x1C;
3836 htcaps->a_mpdu_params &= ~(0x1C);
3837 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3838
3839 return 0;
3840}
3841
3842
3843static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3844 struct ieee80211_ht_capabilities *htcaps,
3845 struct ieee80211_ht_capabilities *htcaps_mask,
3846 int disabled)
3847{
3848 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003849 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3850 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003851
3852 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3853
3854 if (disabled)
3855 htcaps->ht_capabilities_info &= ~msk;
3856 else
3857 htcaps->ht_capabilities_info |= msk;
3858
3859 htcaps_mask->ht_capabilities_info |= msk;
3860
3861 return 0;
3862}
3863
3864
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003865static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3866 struct ieee80211_ht_capabilities *htcaps,
3867 struct ieee80211_ht_capabilities *htcaps_mask,
3868 int disabled)
3869{
3870 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003871 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3872 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003873
3874 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3875
3876 if (disabled)
3877 htcaps->ht_capabilities_info &= ~msk;
3878 else
3879 htcaps->ht_capabilities_info |= msk;
3880
3881 htcaps_mask->ht_capabilities_info |= msk;
3882
3883 return 0;
3884}
3885
3886
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003887static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3888 struct ieee80211_ht_capabilities *htcaps,
3889 struct ieee80211_ht_capabilities *htcaps_mask,
3890 int disabled)
3891{
3892 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003893 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003894
3895 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3896
3897 if (disabled)
3898 htcaps->ht_capabilities_info &= ~msk;
3899 else
3900 htcaps->ht_capabilities_info |= msk;
3901
3902 htcaps_mask->ht_capabilities_info |= msk;
3903
3904 return 0;
3905}
3906
3907
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003908void wpa_supplicant_apply_ht_overrides(
3909 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3910 struct wpa_driver_associate_params *params)
3911{
3912 struct ieee80211_ht_capabilities *htcaps;
3913 struct ieee80211_ht_capabilities *htcaps_mask;
3914
3915 if (!ssid)
3916 return;
3917
3918 params->disable_ht = ssid->disable_ht;
3919 if (!params->htcaps || !params->htcaps_mask)
3920 return;
3921
3922 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3923 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3924 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3925 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3926 ssid->disable_max_amsdu);
3927 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3928 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3929 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003930 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003931 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003932
3933 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003934 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003935 htcaps->ht_capabilities_info |= bit;
3936 htcaps_mask->ht_capabilities_info |= bit;
3937 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003938}
3939
3940#endif /* CONFIG_HT_OVERRIDES */
3941
3942
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003943#ifdef CONFIG_VHT_OVERRIDES
3944void wpa_supplicant_apply_vht_overrides(
3945 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3946 struct wpa_driver_associate_params *params)
3947{
3948 struct ieee80211_vht_capabilities *vhtcaps;
3949 struct ieee80211_vht_capabilities *vhtcaps_mask;
3950
3951 if (!ssid)
3952 return;
3953
3954 params->disable_vht = ssid->disable_vht;
3955
3956 vhtcaps = (void *) params->vhtcaps;
3957 vhtcaps_mask = (void *) params->vhtcaps_mask;
3958
3959 if (!vhtcaps || !vhtcaps_mask)
3960 return;
3961
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003962 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
3963 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003964
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003965#ifdef CONFIG_HT_OVERRIDES
3966 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003967 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3968 int max_ampdu;
3969
3970 max_ampdu = (ssid->vht_capa &
3971 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3972 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003973
3974 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3975 wpa_set_ampdu_factor(wpa_s,
3976 (void *) params->htcaps,
3977 (void *) params->htcaps_mask,
3978 max_ampdu);
3979 }
3980#endif /* CONFIG_HT_OVERRIDES */
3981
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003982#define OVERRIDE_MCS(i) \
3983 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3984 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003985 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003986 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003987 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
3988 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003989 } \
3990 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3991 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003992 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003993 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003994 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
3995 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003996 }
3997
3998 OVERRIDE_MCS(1);
3999 OVERRIDE_MCS(2);
4000 OVERRIDE_MCS(3);
4001 OVERRIDE_MCS(4);
4002 OVERRIDE_MCS(5);
4003 OVERRIDE_MCS(6);
4004 OVERRIDE_MCS(7);
4005 OVERRIDE_MCS(8);
4006}
4007#endif /* CONFIG_VHT_OVERRIDES */
4008
4009
Dmitry Shmidt04949592012-07-19 12:16:46 -07004010static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4011{
4012#ifdef PCSC_FUNCS
4013 size_t len;
4014
4015 if (!wpa_s->conf->pcsc_reader)
4016 return 0;
4017
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004018 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004019 if (!wpa_s->scard)
4020 return 1;
4021
4022 if (wpa_s->conf->pcsc_pin &&
4023 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4024 scard_deinit(wpa_s->scard);
4025 wpa_s->scard = NULL;
4026 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4027 return -1;
4028 }
4029
4030 len = sizeof(wpa_s->imsi) - 1;
4031 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4032 scard_deinit(wpa_s->scard);
4033 wpa_s->scard = NULL;
4034 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4035 return -1;
4036 }
4037 wpa_s->imsi[len] = '\0';
4038
4039 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4040
4041 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4042 wpa_s->imsi, wpa_s->mnc_len);
4043
4044 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4045 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4046#endif /* PCSC_FUNCS */
4047
4048 return 0;
4049}
4050
4051
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004052int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4053{
4054 char *val, *pos;
4055
4056 ext_password_deinit(wpa_s->ext_pw);
4057 wpa_s->ext_pw = NULL;
4058 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4059
4060 if (!wpa_s->conf->ext_password_backend)
4061 return 0;
4062
4063 val = os_strdup(wpa_s->conf->ext_password_backend);
4064 if (val == NULL)
4065 return -1;
4066 pos = os_strchr(val, ':');
4067 if (pos)
4068 *pos++ = '\0';
4069
4070 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4071
4072 wpa_s->ext_pw = ext_password_init(val, pos);
4073 os_free(val);
4074 if (wpa_s->ext_pw == NULL) {
4075 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4076 return -1;
4077 }
4078 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4079
4080 return 0;
4081}
4082
4083
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004084#ifdef CONFIG_FST
4085
4086static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4087{
4088 struct wpa_supplicant *wpa_s = ctx;
4089
4090 return (is_zero_ether_addr(wpa_s->bssid) ||
4091 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4092}
4093
4094
4095static void wpas_fst_get_channel_info_cb(void *ctx,
4096 enum hostapd_hw_mode *hw_mode,
4097 u8 *channel)
4098{
4099 struct wpa_supplicant *wpa_s = ctx;
4100
4101 if (wpa_s->current_bss) {
4102 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4103 channel);
4104 } else if (wpa_s->hw.num_modes) {
4105 *hw_mode = wpa_s->hw.modes[0].mode;
4106 } else {
4107 WPA_ASSERT(0);
4108 *hw_mode = 0;
4109 }
4110}
4111
4112
4113static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4114{
4115 struct wpa_supplicant *wpa_s = ctx;
4116
4117 *modes = wpa_s->hw.modes;
4118 return wpa_s->hw.num_modes;
4119}
4120
4121
4122static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4123{
4124 struct wpa_supplicant *wpa_s = ctx;
4125
4126 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4127 wpa_s->fst_ies = fst_ies;
4128}
4129
4130
4131static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4132{
4133 struct wpa_supplicant *wpa_s = ctx;
4134
4135 WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
4136 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
4137 wpa_s->own_addr, wpa_s->bssid,
4138 wpabuf_head(data), wpabuf_len(data),
4139 0);
4140}
4141
4142
4143static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4144{
4145 struct wpa_supplicant *wpa_s = ctx;
4146
4147 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4148 return wpa_s->received_mb_ies;
4149}
4150
4151
4152static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4153 const u8 *buf, size_t size)
4154{
4155 struct wpa_supplicant *wpa_s = ctx;
4156 struct mb_ies_info info;
4157
4158 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4159
4160 if (!mb_ies_info_by_ies(&info, buf, size)) {
4161 wpabuf_free(wpa_s->received_mb_ies);
4162 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4163 }
4164}
4165
4166
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004167static const u8 * wpas_fst_get_peer_first(void *ctx,
4168 struct fst_get_peer_ctx **get_ctx,
4169 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004170{
4171 struct wpa_supplicant *wpa_s = ctx;
4172
4173 *get_ctx = NULL;
4174 if (!is_zero_ether_addr(wpa_s->bssid))
4175 return (wpa_s->received_mb_ies || !mb_only) ?
4176 wpa_s->bssid : NULL;
4177 return NULL;
4178}
4179
4180
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004181static const u8 * wpas_fst_get_peer_next(void *ctx,
4182 struct fst_get_peer_ctx **get_ctx,
4183 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004184{
4185 return NULL;
4186}
4187
4188void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4189 struct fst_wpa_obj *iface_obj)
4190{
4191 iface_obj->ctx = wpa_s;
4192 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4193 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4194 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4195 iface_obj->set_ies = wpas_fst_set_ies_cb;
4196 iface_obj->send_action = wpas_fst_send_action_cb;
4197 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4198 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4199 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4200 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4201}
4202#endif /* CONFIG_FST */
4203
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004204static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004205 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004206{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004207 struct wowlan_triggers *triggers;
4208 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004209
4210 if (!wpa_s->conf->wowlan_triggers)
4211 return 0;
4212
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004213 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4214 if (triggers) {
4215 ret = wpa_drv_wowlan(wpa_s, triggers);
4216 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004217 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004218 return ret;
4219}
4220
4221
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004222enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004223{
4224 if (freq < 3000)
4225 return BAND_2_4_GHZ;
4226 if (freq > 50000)
4227 return BAND_60_GHZ;
4228 return BAND_5_GHZ;
4229}
4230
4231
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004232unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004233{
4234 int i;
4235 unsigned int band = 0;
4236
4237 if (freqs) {
4238 /* freqs are specified for the radio work */
4239 for (i = 0; freqs[i]; i++)
4240 band |= wpas_freq_to_band(freqs[i]);
4241 } else {
4242 /*
4243 * freqs are not specified, implies all
4244 * the supported freqs by HW
4245 */
4246 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4247 if (wpa_s->hw.modes[i].num_channels != 0) {
4248 if (wpa_s->hw.modes[i].mode ==
4249 HOSTAPD_MODE_IEEE80211B ||
4250 wpa_s->hw.modes[i].mode ==
4251 HOSTAPD_MODE_IEEE80211G)
4252 band |= BAND_2_4_GHZ;
4253 else if (wpa_s->hw.modes[i].mode ==
4254 HOSTAPD_MODE_IEEE80211A)
4255 band |= BAND_5_GHZ;
4256 else if (wpa_s->hw.modes[i].mode ==
4257 HOSTAPD_MODE_IEEE80211AD)
4258 band |= BAND_60_GHZ;
4259 else if (wpa_s->hw.modes[i].mode ==
4260 HOSTAPD_MODE_IEEE80211ANY)
4261 band = BAND_2_4_GHZ | BAND_5_GHZ |
4262 BAND_60_GHZ;
4263 }
4264 }
4265 }
4266
4267 return band;
4268}
4269
4270
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004271static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4272 const char *rn)
4273{
4274 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4275 struct wpa_radio *radio;
4276
4277 while (rn && iface) {
4278 radio = iface->radio;
4279 if (radio && os_strcmp(rn, radio->name) == 0) {
4280 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4281 wpa_s->ifname, rn);
4282 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4283 return radio;
4284 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004285
4286 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004287 }
4288
4289 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4290 wpa_s->ifname, rn ? rn : "N/A");
4291 radio = os_zalloc(sizeof(*radio));
4292 if (radio == NULL)
4293 return NULL;
4294
4295 if (rn)
4296 os_strlcpy(radio->name, rn, sizeof(radio->name));
4297 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004298 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004299 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4300
4301 return radio;
4302}
4303
4304
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004305static void radio_work_free(struct wpa_radio_work *work)
4306{
4307 if (work->wpa_s->scan_work == work) {
4308 /* This should not really happen. */
4309 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4310 work->type, work, work->started);
4311 work->wpa_s->scan_work = NULL;
4312 }
4313
4314#ifdef CONFIG_P2P
4315 if (work->wpa_s->p2p_scan_work == work) {
4316 /* This should not really happen. */
4317 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4318 work->type, work, work->started);
4319 work->wpa_s->p2p_scan_work = NULL;
4320 }
4321#endif /* CONFIG_P2P */
4322
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004323 if (work->started) {
4324 work->wpa_s->radio->num_active_works--;
4325 wpa_dbg(work->wpa_s, MSG_DEBUG,
4326 "radio_work_free('%s'@%p: num_active_works --> %u",
4327 work->type, work,
4328 work->wpa_s->radio->num_active_works);
4329 }
4330
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004331 dl_list_del(&work->list);
4332 os_free(work);
4333}
4334
4335
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004336static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4337{
4338 struct wpa_radio_work *active_work = NULL;
4339 struct wpa_radio_work *tmp;
4340
4341 /* Get the active work to know the type and band. */
4342 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4343 if (tmp->started) {
4344 active_work = tmp;
4345 break;
4346 }
4347 }
4348
4349 if (!active_work) {
4350 /* No active work, start one */
4351 radio->num_active_works = 0;
4352 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4353 list) {
4354 if (os_strcmp(tmp->type, "scan") == 0 &&
4355 radio->external_scan_running &&
4356 (((struct wpa_driver_scan_params *)
4357 tmp->ctx)->only_new_results ||
4358 tmp->wpa_s->clear_driver_scan_cache))
4359 continue;
4360 return tmp;
4361 }
4362 return NULL;
4363 }
4364
4365 if (os_strcmp(active_work->type, "sme-connect") == 0 ||
4366 os_strcmp(active_work->type, "connect") == 0) {
4367 /*
4368 * If the active work is either connect or sme-connect,
4369 * do not parallelize them with other radio works.
4370 */
4371 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4372 "Do not parallelize radio work with %s",
4373 active_work->type);
4374 return NULL;
4375 }
4376
4377 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4378 if (tmp->started)
4379 continue;
4380
4381 /*
4382 * If connect or sme-connect are enqueued, parallelize only
4383 * those operations ahead of them in the queue.
4384 */
4385 if (os_strcmp(tmp->type, "connect") == 0 ||
4386 os_strcmp(tmp->type, "sme-connect") == 0)
4387 break;
4388
4389 /*
4390 * Check that the radio works are distinct and
4391 * on different bands.
4392 */
4393 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4394 (active_work->bands != tmp->bands)) {
4395 /*
4396 * If a scan has to be scheduled through nl80211 scan
4397 * interface and if an external scan is already running,
4398 * do not schedule the scan since it is likely to get
4399 * rejected by kernel.
4400 */
4401 if (os_strcmp(tmp->type, "scan") == 0 &&
4402 radio->external_scan_running &&
4403 (((struct wpa_driver_scan_params *)
4404 tmp->ctx)->only_new_results ||
4405 tmp->wpa_s->clear_driver_scan_cache))
4406 continue;
4407
4408 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4409 "active_work:%s new_work:%s",
4410 active_work->type, tmp->type);
4411 return tmp;
4412 }
4413 }
4414
4415 /* Did not find a radio work to schedule in parallel. */
4416 return NULL;
4417}
4418
4419
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004420static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4421{
4422 struct wpa_radio *radio = eloop_ctx;
4423 struct wpa_radio_work *work;
4424 struct os_reltime now, diff;
4425 struct wpa_supplicant *wpa_s;
4426
4427 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004428 if (work == NULL) {
4429 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004430 return;
4431 }
4432
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004433 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4434 radio_list);
4435
4436 if (!(wpa_s &&
4437 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4438 if (work->started)
4439 return; /* already started and still in progress */
4440
4441 if (wpa_s && wpa_s->radio->external_scan_running) {
4442 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4443 return;
4444 }
4445 } else {
4446 work = NULL;
4447 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4448 /* get the work to schedule next */
4449 work = radio_work_get_next_work(radio);
4450 }
4451 if (!work)
4452 return;
4453 }
4454
4455 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004456 os_get_reltime(&now);
4457 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004458 wpa_dbg(wpa_s, MSG_DEBUG,
4459 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004460 work->type, work, diff.sec, diff.usec);
4461 work->started = 1;
4462 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004463 radio->num_active_works++;
4464
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004465 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004466
4467 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4468 radio->num_active_works < MAX_ACTIVE_WORKS)
4469 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004470}
4471
4472
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004473/*
4474 * This function removes both started and pending radio works running on
4475 * the provided interface's radio.
4476 * Prior to the removal of the radio work, its callback (cb) is called with
4477 * deinit set to be 1. Each work's callback is responsible for clearing its
4478 * internal data and restoring to a correct state.
4479 * @wpa_s: wpa_supplicant data
4480 * @type: type of works to be removed
4481 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4482 * this interface's works.
4483 */
4484void radio_remove_works(struct wpa_supplicant *wpa_s,
4485 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004486{
4487 struct wpa_radio_work *work, *tmp;
4488 struct wpa_radio *radio = wpa_s->radio;
4489
4490 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4491 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004492 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004493 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004494
4495 /* skip other ifaces' works */
4496 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004497 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004498
4499 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4500 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004501 work->cb(work, 1);
4502 radio_work_free(work);
4503 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004504
4505 /* in case we removed the started work */
4506 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004507}
4508
4509
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004510static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4511{
4512 struct wpa_radio *radio = wpa_s->radio;
4513
4514 if (!radio)
4515 return;
4516
4517 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4518 wpa_s->ifname, radio->name);
4519 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004520 radio_remove_works(wpa_s, NULL, 0);
4521 wpa_s->radio = NULL;
4522 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004523 return; /* Interfaces remain for this radio */
4524
4525 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004526 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004527 os_free(radio);
4528}
4529
4530
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004531void radio_work_check_next(struct wpa_supplicant *wpa_s)
4532{
4533 struct wpa_radio *radio = wpa_s->radio;
4534
4535 if (dl_list_empty(&radio->work))
4536 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004537 if (wpa_s->ext_work_in_progress) {
4538 wpa_printf(MSG_DEBUG,
4539 "External radio work in progress - delay start of pending item");
4540 return;
4541 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004542 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4543 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4544}
4545
4546
4547/**
4548 * radio_add_work - Add a radio work item
4549 * @wpa_s: Pointer to wpa_supplicant data
4550 * @freq: Frequency of the offchannel operation in MHz or 0
4551 * @type: Unique identifier for each type of work
4552 * @next: Force as the next work to be executed
4553 * @cb: Callback function for indicating when radio is available
4554 * @ctx: Context pointer for the work (work->ctx in cb())
4555 * Returns: 0 on success, -1 on failure
4556 *
4557 * This function is used to request time for an operation that requires
4558 * exclusive radio control. Once the radio is available, the registered callback
4559 * function will be called. radio_work_done() must be called once the exclusive
4560 * radio operation has been completed, so that the radio is freed for other
4561 * operations. The special case of deinit=1 is used to free the context data
4562 * during interface removal. That does not allow the callback function to start
4563 * the radio operation, i.e., it must free any resources allocated for the radio
4564 * work and return.
4565 *
4566 * The @freq parameter can be used to indicate a single channel on which the
4567 * offchannel operation will occur. This may allow multiple radio work
4568 * operations to be performed in parallel if they apply for the same channel.
4569 * Setting this to 0 indicates that the work item may use multiple channels or
4570 * requires exclusive control of the radio.
4571 */
4572int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4573 const char *type, int next,
4574 void (*cb)(struct wpa_radio_work *work, int deinit),
4575 void *ctx)
4576{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004577 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004578 struct wpa_radio_work *work;
4579 int was_empty;
4580
4581 work = os_zalloc(sizeof(*work));
4582 if (work == NULL)
4583 return -1;
4584 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4585 os_get_reltime(&work->time);
4586 work->freq = freq;
4587 work->type = type;
4588 work->wpa_s = wpa_s;
4589 work->cb = cb;
4590 work->ctx = ctx;
4591
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004592 if (freq)
4593 work->bands = wpas_freq_to_band(freq);
4594 else if (os_strcmp(type, "scan") == 0 ||
4595 os_strcmp(type, "p2p-scan") == 0)
4596 work->bands = wpas_get_bands(wpa_s,
4597 ((struct wpa_driver_scan_params *)
4598 ctx)->freqs);
4599 else
4600 work->bands = wpas_get_bands(wpa_s, NULL);
4601
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004602 was_empty = dl_list_empty(&wpa_s->radio->work);
4603 if (next)
4604 dl_list_add(&wpa_s->radio->work, &work->list);
4605 else
4606 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4607 if (was_empty) {
4608 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4609 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004610 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4611 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4612 wpa_dbg(wpa_s, MSG_DEBUG,
4613 "Try to schedule a radio work (num_active_works=%u)",
4614 radio->num_active_works);
4615 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004616 }
4617
4618 return 0;
4619}
4620
4621
4622/**
4623 * radio_work_done - Indicate that a radio work item has been completed
4624 * @work: Completed work
4625 *
4626 * This function is called once the callback function registered with
4627 * radio_add_work() has completed its work.
4628 */
4629void radio_work_done(struct wpa_radio_work *work)
4630{
4631 struct wpa_supplicant *wpa_s = work->wpa_s;
4632 struct os_reltime now, diff;
4633 unsigned int started = work->started;
4634
4635 os_get_reltime(&now);
4636 os_reltime_sub(&now, &work->time, &diff);
4637 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4638 work->type, work, started ? "done" : "canceled",
4639 diff.sec, diff.usec);
4640 radio_work_free(work);
4641 if (started)
4642 radio_work_check_next(wpa_s);
4643}
4644
4645
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004646struct wpa_radio_work *
4647radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004648{
4649 struct wpa_radio_work *work;
4650 struct wpa_radio *radio = wpa_s->radio;
4651
4652 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4653 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004654 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004655 }
4656
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004657 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004658}
4659
4660
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004661static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4662 struct wpa_interface *iface)
4663{
4664 const char *ifname, *driver, *rn;
4665
4666 driver = iface->driver;
4667next_driver:
4668 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4669 return -1;
4670
4671 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4672 if (wpa_s->drv_priv == NULL) {
4673 const char *pos;
4674 pos = driver ? os_strchr(driver, ',') : NULL;
4675 if (pos) {
4676 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4677 "driver interface - try next driver wrapper");
4678 driver = pos + 1;
4679 goto next_driver;
4680 }
4681 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4682 "interface");
4683 return -1;
4684 }
4685 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4686 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4687 "driver_param '%s'", wpa_s->conf->driver_param);
4688 return -1;
4689 }
4690
4691 ifname = wpa_drv_get_ifname(wpa_s);
4692 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4693 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4694 "interface name with '%s'", ifname);
4695 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4696 }
4697
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004698 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004699 if (rn && rn[0] == '\0')
4700 rn = NULL;
4701
4702 wpa_s->radio = radio_add_interface(wpa_s, rn);
4703 if (wpa_s->radio == NULL)
4704 return -1;
4705
4706 return 0;
4707}
4708
4709
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004710static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4711 struct wpa_interface *iface)
4712{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004713 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004714 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004715
4716 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4717 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4718 iface->confname ? iface->confname : "N/A",
4719 iface->driver ? iface->driver : "default",
4720 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4721 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4722
4723 if (iface->confname) {
4724#ifdef CONFIG_BACKEND_FILE
4725 wpa_s->confname = os_rel2abs_path(iface->confname);
4726 if (wpa_s->confname == NULL) {
4727 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4728 "for configuration file '%s'.",
4729 iface->confname);
4730 return -1;
4731 }
4732 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4733 iface->confname, wpa_s->confname);
4734#else /* CONFIG_BACKEND_FILE */
4735 wpa_s->confname = os_strdup(iface->confname);
4736#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004737 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004738 if (wpa_s->conf == NULL) {
4739 wpa_printf(MSG_ERROR, "Failed to read or parse "
4740 "configuration '%s'.", wpa_s->confname);
4741 return -1;
4742 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004743 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4744 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004745
4746 /*
4747 * Override ctrl_interface and driver_param if set on command
4748 * line.
4749 */
4750 if (iface->ctrl_interface) {
4751 os_free(wpa_s->conf->ctrl_interface);
4752 wpa_s->conf->ctrl_interface =
4753 os_strdup(iface->ctrl_interface);
4754 }
4755
4756 if (iface->driver_param) {
4757 os_free(wpa_s->conf->driver_param);
4758 wpa_s->conf->driver_param =
4759 os_strdup(iface->driver_param);
4760 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004761
4762 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4763 os_free(wpa_s->conf->ctrl_interface);
4764 wpa_s->conf->ctrl_interface = NULL;
4765 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004766 } else
4767 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4768 iface->driver_param);
4769
4770 if (wpa_s->conf == NULL) {
4771 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4772 return -1;
4773 }
4774
4775 if (iface->ifname == NULL) {
4776 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4777 return -1;
4778 }
4779 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4780 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4781 iface->ifname);
4782 return -1;
4783 }
4784 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4785
4786 if (iface->bridge_ifname) {
4787 if (os_strlen(iface->bridge_ifname) >=
4788 sizeof(wpa_s->bridge_ifname)) {
4789 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4790 "name '%s'.", iface->bridge_ifname);
4791 return -1;
4792 }
4793 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4794 sizeof(wpa_s->bridge_ifname));
4795 }
4796
4797 /* RSNA Supplicant Key Management - INITIALIZE */
4798 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4799 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4800
4801 /* Initialize driver interface and register driver event handler before
4802 * L2 receive handler so that association events are processed before
4803 * EAPOL-Key packets if both become available for the same select()
4804 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004805 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004806 return -1;
4807
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004808 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4809 return -1;
4810
4811 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4812 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4813 NULL);
4814 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4815
4816 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4817 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4818 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4819 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4820 "dot11RSNAConfigPMKLifetime");
4821 return -1;
4822 }
4823
4824 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4825 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4826 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4827 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4828 "dot11RSNAConfigPMKReauthThreshold");
4829 return -1;
4830 }
4831
4832 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4833 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4834 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4835 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4836 "dot11RSNAConfigSATimeout");
4837 return -1;
4838 }
4839
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004840 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4841 &wpa_s->hw.num_modes,
4842 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004843 if (wpa_s->hw.modes) {
4844 u16 i;
4845
4846 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4847 if (wpa_s->hw.modes[i].vht_capab) {
4848 wpa_s->hw_capab = CAPAB_VHT;
4849 break;
4850 }
4851
4852 if (wpa_s->hw.modes[i].ht_capab &
4853 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4854 wpa_s->hw_capab = CAPAB_HT40;
4855 else if (wpa_s->hw.modes[i].ht_capab &&
4856 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4857 wpa_s->hw_capab = CAPAB_HT;
4858 }
4859 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004860
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004861 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4862 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004863 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004864 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004865 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004866 wpa_s->drv_smps_modes = capa.smps_modes;
4867 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004868 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004869 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004870 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004871 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
4872 wpa_s->max_sched_scan_plan_interval =
4873 capa.max_sched_scan_plan_interval;
4874 wpa_s->max_sched_scan_plan_iterations =
4875 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004876 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4877 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004878 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4879 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004880 wpa_s->extended_capa = capa.extended_capa;
4881 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4882 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004883 wpa_s->num_multichan_concurrent =
4884 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004885 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4886
4887 if (capa.mac_addr_rand_scan_supported)
4888 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4889 if (wpa_s->sched_scan_supported &&
4890 capa.mac_addr_rand_sched_scan_supported)
4891 wpa_s->mac_addr_rand_supported |=
4892 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004893 }
4894 if (wpa_s->max_remain_on_chan == 0)
4895 wpa_s->max_remain_on_chan = 1000;
4896
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004897 /*
4898 * Only take p2p_mgmt parameters when P2P Device is supported.
4899 * Doing it here as it determines whether l2_packet_init() will be done
4900 * during wpa_supplicant_driver_init().
4901 */
4902 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4903 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4904 else
4905 iface->p2p_mgmt = 1;
4906
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004907 if (wpa_s->num_multichan_concurrent == 0)
4908 wpa_s->num_multichan_concurrent = 1;
4909
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004910 if (wpa_supplicant_driver_init(wpa_s) < 0)
4911 return -1;
4912
4913#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004914 if ((!iface->p2p_mgmt ||
4915 !(wpa_s->drv_flags &
4916 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4917 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004918 return -1;
4919#endif /* CONFIG_TDLS */
4920
4921 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4922 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4923 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4924 return -1;
4925 }
4926
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004927#ifdef CONFIG_FST
4928 if (wpa_s->conf->fst_group_id) {
4929 struct fst_iface_cfg cfg;
4930 struct fst_wpa_obj iface_obj;
4931
4932 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4933 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4934 sizeof(cfg.group_id));
4935 cfg.priority = wpa_s->conf->fst_priority;
4936 cfg.llt = wpa_s->conf->fst_llt;
4937
4938 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4939 &iface_obj, &cfg);
4940 if (!wpa_s->fst) {
4941 wpa_msg(wpa_s, MSG_ERROR,
4942 "FST: Cannot attach iface %s to group %s",
4943 wpa_s->ifname, cfg.group_id);
4944 return -1;
4945 }
4946 }
4947#endif /* CONFIG_FST */
4948
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004949 if (wpas_wps_init(wpa_s))
4950 return -1;
4951
4952 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4953 return -1;
4954 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4955
4956 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4957 if (wpa_s->ctrl_iface == NULL) {
4958 wpa_printf(MSG_ERROR,
4959 "Failed to initialize control interface '%s'.\n"
4960 "You may have another wpa_supplicant process "
4961 "already running or the file was\n"
4962 "left by an unclean termination of wpa_supplicant "
4963 "in which case you will need\n"
4964 "to manually remove this file before starting "
4965 "wpa_supplicant again.\n",
4966 wpa_s->conf->ctrl_interface);
4967 return -1;
4968 }
4969
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004970 wpa_s->gas = gas_query_init(wpa_s);
4971 if (wpa_s->gas == NULL) {
4972 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4973 return -1;
4974 }
4975
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004976 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004977 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4978 return -1;
4979 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004980
4981 if (wpa_bss_init(wpa_s) < 0)
4982 return -1;
4983
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004984 /*
4985 * Set Wake-on-WLAN triggers, if configured.
4986 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4987 * have effect anyway when the interface is down).
4988 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004989 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004990 return -1;
4991
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004992#ifdef CONFIG_EAP_PROXY
4993{
4994 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004995 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4996 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004997 if (wpa_s->mnc_len > 0) {
4998 wpa_s->imsi[len] = '\0';
4999 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5000 wpa_s->imsi, wpa_s->mnc_len);
5001 } else {
5002 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5003 }
5004}
5005#endif /* CONFIG_EAP_PROXY */
5006
Dmitry Shmidt04949592012-07-19 12:16:46 -07005007 if (pcsc_reader_init(wpa_s) < 0)
5008 return -1;
5009
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005010 if (wpas_init_ext_pw(wpa_s) < 0)
5011 return -1;
5012
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005013 wpas_rrm_reset(wpa_s);
5014
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005015 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5016
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005017#ifdef CONFIG_HS20
5018 hs20_init(wpa_s);
5019#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005020#ifdef CONFIG_MBO
5021 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5022#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005023
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005024 wpa_supplicant_set_default_scan_ies(wpa_s);
5025
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005026 return 0;
5027}
5028
5029
5030static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005031 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005032{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005033 struct wpa_global *global = wpa_s->global;
5034 struct wpa_supplicant *iface, *prev;
5035
5036 if (wpa_s == wpa_s->parent)
5037 wpas_p2p_group_remove(wpa_s, "*");
5038
5039 iface = global->ifaces;
5040 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005041 if (iface->p2pdev == wpa_s)
5042 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005043 if (iface == wpa_s || iface->parent != wpa_s) {
5044 iface = iface->next;
5045 continue;
5046 }
5047 wpa_printf(MSG_DEBUG,
5048 "Remove remaining child interface %s from parent %s",
5049 iface->ifname, wpa_s->ifname);
5050 prev = iface;
5051 iface = iface->next;
5052 wpa_supplicant_remove_iface(global, prev, terminate);
5053 }
5054
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005055 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005056 if (wpa_s->drv_priv) {
5057 wpa_supplicant_deauthenticate(wpa_s,
5058 WLAN_REASON_DEAUTH_LEAVING);
5059
5060 wpa_drv_set_countermeasures(wpa_s, 0);
5061 wpa_clear_keys(wpa_s, NULL);
5062 }
5063
5064 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005065 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005066
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005067 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005068 radio_remove_interface(wpa_s);
5069
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005070#ifdef CONFIG_FST
5071 if (wpa_s->fst) {
5072 fst_detach(wpa_s->fst);
5073 wpa_s->fst = NULL;
5074 }
5075 if (wpa_s->received_mb_ies) {
5076 wpabuf_free(wpa_s->received_mb_ies);
5077 wpa_s->received_mb_ies = NULL;
5078 }
5079#endif /* CONFIG_FST */
5080
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005081 if (wpa_s->drv_priv)
5082 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005083
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005084 if (notify)
5085 wpas_notify_iface_removed(wpa_s);
5086
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005087 if (terminate)
5088 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005089
5090 if (wpa_s->ctrl_iface) {
5091 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5092 wpa_s->ctrl_iface = NULL;
5093 }
5094
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005095#ifdef CONFIG_MESH
5096 if (wpa_s->ifmsh) {
5097 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5098 wpa_s->ifmsh = NULL;
5099 }
5100#endif /* CONFIG_MESH */
5101
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005102 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005103 wpa_config_free(wpa_s->conf);
5104 wpa_s->conf = NULL;
5105 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005106
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005107 os_free(wpa_s->ssids_from_scan_req);
5108
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005109 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005110}
5111
5112
Dmitry Shmidte4663042016-04-04 10:07:49 -07005113#ifdef CONFIG_MATCH_IFACE
5114
5115/**
5116 * wpa_supplicant_match_iface - Match an interface description to a name
5117 * @global: Pointer to global data from wpa_supplicant_init()
5118 * @ifname: Name of the interface to match
5119 * Returns: Pointer to the created interface description or %NULL on failure
5120 */
5121struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5122 const char *ifname)
5123{
5124 int i;
5125 struct wpa_interface *iface, *miface;
5126
5127 for (i = 0; i < global->params.match_iface_count; i++) {
5128 miface = &global->params.match_ifaces[i];
5129 if (!miface->ifname ||
5130 fnmatch(miface->ifname, ifname, 0) == 0) {
5131 iface = os_zalloc(sizeof(*iface));
5132 if (!iface)
5133 return NULL;
5134 *iface = *miface;
5135 iface->ifname = ifname;
5136 return iface;
5137 }
5138 }
5139
5140 return NULL;
5141}
5142
5143
5144/**
5145 * wpa_supplicant_match_existing - Match existing interfaces
5146 * @global: Pointer to global data from wpa_supplicant_init()
5147 * Returns: 0 on success, -1 on failure
5148 */
5149static int wpa_supplicant_match_existing(struct wpa_global *global)
5150{
5151 struct if_nameindex *ifi, *ifp;
5152 struct wpa_supplicant *wpa_s;
5153 struct wpa_interface *iface;
5154
5155 ifp = if_nameindex();
5156 if (!ifp) {
5157 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5158 return -1;
5159 }
5160
5161 for (ifi = ifp; ifi->if_name; ifi++) {
5162 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5163 if (wpa_s)
5164 continue;
5165 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5166 if (iface) {
5167 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5168 os_free(iface);
5169 if (wpa_s)
5170 wpa_s->matched = 1;
5171 }
5172 }
5173
5174 if_freenameindex(ifp);
5175 return 0;
5176}
5177
5178#endif /* CONFIG_MATCH_IFACE */
5179
5180
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005181/**
5182 * wpa_supplicant_add_iface - Add a new network interface
5183 * @global: Pointer to global data from wpa_supplicant_init()
5184 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005185 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005186 * Returns: Pointer to the created interface or %NULL on failure
5187 *
5188 * This function is used to add new network interfaces for %wpa_supplicant.
5189 * This can be called before wpa_supplicant_run() to add interfaces before the
5190 * main event loop has been started. In addition, new interfaces can be added
5191 * dynamically while %wpa_supplicant is already running. This could happen,
5192 * e.g., when a hotplug network adapter is inserted.
5193 */
5194struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005195 struct wpa_interface *iface,
5196 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005197{
5198 struct wpa_supplicant *wpa_s;
5199 struct wpa_interface t_iface;
5200 struct wpa_ssid *ssid;
5201
5202 if (global == NULL || iface == NULL)
5203 return NULL;
5204
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005205 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005206 if (wpa_s == NULL)
5207 return NULL;
5208
5209 wpa_s->global = global;
5210
5211 t_iface = *iface;
5212 if (global->params.override_driver) {
5213 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5214 "('%s' -> '%s')",
5215 iface->driver, global->params.override_driver);
5216 t_iface.driver = global->params.override_driver;
5217 }
5218 if (global->params.override_ctrl_interface) {
5219 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5220 "ctrl_interface ('%s' -> '%s')",
5221 iface->ctrl_interface,
5222 global->params.override_ctrl_interface);
5223 t_iface.ctrl_interface =
5224 global->params.override_ctrl_interface;
5225 }
5226 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5227 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5228 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005229 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005230 return NULL;
5231 }
5232
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005233 /* Notify the control interfaces about new iface */
5234 if (wpas_notify_iface_added(wpa_s)) {
5235 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5236 return NULL;
5237 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005238
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005239 /* Notify the control interfaces about new networks for non p2p mgmt
5240 * ifaces. */
5241 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005242 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5243 wpas_notify_network_added(wpa_s, ssid);
5244 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005245
5246 wpa_s->next = global->ifaces;
5247 global->ifaces = wpa_s;
5248
5249 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005250 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005251
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005252#ifdef CONFIG_P2P
5253 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005254 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005255 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005256 wpas_p2p_add_p2pdev_interface(
5257 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005258 wpa_printf(MSG_INFO,
5259 "P2P: Failed to enable P2P Device interface");
5260 /* Try to continue without. P2P will be disabled. */
5261 }
5262#endif /* CONFIG_P2P */
5263
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005264 return wpa_s;
5265}
5266
5267
5268/**
5269 * wpa_supplicant_remove_iface - Remove a network interface
5270 * @global: Pointer to global data from wpa_supplicant_init()
5271 * @wpa_s: Pointer to the network interface to be removed
5272 * Returns: 0 if interface was removed, -1 if interface was not found
5273 *
5274 * This function can be used to dynamically remove network interfaces from
5275 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5276 * addition, this function is used to remove all remaining interfaces when
5277 * %wpa_supplicant is terminated.
5278 */
5279int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005280 struct wpa_supplicant *wpa_s,
5281 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005282{
5283 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005284#ifdef CONFIG_MESH
5285 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5286 char *ifname = NULL;
5287#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005288
5289 /* Remove interface from the global list of interfaces */
5290 prev = global->ifaces;
5291 if (prev == wpa_s) {
5292 global->ifaces = wpa_s->next;
5293 } else {
5294 while (prev && prev->next != wpa_s)
5295 prev = prev->next;
5296 if (prev == NULL)
5297 return -1;
5298 prev->next = wpa_s->next;
5299 }
5300
5301 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5302
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005303#ifdef CONFIG_MESH
5304 if (mesh_if_created) {
5305 ifname = os_strdup(wpa_s->ifname);
5306 if (ifname == NULL) {
5307 wpa_dbg(wpa_s, MSG_ERROR,
5308 "mesh: Failed to malloc ifname");
5309 return -1;
5310 }
5311 }
5312#endif /* CONFIG_MESH */
5313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005314 if (global->p2p_group_formation == wpa_s)
5315 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005316 if (global->p2p_invite_group == wpa_s)
5317 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005318 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005319
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005320#ifdef CONFIG_MESH
5321 if (mesh_if_created) {
5322 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
5323 os_free(ifname);
5324 }
5325#endif /* CONFIG_MESH */
5326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005327 return 0;
5328}
5329
5330
5331/**
5332 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5333 * @wpa_s: Pointer to the network interface
5334 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5335 */
5336const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5337{
5338 const char *eapol_method;
5339
5340 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5341 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5342 return "NO-EAP";
5343 }
5344
5345 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5346 if (eapol_method == NULL)
5347 return "UNKNOWN-EAP";
5348
5349 return eapol_method;
5350}
5351
5352
5353/**
5354 * wpa_supplicant_get_iface - Get a new network interface
5355 * @global: Pointer to global data from wpa_supplicant_init()
5356 * @ifname: Interface name
5357 * Returns: Pointer to the interface or %NULL if not found
5358 */
5359struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5360 const char *ifname)
5361{
5362 struct wpa_supplicant *wpa_s;
5363
5364 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5365 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5366 return wpa_s;
5367 }
5368 return NULL;
5369}
5370
5371
5372#ifndef CONFIG_NO_WPA_MSG
5373static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5374{
5375 struct wpa_supplicant *wpa_s = ctx;
5376 if (wpa_s == NULL)
5377 return NULL;
5378 return wpa_s->ifname;
5379}
5380#endif /* CONFIG_NO_WPA_MSG */
5381
5382
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005383#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5384#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5385#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5386
5387/* Periodic cleanup tasks */
5388static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5389{
5390 struct wpa_global *global = eloop_ctx;
5391 struct wpa_supplicant *wpa_s;
5392
5393 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5394 wpas_periodic, global, NULL);
5395
5396#ifdef CONFIG_P2P
5397 if (global->p2p)
5398 p2p_expire_peers(global->p2p);
5399#endif /* CONFIG_P2P */
5400
5401 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5402 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5403#ifdef CONFIG_AP
5404 ap_periodic(wpa_s);
5405#endif /* CONFIG_AP */
5406 }
5407}
5408
5409
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005410/**
5411 * wpa_supplicant_init - Initialize %wpa_supplicant
5412 * @params: Parameters for %wpa_supplicant
5413 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5414 *
5415 * This function is used to initialize %wpa_supplicant. After successful
5416 * initialization, the returned data pointer can be used to add and remove
5417 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5418 */
5419struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5420{
5421 struct wpa_global *global;
5422 int ret, i;
5423
5424 if (params == NULL)
5425 return NULL;
5426
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005427#ifdef CONFIG_DRIVER_NDIS
5428 {
5429 void driver_ndis_init_ops(void);
5430 driver_ndis_init_ops();
5431 }
5432#endif /* CONFIG_DRIVER_NDIS */
5433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005434#ifndef CONFIG_NO_WPA_MSG
5435 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5436#endif /* CONFIG_NO_WPA_MSG */
5437
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005438 if (params->wpa_debug_file_path)
5439 wpa_debug_open_file(params->wpa_debug_file_path);
5440 else
5441 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005442 if (params->wpa_debug_syslog)
5443 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005444 if (params->wpa_debug_tracing) {
5445 ret = wpa_debug_open_linux_tracing();
5446 if (ret) {
5447 wpa_printf(MSG_ERROR,
5448 "Failed to enable trace logging");
5449 return NULL;
5450 }
5451 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005452
5453 ret = eap_register_methods();
5454 if (ret) {
5455 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5456 if (ret == -2)
5457 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5458 "the same EAP type.");
5459 return NULL;
5460 }
5461
5462 global = os_zalloc(sizeof(*global));
5463 if (global == NULL)
5464 return NULL;
5465 dl_list_init(&global->p2p_srv_bonjour);
5466 dl_list_init(&global->p2p_srv_upnp);
5467 global->params.daemonize = params->daemonize;
5468 global->params.wait_for_monitor = params->wait_for_monitor;
5469 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5470 if (params->pid_file)
5471 global->params.pid_file = os_strdup(params->pid_file);
5472 if (params->ctrl_interface)
5473 global->params.ctrl_interface =
5474 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005475 if (params->ctrl_interface_group)
5476 global->params.ctrl_interface_group =
5477 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005478 if (params->override_driver)
5479 global->params.override_driver =
5480 os_strdup(params->override_driver);
5481 if (params->override_ctrl_interface)
5482 global->params.override_ctrl_interface =
5483 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005484#ifdef CONFIG_MATCH_IFACE
5485 global->params.match_iface_count = params->match_iface_count;
5486 if (params->match_iface_count) {
5487 global->params.match_ifaces =
5488 os_calloc(params->match_iface_count,
5489 sizeof(struct wpa_interface));
5490 os_memcpy(global->params.match_ifaces,
5491 params->match_ifaces,
5492 params->match_iface_count *
5493 sizeof(struct wpa_interface));
5494 }
5495#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005496#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005497 if (params->conf_p2p_dev)
5498 global->params.conf_p2p_dev =
5499 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005500#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005501 wpa_debug_level = global->params.wpa_debug_level =
5502 params->wpa_debug_level;
5503 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5504 params->wpa_debug_show_keys;
5505 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5506 params->wpa_debug_timestamp;
5507
5508 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5509
5510 if (eloop_init()) {
5511 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5512 wpa_supplicant_deinit(global);
5513 return NULL;
5514 }
5515
Jouni Malinen75ecf522011-06-27 15:19:46 -07005516 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005517
5518 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5519 if (global->ctrl_iface == NULL) {
5520 wpa_supplicant_deinit(global);
5521 return NULL;
5522 }
5523
5524 if (wpas_notify_supplicant_initialized(global)) {
5525 wpa_supplicant_deinit(global);
5526 return NULL;
5527 }
5528
5529 for (i = 0; wpa_drivers[i]; i++)
5530 global->drv_count++;
5531 if (global->drv_count == 0) {
5532 wpa_printf(MSG_ERROR, "No drivers enabled");
5533 wpa_supplicant_deinit(global);
5534 return NULL;
5535 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005536 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005537 if (global->drv_priv == NULL) {
5538 wpa_supplicant_deinit(global);
5539 return NULL;
5540 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005541
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005542#ifdef CONFIG_WIFI_DISPLAY
5543 if (wifi_display_init(global) < 0) {
5544 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5545 wpa_supplicant_deinit(global);
5546 return NULL;
5547 }
5548#endif /* CONFIG_WIFI_DISPLAY */
5549
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005550 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5551 wpas_periodic, global, NULL);
5552
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005553 return global;
5554}
5555
5556
5557/**
5558 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5559 * @global: Pointer to global data from wpa_supplicant_init()
5560 * Returns: 0 after successful event loop run, -1 on failure
5561 *
5562 * This function starts the main event loop and continues running as long as
5563 * there are any remaining events. In most cases, this function is running as
5564 * long as the %wpa_supplicant process in still in use.
5565 */
5566int wpa_supplicant_run(struct wpa_global *global)
5567{
5568 struct wpa_supplicant *wpa_s;
5569
5570 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005571 (wpa_supplicant_daemon(global->params.pid_file) ||
5572 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005573 return -1;
5574
Dmitry Shmidte4663042016-04-04 10:07:49 -07005575#ifdef CONFIG_MATCH_IFACE
5576 if (wpa_supplicant_match_existing(global))
5577 return -1;
5578#endif
5579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005580 if (global->params.wait_for_monitor) {
5581 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005582 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005583 wpa_supplicant_ctrl_iface_wait(
5584 wpa_s->ctrl_iface);
5585 }
5586
5587 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5588 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5589
5590 eloop_run();
5591
5592 return 0;
5593}
5594
5595
5596/**
5597 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5598 * @global: Pointer to global data from wpa_supplicant_init()
5599 *
5600 * This function is called to deinitialize %wpa_supplicant and to free all
5601 * allocated resources. Remaining network interfaces will also be removed.
5602 */
5603void wpa_supplicant_deinit(struct wpa_global *global)
5604{
5605 int i;
5606
5607 if (global == NULL)
5608 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005609
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005610 eloop_cancel_timeout(wpas_periodic, global, NULL);
5611
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005612#ifdef CONFIG_WIFI_DISPLAY
5613 wifi_display_deinit(global);
5614#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005615
5616 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005617 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005618
5619 if (global->ctrl_iface)
5620 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5621
5622 wpas_notify_supplicant_deinitialized(global);
5623
5624 eap_peer_unregister_methods();
5625#ifdef CONFIG_AP
5626 eap_server_unregister_methods();
5627#endif /* CONFIG_AP */
5628
5629 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5630 if (!global->drv_priv[i])
5631 continue;
5632 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5633 }
5634 os_free(global->drv_priv);
5635
5636 random_deinit();
5637
5638 eloop_destroy();
5639
5640 if (global->params.pid_file) {
5641 os_daemonize_terminate(global->params.pid_file);
5642 os_free(global->params.pid_file);
5643 }
5644 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005645 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005646 os_free(global->params.override_driver);
5647 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005648#ifdef CONFIG_MATCH_IFACE
5649 os_free(global->params.match_ifaces);
5650#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005651#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005652 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005653#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005654
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005655 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005656 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005657 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005659 os_free(global);
5660 wpa_debug_close_syslog();
5661 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005662 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005663}
5664
5665
5666void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5667{
5668 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5669 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5670 char country[3];
5671 country[0] = wpa_s->conf->country[0];
5672 country[1] = wpa_s->conf->country[1];
5673 country[2] = '\0';
5674 if (wpa_drv_set_country(wpa_s, country) < 0) {
5675 wpa_printf(MSG_ERROR, "Failed to set country code "
5676 "'%s'", country);
5677 }
5678 }
5679
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005680 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5681 wpas_init_ext_pw(wpa_s);
5682
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005683 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5684 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5685
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005686#ifdef CONFIG_WPS
5687 wpas_wps_update_config(wpa_s);
5688#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005689 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005690 wpa_s->conf->changed_parameters = 0;
5691}
5692
5693
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005694void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005695{
5696 int i;
5697
5698 for (i = 0; i < *num_freqs; i++) {
5699 if (freqs[i] == freq)
5700 return;
5701 }
5702
5703 freqs[*num_freqs] = freq;
5704 (*num_freqs)++;
5705}
5706
5707
5708static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5709{
5710 struct wpa_bss *bss, *cbss;
5711 const int max_freqs = 10;
5712 int *freqs;
5713 int num_freqs = 0;
5714
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005715 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005716 if (freqs == NULL)
5717 return NULL;
5718
5719 cbss = wpa_s->current_bss;
5720
5721 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5722 if (bss == cbss)
5723 continue;
5724 if (bss->ssid_len == cbss->ssid_len &&
5725 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5726 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5727 add_freq(freqs, &num_freqs, bss->freq);
5728 if (num_freqs == max_freqs)
5729 break;
5730 }
5731 }
5732
5733 if (num_freqs == 0) {
5734 os_free(freqs);
5735 freqs = NULL;
5736 }
5737
5738 return freqs;
5739}
5740
5741
5742void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5743{
5744 int timeout;
5745 int count;
5746 int *freqs = NULL;
5747
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005748 wpas_connect_work_done(wpa_s);
5749
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005750 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005751 * Remove possible authentication timeout since the connection failed.
5752 */
5753 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5754
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005755 /*
5756 * There is no point in blacklisting the AP if this event is
5757 * generated based on local request to disconnect.
5758 */
5759 if (wpa_s->own_disconnect_req) {
5760 wpa_s->own_disconnect_req = 0;
5761 wpa_dbg(wpa_s, MSG_DEBUG,
5762 "Ignore connection failure due to local request to disconnect");
5763 return;
5764 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005765 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005766 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5767 "indication since interface has been put into "
5768 "disconnected state");
5769 return;
5770 }
5771
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005772 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005773 * Add the failed BSSID into the blacklist and speed up next scan
5774 * attempt if there could be other APs that could accept association.
5775 * The current blacklist count indicates how many times we have tried
5776 * connecting to this AP and multiple attempts mean that other APs are
5777 * either not available or has already been tried, so that we can start
5778 * increasing the delay here to avoid constant scanning.
5779 */
5780 count = wpa_blacklist_add(wpa_s, bssid);
5781 if (count == 1 && wpa_s->current_bss) {
5782 /*
5783 * This BSS was not in the blacklist before. If there is
5784 * another BSS available for the same ESS, we should try that
5785 * next. Otherwise, we may as well try this one once more
5786 * before allowing other, likely worse, ESSes to be considered.
5787 */
5788 freqs = get_bss_freqs_in_ess(wpa_s);
5789 if (freqs) {
5790 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5791 "has been seen; try it next");
5792 wpa_blacklist_add(wpa_s, bssid);
5793 /*
5794 * On the next scan, go through only the known channels
5795 * used in this ESS based on previous scans to speed up
5796 * common load balancing use case.
5797 */
5798 os_free(wpa_s->next_scan_freqs);
5799 wpa_s->next_scan_freqs = freqs;
5800 }
5801 }
5802
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005803 /*
5804 * Add previous failure count in case the temporary blacklist was
5805 * cleared due to no other BSSes being available.
5806 */
5807 count += wpa_s->extra_blacklist_count;
5808
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005809 if (count > 3 && wpa_s->current_ssid) {
5810 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5811 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005812 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005813 }
5814
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005815 switch (count) {
5816 case 1:
5817 timeout = 100;
5818 break;
5819 case 2:
5820 timeout = 500;
5821 break;
5822 case 3:
5823 timeout = 1000;
5824 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005825 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005826 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005827 break;
5828 default:
5829 timeout = 10000;
5830 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005831 }
5832
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005833 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5834 "ms", count, timeout);
5835
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005836 /*
5837 * TODO: if more than one possible AP is available in scan results,
5838 * could try the other ones before requesting a new scan.
5839 */
5840 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5841 1000 * (timeout % 1000));
5842}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005843
5844
5845int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5846{
5847 return wpa_s->conf->ap_scan == 2 ||
5848 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5849}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005850
Dmitry Shmidt04949592012-07-19 12:16:46 -07005851
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005852#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005853int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5854 struct wpa_ssid *ssid,
5855 const char *field,
5856 const char *value)
5857{
5858#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005859 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005860
5861 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5862 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5863 (const u8 *) value, os_strlen(value));
5864
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005865 rtype = wpa_supplicant_ctrl_req_from_string(field);
5866 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
5867#else /* IEEE8021X_EAPOL */
5868 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5869 return -1;
5870#endif /* IEEE8021X_EAPOL */
5871}
5872
5873int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5874 struct wpa_ssid *ssid,
5875 enum wpa_ctrl_req_type rtype,
5876 const char *value)
5877{
5878#ifdef IEEE8021X_EAPOL
5879 struct eap_peer_config *eap = &ssid->eap;
5880
5881 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005882 case WPA_CTRL_REQ_EAP_IDENTITY:
5883 os_free(eap->identity);
5884 eap->identity = (u8 *) os_strdup(value);
5885 eap->identity_len = os_strlen(value);
5886 eap->pending_req_identity = 0;
5887 if (ssid == wpa_s->current_ssid)
5888 wpa_s->reassociate = 1;
5889 break;
5890 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005891 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005892 eap->password = (u8 *) os_strdup(value);
5893 eap->password_len = os_strlen(value);
5894 eap->pending_req_password = 0;
5895 if (ssid == wpa_s->current_ssid)
5896 wpa_s->reassociate = 1;
5897 break;
5898 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005899 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005900 eap->new_password = (u8 *) os_strdup(value);
5901 eap->new_password_len = os_strlen(value);
5902 eap->pending_req_new_password = 0;
5903 if (ssid == wpa_s->current_ssid)
5904 wpa_s->reassociate = 1;
5905 break;
5906 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005907 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005908 eap->pin = os_strdup(value);
5909 eap->pending_req_pin = 0;
5910 if (ssid == wpa_s->current_ssid)
5911 wpa_s->reassociate = 1;
5912 break;
5913 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005914 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005915 eap->otp = (u8 *) os_strdup(value);
5916 eap->otp_len = os_strlen(value);
5917 os_free(eap->pending_req_otp);
5918 eap->pending_req_otp = NULL;
5919 eap->pending_req_otp_len = 0;
5920 break;
5921 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005922 str_clear_free(eap->private_key_passwd);
5923 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005924 eap->pending_req_passphrase = 0;
5925 if (ssid == wpa_s->current_ssid)
5926 wpa_s->reassociate = 1;
5927 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005928 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005929 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005930 eap->external_sim_resp = os_strdup(value);
5931 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005932 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5933 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5934 return -1;
5935 ssid->mem_only_psk = 1;
5936 if (ssid->passphrase)
5937 wpa_config_update_psk(ssid);
5938 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5939 wpa_supplicant_req_scan(wpa_s, 0, 0);
5940 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005941 case WPA_CTRL_REQ_EXT_CERT_CHECK:
5942 if (eap->pending_ext_cert_check != PENDING_CHECK)
5943 return -1;
5944 if (os_strcmp(value, "good") == 0)
5945 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
5946 else if (os_strcmp(value, "bad") == 0)
5947 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
5948 else
5949 return -1;
5950 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005951 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005952 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005953 return -1;
5954 }
5955
5956 return 0;
5957#else /* IEEE8021X_EAPOL */
5958 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5959 return -1;
5960#endif /* IEEE8021X_EAPOL */
5961}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005962#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005963
5964
5965int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5966{
5967 int i;
5968 unsigned int drv_enc;
5969
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005970 if (wpa_s->p2p_mgmt)
5971 return 1; /* no normal network profiles on p2p_mgmt interface */
5972
Dmitry Shmidt04949592012-07-19 12:16:46 -07005973 if (ssid == NULL)
5974 return 1;
5975
5976 if (ssid->disabled)
5977 return 1;
5978
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005979 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005980 drv_enc = wpa_s->drv_enc;
5981 else
5982 drv_enc = (unsigned int) -1;
5983
5984 for (i = 0; i < NUM_WEP_KEYS; i++) {
5985 size_t len = ssid->wep_key_len[i];
5986 if (len == 0)
5987 continue;
5988 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5989 continue;
5990 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5991 continue;
5992 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5993 continue;
5994 return 1; /* invalid WEP key */
5995 }
5996
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005997 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005998 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5999 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006000 return 1;
6001
Dmitry Shmidt04949592012-07-19 12:16:46 -07006002 return 0;
6003}
6004
6005
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006006int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6007{
6008#ifdef CONFIG_IEEE80211W
6009 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6010 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6011 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6012 /*
6013 * Driver does not support BIP -- ignore pmf=1 default
6014 * since the connection with PMF would fail and the
6015 * configuration does not require PMF to be enabled.
6016 */
6017 return NO_MGMT_FRAME_PROTECTION;
6018 }
6019
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006020 if (ssid &&
6021 (ssid->key_mgmt &
6022 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6023 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6024 /*
6025 * Do not use the default PMF value for non-RSN networks
6026 * since PMF is available only with RSN and pmf=2
6027 * configuration would otherwise prevent connections to
6028 * all open networks.
6029 */
6030 return NO_MGMT_FRAME_PROTECTION;
6031 }
6032
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006033 return wpa_s->conf->pmf;
6034 }
6035
6036 return ssid->ieee80211w;
6037#else /* CONFIG_IEEE80211W */
6038 return NO_MGMT_FRAME_PROTECTION;
6039#endif /* CONFIG_IEEE80211W */
6040}
6041
6042
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006043int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006044{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006045 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006046 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006047 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006048 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006049 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006050}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006051
6052
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006053void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006054{
6055 struct wpa_ssid *ssid = wpa_s->current_ssid;
6056 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006057 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006058
6059 if (ssid == NULL) {
6060 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6061 "SSID block");
6062 return;
6063 }
6064
6065 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6066 return;
6067
6068 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006069
6070#ifdef CONFIG_P2P
6071 if (ssid->p2p_group &&
6072 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6073 /*
6074 * Skip the wait time since there is a short timeout on the
6075 * connection to a P2P group.
6076 */
6077 return;
6078 }
6079#endif /* CONFIG_P2P */
6080
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006081 if (ssid->auth_failures > 50)
6082 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006083 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006084 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006085 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006086 dur = 90;
6087 else if (ssid->auth_failures > 3)
6088 dur = 60;
6089 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006090 dur = 30;
6091 else if (ssid->auth_failures > 1)
6092 dur = 20;
6093 else
6094 dur = 10;
6095
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006096 if (ssid->auth_failures > 1 &&
6097 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6098 dur += os_random() % (ssid->auth_failures * 10);
6099
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006100 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006101 if (now.sec + dur <= ssid->disabled_until.sec)
6102 return;
6103
6104 ssid->disabled_until.sec = now.sec + dur;
6105
6106 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006107 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006108 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006109 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006110}
6111
6112
6113void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6114 struct wpa_ssid *ssid, int clear_failures)
6115{
6116 if (ssid == NULL)
6117 return;
6118
6119 if (ssid->disabled_until.sec) {
6120 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6121 "id=%d ssid=\"%s\"",
6122 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6123 }
6124 ssid->disabled_until.sec = 0;
6125 ssid->disabled_until.usec = 0;
6126 if (clear_failures)
6127 ssid->auth_failures = 0;
6128}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006129
6130
6131int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6132{
6133 size_t i;
6134
6135 if (wpa_s->disallow_aps_bssid == NULL)
6136 return 0;
6137
6138 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6139 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6140 bssid, ETH_ALEN) == 0)
6141 return 1;
6142 }
6143
6144 return 0;
6145}
6146
6147
6148int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6149 size_t ssid_len)
6150{
6151 size_t i;
6152
6153 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6154 return 0;
6155
6156 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6157 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6158 if (ssid_len == s->ssid_len &&
6159 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6160 return 1;
6161 }
6162
6163 return 0;
6164}
6165
6166
6167/**
6168 * wpas_request_connection - Request a new connection
6169 * @wpa_s: Pointer to the network interface
6170 *
6171 * This function is used to request a new connection to be found. It will mark
6172 * the interface to allow reassociation and request a new scan to find a
6173 * suitable network to connect to.
6174 */
6175void wpas_request_connection(struct wpa_supplicant *wpa_s)
6176{
6177 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006178 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006179 wpa_supplicant_reinit_autoscan(wpa_s);
6180 wpa_s->extra_blacklist_count = 0;
6181 wpa_s->disconnected = 0;
6182 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006183
6184 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6185 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006186 else
6187 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006188}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006189
Roshan Pius02242d72016-08-09 15:31:48 -07006190/**
6191 * wpas_request_disconnection - Request disconnection
6192 * @wpa_s: Pointer to the network interface
6193 *
6194 * This function is used to request disconnection from the currently connected
6195 * network. This will stop any ongoing scans and initiate deauthentication.
6196 */
6197void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6198{
6199#ifdef CONFIG_SME
6200 wpa_s->sme.prev_bssid_set = 0;
6201#endif /* CONFIG_SME */
6202 wpa_s->reassociate = 0;
6203 wpa_s->disconnected = 1;
6204 wpa_supplicant_cancel_sched_scan(wpa_s);
6205 wpa_supplicant_cancel_scan(wpa_s);
6206 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6207 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6208}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006209
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006210
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006211void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6212 struct wpa_used_freq_data *freqs_data,
6213 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006214{
6215 unsigned int i;
6216
6217 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6218 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006219 for (i = 0; i < len; i++) {
6220 struct wpa_used_freq_data *cur = &freqs_data[i];
6221 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6222 i, cur->freq, cur->flags);
6223 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006224}
6225
6226
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006227/*
6228 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006229 * are using the same radio as the current interface, and in addition, get
6230 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006231 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006232int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6233 struct wpa_used_freq_data *freqs_data,
6234 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006235{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006236 struct wpa_supplicant *ifs;
6237 u8 bssid[ETH_ALEN];
6238 int freq;
6239 unsigned int idx = 0, i;
6240
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006241 wpa_dbg(wpa_s, MSG_DEBUG,
6242 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006243 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006244
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006245 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6246 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006247 if (idx == len)
6248 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006249
6250 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6251 continue;
6252
6253 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006254 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6255 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006256 freq = ifs->current_ssid->frequency;
6257 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6258 freq = ifs->assoc_freq;
6259 else
6260 continue;
6261
6262 /* Hold only distinct freqs */
6263 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006264 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006265 break;
6266
6267 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006268 freqs_data[idx++].freq = freq;
6269
6270 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006271 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006272 WPA_FREQ_USED_BY_P2P_CLIENT :
6273 WPA_FREQ_USED_BY_INFRA_STATION;
6274 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006275 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006276
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006277 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006278 return idx;
6279}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006280
6281
6282/*
6283 * Find the operating frequencies of any of the virtual interfaces that
6284 * are using the same radio as the current interface.
6285 */
6286int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6287 int *freq_array, unsigned int len)
6288{
6289 struct wpa_used_freq_data *freqs_data;
6290 int num, i;
6291
6292 os_memset(freq_array, 0, sizeof(int) * len);
6293
6294 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6295 if (!freqs_data)
6296 return -1;
6297
6298 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6299 for (i = 0; i < num; i++)
6300 freq_array[i] = freqs_data[i].freq;
6301
6302 os_free(freqs_data);
6303
6304 return num;
6305}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006306
6307
6308static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
6309{
6310 struct rrm_data *rrm = data;
6311
6312 if (!rrm->notify_neighbor_rep) {
6313 wpa_printf(MSG_ERROR,
6314 "RRM: Unexpected neighbor report timeout");
6315 return;
6316 }
6317
6318 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
6319 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
6320
6321 rrm->notify_neighbor_rep = NULL;
6322 rrm->neighbor_rep_cb_ctx = NULL;
6323}
6324
6325
6326/*
6327 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
6328 * @wpa_s: Pointer to wpa_supplicant
6329 */
6330void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
6331{
6332 wpa_s->rrm.rrm_used = 0;
6333
6334 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6335 NULL);
6336 if (wpa_s->rrm.notify_neighbor_rep)
6337 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
6338 wpa_s->rrm.next_neighbor_rep_token = 1;
6339}
6340
6341
6342/*
6343 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
6344 * @wpa_s: Pointer to wpa_supplicant
6345 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
6346 * @report_len: Length of neighbor report buffer
6347 */
6348void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
6349 const u8 *report, size_t report_len)
6350{
6351 struct wpabuf *neighbor_rep;
6352
6353 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
6354 if (report_len < 1)
6355 return;
6356
6357 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
6358 wpa_printf(MSG_DEBUG,
6359 "RRM: Discarding neighbor report with token %d (expected %d)",
6360 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
6361 return;
6362 }
6363
6364 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6365 NULL);
6366
6367 if (!wpa_s->rrm.notify_neighbor_rep) {
6368 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
6369 return;
6370 }
6371
6372 /* skipping the first byte, which is only an id (dialog token) */
6373 neighbor_rep = wpabuf_alloc(report_len - 1);
6374 if (neighbor_rep == NULL)
6375 return;
6376 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
6377 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
6378 report[0]);
6379 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
6380 neighbor_rep);
6381 wpa_s->rrm.notify_neighbor_rep = NULL;
6382 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
6383}
6384
6385
Dmitry Shmidtff787d52015-01-12 13:01:47 -08006386#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
6387/* Workaround different, undefined for Windows, error codes used here */
6388#define ENOTCONN -1
6389#define EOPNOTSUPP -1
6390#define ECANCELED -1
6391#endif
6392
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006393/* Measurement Request element + Location Subject + Maximum Age subelement */
6394#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
6395/* Measurement Request element + Location Civic Request */
6396#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
6397
6398
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006399/**
6400 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
6401 * @wpa_s: Pointer to wpa_supplicant
6402 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
6403 * is sent in the request.
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006404 * @lci: if set, neighbor request will include LCI request
6405 * @civic: if set, neighbor request will include civic location request
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006406 * @cb: Callback function to be called once the requested report arrives, or
6407 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
6408 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
6409 * the requester's responsibility to free it.
6410 * In the latter case NULL will be sent in 'neighbor_rep'.
6411 * @cb_ctx: Context value to send the callback function
6412 * Returns: 0 in case of success, negative error code otherwise
6413 *
6414 * In case there is a previous request which has not been answered yet, the
6415 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
6416 * Request must contain a callback function.
6417 */
6418int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006419 const struct wpa_ssid_value *ssid,
6420 int lci, int civic,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006421 void (*cb)(void *ctx,
6422 struct wpabuf *neighbor_rep),
6423 void *cb_ctx)
6424{
6425 struct wpabuf *buf;
6426 const u8 *rrm_ie;
6427
6428 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
6429 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
6430 return -ENOTCONN;
6431 }
6432
6433 if (!wpa_s->rrm.rrm_used) {
6434 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
6435 return -EOPNOTSUPP;
6436 }
6437
6438 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
6439 WLAN_EID_RRM_ENABLED_CAPABILITIES);
6440 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
6441 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
6442 wpa_printf(MSG_DEBUG,
6443 "RRM: No network support for Neighbor Report.");
6444 return -EOPNOTSUPP;
6445 }
6446
6447 if (!cb) {
6448 wpa_printf(MSG_DEBUG,
6449 "RRM: Neighbor Report request must provide a callback.");
6450 return -EINVAL;
6451 }
6452
6453 /* Refuse if there's a live request */
6454 if (wpa_s->rrm.notify_neighbor_rep) {
6455 wpa_printf(MSG_DEBUG,
6456 "RRM: Currently handling previous Neighbor Report.");
6457 return -EBUSY;
6458 }
6459
6460 /* 3 = action category + action code + dialog token */
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006461 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
6462 (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
6463 (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006464 if (buf == NULL) {
6465 wpa_printf(MSG_DEBUG,
6466 "RRM: Failed to allocate Neighbor Report Request");
6467 return -ENOMEM;
6468 }
6469
6470 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
6471 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
6472 wpa_s->rrm.next_neighbor_rep_token);
6473
6474 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6475 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
6476 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
6477 if (ssid) {
6478 wpabuf_put_u8(buf, WLAN_EID_SSID);
6479 wpabuf_put_u8(buf, ssid->ssid_len);
6480 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
6481 }
6482
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006483 if (lci) {
6484 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6485 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6486 wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
6487
6488 /*
6489 * Measurement token; nonzero number that is unique among the
6490 * Measurement Request elements in a particular frame.
6491 */
6492 wpabuf_put_u8(buf, 1); /* Measurement Token */
6493
6494 /*
6495 * Parallel, Enable, Request, and Report bits are 0, Duration is
6496 * reserved.
6497 */
6498 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6499 wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
6500
6501 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
6502 /* Location Subject */
6503 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6504
6505 /* Optional Subelements */
6506 /*
6507 * IEEE P802.11-REVmc/D5.0 Figure 9-170
6508 * The Maximum Age subelement is required, otherwise the AP can
6509 * send only data that was determined after receiving the
6510 * request. Setting it here to unlimited age.
6511 */
6512 wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
6513 wpabuf_put_u8(buf, 2);
6514 wpabuf_put_le16(buf, 0xffff);
6515 }
6516
6517 if (civic) {
6518 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6519 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6520 wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
6521
6522 /*
6523 * Measurement token; nonzero number that is unique among the
6524 * Measurement Request elements in a particular frame.
6525 */
6526 wpabuf_put_u8(buf, 2); /* Measurement Token */
6527
6528 /*
6529 * Parallel, Enable, Request, and Report bits are 0, Duration is
6530 * reserved.
6531 */
6532 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6533 /* Measurement Type */
6534 wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
6535
6536 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
6537 * Location Civic request */
6538 /* Location Subject */
6539 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6540 wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
6541 /* Location Service Interval Units: Seconds */
6542 wpabuf_put_u8(buf, 0);
6543 /* Location Service Interval: 0 - Only one report is requested
6544 */
6545 wpabuf_put_le16(buf, 0);
6546 /* No optional subelements */
6547 }
6548
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006549 wpa_s->rrm.next_neighbor_rep_token++;
6550
6551 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
6552 wpa_s->own_addr, wpa_s->bssid,
6553 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
6554 wpa_printf(MSG_DEBUG,
6555 "RRM: Failed to send Neighbor Report Request");
6556 wpabuf_free(buf);
6557 return -ECANCELED;
6558 }
6559
6560 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
6561 wpa_s->rrm.notify_neighbor_rep = cb;
6562 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
6563 wpas_rrm_neighbor_rep_timeout_handler,
6564 &wpa_s->rrm, NULL);
6565
6566 wpabuf_free(buf);
6567 return 0;
6568}
6569
6570
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006571static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
6572 const u8 *request, size_t len,
6573 struct wpabuf *report)
6574{
6575 u8 token, type, subject;
6576 u16 max_age = 0;
6577 struct os_reltime t, diff;
6578 unsigned long diff_l;
6579 u8 *ptoken;
6580 const u8 *subelem;
6581
6582 if (!wpa_s->lci || len < 3 + 4)
6583 return report;
6584
6585 token = *request++;
6586 /* Measurement request mode isn't used */
6587 request++;
6588 type = *request++;
6589 subject = *request++;
6590
6591 wpa_printf(MSG_DEBUG,
6592 "Measurement request token %u type %u location subject %u",
6593 token, type, subject);
6594
6595 if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
6596 wpa_printf(MSG_INFO,
6597 "Not building LCI report - bad type or location subject");
6598 return report;
6599 }
6600
6601 /* Subelements are formatted exactly like elements */
6602 subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
6603 if (subelem && subelem[1] == 2)
6604 max_age = WPA_GET_LE16(subelem + 2);
6605
6606 if (os_get_reltime(&t))
6607 return report;
6608
6609 os_reltime_sub(&t, &wpa_s->lci_time, &diff);
6610 /* LCI age is calculated in 10th of a second units. */
6611 diff_l = diff.sec * 10 + diff.usec / 100000;
6612
6613 if (max_age != 0xffff && max_age < diff_l)
6614 return report;
6615
6616 if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
6617 return report;
6618
6619 wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
6620 wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
6621 /* We'll override user's measurement token */
6622 ptoken = wpabuf_put(report, 0);
6623 wpabuf_put_buf(report, wpa_s->lci);
6624 *ptoken = token;
6625
6626 return report;
6627}
6628
6629
6630void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
6631 const u8 *src,
6632 const u8 *frame, size_t len)
6633{
6634 struct wpabuf *buf, *report;
6635 u8 token;
6636 const u8 *ie, *end;
6637
6638 if (wpa_s->wpa_state != WPA_COMPLETED) {
6639 wpa_printf(MSG_INFO,
6640 "RRM: Ignoring radio measurement request: Not associated");
6641 return;
6642 }
6643
6644 if (!wpa_s->rrm.rrm_used) {
6645 wpa_printf(MSG_INFO,
6646 "RRM: Ignoring radio measurement request: Not RRM network");
6647 return;
6648 }
6649
6650 if (len < 3) {
6651 wpa_printf(MSG_INFO,
6652 "RRM: Ignoring too short radio measurement request");
6653 return;
6654 }
6655
6656 end = frame + len;
6657
6658 token = *frame++;
6659
6660 /* Ignore number of repetitions because it's not used in LCI request */
6661 frame += 2;
6662
6663 report = NULL;
6664 while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
6665 ie[1] >= 3) {
6666 u8 msmt_type;
6667
6668 msmt_type = ie[4];
6669 wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
6670
6671 switch (msmt_type) {
6672 case MEASURE_TYPE_LCI:
6673 report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
6674 report);
6675 break;
6676 default:
6677 wpa_printf(MSG_INFO,
6678 "RRM: Unsupported radio measurement request %d",
6679 msmt_type);
6680 break;
6681 }
6682
6683 frame = ie + ie[1] + 2;
6684 }
6685
6686 if (!report)
6687 return;
6688
6689 buf = wpabuf_alloc(3 + wpabuf_len(report));
6690 if (!buf) {
6691 wpabuf_free(report);
6692 return;
6693 }
6694
6695 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6696 wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
6697 wpabuf_put_u8(buf, token);
6698
6699 wpabuf_put_buf(buf, report);
6700 wpabuf_free(report);
6701
6702 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6703 wpa_s->own_addr, wpa_s->bssid,
6704 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6705 wpa_printf(MSG_ERROR,
6706 "RRM: Radio measurement report failed: Sending Action frame failed");
6707 }
6708 wpabuf_free(buf);
6709}
6710
6711
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006712void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
6713 const u8 *src,
6714 const u8 *frame, size_t len,
6715 int rssi)
6716{
6717 struct wpabuf *buf;
6718 const struct rrm_link_measurement_request *req;
6719 struct rrm_link_measurement_report report;
6720
6721 if (wpa_s->wpa_state != WPA_COMPLETED) {
6722 wpa_printf(MSG_INFO,
6723 "RRM: Ignoring link measurement request. Not associated");
6724 return;
6725 }
6726
6727 if (!wpa_s->rrm.rrm_used) {
6728 wpa_printf(MSG_INFO,
6729 "RRM: Ignoring link measurement request. Not RRM network");
6730 return;
6731 }
6732
6733 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
6734 wpa_printf(MSG_INFO,
6735 "RRM: Measurement report failed. TX power insertion not supported");
6736 return;
6737 }
6738
6739 req = (const struct rrm_link_measurement_request *) frame;
6740 if (len < sizeof(*req)) {
6741 wpa_printf(MSG_INFO,
6742 "RRM: Link measurement report failed. Request too short");
6743 return;
6744 }
6745
6746 os_memset(&report, 0, sizeof(report));
6747 report.tpc.eid = WLAN_EID_TPC_REPORT;
6748 report.tpc.len = 2;
6749 report.rsni = 255; /* 255 indicates that RSNI is not available */
6750 report.dialog_token = req->dialog_token;
6751
6752 /*
6753 * It's possible to estimate RCPI based on RSSI in dBm. This
6754 * calculation will not reflect the correct value for high rates,
6755 * but it's good enough for Action frames which are transmitted
6756 * with up to 24 Mbps rates.
6757 */
6758 if (!rssi)
6759 report.rcpi = 255; /* not available */
6760 else if (rssi < -110)
6761 report.rcpi = 0;
6762 else if (rssi > 0)
6763 report.rcpi = 220;
6764 else
6765 report.rcpi = (rssi + 110) * 2;
6766
6767 /* action_category + action_code */
6768 buf = wpabuf_alloc(2 + sizeof(report));
6769 if (buf == NULL) {
6770 wpa_printf(MSG_ERROR,
6771 "RRM: Link measurement report failed. Buffer allocation failed");
6772 return;
6773 }
6774
6775 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6776 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
6777 wpabuf_put_data(buf, &report, sizeof(report));
6778 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
6779 wpabuf_head(buf), wpabuf_len(buf));
6780
6781 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6782 wpa_s->own_addr, wpa_s->bssid,
6783 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6784 wpa_printf(MSG_ERROR,
6785 "RRM: Link measurement report failed. Send action failed");
6786 }
6787 wpabuf_free(buf);
6788}
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006789
6790
6791struct wpa_supplicant *
6792wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6793{
6794 switch (frame) {
6795#ifdef CONFIG_P2P
6796 case VENDOR_ELEM_PROBE_REQ_P2P:
6797 case VENDOR_ELEM_PROBE_RESP_P2P:
6798 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6799 case VENDOR_ELEM_BEACON_P2P_GO:
6800 case VENDOR_ELEM_P2P_PD_REQ:
6801 case VENDOR_ELEM_P2P_PD_RESP:
6802 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6803 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6804 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6805 case VENDOR_ELEM_P2P_INV_REQ:
6806 case VENDOR_ELEM_P2P_INV_RESP:
6807 case VENDOR_ELEM_P2P_ASSOC_REQ:
6808 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006809 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006810#endif /* CONFIG_P2P */
6811 default:
6812 return wpa_s;
6813 }
6814}
6815
6816
6817void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6818{
6819 unsigned int i;
6820 char buf[30];
6821
6822 wpa_printf(MSG_DEBUG, "Update vendor elements");
6823
6824 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6825 if (wpa_s->vendor_elem[i]) {
6826 int res;
6827
6828 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6829 if (!os_snprintf_error(sizeof(buf), res)) {
6830 wpa_hexdump_buf(MSG_DEBUG, buf,
6831 wpa_s->vendor_elem[i]);
6832 }
6833 }
6834 }
6835
6836#ifdef CONFIG_P2P
6837 if (wpa_s->parent == wpa_s &&
6838 wpa_s->global->p2p &&
6839 !wpa_s->global->p2p_disabled)
6840 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6841#endif /* CONFIG_P2P */
6842}
6843
6844
6845int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6846 const u8 *elem, size_t len)
6847{
6848 u8 *ie, *end;
6849
6850 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6851 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6852
6853 for (; ie + 1 < end; ie += 2 + ie[1]) {
6854 if (ie + len > end)
6855 break;
6856 if (os_memcmp(ie, elem, len) != 0)
6857 continue;
6858
6859 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6860 wpabuf_free(wpa_s->vendor_elem[frame]);
6861 wpa_s->vendor_elem[frame] = NULL;
6862 } else {
6863 os_memmove(ie, ie + len, end - (ie + len));
6864 wpa_s->vendor_elem[frame]->used -= len;
6865 }
6866 wpas_vendor_elem_update(wpa_s);
6867 return 0;
6868 }
6869
6870 return -1;
6871}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006872
6873
6874struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6875 u16 num_modes, enum hostapd_hw_mode mode)
6876{
6877 u16 i;
6878
6879 for (i = 0; i < num_modes; i++) {
6880 if (modes[i].mode == mode)
6881 return &modes[i];
6882 }
6883
6884 return NULL;
6885}
6886
6887
6888static struct
6889wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6890 const u8 *bssid)
6891{
6892 struct wpa_bss_tmp_disallowed *bss;
6893
6894 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6895 struct wpa_bss_tmp_disallowed, list) {
6896 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6897 return bss;
6898 }
6899
6900 return NULL;
6901}
6902
6903
6904void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6905 unsigned int sec)
6906{
6907 struct wpa_bss_tmp_disallowed *bss;
6908 struct os_reltime until;
6909
6910 os_get_reltime(&until);
6911 until.sec += sec;
6912
6913 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6914 if (bss) {
6915 bss->disallowed_until = until;
6916 return;
6917 }
6918
6919 bss = os_malloc(sizeof(*bss));
6920 if (!bss) {
6921 wpa_printf(MSG_DEBUG,
6922 "Failed to allocate memory for temp disallow BSS");
6923 return;
6924 }
6925
6926 bss->disallowed_until = until;
6927 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6928 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
6929}
6930
6931
6932int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6933{
6934 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
6935 struct os_reltime now, age;
6936
6937 os_get_reltime(&now);
6938
6939 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6940 struct wpa_bss_tmp_disallowed, list) {
6941 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
6942 /* This BSS is not disallowed anymore */
6943 dl_list_del(&tmp->list);
6944 os_free(tmp);
6945 continue;
6946 }
6947 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6948 bss = tmp;
6949 break;
6950 }
6951 }
6952 if (!bss)
6953 return 0;
6954
6955 os_reltime_sub(&bss->disallowed_until, &now, &age);
6956 wpa_printf(MSG_DEBUG,
6957 "BSS " MACSTR " disabled for %ld.%0ld seconds",
6958 MAC2STR(bss->bssid), age.sec, age.usec);
6959 return 1;
6960}