blob: c801ccf9b130e8c2daa5f1c0c6c1ee03a7842204 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003 * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
Dmitry Shmidte4663042016-04-04 10:07:49 -070014#ifdef CONFIG_MATCH_IFACE
15#include <net/if.h>
16#include <fnmatch.h>
17#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include "common.h"
20#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "eapol_supp/eapol_supp_sm.h"
23#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070024#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "eap_server/eap_methods.h"
26#include "rsn_supp/wpa.h"
27#include "eloop.h"
28#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070029#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "l2_packet/l2_packet.h"
31#include "wpa_supplicant_i.h"
32#include "driver_i.h"
33#include "ctrl_iface.h"
34#include "pcsc_funcs.h"
35#include "common/version.h"
36#include "rsn_supp/preauth.h"
37#include "rsn_supp/pmksa_cache.h"
38#include "common/wpa_ctrl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070039#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080040#include "common/hw_features_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041#include "p2p/p2p.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080042#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043#include "blacklist.h"
44#include "wpas_glue.h"
45#include "wps_supplicant.h"
46#include "ibss_rsn.h"
47#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080048#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "ap.h"
50#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070051#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070052#include "notify.h"
53#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070054#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070055#include "bss.h"
56#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080057#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070058#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070059#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070060#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080061#include "mesh.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070062
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070063const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070064"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidtde47be72016-01-07 12:52:55 -080065"Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070066
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070067const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080068"This software may be distributed under the terms of the BSD license.\n"
69"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070#ifdef EAP_TLS_OPENSSL
71"\nThis product includes software developed by the OpenSSL Project\n"
72"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
73#endif /* EAP_TLS_OPENSSL */
74;
75
76#ifndef CONFIG_NO_STDOUT_DEBUG
77/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070078const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080079"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070080const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080081"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082"\n"
83"Redistribution and use in source and binary forms, with or without\n"
84"modification, are permitted provided that the following conditions are\n"
85"met:\n"
86"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070087const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088"1. Redistributions of source code must retain the above copyright\n"
89" notice, this list of conditions and the following disclaimer.\n"
90"\n"
91"2. Redistributions in binary form must reproduce the above copyright\n"
92" notice, this list of conditions and the following disclaimer in the\n"
93" documentation and/or other materials provided with the distribution.\n"
94"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070095const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
97" names of its contributors may be used to endorse or promote products\n"
98" derived from this software without specific prior written permission.\n"
99"\n"
100"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
101"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
102"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
103"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700104const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
106"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
107"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
108"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
109"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
110"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
111"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
112"\n";
113#endif /* CONFIG_NO_STDOUT_DEBUG */
114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700115/* Configure default/group WEP keys for static WEP */
116int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
117{
118 int i, set = 0;
119
120 for (i = 0; i < NUM_WEP_KEYS; i++) {
121 if (ssid->wep_key_len[i] == 0)
122 continue;
123
124 set = 1;
125 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
126 i, i == ssid->wep_tx_keyidx, NULL, 0,
127 ssid->wep_key[i], ssid->wep_key_len[i]);
128 }
129
130 return set;
131}
132
133
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700134int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
135 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136{
137 u8 key[32];
138 size_t keylen;
139 enum wpa_alg alg;
140 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800141 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700142
143 /* IBSS/WPA-None uses only one key (Group) for both receiving and
144 * sending unicast and multicast packets. */
145
146 if (ssid->mode != WPAS_MODE_IBSS) {
147 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
148 "IBSS/ad-hoc) for WPA-None", ssid->mode);
149 return -1;
150 }
151
152 if (!ssid->psk_set) {
153 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
154 "WPA-None");
155 return -1;
156 }
157
158 switch (wpa_s->group_cipher) {
159 case WPA_CIPHER_CCMP:
160 os_memcpy(key, ssid->psk, 16);
161 keylen = 16;
162 alg = WPA_ALG_CCMP;
163 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700164 case WPA_CIPHER_GCMP:
165 os_memcpy(key, ssid->psk, 16);
166 keylen = 16;
167 alg = WPA_ALG_GCMP;
168 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700169 case WPA_CIPHER_TKIP:
170 /* WPA-None uses the same Michael MIC key for both TX and RX */
171 os_memcpy(key, ssid->psk, 16 + 8);
172 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
173 keylen = 32;
174 alg = WPA_ALG_TKIP;
175 break;
176 default:
177 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
178 "WPA-None", wpa_s->group_cipher);
179 return -1;
180 }
181
182 /* TODO: should actually remember the previously used seq#, both for TX
183 * and RX from each STA.. */
184
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800185 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
186 os_memset(key, 0, sizeof(key));
187 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700188}
189
190
191static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
192{
193 struct wpa_supplicant *wpa_s = eloop_ctx;
194 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700195 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
196 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
197 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700198 bssid = wpa_s->pending_bssid;
199 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
200 MAC2STR(bssid));
201 wpa_blacklist_add(wpa_s, bssid);
202 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800203 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700204 wpa_s->reassociate = 1;
205
206 /*
207 * If we timed out, the AP or the local radio may be busy.
208 * So, wait a second until scanning again.
209 */
210 wpa_supplicant_req_scan(wpa_s, 1, 0);
211}
212
213
214/**
215 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
216 * @wpa_s: Pointer to wpa_supplicant data
217 * @sec: Number of seconds after which to time out authentication
218 * @usec: Number of microseconds after which to time out authentication
219 *
220 * This function is used to schedule a timeout for the current authentication
221 * attempt.
222 */
223void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
224 int sec, int usec)
225{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700226 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700227 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
228 return;
229
230 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
231 "%d usec", sec, usec);
232 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
233 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
234}
235
236
237/**
238 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
239 * @wpa_s: Pointer to wpa_supplicant data
240 *
241 * This function is used to cancel authentication timeout scheduled with
242 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
243 * been completed.
244 */
245void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
246{
247 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
248 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
249 wpa_blacklist_del(wpa_s, wpa_s->bssid);
250}
251
252
253/**
254 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
255 * @wpa_s: Pointer to wpa_supplicant data
256 *
257 * This function is used to configure EAPOL state machine based on the selected
258 * authentication mode.
259 */
260void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
261{
262#ifdef IEEE8021X_EAPOL
263 struct eapol_config eapol_conf;
264 struct wpa_ssid *ssid = wpa_s->current_ssid;
265
266#ifdef CONFIG_IBSS_RSN
267 if (ssid->mode == WPAS_MODE_IBSS &&
268 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
269 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
270 /*
271 * RSN IBSS authentication is per-STA and we can disable the
272 * per-BSSID EAPOL authentication.
273 */
274 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
275 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
276 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
277 return;
278 }
279#endif /* CONFIG_IBSS_RSN */
280
281 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
282 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
283
284 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
285 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
286 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
287 else
288 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
289
290 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
291 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
292 eapol_conf.accept_802_1x_keys = 1;
293 eapol_conf.required_keys = 0;
294 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
295 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
296 }
297 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
298 eapol_conf.required_keys |=
299 EAPOL_REQUIRE_KEY_BROADCAST;
300 }
301
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700302 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303 eapol_conf.required_keys = 0;
304 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700305 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700306 eapol_conf.workaround = ssid->eap_workaround;
307 eapol_conf.eap_disabled =
308 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
309 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
310 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700311 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800312
313#ifdef CONFIG_WPS
314 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
315 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
316 if (wpa_s->current_bss) {
317 struct wpabuf *ie;
318 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
319 WPS_IE_VENDOR_TYPE);
320 if (ie) {
321 if (wps_is_20(ie))
322 eapol_conf.wps |=
323 EAPOL_PEER_IS_WPS20_AP;
324 wpabuf_free(ie);
325 }
326 }
327 }
328#endif /* CONFIG_WPS */
329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700330 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700331
332 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800333#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700334}
335
336
337/**
338 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
339 * @wpa_s: Pointer to wpa_supplicant data
340 * @ssid: Configuration data for the network
341 *
342 * This function is used to configure WPA state machine and related parameters
343 * to a mode where WPA is not enabled. This is called as part of the
344 * authentication configuration when the selected network does not use WPA.
345 */
346void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
347 struct wpa_ssid *ssid)
348{
349 int i;
350
351 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
352 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
353 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
354 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
355 else
356 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
357 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
358 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
359 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
360 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
361 wpa_s->group_cipher = WPA_CIPHER_NONE;
362 wpa_s->mgmt_group_cipher = 0;
363
364 for (i = 0; i < NUM_WEP_KEYS; i++) {
365 if (ssid->wep_key_len[i] > 5) {
366 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
367 wpa_s->group_cipher = WPA_CIPHER_WEP104;
368 break;
369 } else if (ssid->wep_key_len[i] > 0) {
370 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
371 wpa_s->group_cipher = WPA_CIPHER_WEP40;
372 break;
373 }
374 }
375
376 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
377 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
378 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
379 wpa_s->pairwise_cipher);
380 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
381#ifdef CONFIG_IEEE80211W
382 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
383 wpa_s->mgmt_group_cipher);
384#endif /* CONFIG_IEEE80211W */
385
386 pmksa_cache_clear_current(wpa_s->wpa);
387}
388
389
Dmitry Shmidt04949592012-07-19 12:16:46 -0700390void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800391{
392 int i;
393 if (wpa_s->hw.modes == NULL)
394 return;
395
396 for (i = 0; i < wpa_s->hw.num_modes; i++) {
397 os_free(wpa_s->hw.modes[i].channels);
398 os_free(wpa_s->hw.modes[i].rates);
399 }
400
401 os_free(wpa_s->hw.modes);
402 wpa_s->hw.modes = NULL;
403}
404
405
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800406static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
407{
408 struct wpa_bss_tmp_disallowed *bss, *prev;
409
410 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
411 struct wpa_bss_tmp_disallowed, list) {
412 dl_list_del(&bss->list);
413 os_free(bss);
414 }
415}
416
417
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
419{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700420 int i;
421
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700422 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700423 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 scard_deinit(wpa_s->scard);
425 wpa_s->scard = NULL;
426 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
427 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
428 l2_packet_deinit(wpa_s->l2);
429 wpa_s->l2 = NULL;
430 if (wpa_s->l2_br) {
431 l2_packet_deinit(wpa_s->l2_br);
432 wpa_s->l2_br = NULL;
433 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800434#ifdef CONFIG_TESTING_OPTIONS
435 l2_packet_deinit(wpa_s->l2_test);
436 wpa_s->l2_test = NULL;
437#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700438
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700439 if (wpa_s->conf != NULL) {
440 struct wpa_ssid *ssid;
441 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
442 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 }
444
445 os_free(wpa_s->confname);
446 wpa_s->confname = NULL;
447
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700448 os_free(wpa_s->confanother);
449 wpa_s->confanother = NULL;
450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451 wpa_sm_set_eapol(wpa_s->wpa, NULL);
452 eapol_sm_deinit(wpa_s->eapol);
453 wpa_s->eapol = NULL;
454
455 rsn_preauth_deinit(wpa_s->wpa);
456
457#ifdef CONFIG_TDLS
458 wpa_tdls_deinit(wpa_s->wpa);
459#endif /* CONFIG_TDLS */
460
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800461 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700462 pmksa_candidate_free(wpa_s->wpa);
463 wpa_sm_deinit(wpa_s->wpa);
464 wpa_s->wpa = NULL;
465 wpa_blacklist_clear(wpa_s);
466
467 wpa_bss_deinit(wpa_s);
468
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700469 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700470 wpa_supplicant_cancel_scan(wpa_s);
471 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800472 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
473#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
474 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
475 wpa_s, NULL);
476#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700477
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700478 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700480 wpas_wps_deinit(wpa_s);
481
482 wpabuf_free(wpa_s->pending_eapol_rx);
483 wpa_s->pending_eapol_rx = NULL;
484
485#ifdef CONFIG_IBSS_RSN
486 ibss_rsn_deinit(wpa_s->ibss_rsn);
487 wpa_s->ibss_rsn = NULL;
488#endif /* CONFIG_IBSS_RSN */
489
490 sme_deinit(wpa_s);
491
492#ifdef CONFIG_AP
493 wpa_supplicant_ap_deinit(wpa_s);
494#endif /* CONFIG_AP */
495
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700496 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700497
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800498#ifdef CONFIG_OFFCHANNEL
499 offchannel_deinit(wpa_s);
500#endif /* CONFIG_OFFCHANNEL */
501
502 wpa_supplicant_cancel_sched_scan(wpa_s);
503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700504 os_free(wpa_s->next_scan_freqs);
505 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800506
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800507 os_free(wpa_s->manual_scan_freqs);
508 wpa_s->manual_scan_freqs = NULL;
509
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700510 os_free(wpa_s->manual_sched_scan_freqs);
511 wpa_s->manual_sched_scan_freqs = NULL;
512
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800513 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
514
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700515 /*
516 * Need to remove any pending gas-query radio work before the
517 * gas_query_deinit() call because gas_query::work has not yet been set
518 * for works that have not been started. gas_query_free() will be unable
519 * to cancel such pending radio works and once the pending gas-query
520 * radio work eventually gets removed, the deinit notification call to
521 * gas_query_start_cb() would result in dereferencing freed memory.
522 */
523 if (wpa_s->radio)
524 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800525 gas_query_deinit(wpa_s->gas);
526 wpa_s->gas = NULL;
527
528 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700529
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700530 ieee802_1x_dealloc_kay_sm(wpa_s);
531
Dmitry Shmidt04949592012-07-19 12:16:46 -0700532 os_free(wpa_s->bssid_filter);
533 wpa_s->bssid_filter = NULL;
534
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800535 os_free(wpa_s->disallow_aps_bssid);
536 wpa_s->disallow_aps_bssid = NULL;
537 os_free(wpa_s->disallow_aps_ssid);
538 wpa_s->disallow_aps_ssid = NULL;
539
Dmitry Shmidt04949592012-07-19 12:16:46 -0700540 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700541#ifdef CONFIG_WNM
542 wnm_deallocate_memory(wpa_s);
543#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700544
545 ext_password_deinit(wpa_s->ext_pw);
546 wpa_s->ext_pw = NULL;
547
548 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800549 wpa_s->last_gas_resp = NULL;
550 wpabuf_free(wpa_s->prev_gas_resp);
551 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700552
553 os_free(wpa_s->last_scan_res);
554 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800555
556#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700557 if (wpa_s->drv_priv)
558 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700559 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800560#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700561
562 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
563 wpabuf_free(wpa_s->vendor_elem[i]);
564 wpa_s->vendor_elem[i] = NULL;
565 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800566
567 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800568
569 wpa_s->sched_scan_plans_num = 0;
570 os_free(wpa_s->sched_scan_plans);
571 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800572
573#ifdef CONFIG_MBO
574 wpa_s->non_pref_chan_num = 0;
575 os_free(wpa_s->non_pref_chan);
576 wpa_s->non_pref_chan = NULL;
577#endif /* CONFIG_MBO */
578
579 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700580
581 wpabuf_free(wpa_s->lci);
582 wpa_s->lci = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700583}
584
585
586/**
587 * wpa_clear_keys - Clear keys configured for the driver
588 * @wpa_s: Pointer to wpa_supplicant data
589 * @addr: Previously used BSSID or %NULL if not available
590 *
591 * This function clears the encryption keys that has been previously configured
592 * for the driver.
593 */
594void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
595{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800596 int i, max;
597
598#ifdef CONFIG_IEEE80211W
599 max = 6;
600#else /* CONFIG_IEEE80211W */
601 max = 4;
602#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700603
604 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800605 for (i = 0; i < max; i++) {
606 if (wpa_s->keys_cleared & BIT(i))
607 continue;
608 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
609 NULL, 0);
610 }
611 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
612 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700613 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
614 0);
615 /* MLME-SETPROTECTION.request(None) */
616 wpa_drv_mlme_setprotection(
617 wpa_s, addr,
618 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
619 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
620 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800621 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700622}
623
624
625/**
626 * wpa_supplicant_state_txt - Get the connection state name as a text string
627 * @state: State (wpa_state; WPA_*)
628 * Returns: The state name as a printable text string
629 */
630const char * wpa_supplicant_state_txt(enum wpa_states state)
631{
632 switch (state) {
633 case WPA_DISCONNECTED:
634 return "DISCONNECTED";
635 case WPA_INACTIVE:
636 return "INACTIVE";
637 case WPA_INTERFACE_DISABLED:
638 return "INTERFACE_DISABLED";
639 case WPA_SCANNING:
640 return "SCANNING";
641 case WPA_AUTHENTICATING:
642 return "AUTHENTICATING";
643 case WPA_ASSOCIATING:
644 return "ASSOCIATING";
645 case WPA_ASSOCIATED:
646 return "ASSOCIATED";
647 case WPA_4WAY_HANDSHAKE:
648 return "4WAY_HANDSHAKE";
649 case WPA_GROUP_HANDSHAKE:
650 return "GROUP_HANDSHAKE";
651 case WPA_COMPLETED:
652 return "COMPLETED";
653 default:
654 return "UNKNOWN";
655 }
656}
657
658
659#ifdef CONFIG_BGSCAN
660
661static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
662{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800663 const char *name;
664
665 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
666 name = wpa_s->current_ssid->bgscan;
667 else
668 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800669 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800670 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800671 if (wpas_driver_bss_selection(wpa_s))
672 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700673 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
674 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800675#ifdef CONFIG_P2P
676 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
677 return;
678#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700679
680 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800681 if (wpa_s->current_ssid) {
682 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700683 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
684 "bgscan");
685 /*
686 * Live without bgscan; it is only used as a roaming
687 * optimization, so the initial connection is not
688 * affected.
689 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700690 } else {
691 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700693 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
694 0);
695 if (scan_res) {
696 bgscan_notify_scan(wpa_s, scan_res);
697 wpa_scan_results_free(scan_res);
698 }
699 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700700 } else
701 wpa_s->bgscan_ssid = NULL;
702}
703
704
705static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
706{
707 if (wpa_s->bgscan_ssid != NULL) {
708 bgscan_deinit(wpa_s);
709 wpa_s->bgscan_ssid = NULL;
710 }
711}
712
713#endif /* CONFIG_BGSCAN */
714
715
Dmitry Shmidt04949592012-07-19 12:16:46 -0700716static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
717{
718 if (autoscan_init(wpa_s, 0))
719 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
720}
721
722
723static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
724{
725 autoscan_deinit(wpa_s);
726}
727
728
729void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
730{
731 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
732 wpa_s->wpa_state == WPA_SCANNING) {
733 autoscan_deinit(wpa_s);
734 wpa_supplicant_start_autoscan(wpa_s);
735 }
736}
737
738
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739/**
740 * wpa_supplicant_set_state - Set current connection state
741 * @wpa_s: Pointer to wpa_supplicant data
742 * @state: The new connection state
743 *
744 * This function is called whenever the connection state changes, e.g.,
745 * association is completed for WPA/WPA2 4-Way Handshake is started.
746 */
747void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
748 enum wpa_states state)
749{
750 enum wpa_states old_state = wpa_s->wpa_state;
751
752 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
753 wpa_supplicant_state_txt(wpa_s->wpa_state),
754 wpa_supplicant_state_txt(state));
755
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800756 if (state == WPA_INTERFACE_DISABLED) {
757 /* Assure normal scan when interface is restored */
758 wpa_s->normal_scans = 0;
759 }
760
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700761 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800762 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700763 /* Reinitialize normal_scan counter */
764 wpa_s->normal_scans = 0;
765 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800766
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700767#ifdef CONFIG_P2P
768 /*
769 * P2PS client has to reply to Probe Request frames received on the
770 * group operating channel. Enable Probe Request frame reporting for
771 * P2P connected client in case p2p_cli_probe configuration property is
772 * set to 1.
773 */
774 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
775 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
776 wpa_s->current_ssid->p2p_group) {
777 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
778 wpa_dbg(wpa_s, MSG_DEBUG,
779 "P2P: Enable CLI Probe Request RX reporting");
780 wpa_s->p2p_cli_probe =
781 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
782 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
783 wpa_dbg(wpa_s, MSG_DEBUG,
784 "P2P: Disable CLI Probe Request RX reporting");
785 wpa_s->p2p_cli_probe = 0;
786 wpa_drv_probe_req_report(wpa_s, 0);
787 }
788 }
789#endif /* CONFIG_P2P */
790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700791 if (state != WPA_SCANNING)
792 wpa_supplicant_notify_scanning(wpa_s, 0);
793
794 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700795 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700796#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700797 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800798 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800799 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700800 ssid ? ssid->id : -1,
801 ssid && ssid->id_str ? ssid->id_str : "");
802#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700803 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700804 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800805 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700806 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807 wpa_drv_set_operstate(wpa_s, 1);
808#ifndef IEEE8021X_EAPOL
809 wpa_drv_set_supp_port(wpa_s, 1);
810#endif /* IEEE8021X_EAPOL */
811 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700812 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700813 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700814
815 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700816 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
817 state == WPA_ASSOCIATED) {
818 wpa_s->new_connection = 1;
819 wpa_drv_set_operstate(wpa_s, 0);
820#ifndef IEEE8021X_EAPOL
821 wpa_drv_set_supp_port(wpa_s, 0);
822#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700823 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700824 }
825 wpa_s->wpa_state = state;
826
827#ifdef CONFIG_BGSCAN
828 if (state == WPA_COMPLETED)
829 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800830 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700831 wpa_supplicant_stop_bgscan(wpa_s);
832#endif /* CONFIG_BGSCAN */
833
Dmitry Shmidt04949592012-07-19 12:16:46 -0700834 if (state == WPA_AUTHENTICATING)
835 wpa_supplicant_stop_autoscan(wpa_s);
836
837 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
838 wpa_supplicant_start_autoscan(wpa_s);
839
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800840 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
841 wmm_ac_notify_disassoc(wpa_s);
842
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700843 if (wpa_s->wpa_state != old_state) {
844 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
845
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700846 /*
847 * Notify the P2P Device interface about a state change in one
848 * of the interfaces.
849 */
850 wpas_p2p_indicate_state_change(wpa_s);
851
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700852 if (wpa_s->wpa_state == WPA_COMPLETED ||
853 old_state == WPA_COMPLETED)
854 wpas_notify_auth_changed(wpa_s);
855 }
856}
857
858
859void wpa_supplicant_terminate_proc(struct wpa_global *global)
860{
861 int pending = 0;
862#ifdef CONFIG_WPS
863 struct wpa_supplicant *wpa_s = global->ifaces;
864 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800865 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700866 if (wpas_wps_terminate_pending(wpa_s) == 1)
867 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700868#ifdef CONFIG_P2P
869 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
870 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
871 wpas_p2p_disconnect(wpa_s);
872#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800873 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700874 }
875#endif /* CONFIG_WPS */
876 if (pending)
877 return;
878 eloop_terminate();
879}
880
881
882static void wpa_supplicant_terminate(int sig, void *signal_ctx)
883{
884 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885 wpa_supplicant_terminate_proc(global);
886}
887
888
889void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
890{
891 enum wpa_states old_state = wpa_s->wpa_state;
892
893 wpa_s->pairwise_cipher = 0;
894 wpa_s->group_cipher = 0;
895 wpa_s->mgmt_group_cipher = 0;
896 wpa_s->key_mgmt = 0;
897 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700898 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700899
900 if (wpa_s->wpa_state != old_state)
901 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
902}
903
904
905/**
906 * wpa_supplicant_reload_configuration - Reload configuration data
907 * @wpa_s: Pointer to wpa_supplicant data
908 * Returns: 0 on success or -1 if configuration parsing failed
909 *
910 * This function can be used to request that the configuration data is reloaded
911 * (e.g., after configuration file change). This function is reloading
912 * configuration only for one interface, so this may need to be called multiple
913 * times if %wpa_supplicant is controlling multiple interfaces and all
914 * interfaces need reconfiguration.
915 */
916int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
917{
918 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700919 int reconf_ctrl;
920 int old_ap_scan;
921
922 if (wpa_s->confname == NULL)
923 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700924 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700925 if (conf == NULL) {
926 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
927 "file '%s' - exiting", wpa_s->confname);
928 return -1;
929 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700930 wpa_config_read(wpa_s->confanother, conf);
931
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700932 conf->changed_parameters = (unsigned int) -1;
933
934 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
935 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
936 os_strcmp(conf->ctrl_interface,
937 wpa_s->conf->ctrl_interface) != 0);
938
939 if (reconf_ctrl && wpa_s->ctrl_iface) {
940 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
941 wpa_s->ctrl_iface = NULL;
942 }
943
944 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800945 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700946 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
947 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800948 wpa_supplicant_deauthenticate(wpa_s,
949 WLAN_REASON_DEAUTH_LEAVING);
950 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700951
952 /*
953 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800954 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700955 */
956 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
957 /*
958 * Clear forced success to clear EAP state for next
959 * authentication.
960 */
961 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
962 }
963 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
964 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800965 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
967 rsn_preauth_deinit(wpa_s->wpa);
968
969 old_ap_scan = wpa_s->conf->ap_scan;
970 wpa_config_free(wpa_s->conf);
971 wpa_s->conf = conf;
972 if (old_ap_scan != wpa_s->conf->ap_scan)
973 wpas_notify_ap_scan_changed(wpa_s);
974
975 if (reconf_ctrl)
976 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
977
978 wpa_supplicant_update_config(wpa_s);
979
980 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700981 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700982 wpa_s->reassociate = 1;
983 wpa_supplicant_req_scan(wpa_s, 0, 0);
984 }
985 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
986 return 0;
987}
988
989
990static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
991{
992 struct wpa_global *global = signal_ctx;
993 struct wpa_supplicant *wpa_s;
994 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
995 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
996 sig);
997 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
998 wpa_supplicant_terminate_proc(global);
999 }
1000 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001001
1002 if (wpa_debug_reopen_file() < 0) {
1003 /* Ignore errors since we cannot really do much to fix this */
1004 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1005 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006}
1007
1008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1010 struct wpa_ssid *ssid,
1011 struct wpa_ie_data *ie)
1012{
1013 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1014 if (ret) {
1015 if (ret == -2) {
1016 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1017 "from association info");
1018 }
1019 return -1;
1020 }
1021
1022 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1023 "cipher suites");
1024 if (!(ie->group_cipher & ssid->group_cipher)) {
1025 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1026 "cipher 0x%x (mask 0x%x) - reject",
1027 ie->group_cipher, ssid->group_cipher);
1028 return -1;
1029 }
1030 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1031 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1032 "cipher 0x%x (mask 0x%x) - reject",
1033 ie->pairwise_cipher, ssid->pairwise_cipher);
1034 return -1;
1035 }
1036 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1037 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1038 "management 0x%x (mask 0x%x) - reject",
1039 ie->key_mgmt, ssid->key_mgmt);
1040 return -1;
1041 }
1042
1043#ifdef CONFIG_IEEE80211W
1044 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001045 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1047 "that does not support management frame protection - "
1048 "reject");
1049 return -1;
1050 }
1051#endif /* CONFIG_IEEE80211W */
1052
1053 return 0;
1054}
1055
1056
1057/**
1058 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1059 * @wpa_s: Pointer to wpa_supplicant data
1060 * @bss: Scan results for the selected BSS, or %NULL if not available
1061 * @ssid: Configuration data for the selected network
1062 * @wpa_ie: Buffer for the WPA/RSN IE
1063 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1064 * used buffer length in case the functions returns success.
1065 * Returns: 0 on success or -1 on failure
1066 *
1067 * This function is used to configure authentication and encryption parameters
1068 * based on the network configuration and scan result for the selected BSS (if
1069 * available).
1070 */
1071int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1072 struct wpa_bss *bss, struct wpa_ssid *ssid,
1073 u8 *wpa_ie, size_t *wpa_ie_len)
1074{
1075 struct wpa_ie_data ie;
1076 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001077 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001078
1079 if (bss) {
1080 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1081 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001082 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001083 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001084 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085
1086 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1087 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1088 (ie.group_cipher & ssid->group_cipher) &&
1089 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1090 (ie.key_mgmt & ssid->key_mgmt)) {
1091 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1092 proto = WPA_PROTO_RSN;
1093 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001094 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001095 (ie.group_cipher & ssid->group_cipher) &&
1096 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1097 (ie.key_mgmt & ssid->key_mgmt)) {
1098 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1099 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001100#ifdef CONFIG_HS20
1101 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1102 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1103 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001104 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001105 ie.group_cipher = WPA_CIPHER_CCMP;
1106 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1107 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1108 proto = WPA_PROTO_OSEN;
1109#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001110 } else if (bss) {
1111 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001112 wpa_dbg(wpa_s, MSG_DEBUG,
1113 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1114 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1115 ssid->key_mgmt);
1116 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1117 MAC2STR(bss->bssid),
1118 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1119 bss_wpa ? " WPA" : "",
1120 bss_rsn ? " RSN" : "",
1121 bss_osen ? " OSEN" : "");
1122 if (bss_rsn) {
1123 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1124 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1125 wpa_dbg(wpa_s, MSG_DEBUG,
1126 "Could not parse RSN element");
1127 } else {
1128 wpa_dbg(wpa_s, MSG_DEBUG,
1129 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1130 ie.pairwise_cipher, ie.group_cipher,
1131 ie.key_mgmt);
1132 }
1133 }
1134 if (bss_wpa) {
1135 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1136 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1137 wpa_dbg(wpa_s, MSG_DEBUG,
1138 "Could not parse WPA element");
1139 } else {
1140 wpa_dbg(wpa_s, MSG_DEBUG,
1141 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1142 ie.pairwise_cipher, ie.group_cipher,
1143 ie.key_mgmt);
1144 }
1145 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146 return -1;
1147 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001148 if (ssid->proto & WPA_PROTO_OSEN)
1149 proto = WPA_PROTO_OSEN;
1150 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001151 proto = WPA_PROTO_RSN;
1152 else
1153 proto = WPA_PROTO_WPA;
1154 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1155 os_memset(&ie, 0, sizeof(ie));
1156 ie.group_cipher = ssid->group_cipher;
1157 ie.pairwise_cipher = ssid->pairwise_cipher;
1158 ie.key_mgmt = ssid->key_mgmt;
1159#ifdef CONFIG_IEEE80211W
1160 ie.mgmt_group_cipher =
1161 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1162 WPA_CIPHER_AES_128_CMAC : 0;
1163#endif /* CONFIG_IEEE80211W */
1164 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1165 "based on configuration");
1166 } else
1167 proto = ie.proto;
1168 }
1169
1170 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1171 "pairwise %d key_mgmt %d proto %d",
1172 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1173#ifdef CONFIG_IEEE80211W
1174 if (ssid->ieee80211w) {
1175 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1176 ie.mgmt_group_cipher);
1177 }
1178#endif /* CONFIG_IEEE80211W */
1179
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001180 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001181 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1182 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001183 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184
1185 if (bss || !wpa_s->ap_ies_from_associnfo) {
1186 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1187 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1188 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1189 bss_rsn ? 2 + bss_rsn[1] : 0))
1190 return -1;
1191 }
1192
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001193#ifdef CONFIG_NO_WPA
1194 wpa_s->group_cipher = WPA_CIPHER_NONE;
1195 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1196#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001198 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1199 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001200 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1201 "cipher");
1202 return -1;
1203 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001204 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1205 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001206
1207 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001208 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1209 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1211 "cipher");
1212 return -1;
1213 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001214 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1215 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001216#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001217
1218 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001219#ifdef CONFIG_SAE
1220 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1221 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1222#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001223 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001224#ifdef CONFIG_SUITEB192
1225 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1226 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1227 wpa_dbg(wpa_s, MSG_DEBUG,
1228 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1229#endif /* CONFIG_SUITEB192 */
1230#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001231 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1232 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1233 wpa_dbg(wpa_s, MSG_DEBUG,
1234 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001235#endif /* CONFIG_SUITEB */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236#ifdef CONFIG_IEEE80211R
1237 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1238 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1239 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1240 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1241 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1242 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1243#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001244#ifdef CONFIG_SAE
1245 } else if (sel & WPA_KEY_MGMT_SAE) {
1246 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1247 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1248 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1249 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1250 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1251#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001252#ifdef CONFIG_IEEE80211W
1253 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1254 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1255 wpa_dbg(wpa_s, MSG_DEBUG,
1256 "WPA: using KEY_MGMT 802.1X with SHA256");
1257 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1258 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1259 wpa_dbg(wpa_s, MSG_DEBUG,
1260 "WPA: using KEY_MGMT PSK with SHA256");
1261#endif /* CONFIG_IEEE80211W */
1262 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1263 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1264 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1265 } else if (sel & WPA_KEY_MGMT_PSK) {
1266 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1267 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1268 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1269 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1270 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001271#ifdef CONFIG_HS20
1272 } else if (sel & WPA_KEY_MGMT_OSEN) {
1273 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1274 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1275#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001276 } else {
1277 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1278 "authenticated key management type");
1279 return -1;
1280 }
1281
1282 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1283 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1284 wpa_s->pairwise_cipher);
1285 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1286
1287#ifdef CONFIG_IEEE80211W
1288 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001289 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001290 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1291 sel = 0;
1292 if (sel & WPA_CIPHER_AES_128_CMAC) {
1293 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1294 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1295 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001296 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1297 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1298 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1299 "BIP-GMAC-128");
1300 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1301 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1302 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1303 "BIP-GMAC-256");
1304 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1305 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1306 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1307 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001308 } else {
1309 wpa_s->mgmt_group_cipher = 0;
1310 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1311 }
1312 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1313 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001314 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001315 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001316#endif /* CONFIG_IEEE80211W */
1317
1318 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1319 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1320 return -1;
1321 }
1322
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001323 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001324 int psk_set = 0;
1325
1326 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001327 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1328 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001329 psk_set = 1;
1330 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001331#ifndef CONFIG_NO_PBKDF2
1332 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1333 ssid->passphrase) {
1334 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001335 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1336 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001337 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1338 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001339 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001340 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001341 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001342 }
1343#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001344#ifdef CONFIG_EXT_PASSWORD
1345 if (ssid->ext_psk) {
1346 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1347 ssid->ext_psk);
1348 char pw_str[64 + 1];
1349 u8 psk[PMK_LEN];
1350
1351 if (pw == NULL) {
1352 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1353 "found from external storage");
1354 return -1;
1355 }
1356
1357 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1358 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1359 "PSK length %d in external storage",
1360 (int) wpabuf_len(pw));
1361 ext_password_free(pw);
1362 return -1;
1363 }
1364
1365 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1366 pw_str[wpabuf_len(pw)] = '\0';
1367
1368#ifndef CONFIG_NO_PBKDF2
1369 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1370 {
1371 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1372 4096, psk, PMK_LEN);
1373 os_memset(pw_str, 0, sizeof(pw_str));
1374 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1375 "external passphrase)",
1376 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001377 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1378 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001379 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001380 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001381 } else
1382#endif /* CONFIG_NO_PBKDF2 */
1383 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1384 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1385 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1386 "Invalid PSK hex string");
1387 os_memset(pw_str, 0, sizeof(pw_str));
1388 ext_password_free(pw);
1389 return -1;
1390 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001391 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1392 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001393 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001394 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001395 } else {
1396 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1397 "PSK available");
1398 os_memset(pw_str, 0, sizeof(pw_str));
1399 ext_password_free(pw);
1400 return -1;
1401 }
1402
1403 os_memset(pw_str, 0, sizeof(pw_str));
1404 ext_password_free(pw);
1405 }
1406#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001407
1408 if (!psk_set) {
1409 wpa_msg(wpa_s, MSG_INFO,
1410 "No PSK available for association");
1411 return -1;
1412 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001413 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001414 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1415
1416 return 0;
1417}
1418
1419
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001420static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1421{
1422 *pos = 0x00;
1423
1424 switch (idx) {
1425 case 0: /* Bits 0-7 */
1426 break;
1427 case 1: /* Bits 8-15 */
1428 break;
1429 case 2: /* Bits 16-23 */
1430#ifdef CONFIG_WNM
1431 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1432 *pos |= 0x08; /* Bit 19 - BSS Transition */
1433#endif /* CONFIG_WNM */
1434 break;
1435 case 3: /* Bits 24-31 */
1436#ifdef CONFIG_WNM
1437 *pos |= 0x02; /* Bit 25 - SSID List */
1438#endif /* CONFIG_WNM */
1439#ifdef CONFIG_INTERWORKING
1440 if (wpa_s->conf->interworking)
1441 *pos |= 0x80; /* Bit 31 - Interworking */
1442#endif /* CONFIG_INTERWORKING */
1443 break;
1444 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001445#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001446 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1447 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001448#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001449 break;
1450 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001451#ifdef CONFIG_HS20
1452 if (wpa_s->conf->hs20)
1453 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1454#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001455#ifdef CONFIG_MBO
1456 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1457#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001458 break;
1459 case 6: /* Bits 48-55 */
1460 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001461 case 7: /* Bits 56-63 */
1462 break;
1463 case 8: /* Bits 64-71 */
1464 if (wpa_s->conf->ftm_responder)
1465 *pos |= 0x40; /* Bit 70 - FTM responder */
1466 if (wpa_s->conf->ftm_initiator)
1467 *pos |= 0x80; /* Bit 71 - FTM initiator */
1468 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001469 }
1470}
1471
1472
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001473int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001474{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001475 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001476 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001477
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001478 if (len < 9 &&
1479 (wpa_s->conf->ftm_initiator || wpa_s->conf->ftm_responder))
1480 len = 9;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001481 if (len < wpa_s->extended_capa_len)
1482 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001483 if (buflen < (size_t) len + 2) {
1484 wpa_printf(MSG_INFO,
1485 "Not enough room for building extended capabilities element");
1486 return -1;
1487 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001488
1489 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001490 *pos++ = len;
1491 for (i = 0; i < len; i++, pos++) {
1492 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001493
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001494 if (i < wpa_s->extended_capa_len) {
1495 *pos &= ~wpa_s->extended_capa_mask[i];
1496 *pos |= wpa_s->extended_capa[i];
1497 }
1498 }
1499
1500 while (len > 0 && buf[1 + len] == 0) {
1501 len--;
1502 buf[1] = len;
1503 }
1504 if (len == 0)
1505 return 0;
1506
1507 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001508}
1509
1510
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001511static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1512 struct wpa_bss *test_bss)
1513{
1514 struct wpa_bss *bss;
1515
1516 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1517 if (bss == test_bss)
1518 return 1;
1519 }
1520
1521 return 0;
1522}
1523
1524
1525static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1526 struct wpa_ssid *test_ssid)
1527{
1528 struct wpa_ssid *ssid;
1529
1530 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1531 if (ssid == test_ssid)
1532 return 1;
1533 }
1534
1535 return 0;
1536}
1537
1538
1539int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1540 struct wpa_ssid *test_ssid)
1541{
1542 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1543 return 0;
1544
1545 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1546}
1547
1548
1549void wpas_connect_work_free(struct wpa_connect_work *cwork)
1550{
1551 if (cwork == NULL)
1552 return;
1553 os_free(cwork);
1554}
1555
1556
1557void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1558{
1559 struct wpa_connect_work *cwork;
1560 struct wpa_radio_work *work = wpa_s->connect_work;
1561
1562 if (!work)
1563 return;
1564
1565 wpa_s->connect_work = NULL;
1566 cwork = work->ctx;
1567 work->ctx = NULL;
1568 wpas_connect_work_free(cwork);
1569 radio_work_done(work);
1570}
1571
1572
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001573int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1574{
1575 struct os_reltime now;
1576 u8 addr[ETH_ALEN];
1577
1578 os_get_reltime(&now);
1579 if (wpa_s->last_mac_addr_style == style &&
1580 wpa_s->last_mac_addr_change.sec != 0 &&
1581 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1582 wpa_s->conf->rand_addr_lifetime)) {
1583 wpa_msg(wpa_s, MSG_DEBUG,
1584 "Previously selected random MAC address has not yet expired");
1585 return 0;
1586 }
1587
1588 switch (style) {
1589 case 1:
1590 if (random_mac_addr(addr) < 0)
1591 return -1;
1592 break;
1593 case 2:
1594 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1595 if (random_mac_addr_keep_oui(addr) < 0)
1596 return -1;
1597 break;
1598 default:
1599 return -1;
1600 }
1601
1602 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1603 wpa_msg(wpa_s, MSG_INFO,
1604 "Failed to set random MAC address");
1605 return -1;
1606 }
1607
1608 os_get_reltime(&wpa_s->last_mac_addr_change);
1609 wpa_s->mac_addr_changed = 1;
1610 wpa_s->last_mac_addr_style = style;
1611
1612 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1613 wpa_msg(wpa_s, MSG_INFO,
1614 "Could not update MAC address information");
1615 return -1;
1616 }
1617
1618 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1619 MAC2STR(addr));
1620
1621 return 0;
1622}
1623
1624
1625int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1626{
1627 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1628 !wpa_s->conf->preassoc_mac_addr)
1629 return 0;
1630
1631 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1632}
1633
1634
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001635static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001637/**
1638 * wpa_supplicant_associate - Request association
1639 * @wpa_s: Pointer to wpa_supplicant data
1640 * @bss: Scan results for the selected BSS, or %NULL if not available
1641 * @ssid: Configuration data for the selected network
1642 *
1643 * This function is used to request %wpa_supplicant to associate with a BSS.
1644 */
1645void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1646 struct wpa_bss *bss, struct wpa_ssid *ssid)
1647{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001648 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001649 int rand_style;
1650
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001651 wpa_s->own_disconnect_req = 0;
1652
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001653 /*
1654 * If we are starting a new connection, any previously pending EAPOL
1655 * RX cannot be valid anymore.
1656 */
1657 wpabuf_free(wpa_s->pending_eapol_rx);
1658 wpa_s->pending_eapol_rx = NULL;
1659
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001660 if (ssid->mac_addr == -1)
1661 rand_style = wpa_s->conf->mac_addr;
1662 else
1663 rand_style = ssid->mac_addr;
1664
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001665 wmm_ac_clear_saved_tspecs(wpa_s);
1666 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001667 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001668
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001669 if (wpa_s->last_ssid == ssid) {
1670 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001671 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001672 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1673 wmm_ac_save_tspecs(wpa_s);
1674 wpa_s->reassoc_same_bss = 1;
1675 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001676 } else if (rand_style > 0) {
1677 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1678 return;
1679 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1680 } else if (wpa_s->mac_addr_changed) {
1681 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1682 wpa_msg(wpa_s, MSG_INFO,
1683 "Could not restore permanent MAC address");
1684 return;
1685 }
1686 wpa_s->mac_addr_changed = 0;
1687 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1688 wpa_msg(wpa_s, MSG_INFO,
1689 "Could not update MAC address information");
1690 return;
1691 }
1692 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1693 }
1694 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001695
1696#ifdef CONFIG_IBSS_RSN
1697 ibss_rsn_deinit(wpa_s->ibss_rsn);
1698 wpa_s->ibss_rsn = NULL;
1699#endif /* CONFIG_IBSS_RSN */
1700
1701 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1702 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1703#ifdef CONFIG_AP
1704 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1705 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1706 "mode");
1707 return;
1708 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001709 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1710 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001711 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1712 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001713 return;
1714 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001715 wpa_s->current_bss = bss;
1716#else /* CONFIG_AP */
1717 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1718 "the build");
1719#endif /* CONFIG_AP */
1720 return;
1721 }
1722
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001723 if (ssid->mode == WPAS_MODE_MESH) {
1724#ifdef CONFIG_MESH
1725 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1726 wpa_msg(wpa_s, MSG_INFO,
1727 "Driver does not support mesh mode");
1728 return;
1729 }
1730 if (bss)
1731 ssid->frequency = bss->freq;
1732 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1733 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1734 return;
1735 }
1736 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001737 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1738 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1739 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001740#else /* CONFIG_MESH */
1741 wpa_msg(wpa_s, MSG_ERROR,
1742 "mesh mode support not included in the build");
1743#endif /* CONFIG_MESH */
1744 return;
1745 }
1746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001747#ifdef CONFIG_TDLS
1748 if (bss)
1749 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1750 bss->ie_len);
1751#endif /* CONFIG_TDLS */
1752
1753 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1754 ssid->mode == IEEE80211_MODE_INFRA) {
1755 sme_authenticate(wpa_s, bss, ssid);
1756 return;
1757 }
1758
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001759 if (wpa_s->connect_work) {
1760 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1761 return;
1762 }
1763
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001764 if (radio_work_pending(wpa_s, "connect")) {
1765 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1766 return;
1767 }
1768
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001769 wpas_abort_ongoing_scan(wpa_s);
1770
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001771 cwork = os_zalloc(sizeof(*cwork));
1772 if (cwork == NULL)
1773 return;
1774
1775 cwork->bss = bss;
1776 cwork->ssid = ssid;
1777
1778 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1779 wpas_start_assoc_cb, cwork) < 0) {
1780 os_free(cwork);
1781 }
1782}
1783
1784
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001785static int bss_is_ibss(struct wpa_bss *bss)
1786{
1787 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1788 IEEE80211_CAP_IBSS;
1789}
1790
1791
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001792static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1793 const struct wpa_ssid *ssid)
1794{
1795 enum hostapd_hw_mode hw_mode;
1796 struct hostapd_hw_modes *mode = NULL;
1797 u8 channel;
1798 int i;
1799
1800#ifdef CONFIG_HT_OVERRIDES
1801 if (ssid->disable_ht)
1802 return 0;
1803#endif /* CONFIG_HT_OVERRIDES */
1804
1805 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1806 if (hw_mode == NUM_HOSTAPD_MODES)
1807 return 0;
1808 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1809 if (wpa_s->hw.modes[i].mode == hw_mode) {
1810 mode = &wpa_s->hw.modes[i];
1811 break;
1812 }
1813 }
1814
1815 if (!mode)
1816 return 0;
1817
1818 return mode->vht_capab != 0;
1819}
1820
1821
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001822void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1823 const struct wpa_ssid *ssid,
1824 struct hostapd_freq_params *freq)
1825{
1826 enum hostapd_hw_mode hw_mode;
1827 struct hostapd_hw_modes *mode = NULL;
1828 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1829 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001830 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001831 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1832 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001833 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001834 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001835 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001836 int chwidth, seg0, seg1;
1837 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001838
1839 freq->freq = ssid->frequency;
1840
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001841 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1842 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1843
1844 if (ssid->mode != WPAS_MODE_IBSS)
1845 break;
1846
1847 /* Don't adjust control freq in case of fixed_freq */
1848 if (ssid->fixed_freq)
1849 break;
1850
1851 if (!bss_is_ibss(bss))
1852 continue;
1853
1854 if (ssid->ssid_len == bss->ssid_len &&
1855 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1856 wpa_printf(MSG_DEBUG,
1857 "IBSS already found in scan results, adjust control freq: %d",
1858 bss->freq);
1859 freq->freq = bss->freq;
1860 obss_scan = 0;
1861 break;
1862 }
1863 }
1864
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001865 /* For IBSS check HT_IBSS flag */
1866 if (ssid->mode == WPAS_MODE_IBSS &&
1867 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1868 return;
1869
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001870 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1871 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1872 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1873 wpa_printf(MSG_DEBUG,
1874 "IBSS: WEP/TKIP detected, do not try to enable HT");
1875 return;
1876 }
1877
1878 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001879 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1880 if (wpa_s->hw.modes[i].mode == hw_mode) {
1881 mode = &wpa_s->hw.modes[i];
1882 break;
1883 }
1884 }
1885
1886 if (!mode)
1887 return;
1888
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001889#ifdef CONFIG_HT_OVERRIDES
1890 if (ssid->disable_ht) {
1891 freq->ht_enabled = 0;
1892 return;
1893 }
1894#endif /* CONFIG_HT_OVERRIDES */
1895
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001896 freq->ht_enabled = ht_supported(mode);
1897 if (!freq->ht_enabled)
1898 return;
1899
1900 /* Setup higher BW only for 5 GHz */
1901 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1902 return;
1903
1904 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1905 pri_chan = &mode->channels[chan_idx];
1906 if (pri_chan->chan == channel)
1907 break;
1908 pri_chan = NULL;
1909 }
1910 if (!pri_chan)
1911 return;
1912
1913 /* Check primary channel flags */
1914 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1915 return;
1916
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001917#ifdef CONFIG_HT_OVERRIDES
1918 if (ssid->disable_ht40)
1919 return;
1920#endif /* CONFIG_HT_OVERRIDES */
1921
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001922 /* Check/setup HT40+/HT40- */
1923 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1924 if (ht40plus[j] == channel) {
1925 ht40 = 1;
1926 break;
1927 }
1928 }
1929
1930 /* Find secondary channel */
1931 for (i = 0; i < mode->num_channels; i++) {
1932 sec_chan = &mode->channels[i];
1933 if (sec_chan->chan == channel + ht40 * 4)
1934 break;
1935 sec_chan = NULL;
1936 }
1937 if (!sec_chan)
1938 return;
1939
1940 /* Check secondary channel flags */
1941 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1942 return;
1943
1944 freq->channel = pri_chan->chan;
1945
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001946 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001947 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1948 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001949 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001950 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1951 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001952 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001953 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001954
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001955 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001956 struct wpa_scan_results *scan_res;
1957
1958 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1959 if (scan_res == NULL) {
1960 /* Back to HT20 */
1961 freq->sec_channel_offset = 0;
1962 return;
1963 }
1964
1965 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1966 sec_chan->chan);
1967 switch (res) {
1968 case 0:
1969 /* Back to HT20 */
1970 freq->sec_channel_offset = 0;
1971 break;
1972 case 1:
1973 /* Configuration allowed */
1974 break;
1975 case 2:
1976 /* Switch pri/sec channels */
1977 freq->freq = hw_get_freq(mode, sec_chan->chan);
1978 freq->sec_channel_offset = -freq->sec_channel_offset;
1979 freq->channel = sec_chan->chan;
1980 break;
1981 default:
1982 freq->sec_channel_offset = 0;
1983 break;
1984 }
1985
1986 wpa_scan_results_free(scan_res);
1987 }
1988
1989 wpa_printf(MSG_DEBUG,
1990 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
1991 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001992
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001993 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001994 return;
1995
1996 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001997 if (ssid->mode == WPAS_MODE_IBSS &&
1998 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001999 return;
2000
2001 vht_freq = *freq;
2002
2003 vht_freq.vht_enabled = vht_supported(mode);
2004 if (!vht_freq.vht_enabled)
2005 return;
2006
2007 /* setup center_freq1, bandwidth */
2008 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2009 if (freq->channel >= vht80[j] &&
2010 freq->channel < vht80[j] + 16)
2011 break;
2012 }
2013
2014 if (j == ARRAY_SIZE(vht80))
2015 return;
2016
2017 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2018 struct hostapd_channel_data *chan;
2019
2020 chan = hw_get_channel_chan(mode, i, NULL);
2021 if (!chan)
2022 return;
2023
2024 /* Back to HT configuration if channel not usable */
2025 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2026 return;
2027 }
2028
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002029 chwidth = VHT_CHANWIDTH_80MHZ;
2030 seg0 = vht80[j] + 6;
2031 seg1 = 0;
2032
2033 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2034 /* setup center_freq2, bandwidth */
2035 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2036 /* Only accept 80 MHz segments separated by a gap */
2037 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2038 continue;
2039 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2040 struct hostapd_channel_data *chan;
2041
2042 chan = hw_get_channel_chan(mode, i, NULL);
2043 if (!chan)
2044 continue;
2045
2046 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2047 HOSTAPD_CHAN_NO_IR |
2048 HOSTAPD_CHAN_RADAR))
2049 continue;
2050
2051 /* Found a suitable second segment for 80+80 */
2052 chwidth = VHT_CHANWIDTH_80P80MHZ;
2053 vht_caps |=
2054 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2055 seg1 = vht80[k] + 6;
2056 }
2057
2058 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2059 break;
2060 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002061 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2062 if (freq->freq == 5180) {
2063 chwidth = VHT_CHANWIDTH_160MHZ;
2064 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2065 seg0 = 50;
2066 } else if (freq->freq == 5520) {
2067 chwidth = VHT_CHANWIDTH_160MHZ;
2068 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2069 seg0 = 114;
2070 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002071 }
2072
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002073 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2074 freq->channel, freq->ht_enabled,
2075 vht_freq.vht_enabled,
2076 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002077 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002078 return;
2079
2080 *freq = vht_freq;
2081
2082 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2083 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002084}
2085
2086
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002087static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2088{
2089 struct wpa_connect_work *cwork = work->ctx;
2090 struct wpa_bss *bss = cwork->bss;
2091 struct wpa_ssid *ssid = cwork->ssid;
2092 struct wpa_supplicant *wpa_s = work->wpa_s;
2093 u8 wpa_ie[200];
2094 size_t wpa_ie_len;
2095 int use_crypt, ret, i, bssid_changed;
2096 int algs = WPA_AUTH_ALG_OPEN;
2097 unsigned int cipher_pairwise, cipher_group;
2098 struct wpa_driver_associate_params params;
2099 int wep_keys_set = 0;
2100 int assoc_failed = 0;
2101 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002102 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002103#ifdef CONFIG_HT_OVERRIDES
2104 struct ieee80211_ht_capabilities htcaps;
2105 struct ieee80211_ht_capabilities htcaps_mask;
2106#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002107#ifdef CONFIG_VHT_OVERRIDES
2108 struct ieee80211_vht_capabilities vhtcaps;
2109 struct ieee80211_vht_capabilities vhtcaps_mask;
2110#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002111#ifdef CONFIG_MBO
2112 const u8 *mbo = NULL;
2113#endif /* CONFIG_MBO */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002114
2115 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002116 if (work->started) {
2117 wpa_s->connect_work = NULL;
2118
2119 /* cancel possible auth. timeout */
2120 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2121 NULL);
2122 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002123 wpas_connect_work_free(cwork);
2124 return;
2125 }
2126
2127 wpa_s->connect_work = work;
2128
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002129 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2130 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002131 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2132 wpas_connect_work_done(wpa_s);
2133 return;
2134 }
2135
Dmitry Shmidte4663042016-04-04 10:07:49 -07002136 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 os_memset(&params, 0, sizeof(params));
2138 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002139 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002140 if (bss &&
2141 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002142#ifdef CONFIG_IEEE80211R
2143 const u8 *ie, *md = NULL;
2144#endif /* CONFIG_IEEE80211R */
2145 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2146 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2147 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2148 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2149 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2150 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2151 if (bssid_changed)
2152 wpas_notify_bssid_changed(wpa_s);
2153#ifdef CONFIG_IEEE80211R
2154 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2155 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2156 md = ie + 2;
2157 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2158 if (md) {
2159 /* Prepare for the next transition */
2160 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2161 }
2162#endif /* CONFIG_IEEE80211R */
2163#ifdef CONFIG_WPS
2164 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2165 wpa_s->conf->ap_scan == 2 &&
2166 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2167 /* Use ap_scan==1 style network selection to find the network
2168 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002169 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002170 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002171 wpa_s->reassociate = 1;
2172 wpa_supplicant_req_scan(wpa_s, 0, 0);
2173 return;
2174#endif /* CONFIG_WPS */
2175 } else {
2176 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2177 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002178 if (bss)
2179 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2180 else
2181 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002182 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002183 if (!wpa_s->pno)
2184 wpa_supplicant_cancel_sched_scan(wpa_s);
2185
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002186 wpa_supplicant_cancel_scan(wpa_s);
2187
2188 /* Starting new association, so clear the possibly used WPA IE from the
2189 * previous association. */
2190 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2191
2192#ifdef IEEE8021X_EAPOL
2193 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2194 if (ssid->leap) {
2195 if (ssid->non_leap == 0)
2196 algs = WPA_AUTH_ALG_LEAP;
2197 else
2198 algs |= WPA_AUTH_ALG_LEAP;
2199 }
2200 }
2201#endif /* IEEE8021X_EAPOL */
2202 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2203 if (ssid->auth_alg) {
2204 algs = ssid->auth_alg;
2205 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2206 "0x%x", algs);
2207 }
2208
2209 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2210 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002211 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002212 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002213 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2214 wpa_s->conf->okc :
2215 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002216 (ssid->proto & WPA_PROTO_RSN);
2217 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002218 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002219 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220 wpa_ie_len = sizeof(wpa_ie);
2221 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2222 wpa_ie, &wpa_ie_len)) {
2223 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2224 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002225 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002226 return;
2227 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002228 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2229 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2230 /*
2231 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2232 * use non-WPA since the scan results did not indicate that the
2233 * AP is using WPA or WPA2.
2234 */
2235 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2236 wpa_ie_len = 0;
2237 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002238 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002239 wpa_ie_len = sizeof(wpa_ie);
2240 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2241 wpa_ie, &wpa_ie_len)) {
2242 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2243 "key management and encryption suites (no "
2244 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002245 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002246 return;
2247 }
2248#ifdef CONFIG_WPS
2249 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2250 struct wpabuf *wps_ie;
2251 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2252 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2253 wpa_ie_len = wpabuf_len(wps_ie);
2254 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2255 } else
2256 wpa_ie_len = 0;
2257 wpabuf_free(wps_ie);
2258 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2259 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2260 params.wps = WPS_MODE_PRIVACY;
2261 else
2262 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002263 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002264#endif /* CONFIG_WPS */
2265 } else {
2266 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2267 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002268 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002269 }
2270
2271#ifdef CONFIG_P2P
2272 if (wpa_s->global->p2p) {
2273 u8 *pos;
2274 size_t len;
2275 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276 pos = wpa_ie + wpa_ie_len;
2277 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002278 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2279 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002280 if (res >= 0)
2281 wpa_ie_len += res;
2282 }
2283
2284 wpa_s->cross_connect_disallowed = 0;
2285 if (bss) {
2286 struct wpabuf *p2p;
2287 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2288 if (p2p) {
2289 wpa_s->cross_connect_disallowed =
2290 p2p_get_cross_connect_disallowed(p2p);
2291 wpabuf_free(p2p);
2292 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2293 "connection",
2294 wpa_s->cross_connect_disallowed ?
2295 "disallows" : "allows");
2296 }
2297 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002298
2299 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002300#endif /* CONFIG_P2P */
2301
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002302#ifdef CONFIG_MBO
2303 if (bss) {
2304 mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
2305 if (mbo) {
2306 int len;
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002307
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002308 len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq,
2309 wpa_ie + wpa_ie_len,
2310 sizeof(wpa_ie) -
2311 wpa_ie_len);
2312 if (len > 0)
2313 wpa_ie_len += len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002314 }
2315 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002316#endif /* CONFIG_MBO */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002317
Dmitry Shmidt56052862013-10-04 10:23:25 -07002318 /*
2319 * Workaround: Add Extended Capabilities element only if the AP
2320 * included this element in Beacon/Probe Response frames. Some older
2321 * APs seem to have interoperability issues if this element is
2322 * included, so while the standard may require us to include the
2323 * element in all cases, it is justifiable to skip it to avoid
2324 * interoperability issues.
2325 */
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002326 if (ssid->p2p_group)
2327 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2328 else
2329 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2330
Dmitry Shmidt56052862013-10-04 10:23:25 -07002331 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002332 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002333 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002334 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2335 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002336 if (ext_capab_len > 0) {
2337 u8 *pos = wpa_ie;
2338 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2339 pos += 2 + pos[1];
2340 os_memmove(pos + ext_capab_len, pos,
2341 wpa_ie_len - (pos - wpa_ie));
2342 wpa_ie_len += ext_capab_len;
2343 os_memcpy(pos, ext_capab, ext_capab_len);
2344 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002345 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002346
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002347#ifdef CONFIG_HS20
2348 if (is_hs20_network(wpa_s, ssid, bss)) {
2349 struct wpabuf *hs20;
2350
2351 hs20 = wpabuf_alloc(20);
2352 if (hs20) {
2353 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2354 size_t len;
2355
2356 wpas_hs20_add_indication(hs20, pps_mo_id);
2357 len = sizeof(wpa_ie) - wpa_ie_len;
2358 if (wpabuf_len(hs20) <= len) {
2359 os_memcpy(wpa_ie + wpa_ie_len,
2360 wpabuf_head(hs20), wpabuf_len(hs20));
2361 wpa_ie_len += wpabuf_len(hs20);
2362 }
2363 wpabuf_free(hs20);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002364
2365 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002366 }
2367 }
2368#endif /* CONFIG_HS20 */
2369
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002370 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2371 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2372 size_t len;
2373
2374 len = sizeof(wpa_ie) - wpa_ie_len;
2375 if (wpabuf_len(buf) <= len) {
2376 os_memcpy(wpa_ie + wpa_ie_len,
2377 wpabuf_head(buf), wpabuf_len(buf));
2378 wpa_ie_len += wpabuf_len(buf);
2379 }
2380 }
2381
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002382#ifdef CONFIG_FST
2383 if (wpa_s->fst_ies) {
2384 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2385
2386 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2387 os_memcpy(wpa_ie + wpa_ie_len,
2388 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2389 wpa_ie_len += fst_ies_len;
2390 }
2391 }
2392#endif /* CONFIG_FST */
2393
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002394#ifdef CONFIG_MBO
2395 if (mbo) {
2396 int len;
2397
2398 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2399 sizeof(wpa_ie) - wpa_ie_len);
2400 if (len >= 0)
2401 wpa_ie_len += len;
2402 }
2403#endif /* CONFIG_MBO */
2404
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002405 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2406 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002407 cipher_pairwise = wpa_s->pairwise_cipher;
2408 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002409 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2410 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2411 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2412 use_crypt = 0;
2413 if (wpa_set_wep_keys(wpa_s, ssid)) {
2414 use_crypt = 1;
2415 wep_keys_set = 1;
2416 }
2417 }
2418 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2419 use_crypt = 0;
2420
2421#ifdef IEEE8021X_EAPOL
2422 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2423 if ((ssid->eapol_flags &
2424 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2425 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2426 !wep_keys_set) {
2427 use_crypt = 0;
2428 } else {
2429 /* Assume that dynamic WEP-104 keys will be used and
2430 * set cipher suites in order for drivers to expect
2431 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002432 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 }
2434 }
2435#endif /* IEEE8021X_EAPOL */
2436
2437 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2438 /* Set the key before (and later after) association */
2439 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2440 }
2441
2442 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2443 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002444 params.ssid = bss->ssid;
2445 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002446 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
2447 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2448 MACSTR " freq=%u MHz based on scan results "
2449 "(bssid_set=%d)",
2450 MAC2STR(bss->bssid), bss->freq,
2451 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002452 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002453 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002454 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002455 params.bssid_hint = bss->bssid;
2456 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002457 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002458 } else {
2459 params.ssid = ssid->ssid;
2460 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002461 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002462 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002463
2464 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2465 wpa_s->conf->ap_scan == 2) {
2466 params.bssid = ssid->bssid;
2467 params.fixed_bssid = 1;
2468 }
2469
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002470 /* Initial frequency for IBSS/mesh */
2471 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002472 ssid->frequency > 0 && params.freq.freq == 0)
2473 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002474
2475 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002476 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002477 if (ssid->beacon_int)
2478 params.beacon_int = ssid->beacon_int;
2479 else
2480 params.beacon_int = wpa_s->conf->beacon_int;
2481 }
2482
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002483 params.wpa_ie = wpa_ie;
2484 params.wpa_ie_len = wpa_ie_len;
2485 params.pairwise_suite = cipher_pairwise;
2486 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002487 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002488 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 params.auth_alg = algs;
2490 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002491 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 for (i = 0; i < NUM_WEP_KEYS; i++) {
2493 if (ssid->wep_key_len[i])
2494 params.wep_key[i] = ssid->wep_key[i];
2495 params.wep_key_len[i] = ssid->wep_key_len[i];
2496 }
2497 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2498
2499 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002500 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2501 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 params.passphrase = ssid->passphrase;
2503 if (ssid->psk_set)
2504 params.psk = ssid->psk;
2505 }
2506
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002507 if (wpa_s->conf->key_mgmt_offload) {
2508 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2509 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002510 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2511 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002512 params.req_key_mgmt_offload =
2513 ssid->proactive_key_caching < 0 ?
2514 wpa_s->conf->okc : ssid->proactive_key_caching;
2515 else
2516 params.req_key_mgmt_offload = 1;
2517
2518 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2519 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2520 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2521 ssid->psk_set)
2522 params.psk = ssid->psk;
2523 }
2524
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002525 params.drop_unencrypted = use_crypt;
2526
2527#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002528 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002529 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2531 struct wpa_ie_data ie;
2532 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2533 ie.capabilities &
2534 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2535 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2536 "MFP: require MFP");
2537 params.mgmt_frame_protection =
2538 MGMT_FRAME_PROTECTION_REQUIRED;
2539 }
2540 }
2541#endif /* CONFIG_IEEE80211W */
2542
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002543 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002545 if (wpa_s->p2pdev->set_sta_uapsd)
2546 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002547 else
2548 params.uapsd = -1;
2549
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002550#ifdef CONFIG_HT_OVERRIDES
2551 os_memset(&htcaps, 0, sizeof(htcaps));
2552 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2553 params.htcaps = (u8 *) &htcaps;
2554 params.htcaps_mask = (u8 *) &htcaps_mask;
2555 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2556#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002557#ifdef CONFIG_VHT_OVERRIDES
2558 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2559 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2560 params.vhtcaps = &vhtcaps;
2561 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002562 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002563#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002564
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002565#ifdef CONFIG_P2P
2566 /*
2567 * If multi-channel concurrency is not supported, check for any
2568 * frequency conflict. In case of any frequency conflict, remove the
2569 * least prioritized connection.
2570 */
2571 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002572 int freq, num;
2573 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002574 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002575 wpa_printf(MSG_DEBUG,
2576 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002577 freq, params.freq.freq);
2578 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002579 wpa_s, params.freq.freq, ssid) < 0) {
2580 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002581 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002582 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002583 }
2584 }
2585#endif /* CONFIG_P2P */
2586
Dmitry Shmidte4663042016-04-04 10:07:49 -07002587 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2588 wpa_s->current_ssid)
2589 params.prev_bssid = prev_bssid;
2590
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002591 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 if (ret < 0) {
2593 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2594 "failed");
2595 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2596 /*
2597 * The driver is known to mean what is saying, so we
2598 * can stop right here; the association will not
2599 * succeed.
2600 */
2601 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002602 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2604 return;
2605 }
2606 /* try to continue anyway; new association will be tried again
2607 * after timeout */
2608 assoc_failed = 1;
2609 }
2610
2611 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2612 /* Set the key after the association just in case association
2613 * cleared the previously configured key. */
2614 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2615 /* No need to timeout authentication since there is no key
2616 * management. */
2617 wpa_supplicant_cancel_auth_timeout(wpa_s);
2618 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2619#ifdef CONFIG_IBSS_RSN
2620 } else if (ssid->mode == WPAS_MODE_IBSS &&
2621 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2622 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2623 /*
2624 * RSN IBSS authentication is per-STA and we can disable the
2625 * per-BSSID authentication.
2626 */
2627 wpa_supplicant_cancel_auth_timeout(wpa_s);
2628#endif /* CONFIG_IBSS_RSN */
2629 } else {
2630 /* Timeout for IEEE 802.11 authentication and association */
2631 int timeout = 60;
2632
2633 if (assoc_failed) {
2634 /* give IBSS a bit more time */
2635 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2636 } else if (wpa_s->conf->ap_scan == 1) {
2637 /* give IBSS a bit more time */
2638 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2639 }
2640 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2641 }
2642
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002643 if (wep_keys_set &&
2644 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 /* Set static WEP keys again */
2646 wpa_set_wep_keys(wpa_s, ssid);
2647 }
2648
2649 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2650 /*
2651 * Do not allow EAP session resumption between different
2652 * network configurations.
2653 */
2654 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2655 }
2656 old_ssid = wpa_s->current_ssid;
2657 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002658
2659 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002660 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002661#ifdef CONFIG_HS20
2662 hs20_configure_frame_filters(wpa_s);
2663#endif /* CONFIG_HS20 */
2664 }
2665
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002666 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2667 wpa_supplicant_initiate_eapol(wpa_s);
2668 if (old_ssid != wpa_s->current_ssid)
2669 wpas_notify_network_changed(wpa_s);
2670}
2671
2672
2673static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2674 const u8 *addr)
2675{
2676 struct wpa_ssid *old_ssid;
2677
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002678 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002679 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002681 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002682 wpa_sm_set_config(wpa_s->wpa, NULL);
2683 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2684 if (old_ssid != wpa_s->current_ssid)
2685 wpas_notify_network_changed(wpa_s);
2686 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2687}
2688
2689
2690/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2692 * @wpa_s: Pointer to wpa_supplicant data
2693 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2694 *
2695 * This function is used to request %wpa_supplicant to deauthenticate from the
2696 * current AP.
2697 */
2698void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2699 int reason_code)
2700{
2701 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002702 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002703 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002704
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002705 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2706 " pending_bssid=" MACSTR " reason=%d state=%s",
2707 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2708 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2709
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002710 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2711 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2712 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002713 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002714 else if (!is_zero_ether_addr(wpa_s->bssid))
2715 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002716 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2717 /*
2718 * When using driver-based BSS selection, we may not know the
2719 * BSSID with which we are currently trying to associate. We
2720 * need to notify the driver of this disconnection even in such
2721 * a case, so use the all zeros address here.
2722 */
2723 addr = wpa_s->bssid;
2724 zero_addr = 1;
2725 }
2726
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002727#ifdef CONFIG_TDLS
2728 wpa_tdls_teardown_peers(wpa_s->wpa);
2729#endif /* CONFIG_TDLS */
2730
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002731#ifdef CONFIG_MESH
2732 if (wpa_s->ifmsh) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002733 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2734 wpa_s->ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002735 wpa_supplicant_leave_mesh(wpa_s);
2736 }
2737#endif /* CONFIG_MESH */
2738
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002739 if (addr) {
2740 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002741 os_memset(&event, 0, sizeof(event));
2742 event.deauth_info.reason_code = (u16) reason_code;
2743 event.deauth_info.locally_generated = 1;
2744 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002745 if (zero_addr)
2746 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002747 }
2748
2749 wpa_supplicant_clear_connection(wpa_s, addr);
2750}
2751
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002752static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2753 struct wpa_ssid *ssid)
2754{
2755 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2756 return;
2757
2758 ssid->disabled = 0;
2759 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2760 wpas_notify_network_enabled_changed(wpa_s, ssid);
2761
2762 /*
2763 * Try to reassociate since there is no current configuration and a new
2764 * network was made available.
2765 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002766 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002767 wpa_s->reassociate = 1;
2768}
2769
Roshan Pius950bec92016-07-19 09:49:24 -07002770/**
2771 * wpa_supplicant_add_network - Add a new network.
2772 * @wpa_s: wpa_supplicant structure for a network interface
2773 * Returns: The new network configuration or %NULL if operation failed
2774 *
2775 * This function performs the following operations:
2776 * 1. Adds a new network.
2777 * 2. Send network addition notification.
2778 * 3. Marks the network disabled.
2779 * 4. Set network default parameters.
2780 */
2781struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2782{
2783 struct wpa_ssid *ssid;
2784
2785 ssid = wpa_config_add_network(wpa_s->conf);
2786 if (!ssid) {
2787 return NULL;
2788 }
2789 wpas_notify_network_added(wpa_s, ssid);
2790 ssid->disabled = 1;
2791 wpa_config_set_network_defaults(ssid);
2792
2793 return ssid;
2794}
2795
2796/**
2797 * wpa_supplicant_remove_network - Remove a configured network based on id
2798 * @wpa_s: wpa_supplicant structure for a network interface
2799 * @id: Unique network id to search for
2800 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2801 * could not be removed
2802 *
2803 * This function performs the following operations:
2804 * 1. Removes the network.
2805 * 2. Send network removal notification.
2806 * 3. Update internal state machines.
2807 * 4. Stop any running sched scans.
2808 */
2809int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2810{
2811 struct wpa_ssid *ssid;
2812 int was_disabled;
2813
2814 ssid = wpa_config_get_network(wpa_s->conf, id);
2815 if (ssid)
2816 wpas_notify_network_removed(wpa_s, ssid);
2817 if (ssid == NULL) {
2818 return -1;
2819 }
2820
2821 if (wpa_s->last_ssid == ssid)
2822 wpa_s->last_ssid = NULL;
2823
2824 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2825#ifdef CONFIG_SME
2826 wpa_s->sme.prev_bssid_set = 0;
2827#endif /* CONFIG_SME */
2828 /*
2829 * Invalidate the EAP session cache if the current or
2830 * previously used network is removed.
2831 */
2832 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2833 }
2834
2835 if (ssid == wpa_s->current_ssid) {
2836 wpa_sm_set_config(wpa_s->wpa, NULL);
2837 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2838
2839 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2840 wpa_s->own_disconnect_req = 1;
2841 wpa_supplicant_deauthenticate(wpa_s,
2842 WLAN_REASON_DEAUTH_LEAVING);
2843 }
2844
2845 was_disabled = ssid->disabled;
2846
2847 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2848 return -2;
2849 }
2850
2851 if (!was_disabled && wpa_s->sched_scanning) {
2852 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2853 "network from filters");
2854 wpa_supplicant_cancel_sched_scan(wpa_s);
2855 wpa_supplicant_req_scan(wpa_s, 0, 0);
2856 }
2857 return 0;
2858}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002859
2860/**
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002861 * wpa_supplicant_add_network - Add a new network
2862 * @wpa_s: wpa_supplicant structure for a network interface
2863 * Returns: The new network configuration or %NULL if operation failed
2864 *
2865 * This function performs the following operations:
2866 * 1. Adds a new network.
2867 * 2. Send network addition notification.
2868 * 3. Marks the network disabled.
2869 * 4. Set network default parameters.
2870 */
2871struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2872{
2873 struct wpa_ssid *ssid;
2874
2875 ssid = wpa_config_add_network(wpa_s->conf);
2876 if (!ssid)
2877 return NULL;
2878 wpas_notify_network_added(wpa_s, ssid);
2879 ssid->disabled = 1;
2880 wpa_config_set_network_defaults(ssid);
2881
2882 return ssid;
2883}
2884
2885
2886/**
2887 * wpa_supplicant_remove_network - Remove a configured network based on id
2888 * @wpa_s: wpa_supplicant structure for a network interface
2889 * @id: Unique network id to search for
2890 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2891 * could not be removed
2892 *
2893 * This function performs the following operations:
2894 * 1. Removes the network.
2895 * 2. Send network removal notification.
2896 * 3. Update internal state machines.
2897 * 4. Stop any running sched scans.
2898 */
2899int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2900{
2901 struct wpa_ssid *ssid;
2902 int was_disabled;
2903
2904 ssid = wpa_config_get_network(wpa_s->conf, id);
2905 if (!ssid)
2906 return -1;
2907 wpas_notify_network_removed(wpa_s, ssid);
2908
2909 if (wpa_s->last_ssid == ssid)
2910 wpa_s->last_ssid = NULL;
2911
2912 if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
2913#ifdef CONFIG_SME
2914 wpa_s->sme.prev_bssid_set = 0;
2915#endif /* CONFIG_SME */
2916 /*
2917 * Invalidate the EAP session cache if the current or
2918 * previously used network is removed.
2919 */
2920 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2921 }
2922
2923 if (ssid == wpa_s->current_ssid) {
2924 wpa_sm_set_config(wpa_s->wpa, NULL);
2925 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2926
2927 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2928 wpa_s->own_disconnect_req = 1;
2929 wpa_supplicant_deauthenticate(wpa_s,
2930 WLAN_REASON_DEAUTH_LEAVING);
2931 }
2932
2933 was_disabled = ssid->disabled;
2934
2935 if (wpa_config_remove_network(wpa_s->conf, id) < 0)
2936 return -2;
2937
2938 if (!was_disabled && wpa_s->sched_scanning) {
2939 wpa_printf(MSG_DEBUG,
2940 "Stop ongoing sched_scan to remove network from filters");
2941 wpa_supplicant_cancel_sched_scan(wpa_s);
2942 wpa_supplicant_req_scan(wpa_s, 0, 0);
2943 }
2944
2945 return 0;
2946}
2947
2948
2949/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002950 * wpa_supplicant_enable_network - Mark a configured network as enabled
2951 * @wpa_s: wpa_supplicant structure for a network interface
2952 * @ssid: wpa_ssid structure for a configured network or %NULL
2953 *
2954 * Enables the specified network or all networks if no network specified.
2955 */
2956void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2957 struct wpa_ssid *ssid)
2958{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002960 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2961 wpa_supplicant_enable_one_network(wpa_s, ssid);
2962 } else
2963 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002965 if (wpa_s->reassociate && !wpa_s->disconnected &&
2966 (!wpa_s->current_ssid ||
2967 wpa_s->wpa_state == WPA_DISCONNECTED ||
2968 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002969 if (wpa_s->sched_scanning) {
2970 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2971 "new network to scan filters");
2972 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002973 }
2974
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002975 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2976 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002977 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002978 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002979 }
2980}
2981
2982
2983/**
2984 * wpa_supplicant_disable_network - Mark a configured network as disabled
2985 * @wpa_s: wpa_supplicant structure for a network interface
2986 * @ssid: wpa_ssid structure for a configured network or %NULL
2987 *
2988 * Disables the specified network or all networks if no network specified.
2989 */
2990void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2991 struct wpa_ssid *ssid)
2992{
2993 struct wpa_ssid *other_ssid;
2994 int was_disabled;
2995
2996 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002997 if (wpa_s->sched_scanning)
2998 wpa_supplicant_cancel_sched_scan(wpa_s);
2999
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003000 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3001 other_ssid = other_ssid->next) {
3002 was_disabled = other_ssid->disabled;
3003 if (was_disabled == 2)
3004 continue; /* do not change persistent P2P group
3005 * data */
3006
3007 other_ssid->disabled = 1;
3008
3009 if (was_disabled != other_ssid->disabled)
3010 wpas_notify_network_enabled_changed(
3011 wpa_s, other_ssid);
3012 }
3013 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003014 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003015 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3016 } else if (ssid->disabled != 2) {
3017 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003018 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003019 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3020
3021 was_disabled = ssid->disabled;
3022
3023 ssid->disabled = 1;
3024
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003025 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003026 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003027 if (wpa_s->sched_scanning) {
3028 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3029 "to remove network from filters");
3030 wpa_supplicant_cancel_sched_scan(wpa_s);
3031 wpa_supplicant_req_scan(wpa_s, 0, 0);
3032 }
3033 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003034 }
3035}
3036
3037
3038/**
3039 * wpa_supplicant_select_network - Attempt association with a network
3040 * @wpa_s: wpa_supplicant structure for a network interface
3041 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3042 */
3043void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3044 struct wpa_ssid *ssid)
3045{
3046
3047 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003048 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003049
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003050 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003051 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3052 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003053 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003054 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003055 disconnected = 1;
3056 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003057
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003058 if (ssid)
3059 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3060
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003061 /*
3062 * Mark all other networks disabled or mark all networks enabled if no
3063 * network specified.
3064 */
3065 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3066 other_ssid = other_ssid->next) {
3067 int was_disabled = other_ssid->disabled;
3068 if (was_disabled == 2)
3069 continue; /* do not change persistent P2P group data */
3070
3071 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003072 if (was_disabled && !other_ssid->disabled)
3073 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003074
3075 if (was_disabled != other_ssid->disabled)
3076 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3077 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003078
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003079 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3080 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003081 /* We are already associated with the selected network */
3082 wpa_printf(MSG_DEBUG, "Already associated with the "
3083 "selected network - do nothing");
3084 return;
3085 }
3086
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003087 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003088 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003089 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003090 wpa_s->connect_without_scan =
3091 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003092
3093 /*
3094 * Don't optimize next scan freqs since a new ESS has been
3095 * selected.
3096 */
3097 os_free(wpa_s->next_scan_freqs);
3098 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003099 } else {
3100 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003101 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003102
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003103 wpa_s->disconnected = 0;
3104 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003105
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003106 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003107 wpa_supplicant_fast_associate(wpa_s) != 1) {
3108 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003109 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003110 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003111 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003112
3113 if (ssid)
3114 wpas_notify_network_selected(wpa_s, ssid);
3115}
3116
3117
3118/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003119 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3120 * @wpa_s: wpa_supplicant structure for a network interface
3121 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3122 * @pkcs11_module_path: PKCS #11 module path or NULL
3123 * Returns: 0 on success; -1 on failure
3124 *
3125 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3126 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3127 * module path fails the paths will be reset to the default value (NULL).
3128 */
3129int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3130 const char *pkcs11_engine_path,
3131 const char *pkcs11_module_path)
3132{
3133 char *pkcs11_engine_path_copy = NULL;
3134 char *pkcs11_module_path_copy = NULL;
3135
3136 if (pkcs11_engine_path != NULL) {
3137 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3138 if (pkcs11_engine_path_copy == NULL)
3139 return -1;
3140 }
3141 if (pkcs11_module_path != NULL) {
3142 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003143 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003144 os_free(pkcs11_engine_path_copy);
3145 return -1;
3146 }
3147 }
3148
3149 os_free(wpa_s->conf->pkcs11_engine_path);
3150 os_free(wpa_s->conf->pkcs11_module_path);
3151 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3152 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3153
3154 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3155 eapol_sm_deinit(wpa_s->eapol);
3156 wpa_s->eapol = NULL;
3157 if (wpa_supplicant_init_eapol(wpa_s)) {
3158 /* Error -> Reset paths to the default value (NULL) once. */
3159 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3160 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3161 NULL);
3162
3163 return -1;
3164 }
3165 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3166
3167 return 0;
3168}
3169
3170
3171/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003172 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3173 * @wpa_s: wpa_supplicant structure for a network interface
3174 * @ap_scan: AP scan mode
3175 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3176 *
3177 */
3178int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3179{
3180
3181 int old_ap_scan;
3182
3183 if (ap_scan < 0 || ap_scan > 2)
3184 return -1;
3185
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003186 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3187 wpa_printf(MSG_INFO,
3188 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3189 }
3190
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003191#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003192 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3193 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3194 wpa_s->wpa_state < WPA_COMPLETED) {
3195 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3196 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003197 return 0;
3198 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003199#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003200
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003201 old_ap_scan = wpa_s->conf->ap_scan;
3202 wpa_s->conf->ap_scan = ap_scan;
3203
3204 if (old_ap_scan != wpa_s->conf->ap_scan)
3205 wpas_notify_ap_scan_changed(wpa_s);
3206
3207 return 0;
3208}
3209
3210
3211/**
3212 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3213 * @wpa_s: wpa_supplicant structure for a network interface
3214 * @expire_age: Expiration age in seconds
3215 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3216 *
3217 */
3218int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3219 unsigned int bss_expire_age)
3220{
3221 if (bss_expire_age < 10) {
3222 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3223 bss_expire_age);
3224 return -1;
3225 }
3226 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3227 bss_expire_age);
3228 wpa_s->conf->bss_expiration_age = bss_expire_age;
3229
3230 return 0;
3231}
3232
3233
3234/**
3235 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3236 * @wpa_s: wpa_supplicant structure for a network interface
3237 * @expire_count: number of scans after which an unseen BSS is reclaimed
3238 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3239 *
3240 */
3241int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3242 unsigned int bss_expire_count)
3243{
3244 if (bss_expire_count < 1) {
3245 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3246 bss_expire_count);
3247 return -1;
3248 }
3249 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3250 bss_expire_count);
3251 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3252
3253 return 0;
3254}
3255
3256
3257/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003258 * wpa_supplicant_set_scan_interval - Set scan interval
3259 * @wpa_s: wpa_supplicant structure for a network interface
3260 * @scan_interval: scan interval in seconds
3261 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3262 *
3263 */
3264int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3265 int scan_interval)
3266{
3267 if (scan_interval < 0) {
3268 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3269 scan_interval);
3270 return -1;
3271 }
3272 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3273 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003274 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003275
3276 return 0;
3277}
3278
3279
3280/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003281 * wpa_supplicant_set_debug_params - Set global debug params
3282 * @global: wpa_global structure
3283 * @debug_level: debug level
3284 * @debug_timestamp: determines if show timestamp in debug data
3285 * @debug_show_keys: determines if show keys in debug data
3286 * Returns: 0 if succeed or -1 if debug_level has wrong value
3287 */
3288int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3289 int debug_timestamp, int debug_show_keys)
3290{
3291
3292 int old_level, old_timestamp, old_show_keys;
3293
3294 /* check for allowed debuglevels */
3295 if (debug_level != MSG_EXCESSIVE &&
3296 debug_level != MSG_MSGDUMP &&
3297 debug_level != MSG_DEBUG &&
3298 debug_level != MSG_INFO &&
3299 debug_level != MSG_WARNING &&
3300 debug_level != MSG_ERROR)
3301 return -1;
3302
3303 old_level = wpa_debug_level;
3304 old_timestamp = wpa_debug_timestamp;
3305 old_show_keys = wpa_debug_show_keys;
3306
3307 wpa_debug_level = debug_level;
3308 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3309 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3310
3311 if (wpa_debug_level != old_level)
3312 wpas_notify_debug_level_changed(global);
3313 if (wpa_debug_timestamp != old_timestamp)
3314 wpas_notify_debug_timestamp_changed(global);
3315 if (wpa_debug_show_keys != old_show_keys)
3316 wpas_notify_debug_show_keys_changed(global);
3317
3318 return 0;
3319}
3320
3321
3322/**
3323 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3324 * @wpa_s: Pointer to wpa_supplicant data
3325 * Returns: A pointer to the current network structure or %NULL on failure
3326 */
3327struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3328{
3329 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003330 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003331 int res;
3332 size_t ssid_len;
3333 u8 bssid[ETH_ALEN];
3334 int wired;
3335
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003336 res = wpa_drv_get_ssid(wpa_s, ssid);
3337 if (res < 0) {
3338 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3339 "driver");
3340 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003341 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003342 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003343
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003344 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003345 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3346 "driver");
3347 return NULL;
3348 }
3349
3350 wired = wpa_s->conf->ap_scan == 0 &&
3351 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3352
3353 entry = wpa_s->conf->ssid;
3354 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003355 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003356 ((ssid_len == entry->ssid_len &&
3357 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3358 (!entry->bssid_set ||
3359 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3360 return entry;
3361#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003362 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003363 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3364 (entry->ssid == NULL || entry->ssid_len == 0) &&
3365 (!entry->bssid_set ||
3366 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3367 return entry;
3368#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003369
Dmitry Shmidt04949592012-07-19 12:16:46 -07003370 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003371 entry->ssid_len == 0 &&
3372 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3373 return entry;
3374
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003375 entry = entry->next;
3376 }
3377
3378 return NULL;
3379}
3380
3381
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003382static int select_driver(struct wpa_supplicant *wpa_s, int i)
3383{
3384 struct wpa_global *global = wpa_s->global;
3385
3386 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003387 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003388 if (global->drv_priv[i] == NULL) {
3389 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3390 "'%s'", wpa_drivers[i]->name);
3391 return -1;
3392 }
3393 }
3394
3395 wpa_s->driver = wpa_drivers[i];
3396 wpa_s->global_drv_priv = global->drv_priv[i];
3397
3398 return 0;
3399}
3400
3401
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003402static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3403 const char *name)
3404{
3405 int i;
3406 size_t len;
3407 const char *pos, *driver = name;
3408
3409 if (wpa_s == NULL)
3410 return -1;
3411
3412 if (wpa_drivers[0] == NULL) {
3413 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3414 "wpa_supplicant");
3415 return -1;
3416 }
3417
3418 if (name == NULL) {
3419 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003420 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003421 }
3422
3423 do {
3424 pos = os_strchr(driver, ',');
3425 if (pos)
3426 len = pos - driver;
3427 else
3428 len = os_strlen(driver);
3429
3430 for (i = 0; wpa_drivers[i]; i++) {
3431 if (os_strlen(wpa_drivers[i]->name) == len &&
3432 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003433 0) {
3434 /* First driver that succeeds wins */
3435 if (select_driver(wpa_s, i) == 0)
3436 return 0;
3437 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003438 }
3439
3440 driver = pos + 1;
3441 } while (pos);
3442
3443 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3444 return -1;
3445}
3446
3447
3448/**
3449 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3450 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3451 * with struct wpa_driver_ops::init()
3452 * @src_addr: Source address of the EAPOL frame
3453 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3454 * @len: Length of the EAPOL data
3455 *
3456 * This function is called for each received EAPOL frame. Most driver
3457 * interfaces rely on more generic OS mechanism for receiving frames through
3458 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3459 * take care of received EAPOL frames and deliver them to the core supplicant
3460 * code by calling this function.
3461 */
3462void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3463 const u8 *buf, size_t len)
3464{
3465 struct wpa_supplicant *wpa_s = ctx;
3466
3467 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3468 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3469
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003470#ifdef CONFIG_TESTING_OPTIONS
3471 if (wpa_s->ignore_auth_resp) {
3472 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3473 return;
3474 }
3475#endif /* CONFIG_TESTING_OPTIONS */
3476
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003477#ifdef CONFIG_PEERKEY
3478 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3479 wpa_s->current_ssid->peerkey &&
3480 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3481 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3482 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3483 return;
3484 }
3485#endif /* CONFIG_PEERKEY */
3486
Jouni Malinena05074c2012-12-21 21:35:35 +02003487 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3488 (wpa_s->last_eapol_matches_bssid &&
3489#ifdef CONFIG_AP
3490 !wpa_s->ap_iface &&
3491#endif /* CONFIG_AP */
3492 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003493 /*
3494 * There is possible race condition between receiving the
3495 * association event and the EAPOL frame since they are coming
3496 * through different paths from the driver. In order to avoid
3497 * issues in trying to process the EAPOL frame before receiving
3498 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003499 * the association event is received. This may also be needed in
3500 * driver-based roaming case, so also use src_addr != BSSID as a
3501 * trigger if we have previously confirmed that the
3502 * Authenticator uses BSSID as the src_addr (which is not the
3503 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003504 */
3505 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003506 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3507 wpa_supplicant_state_txt(wpa_s->wpa_state),
3508 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003509 wpabuf_free(wpa_s->pending_eapol_rx);
3510 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3511 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003512 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003513 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3514 ETH_ALEN);
3515 }
3516 return;
3517 }
3518
Jouni Malinena05074c2012-12-21 21:35:35 +02003519 wpa_s->last_eapol_matches_bssid =
3520 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003522#ifdef CONFIG_AP
3523 if (wpa_s->ap_iface) {
3524 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3525 return;
3526 }
3527#endif /* CONFIG_AP */
3528
3529 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3530 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3531 "no key management is configured");
3532 return;
3533 }
3534
3535 if (wpa_s->eapol_received == 0 &&
3536 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3537 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3538 wpa_s->wpa_state != WPA_COMPLETED) &&
3539 (wpa_s->current_ssid == NULL ||
3540 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3541 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003542 int timeout = 10;
3543
3544 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3545 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3546 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3547 /* Use longer timeout for IEEE 802.1X/EAP */
3548 timeout = 70;
3549 }
3550
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003551#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003552 if (wpa_s->current_ssid && wpa_s->current_bss &&
3553 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3554 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3555 /*
3556 * Use shorter timeout if going through WPS AP iteration
3557 * for PIN config method with an AP that does not
3558 * advertise Selected Registrar.
3559 */
3560 struct wpabuf *wps_ie;
3561
3562 wps_ie = wpa_bss_get_vendor_ie_multi(
3563 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3564 if (wps_ie &&
3565 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3566 timeout = 10;
3567 wpabuf_free(wps_ie);
3568 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003569#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003570
3571 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003572 }
3573 wpa_s->eapol_received++;
3574
3575 if (wpa_s->countermeasures) {
3576 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3577 "EAPOL packet");
3578 return;
3579 }
3580
3581#ifdef CONFIG_IBSS_RSN
3582 if (wpa_s->current_ssid &&
3583 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3584 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3585 return;
3586 }
3587#endif /* CONFIG_IBSS_RSN */
3588
3589 /* Source address of the incoming EAPOL frame could be compared to the
3590 * current BSSID. However, it is possible that a centralized
3591 * Authenticator could be using another MAC address than the BSSID of
3592 * an AP, so just allow any address to be used for now. The replies are
3593 * still sent to the current BSSID (if available), though. */
3594
3595 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3596 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3597 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3598 return;
3599 wpa_drv_poll(wpa_s);
3600 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3601 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3602 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3603 /*
3604 * Set portValid = TRUE here since we are going to skip 4-way
3605 * handshake processing which would normally set portValid. We
3606 * need this to allow the EAPOL state machines to be completed
3607 * without going through EAPOL-Key handshake.
3608 */
3609 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3610 }
3611}
3612
3613
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003614int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003615{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003616 if ((!wpa_s->p2p_mgmt ||
3617 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3618 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003619 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003620 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3621 wpa_drv_get_mac_addr(wpa_s),
3622 ETH_P_EAPOL,
3623 wpa_supplicant_rx_eapol, wpa_s, 0);
3624 if (wpa_s->l2 == NULL)
3625 return -1;
3626 } else {
3627 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3628 if (addr)
3629 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3630 }
3631
3632 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3633 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3634 return -1;
3635 }
3636
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003637 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3638
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003639 return 0;
3640}
3641
3642
Dmitry Shmidt04949592012-07-19 12:16:46 -07003643static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3644 const u8 *buf, size_t len)
3645{
3646 struct wpa_supplicant *wpa_s = ctx;
3647 const struct l2_ethhdr *eth;
3648
3649 if (len < sizeof(*eth))
3650 return;
3651 eth = (const struct l2_ethhdr *) buf;
3652
3653 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3654 !(eth->h_dest[0] & 0x01)) {
3655 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3656 " (bridge - not for this interface - ignore)",
3657 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3658 return;
3659 }
3660
3661 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3662 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3663 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3664 len - sizeof(*eth));
3665}
3666
3667
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003668/**
3669 * wpa_supplicant_driver_init - Initialize driver interface parameters
3670 * @wpa_s: Pointer to wpa_supplicant data
3671 * Returns: 0 on success, -1 on failure
3672 *
3673 * This function is called to initialize driver interface parameters.
3674 * wpa_drv_init() must have been called before this function to initialize the
3675 * driver interface.
3676 */
3677int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3678{
3679 static int interface_count = 0;
3680
3681 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3682 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003683
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003684 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3685 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003686 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003687 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3688
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003689 if (wpa_s->bridge_ifname[0]) {
3690 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3691 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003692 wpa_s->l2_br = l2_packet_init_bridge(
3693 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3694 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003695 if (wpa_s->l2_br == NULL) {
3696 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3697 "connection for the bridge interface '%s'",
3698 wpa_s->bridge_ifname);
3699 return -1;
3700 }
3701 }
3702
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003703 if (wpa_s->conf->ap_scan == 2 &&
3704 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3705 wpa_printf(MSG_INFO,
3706 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3707 }
3708
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003709 wpa_clear_keys(wpa_s, NULL);
3710
3711 /* Make sure that TKIP countermeasures are not left enabled (could
3712 * happen if wpa_supplicant is killed during countermeasures. */
3713 wpa_drv_set_countermeasures(wpa_s, 0);
3714
3715 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3716 wpa_drv_flush_pmkid(wpa_s);
3717
3718 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003719 wpa_s->prev_scan_wildcard = 0;
3720
Dmitry Shmidt04949592012-07-19 12:16:46 -07003721 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003722 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3723 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3724 interface_count = 0;
3725 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003726#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003727 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003728 wpa_supplicant_delayed_sched_scan(wpa_s,
3729 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003730 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003731 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003732 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003733#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003734 interface_count++;
3735 } else
3736 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3737
3738 return 0;
3739}
3740
3741
3742static int wpa_supplicant_daemon(const char *pid_file)
3743{
3744 wpa_printf(MSG_DEBUG, "Daemonize..");
3745 return os_daemonize(pid_file);
3746}
3747
3748
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003749static struct wpa_supplicant *
3750wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003751{
3752 struct wpa_supplicant *wpa_s;
3753
3754 wpa_s = os_zalloc(sizeof(*wpa_s));
3755 if (wpa_s == NULL)
3756 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003757 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003758 wpa_s->scan_interval = 5;
3759 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003760 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003761 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003762 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003763
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003764 dl_list_init(&wpa_s->bss_tmp_disallowed);
3765
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003766 return wpa_s;
3767}
3768
3769
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003770#ifdef CONFIG_HT_OVERRIDES
3771
3772static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3773 struct ieee80211_ht_capabilities *htcaps,
3774 struct ieee80211_ht_capabilities *htcaps_mask,
3775 const char *ht_mcs)
3776{
3777 /* parse ht_mcs into hex array */
3778 int i;
3779 const char *tmp = ht_mcs;
3780 char *end = NULL;
3781
3782 /* If ht_mcs is null, do not set anything */
3783 if (!ht_mcs)
3784 return 0;
3785
3786 /* This is what we are setting in the kernel */
3787 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3788
3789 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3790
3791 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3792 errno = 0;
3793 long v = strtol(tmp, &end, 16);
3794 if (errno == 0) {
3795 wpa_msg(wpa_s, MSG_DEBUG,
3796 "htcap value[%i]: %ld end: %p tmp: %p",
3797 i, v, end, tmp);
3798 if (end == tmp)
3799 break;
3800
3801 htcaps->supported_mcs_set[i] = v;
3802 tmp = end;
3803 } else {
3804 wpa_msg(wpa_s, MSG_ERROR,
3805 "Failed to parse ht-mcs: %s, error: %s\n",
3806 ht_mcs, strerror(errno));
3807 return -1;
3808 }
3809 }
3810
3811 /*
3812 * If we were able to parse any values, then set mask for the MCS set.
3813 */
3814 if (i) {
3815 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3816 IEEE80211_HT_MCS_MASK_LEN - 1);
3817 /* skip the 3 reserved bits */
3818 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3819 0x1f;
3820 }
3821
3822 return 0;
3823}
3824
3825
3826static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3827 struct ieee80211_ht_capabilities *htcaps,
3828 struct ieee80211_ht_capabilities *htcaps_mask,
3829 int disabled)
3830{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003831 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003832
3833 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3834
3835 if (disabled == -1)
3836 return 0;
3837
3838 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3839 htcaps_mask->ht_capabilities_info |= msk;
3840 if (disabled)
3841 htcaps->ht_capabilities_info &= msk;
3842 else
3843 htcaps->ht_capabilities_info |= msk;
3844
3845 return 0;
3846}
3847
3848
3849static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3850 struct ieee80211_ht_capabilities *htcaps,
3851 struct ieee80211_ht_capabilities *htcaps_mask,
3852 int factor)
3853{
3854 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3855
3856 if (factor == -1)
3857 return 0;
3858
3859 if (factor < 0 || factor > 3) {
3860 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3861 "Must be 0-3 or -1", factor);
3862 return -EINVAL;
3863 }
3864
3865 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3866 htcaps->a_mpdu_params &= ~0x3;
3867 htcaps->a_mpdu_params |= factor & 0x3;
3868
3869 return 0;
3870}
3871
3872
3873static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3874 struct ieee80211_ht_capabilities *htcaps,
3875 struct ieee80211_ht_capabilities *htcaps_mask,
3876 int density)
3877{
3878 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3879
3880 if (density == -1)
3881 return 0;
3882
3883 if (density < 0 || density > 7) {
3884 wpa_msg(wpa_s, MSG_ERROR,
3885 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3886 density);
3887 return -EINVAL;
3888 }
3889
3890 htcaps_mask->a_mpdu_params |= 0x1C;
3891 htcaps->a_mpdu_params &= ~(0x1C);
3892 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3893
3894 return 0;
3895}
3896
3897
3898static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3899 struct ieee80211_ht_capabilities *htcaps,
3900 struct ieee80211_ht_capabilities *htcaps_mask,
3901 int disabled)
3902{
3903 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003904 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3905 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003906
3907 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3908
3909 if (disabled)
3910 htcaps->ht_capabilities_info &= ~msk;
3911 else
3912 htcaps->ht_capabilities_info |= msk;
3913
3914 htcaps_mask->ht_capabilities_info |= msk;
3915
3916 return 0;
3917}
3918
3919
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003920static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3921 struct ieee80211_ht_capabilities *htcaps,
3922 struct ieee80211_ht_capabilities *htcaps_mask,
3923 int disabled)
3924{
3925 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003926 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3927 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003928
3929 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3930
3931 if (disabled)
3932 htcaps->ht_capabilities_info &= ~msk;
3933 else
3934 htcaps->ht_capabilities_info |= msk;
3935
3936 htcaps_mask->ht_capabilities_info |= msk;
3937
3938 return 0;
3939}
3940
3941
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003942static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3943 struct ieee80211_ht_capabilities *htcaps,
3944 struct ieee80211_ht_capabilities *htcaps_mask,
3945 int disabled)
3946{
3947 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003948 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003949
3950 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3951
3952 if (disabled)
3953 htcaps->ht_capabilities_info &= ~msk;
3954 else
3955 htcaps->ht_capabilities_info |= msk;
3956
3957 htcaps_mask->ht_capabilities_info |= msk;
3958
3959 return 0;
3960}
3961
3962
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003963void wpa_supplicant_apply_ht_overrides(
3964 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3965 struct wpa_driver_associate_params *params)
3966{
3967 struct ieee80211_ht_capabilities *htcaps;
3968 struct ieee80211_ht_capabilities *htcaps_mask;
3969
3970 if (!ssid)
3971 return;
3972
3973 params->disable_ht = ssid->disable_ht;
3974 if (!params->htcaps || !params->htcaps_mask)
3975 return;
3976
3977 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3978 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3979 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3980 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3981 ssid->disable_max_amsdu);
3982 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3983 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3984 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003985 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003986 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003987
3988 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003989 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003990 htcaps->ht_capabilities_info |= bit;
3991 htcaps_mask->ht_capabilities_info |= bit;
3992 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003993}
3994
3995#endif /* CONFIG_HT_OVERRIDES */
3996
3997
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003998#ifdef CONFIG_VHT_OVERRIDES
3999void wpa_supplicant_apply_vht_overrides(
4000 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4001 struct wpa_driver_associate_params *params)
4002{
4003 struct ieee80211_vht_capabilities *vhtcaps;
4004 struct ieee80211_vht_capabilities *vhtcaps_mask;
4005
4006 if (!ssid)
4007 return;
4008
4009 params->disable_vht = ssid->disable_vht;
4010
4011 vhtcaps = (void *) params->vhtcaps;
4012 vhtcaps_mask = (void *) params->vhtcaps_mask;
4013
4014 if (!vhtcaps || !vhtcaps_mask)
4015 return;
4016
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004017 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
4018 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004019
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004020#ifdef CONFIG_HT_OVERRIDES
4021 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004022 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
4023 int max_ampdu;
4024
4025 max_ampdu = (ssid->vht_capa &
4026 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4027 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004028
4029 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4030 wpa_set_ampdu_factor(wpa_s,
4031 (void *) params->htcaps,
4032 (void *) params->htcaps_mask,
4033 max_ampdu);
4034 }
4035#endif /* CONFIG_HT_OVERRIDES */
4036
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004037#define OVERRIDE_MCS(i) \
4038 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4039 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004040 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004041 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004042 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4043 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004044 } \
4045 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4046 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004047 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004048 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004049 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4050 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004051 }
4052
4053 OVERRIDE_MCS(1);
4054 OVERRIDE_MCS(2);
4055 OVERRIDE_MCS(3);
4056 OVERRIDE_MCS(4);
4057 OVERRIDE_MCS(5);
4058 OVERRIDE_MCS(6);
4059 OVERRIDE_MCS(7);
4060 OVERRIDE_MCS(8);
4061}
4062#endif /* CONFIG_VHT_OVERRIDES */
4063
4064
Dmitry Shmidt04949592012-07-19 12:16:46 -07004065static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4066{
4067#ifdef PCSC_FUNCS
4068 size_t len;
4069
4070 if (!wpa_s->conf->pcsc_reader)
4071 return 0;
4072
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004073 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004074 if (!wpa_s->scard)
4075 return 1;
4076
4077 if (wpa_s->conf->pcsc_pin &&
4078 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4079 scard_deinit(wpa_s->scard);
4080 wpa_s->scard = NULL;
4081 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4082 return -1;
4083 }
4084
4085 len = sizeof(wpa_s->imsi) - 1;
4086 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4087 scard_deinit(wpa_s->scard);
4088 wpa_s->scard = NULL;
4089 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4090 return -1;
4091 }
4092 wpa_s->imsi[len] = '\0';
4093
4094 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4095
4096 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4097 wpa_s->imsi, wpa_s->mnc_len);
4098
4099 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4100 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4101#endif /* PCSC_FUNCS */
4102
4103 return 0;
4104}
4105
4106
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004107int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4108{
4109 char *val, *pos;
4110
4111 ext_password_deinit(wpa_s->ext_pw);
4112 wpa_s->ext_pw = NULL;
4113 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4114
4115 if (!wpa_s->conf->ext_password_backend)
4116 return 0;
4117
4118 val = os_strdup(wpa_s->conf->ext_password_backend);
4119 if (val == NULL)
4120 return -1;
4121 pos = os_strchr(val, ':');
4122 if (pos)
4123 *pos++ = '\0';
4124
4125 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4126
4127 wpa_s->ext_pw = ext_password_init(val, pos);
4128 os_free(val);
4129 if (wpa_s->ext_pw == NULL) {
4130 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4131 return -1;
4132 }
4133 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4134
4135 return 0;
4136}
4137
4138
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004139#ifdef CONFIG_FST
4140
4141static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4142{
4143 struct wpa_supplicant *wpa_s = ctx;
4144
4145 return (is_zero_ether_addr(wpa_s->bssid) ||
4146 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4147}
4148
4149
4150static void wpas_fst_get_channel_info_cb(void *ctx,
4151 enum hostapd_hw_mode *hw_mode,
4152 u8 *channel)
4153{
4154 struct wpa_supplicant *wpa_s = ctx;
4155
4156 if (wpa_s->current_bss) {
4157 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4158 channel);
4159 } else if (wpa_s->hw.num_modes) {
4160 *hw_mode = wpa_s->hw.modes[0].mode;
4161 } else {
4162 WPA_ASSERT(0);
4163 *hw_mode = 0;
4164 }
4165}
4166
4167
4168static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4169{
4170 struct wpa_supplicant *wpa_s = ctx;
4171
4172 *modes = wpa_s->hw.modes;
4173 return wpa_s->hw.num_modes;
4174}
4175
4176
4177static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4178{
4179 struct wpa_supplicant *wpa_s = ctx;
4180
4181 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4182 wpa_s->fst_ies = fst_ies;
4183}
4184
4185
4186static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4187{
4188 struct wpa_supplicant *wpa_s = ctx;
4189
4190 WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
4191 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
4192 wpa_s->own_addr, wpa_s->bssid,
4193 wpabuf_head(data), wpabuf_len(data),
4194 0);
4195}
4196
4197
4198static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4199{
4200 struct wpa_supplicant *wpa_s = ctx;
4201
4202 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4203 return wpa_s->received_mb_ies;
4204}
4205
4206
4207static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4208 const u8 *buf, size_t size)
4209{
4210 struct wpa_supplicant *wpa_s = ctx;
4211 struct mb_ies_info info;
4212
4213 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4214
4215 if (!mb_ies_info_by_ies(&info, buf, size)) {
4216 wpabuf_free(wpa_s->received_mb_ies);
4217 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4218 }
4219}
4220
4221
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004222static const u8 * wpas_fst_get_peer_first(void *ctx,
4223 struct fst_get_peer_ctx **get_ctx,
4224 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004225{
4226 struct wpa_supplicant *wpa_s = ctx;
4227
4228 *get_ctx = NULL;
4229 if (!is_zero_ether_addr(wpa_s->bssid))
4230 return (wpa_s->received_mb_ies || !mb_only) ?
4231 wpa_s->bssid : NULL;
4232 return NULL;
4233}
4234
4235
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004236static const u8 * wpas_fst_get_peer_next(void *ctx,
4237 struct fst_get_peer_ctx **get_ctx,
4238 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004239{
4240 return NULL;
4241}
4242
4243void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4244 struct fst_wpa_obj *iface_obj)
4245{
4246 iface_obj->ctx = wpa_s;
4247 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4248 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4249 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4250 iface_obj->set_ies = wpas_fst_set_ies_cb;
4251 iface_obj->send_action = wpas_fst_send_action_cb;
4252 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4253 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4254 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4255 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4256}
4257#endif /* CONFIG_FST */
4258
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004259static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004260 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004261{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004262 struct wowlan_triggers *triggers;
4263 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004264
4265 if (!wpa_s->conf->wowlan_triggers)
4266 return 0;
4267
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004268 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4269 if (triggers) {
4270 ret = wpa_drv_wowlan(wpa_s, triggers);
4271 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004272 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004273 return ret;
4274}
4275
4276
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004277enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004278{
4279 if (freq < 3000)
4280 return BAND_2_4_GHZ;
4281 if (freq > 50000)
4282 return BAND_60_GHZ;
4283 return BAND_5_GHZ;
4284}
4285
4286
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004287unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004288{
4289 int i;
4290 unsigned int band = 0;
4291
4292 if (freqs) {
4293 /* freqs are specified for the radio work */
4294 for (i = 0; freqs[i]; i++)
4295 band |= wpas_freq_to_band(freqs[i]);
4296 } else {
4297 /*
4298 * freqs are not specified, implies all
4299 * the supported freqs by HW
4300 */
4301 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4302 if (wpa_s->hw.modes[i].num_channels != 0) {
4303 if (wpa_s->hw.modes[i].mode ==
4304 HOSTAPD_MODE_IEEE80211B ||
4305 wpa_s->hw.modes[i].mode ==
4306 HOSTAPD_MODE_IEEE80211G)
4307 band |= BAND_2_4_GHZ;
4308 else if (wpa_s->hw.modes[i].mode ==
4309 HOSTAPD_MODE_IEEE80211A)
4310 band |= BAND_5_GHZ;
4311 else if (wpa_s->hw.modes[i].mode ==
4312 HOSTAPD_MODE_IEEE80211AD)
4313 band |= BAND_60_GHZ;
4314 else if (wpa_s->hw.modes[i].mode ==
4315 HOSTAPD_MODE_IEEE80211ANY)
4316 band = BAND_2_4_GHZ | BAND_5_GHZ |
4317 BAND_60_GHZ;
4318 }
4319 }
4320 }
4321
4322 return band;
4323}
4324
4325
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004326static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4327 const char *rn)
4328{
4329 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4330 struct wpa_radio *radio;
4331
4332 while (rn && iface) {
4333 radio = iface->radio;
4334 if (radio && os_strcmp(rn, radio->name) == 0) {
4335 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4336 wpa_s->ifname, rn);
4337 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4338 return radio;
4339 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004340
4341 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004342 }
4343
4344 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4345 wpa_s->ifname, rn ? rn : "N/A");
4346 radio = os_zalloc(sizeof(*radio));
4347 if (radio == NULL)
4348 return NULL;
4349
4350 if (rn)
4351 os_strlcpy(radio->name, rn, sizeof(radio->name));
4352 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004353 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004354 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4355
4356 return radio;
4357}
4358
4359
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004360static void radio_work_free(struct wpa_radio_work *work)
4361{
4362 if (work->wpa_s->scan_work == work) {
4363 /* This should not really happen. */
4364 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4365 work->type, work, work->started);
4366 work->wpa_s->scan_work = NULL;
4367 }
4368
4369#ifdef CONFIG_P2P
4370 if (work->wpa_s->p2p_scan_work == work) {
4371 /* This should not really happen. */
4372 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4373 work->type, work, work->started);
4374 work->wpa_s->p2p_scan_work = NULL;
4375 }
4376#endif /* CONFIG_P2P */
4377
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004378 if (work->started) {
4379 work->wpa_s->radio->num_active_works--;
4380 wpa_dbg(work->wpa_s, MSG_DEBUG,
4381 "radio_work_free('%s'@%p: num_active_works --> %u",
4382 work->type, work,
4383 work->wpa_s->radio->num_active_works);
4384 }
4385
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004386 dl_list_del(&work->list);
4387 os_free(work);
4388}
4389
4390
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004391static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4392{
4393 struct wpa_radio_work *active_work = NULL;
4394 struct wpa_radio_work *tmp;
4395
4396 /* Get the active work to know the type and band. */
4397 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4398 if (tmp->started) {
4399 active_work = tmp;
4400 break;
4401 }
4402 }
4403
4404 if (!active_work) {
4405 /* No active work, start one */
4406 radio->num_active_works = 0;
4407 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4408 list) {
4409 if (os_strcmp(tmp->type, "scan") == 0 &&
4410 radio->external_scan_running &&
4411 (((struct wpa_driver_scan_params *)
4412 tmp->ctx)->only_new_results ||
4413 tmp->wpa_s->clear_driver_scan_cache))
4414 continue;
4415 return tmp;
4416 }
4417 return NULL;
4418 }
4419
4420 if (os_strcmp(active_work->type, "sme-connect") == 0 ||
4421 os_strcmp(active_work->type, "connect") == 0) {
4422 /*
4423 * If the active work is either connect or sme-connect,
4424 * do not parallelize them with other radio works.
4425 */
4426 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4427 "Do not parallelize radio work with %s",
4428 active_work->type);
4429 return NULL;
4430 }
4431
4432 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4433 if (tmp->started)
4434 continue;
4435
4436 /*
4437 * If connect or sme-connect are enqueued, parallelize only
4438 * those operations ahead of them in the queue.
4439 */
4440 if (os_strcmp(tmp->type, "connect") == 0 ||
4441 os_strcmp(tmp->type, "sme-connect") == 0)
4442 break;
4443
4444 /*
4445 * Check that the radio works are distinct and
4446 * on different bands.
4447 */
4448 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4449 (active_work->bands != tmp->bands)) {
4450 /*
4451 * If a scan has to be scheduled through nl80211 scan
4452 * interface and if an external scan is already running,
4453 * do not schedule the scan since it is likely to get
4454 * rejected by kernel.
4455 */
4456 if (os_strcmp(tmp->type, "scan") == 0 &&
4457 radio->external_scan_running &&
4458 (((struct wpa_driver_scan_params *)
4459 tmp->ctx)->only_new_results ||
4460 tmp->wpa_s->clear_driver_scan_cache))
4461 continue;
4462
4463 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4464 "active_work:%s new_work:%s",
4465 active_work->type, tmp->type);
4466 return tmp;
4467 }
4468 }
4469
4470 /* Did not find a radio work to schedule in parallel. */
4471 return NULL;
4472}
4473
4474
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004475static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4476{
4477 struct wpa_radio *radio = eloop_ctx;
4478 struct wpa_radio_work *work;
4479 struct os_reltime now, diff;
4480 struct wpa_supplicant *wpa_s;
4481
4482 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004483 if (work == NULL) {
4484 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004485 return;
4486 }
4487
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004488 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4489 radio_list);
4490
4491 if (!(wpa_s &&
4492 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4493 if (work->started)
4494 return; /* already started and still in progress */
4495
4496 if (wpa_s && wpa_s->radio->external_scan_running) {
4497 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4498 return;
4499 }
4500 } else {
4501 work = NULL;
4502 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4503 /* get the work to schedule next */
4504 work = radio_work_get_next_work(radio);
4505 }
4506 if (!work)
4507 return;
4508 }
4509
4510 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004511 os_get_reltime(&now);
4512 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004513 wpa_dbg(wpa_s, MSG_DEBUG,
4514 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004515 work->type, work, diff.sec, diff.usec);
4516 work->started = 1;
4517 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004518 radio->num_active_works++;
4519
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004520 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004521
4522 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4523 radio->num_active_works < MAX_ACTIVE_WORKS)
4524 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004525}
4526
4527
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004528/*
4529 * This function removes both started and pending radio works running on
4530 * the provided interface's radio.
4531 * Prior to the removal of the radio work, its callback (cb) is called with
4532 * deinit set to be 1. Each work's callback is responsible for clearing its
4533 * internal data and restoring to a correct state.
4534 * @wpa_s: wpa_supplicant data
4535 * @type: type of works to be removed
4536 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4537 * this interface's works.
4538 */
4539void radio_remove_works(struct wpa_supplicant *wpa_s,
4540 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004541{
4542 struct wpa_radio_work *work, *tmp;
4543 struct wpa_radio *radio = wpa_s->radio;
4544
4545 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4546 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004547 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004548 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004549
4550 /* skip other ifaces' works */
4551 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004552 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004553
4554 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4555 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004556 work->cb(work, 1);
4557 radio_work_free(work);
4558 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004559
4560 /* in case we removed the started work */
4561 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004562}
4563
4564
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004565static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4566{
4567 struct wpa_radio *radio = wpa_s->radio;
4568
4569 if (!radio)
4570 return;
4571
4572 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4573 wpa_s->ifname, radio->name);
4574 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004575 radio_remove_works(wpa_s, NULL, 0);
4576 wpa_s->radio = NULL;
4577 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004578 return; /* Interfaces remain for this radio */
4579
4580 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004581 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004582 os_free(radio);
4583}
4584
4585
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004586void radio_work_check_next(struct wpa_supplicant *wpa_s)
4587{
4588 struct wpa_radio *radio = wpa_s->radio;
4589
4590 if (dl_list_empty(&radio->work))
4591 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004592 if (wpa_s->ext_work_in_progress) {
4593 wpa_printf(MSG_DEBUG,
4594 "External radio work in progress - delay start of pending item");
4595 return;
4596 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004597 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4598 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4599}
4600
4601
4602/**
4603 * radio_add_work - Add a radio work item
4604 * @wpa_s: Pointer to wpa_supplicant data
4605 * @freq: Frequency of the offchannel operation in MHz or 0
4606 * @type: Unique identifier for each type of work
4607 * @next: Force as the next work to be executed
4608 * @cb: Callback function for indicating when radio is available
4609 * @ctx: Context pointer for the work (work->ctx in cb())
4610 * Returns: 0 on success, -1 on failure
4611 *
4612 * This function is used to request time for an operation that requires
4613 * exclusive radio control. Once the radio is available, the registered callback
4614 * function will be called. radio_work_done() must be called once the exclusive
4615 * radio operation has been completed, so that the radio is freed for other
4616 * operations. The special case of deinit=1 is used to free the context data
4617 * during interface removal. That does not allow the callback function to start
4618 * the radio operation, i.e., it must free any resources allocated for the radio
4619 * work and return.
4620 *
4621 * The @freq parameter can be used to indicate a single channel on which the
4622 * offchannel operation will occur. This may allow multiple radio work
4623 * operations to be performed in parallel if they apply for the same channel.
4624 * Setting this to 0 indicates that the work item may use multiple channels or
4625 * requires exclusive control of the radio.
4626 */
4627int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4628 const char *type, int next,
4629 void (*cb)(struct wpa_radio_work *work, int deinit),
4630 void *ctx)
4631{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004632 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004633 struct wpa_radio_work *work;
4634 int was_empty;
4635
4636 work = os_zalloc(sizeof(*work));
4637 if (work == NULL)
4638 return -1;
4639 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4640 os_get_reltime(&work->time);
4641 work->freq = freq;
4642 work->type = type;
4643 work->wpa_s = wpa_s;
4644 work->cb = cb;
4645 work->ctx = ctx;
4646
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004647 if (freq)
4648 work->bands = wpas_freq_to_band(freq);
4649 else if (os_strcmp(type, "scan") == 0 ||
4650 os_strcmp(type, "p2p-scan") == 0)
4651 work->bands = wpas_get_bands(wpa_s,
4652 ((struct wpa_driver_scan_params *)
4653 ctx)->freqs);
4654 else
4655 work->bands = wpas_get_bands(wpa_s, NULL);
4656
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004657 was_empty = dl_list_empty(&wpa_s->radio->work);
4658 if (next)
4659 dl_list_add(&wpa_s->radio->work, &work->list);
4660 else
4661 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4662 if (was_empty) {
4663 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4664 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004665 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4666 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4667 wpa_dbg(wpa_s, MSG_DEBUG,
4668 "Try to schedule a radio work (num_active_works=%u)",
4669 radio->num_active_works);
4670 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004671 }
4672
4673 return 0;
4674}
4675
4676
4677/**
4678 * radio_work_done - Indicate that a radio work item has been completed
4679 * @work: Completed work
4680 *
4681 * This function is called once the callback function registered with
4682 * radio_add_work() has completed its work.
4683 */
4684void radio_work_done(struct wpa_radio_work *work)
4685{
4686 struct wpa_supplicant *wpa_s = work->wpa_s;
4687 struct os_reltime now, diff;
4688 unsigned int started = work->started;
4689
4690 os_get_reltime(&now);
4691 os_reltime_sub(&now, &work->time, &diff);
4692 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4693 work->type, work, started ? "done" : "canceled",
4694 diff.sec, diff.usec);
4695 radio_work_free(work);
4696 if (started)
4697 radio_work_check_next(wpa_s);
4698}
4699
4700
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004701struct wpa_radio_work *
4702radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004703{
4704 struct wpa_radio_work *work;
4705 struct wpa_radio *radio = wpa_s->radio;
4706
4707 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4708 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004709 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004710 }
4711
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004712 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004713}
4714
4715
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004716static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4717 struct wpa_interface *iface)
4718{
4719 const char *ifname, *driver, *rn;
4720
4721 driver = iface->driver;
4722next_driver:
4723 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4724 return -1;
4725
4726 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4727 if (wpa_s->drv_priv == NULL) {
4728 const char *pos;
4729 pos = driver ? os_strchr(driver, ',') : NULL;
4730 if (pos) {
4731 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4732 "driver interface - try next driver wrapper");
4733 driver = pos + 1;
4734 goto next_driver;
4735 }
4736 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4737 "interface");
4738 return -1;
4739 }
4740 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4741 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4742 "driver_param '%s'", wpa_s->conf->driver_param);
4743 return -1;
4744 }
4745
4746 ifname = wpa_drv_get_ifname(wpa_s);
4747 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4748 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4749 "interface name with '%s'", ifname);
4750 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4751 }
4752
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004753 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004754 if (rn && rn[0] == '\0')
4755 rn = NULL;
4756
4757 wpa_s->radio = radio_add_interface(wpa_s, rn);
4758 if (wpa_s->radio == NULL)
4759 return -1;
4760
4761 return 0;
4762}
4763
4764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004765static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4766 struct wpa_interface *iface)
4767{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004768 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004769 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004770
4771 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4772 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4773 iface->confname ? iface->confname : "N/A",
4774 iface->driver ? iface->driver : "default",
4775 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4776 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4777
4778 if (iface->confname) {
4779#ifdef CONFIG_BACKEND_FILE
4780 wpa_s->confname = os_rel2abs_path(iface->confname);
4781 if (wpa_s->confname == NULL) {
4782 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4783 "for configuration file '%s'.",
4784 iface->confname);
4785 return -1;
4786 }
4787 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4788 iface->confname, wpa_s->confname);
4789#else /* CONFIG_BACKEND_FILE */
4790 wpa_s->confname = os_strdup(iface->confname);
4791#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004792 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004793 if (wpa_s->conf == NULL) {
4794 wpa_printf(MSG_ERROR, "Failed to read or parse "
4795 "configuration '%s'.", wpa_s->confname);
4796 return -1;
4797 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004798 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4799 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004800
4801 /*
4802 * Override ctrl_interface and driver_param if set on command
4803 * line.
4804 */
4805 if (iface->ctrl_interface) {
4806 os_free(wpa_s->conf->ctrl_interface);
4807 wpa_s->conf->ctrl_interface =
4808 os_strdup(iface->ctrl_interface);
4809 }
4810
4811 if (iface->driver_param) {
4812 os_free(wpa_s->conf->driver_param);
4813 wpa_s->conf->driver_param =
4814 os_strdup(iface->driver_param);
4815 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004816
4817 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4818 os_free(wpa_s->conf->ctrl_interface);
4819 wpa_s->conf->ctrl_interface = NULL;
4820 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004821 } else
4822 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4823 iface->driver_param);
4824
4825 if (wpa_s->conf == NULL) {
4826 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4827 return -1;
4828 }
4829
4830 if (iface->ifname == NULL) {
4831 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4832 return -1;
4833 }
4834 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4835 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4836 iface->ifname);
4837 return -1;
4838 }
4839 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4840
4841 if (iface->bridge_ifname) {
4842 if (os_strlen(iface->bridge_ifname) >=
4843 sizeof(wpa_s->bridge_ifname)) {
4844 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4845 "name '%s'.", iface->bridge_ifname);
4846 return -1;
4847 }
4848 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4849 sizeof(wpa_s->bridge_ifname));
4850 }
4851
4852 /* RSNA Supplicant Key Management - INITIALIZE */
4853 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4854 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4855
4856 /* Initialize driver interface and register driver event handler before
4857 * L2 receive handler so that association events are processed before
4858 * EAPOL-Key packets if both become available for the same select()
4859 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004860 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004861 return -1;
4862
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004863 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4864 return -1;
4865
4866 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4867 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4868 NULL);
4869 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4870
4871 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4872 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4873 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4874 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4875 "dot11RSNAConfigPMKLifetime");
4876 return -1;
4877 }
4878
4879 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4880 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4881 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4882 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4883 "dot11RSNAConfigPMKReauthThreshold");
4884 return -1;
4885 }
4886
4887 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4888 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4889 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4890 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4891 "dot11RSNAConfigSATimeout");
4892 return -1;
4893 }
4894
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004895 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4896 &wpa_s->hw.num_modes,
4897 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004898 if (wpa_s->hw.modes) {
4899 u16 i;
4900
4901 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4902 if (wpa_s->hw.modes[i].vht_capab) {
4903 wpa_s->hw_capab = CAPAB_VHT;
4904 break;
4905 }
4906
4907 if (wpa_s->hw.modes[i].ht_capab &
4908 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4909 wpa_s->hw_capab = CAPAB_HT40;
4910 else if (wpa_s->hw.modes[i].ht_capab &&
4911 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4912 wpa_s->hw_capab = CAPAB_HT;
4913 }
4914 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004915
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004916 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4917 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004918 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004919 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004920 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004921 wpa_s->drv_smps_modes = capa.smps_modes;
4922 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004923 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004924 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004925 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004926 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
4927 wpa_s->max_sched_scan_plan_interval =
4928 capa.max_sched_scan_plan_interval;
4929 wpa_s->max_sched_scan_plan_iterations =
4930 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004931 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4932 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004933 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4934 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004935 wpa_s->extended_capa = capa.extended_capa;
4936 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4937 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004938 wpa_s->num_multichan_concurrent =
4939 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004940 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4941
4942 if (capa.mac_addr_rand_scan_supported)
4943 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4944 if (wpa_s->sched_scan_supported &&
4945 capa.mac_addr_rand_sched_scan_supported)
4946 wpa_s->mac_addr_rand_supported |=
4947 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004948 }
4949 if (wpa_s->max_remain_on_chan == 0)
4950 wpa_s->max_remain_on_chan = 1000;
4951
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004952 /*
4953 * Only take p2p_mgmt parameters when P2P Device is supported.
4954 * Doing it here as it determines whether l2_packet_init() will be done
4955 * during wpa_supplicant_driver_init().
4956 */
4957 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4958 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4959 else
4960 iface->p2p_mgmt = 1;
4961
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004962 if (wpa_s->num_multichan_concurrent == 0)
4963 wpa_s->num_multichan_concurrent = 1;
4964
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004965 if (wpa_supplicant_driver_init(wpa_s) < 0)
4966 return -1;
4967
4968#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004969 if ((!iface->p2p_mgmt ||
4970 !(wpa_s->drv_flags &
4971 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4972 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004973 return -1;
4974#endif /* CONFIG_TDLS */
4975
4976 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4977 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4978 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4979 return -1;
4980 }
4981
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004982#ifdef CONFIG_FST
4983 if (wpa_s->conf->fst_group_id) {
4984 struct fst_iface_cfg cfg;
4985 struct fst_wpa_obj iface_obj;
4986
4987 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4988 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4989 sizeof(cfg.group_id));
4990 cfg.priority = wpa_s->conf->fst_priority;
4991 cfg.llt = wpa_s->conf->fst_llt;
4992
4993 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4994 &iface_obj, &cfg);
4995 if (!wpa_s->fst) {
4996 wpa_msg(wpa_s, MSG_ERROR,
4997 "FST: Cannot attach iface %s to group %s",
4998 wpa_s->ifname, cfg.group_id);
4999 return -1;
5000 }
5001 }
5002#endif /* CONFIG_FST */
5003
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005004 if (wpas_wps_init(wpa_s))
5005 return -1;
5006
5007 if (wpa_supplicant_init_eapol(wpa_s) < 0)
5008 return -1;
5009 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
5010
5011 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
5012 if (wpa_s->ctrl_iface == NULL) {
5013 wpa_printf(MSG_ERROR,
5014 "Failed to initialize control interface '%s'.\n"
5015 "You may have another wpa_supplicant process "
5016 "already running or the file was\n"
5017 "left by an unclean termination of wpa_supplicant "
5018 "in which case you will need\n"
5019 "to manually remove this file before starting "
5020 "wpa_supplicant again.\n",
5021 wpa_s->conf->ctrl_interface);
5022 return -1;
5023 }
5024
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005025 wpa_s->gas = gas_query_init(wpa_s);
5026 if (wpa_s->gas == NULL) {
5027 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5028 return -1;
5029 }
5030
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005031 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005032 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5033 return -1;
5034 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005035
5036 if (wpa_bss_init(wpa_s) < 0)
5037 return -1;
5038
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005039 /*
5040 * Set Wake-on-WLAN triggers, if configured.
5041 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5042 * have effect anyway when the interface is down).
5043 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005044 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005045 return -1;
5046
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005047#ifdef CONFIG_EAP_PROXY
5048{
5049 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005050 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
5051 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005052 if (wpa_s->mnc_len > 0) {
5053 wpa_s->imsi[len] = '\0';
5054 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5055 wpa_s->imsi, wpa_s->mnc_len);
5056 } else {
5057 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5058 }
5059}
5060#endif /* CONFIG_EAP_PROXY */
5061
Dmitry Shmidt04949592012-07-19 12:16:46 -07005062 if (pcsc_reader_init(wpa_s) < 0)
5063 return -1;
5064
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005065 if (wpas_init_ext_pw(wpa_s) < 0)
5066 return -1;
5067
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005068 wpas_rrm_reset(wpa_s);
5069
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005070 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5071
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005072#ifdef CONFIG_HS20
5073 hs20_init(wpa_s);
5074#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005075#ifdef CONFIG_MBO
5076 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5077#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005078
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005079 wpa_supplicant_set_default_scan_ies(wpa_s);
5080
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005081 return 0;
5082}
5083
5084
5085static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005086 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005087{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005088 struct wpa_global *global = wpa_s->global;
5089 struct wpa_supplicant *iface, *prev;
5090
5091 if (wpa_s == wpa_s->parent)
5092 wpas_p2p_group_remove(wpa_s, "*");
5093
5094 iface = global->ifaces;
5095 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005096 if (iface->p2pdev == wpa_s)
5097 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005098 if (iface == wpa_s || iface->parent != wpa_s) {
5099 iface = iface->next;
5100 continue;
5101 }
5102 wpa_printf(MSG_DEBUG,
5103 "Remove remaining child interface %s from parent %s",
5104 iface->ifname, wpa_s->ifname);
5105 prev = iface;
5106 iface = iface->next;
5107 wpa_supplicant_remove_iface(global, prev, terminate);
5108 }
5109
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005110 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005111 if (wpa_s->drv_priv) {
5112 wpa_supplicant_deauthenticate(wpa_s,
5113 WLAN_REASON_DEAUTH_LEAVING);
5114
5115 wpa_drv_set_countermeasures(wpa_s, 0);
5116 wpa_clear_keys(wpa_s, NULL);
5117 }
5118
5119 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005120 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005121
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005122 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005123 radio_remove_interface(wpa_s);
5124
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005125#ifdef CONFIG_FST
5126 if (wpa_s->fst) {
5127 fst_detach(wpa_s->fst);
5128 wpa_s->fst = NULL;
5129 }
5130 if (wpa_s->received_mb_ies) {
5131 wpabuf_free(wpa_s->received_mb_ies);
5132 wpa_s->received_mb_ies = NULL;
5133 }
5134#endif /* CONFIG_FST */
5135
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005136 if (wpa_s->drv_priv)
5137 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005138
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005139 if (notify)
5140 wpas_notify_iface_removed(wpa_s);
5141
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005142 if (terminate)
5143 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005144
5145 if (wpa_s->ctrl_iface) {
5146 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5147 wpa_s->ctrl_iface = NULL;
5148 }
5149
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005150#ifdef CONFIG_MESH
5151 if (wpa_s->ifmsh) {
5152 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5153 wpa_s->ifmsh = NULL;
5154 }
5155#endif /* CONFIG_MESH */
5156
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005157 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005158 wpa_config_free(wpa_s->conf);
5159 wpa_s->conf = NULL;
5160 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005161
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005162 os_free(wpa_s->ssids_from_scan_req);
5163
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005164 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005165}
5166
5167
Dmitry Shmidte4663042016-04-04 10:07:49 -07005168#ifdef CONFIG_MATCH_IFACE
5169
5170/**
5171 * wpa_supplicant_match_iface - Match an interface description to a name
5172 * @global: Pointer to global data from wpa_supplicant_init()
5173 * @ifname: Name of the interface to match
5174 * Returns: Pointer to the created interface description or %NULL on failure
5175 */
5176struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5177 const char *ifname)
5178{
5179 int i;
5180 struct wpa_interface *iface, *miface;
5181
5182 for (i = 0; i < global->params.match_iface_count; i++) {
5183 miface = &global->params.match_ifaces[i];
5184 if (!miface->ifname ||
5185 fnmatch(miface->ifname, ifname, 0) == 0) {
5186 iface = os_zalloc(sizeof(*iface));
5187 if (!iface)
5188 return NULL;
5189 *iface = *miface;
5190 iface->ifname = ifname;
5191 return iface;
5192 }
5193 }
5194
5195 return NULL;
5196}
5197
5198
5199/**
5200 * wpa_supplicant_match_existing - Match existing interfaces
5201 * @global: Pointer to global data from wpa_supplicant_init()
5202 * Returns: 0 on success, -1 on failure
5203 */
5204static int wpa_supplicant_match_existing(struct wpa_global *global)
5205{
5206 struct if_nameindex *ifi, *ifp;
5207 struct wpa_supplicant *wpa_s;
5208 struct wpa_interface *iface;
5209
5210 ifp = if_nameindex();
5211 if (!ifp) {
5212 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5213 return -1;
5214 }
5215
5216 for (ifi = ifp; ifi->if_name; ifi++) {
5217 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5218 if (wpa_s)
5219 continue;
5220 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5221 if (iface) {
5222 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5223 os_free(iface);
5224 if (wpa_s)
5225 wpa_s->matched = 1;
5226 }
5227 }
5228
5229 if_freenameindex(ifp);
5230 return 0;
5231}
5232
5233#endif /* CONFIG_MATCH_IFACE */
5234
5235
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005236/**
5237 * wpa_supplicant_add_iface - Add a new network interface
5238 * @global: Pointer to global data from wpa_supplicant_init()
5239 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005240 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005241 * Returns: Pointer to the created interface or %NULL on failure
5242 *
5243 * This function is used to add new network interfaces for %wpa_supplicant.
5244 * This can be called before wpa_supplicant_run() to add interfaces before the
5245 * main event loop has been started. In addition, new interfaces can be added
5246 * dynamically while %wpa_supplicant is already running. This could happen,
5247 * e.g., when a hotplug network adapter is inserted.
5248 */
5249struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005250 struct wpa_interface *iface,
5251 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005252{
5253 struct wpa_supplicant *wpa_s;
5254 struct wpa_interface t_iface;
5255 struct wpa_ssid *ssid;
5256
5257 if (global == NULL || iface == NULL)
5258 return NULL;
5259
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005260 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005261 if (wpa_s == NULL)
5262 return NULL;
5263
5264 wpa_s->global = global;
5265
5266 t_iface = *iface;
5267 if (global->params.override_driver) {
5268 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5269 "('%s' -> '%s')",
5270 iface->driver, global->params.override_driver);
5271 t_iface.driver = global->params.override_driver;
5272 }
5273 if (global->params.override_ctrl_interface) {
5274 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5275 "ctrl_interface ('%s' -> '%s')",
5276 iface->ctrl_interface,
5277 global->params.override_ctrl_interface);
5278 t_iface.ctrl_interface =
5279 global->params.override_ctrl_interface;
5280 }
5281 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5282 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5283 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005284 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005285 return NULL;
5286 }
5287
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005288 if (iface->p2p_mgmt == 0) {
5289 /* Notify the control interfaces about new iface */
5290 if (wpas_notify_iface_added(wpa_s)) {
5291 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5292 return NULL;
5293 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005294
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005295 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5296 wpas_notify_network_added(wpa_s, ssid);
5297 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005298
5299 wpa_s->next = global->ifaces;
5300 global->ifaces = wpa_s;
5301
5302 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005303 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005304
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005305#ifdef CONFIG_P2P
5306 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005307 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005308 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005309 wpas_p2p_add_p2pdev_interface(
5310 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005311 wpa_printf(MSG_INFO,
5312 "P2P: Failed to enable P2P Device interface");
5313 /* Try to continue without. P2P will be disabled. */
5314 }
5315#endif /* CONFIG_P2P */
5316
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005317 return wpa_s;
5318}
5319
5320
5321/**
5322 * wpa_supplicant_remove_iface - Remove a network interface
5323 * @global: Pointer to global data from wpa_supplicant_init()
5324 * @wpa_s: Pointer to the network interface to be removed
5325 * Returns: 0 if interface was removed, -1 if interface was not found
5326 *
5327 * This function can be used to dynamically remove network interfaces from
5328 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5329 * addition, this function is used to remove all remaining interfaces when
5330 * %wpa_supplicant is terminated.
5331 */
5332int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005333 struct wpa_supplicant *wpa_s,
5334 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005335{
5336 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005337#ifdef CONFIG_MESH
5338 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5339 char *ifname = NULL;
5340#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005341
5342 /* Remove interface from the global list of interfaces */
5343 prev = global->ifaces;
5344 if (prev == wpa_s) {
5345 global->ifaces = wpa_s->next;
5346 } else {
5347 while (prev && prev->next != wpa_s)
5348 prev = prev->next;
5349 if (prev == NULL)
5350 return -1;
5351 prev->next = wpa_s->next;
5352 }
5353
5354 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5355
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005356#ifdef CONFIG_MESH
5357 if (mesh_if_created) {
5358 ifname = os_strdup(wpa_s->ifname);
5359 if (ifname == NULL) {
5360 wpa_dbg(wpa_s, MSG_ERROR,
5361 "mesh: Failed to malloc ifname");
5362 return -1;
5363 }
5364 }
5365#endif /* CONFIG_MESH */
5366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005367 if (global->p2p_group_formation == wpa_s)
5368 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005369 if (global->p2p_invite_group == wpa_s)
5370 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005371 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005372
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005373#ifdef CONFIG_MESH
5374 if (mesh_if_created) {
5375 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
5376 os_free(ifname);
5377 }
5378#endif /* CONFIG_MESH */
5379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005380 return 0;
5381}
5382
5383
5384/**
5385 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5386 * @wpa_s: Pointer to the network interface
5387 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5388 */
5389const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5390{
5391 const char *eapol_method;
5392
5393 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5394 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5395 return "NO-EAP";
5396 }
5397
5398 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5399 if (eapol_method == NULL)
5400 return "UNKNOWN-EAP";
5401
5402 return eapol_method;
5403}
5404
5405
5406/**
5407 * wpa_supplicant_get_iface - Get a new network interface
5408 * @global: Pointer to global data from wpa_supplicant_init()
5409 * @ifname: Interface name
5410 * Returns: Pointer to the interface or %NULL if not found
5411 */
5412struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5413 const char *ifname)
5414{
5415 struct wpa_supplicant *wpa_s;
5416
5417 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5418 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5419 return wpa_s;
5420 }
5421 return NULL;
5422}
5423
5424
5425#ifndef CONFIG_NO_WPA_MSG
5426static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5427{
5428 struct wpa_supplicant *wpa_s = ctx;
5429 if (wpa_s == NULL)
5430 return NULL;
5431 return wpa_s->ifname;
5432}
5433#endif /* CONFIG_NO_WPA_MSG */
5434
5435
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005436#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5437#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5438#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5439
5440/* Periodic cleanup tasks */
5441static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5442{
5443 struct wpa_global *global = eloop_ctx;
5444 struct wpa_supplicant *wpa_s;
5445
5446 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5447 wpas_periodic, global, NULL);
5448
5449#ifdef CONFIG_P2P
5450 if (global->p2p)
5451 p2p_expire_peers(global->p2p);
5452#endif /* CONFIG_P2P */
5453
5454 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5455 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5456#ifdef CONFIG_AP
5457 ap_periodic(wpa_s);
5458#endif /* CONFIG_AP */
5459 }
5460}
5461
5462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005463/**
5464 * wpa_supplicant_init - Initialize %wpa_supplicant
5465 * @params: Parameters for %wpa_supplicant
5466 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5467 *
5468 * This function is used to initialize %wpa_supplicant. After successful
5469 * initialization, the returned data pointer can be used to add and remove
5470 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5471 */
5472struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5473{
5474 struct wpa_global *global;
5475 int ret, i;
5476
5477 if (params == NULL)
5478 return NULL;
5479
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005480#ifdef CONFIG_DRIVER_NDIS
5481 {
5482 void driver_ndis_init_ops(void);
5483 driver_ndis_init_ops();
5484 }
5485#endif /* CONFIG_DRIVER_NDIS */
5486
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005487#ifndef CONFIG_NO_WPA_MSG
5488 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5489#endif /* CONFIG_NO_WPA_MSG */
5490
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005491 if (params->wpa_debug_file_path)
5492 wpa_debug_open_file(params->wpa_debug_file_path);
5493 else
5494 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005495 if (params->wpa_debug_syslog)
5496 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005497 if (params->wpa_debug_tracing) {
5498 ret = wpa_debug_open_linux_tracing();
5499 if (ret) {
5500 wpa_printf(MSG_ERROR,
5501 "Failed to enable trace logging");
5502 return NULL;
5503 }
5504 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005505
5506 ret = eap_register_methods();
5507 if (ret) {
5508 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5509 if (ret == -2)
5510 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5511 "the same EAP type.");
5512 return NULL;
5513 }
5514
5515 global = os_zalloc(sizeof(*global));
5516 if (global == NULL)
5517 return NULL;
5518 dl_list_init(&global->p2p_srv_bonjour);
5519 dl_list_init(&global->p2p_srv_upnp);
5520 global->params.daemonize = params->daemonize;
5521 global->params.wait_for_monitor = params->wait_for_monitor;
5522 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5523 if (params->pid_file)
5524 global->params.pid_file = os_strdup(params->pid_file);
5525 if (params->ctrl_interface)
5526 global->params.ctrl_interface =
5527 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005528 if (params->ctrl_interface_group)
5529 global->params.ctrl_interface_group =
5530 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005531 if (params->override_driver)
5532 global->params.override_driver =
5533 os_strdup(params->override_driver);
5534 if (params->override_ctrl_interface)
5535 global->params.override_ctrl_interface =
5536 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005537#ifdef CONFIG_MATCH_IFACE
5538 global->params.match_iface_count = params->match_iface_count;
5539 if (params->match_iface_count) {
5540 global->params.match_ifaces =
5541 os_calloc(params->match_iface_count,
5542 sizeof(struct wpa_interface));
5543 os_memcpy(global->params.match_ifaces,
5544 params->match_ifaces,
5545 params->match_iface_count *
5546 sizeof(struct wpa_interface));
5547 }
5548#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005549#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005550 if (params->conf_p2p_dev)
5551 global->params.conf_p2p_dev =
5552 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005553#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005554 wpa_debug_level = global->params.wpa_debug_level =
5555 params->wpa_debug_level;
5556 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5557 params->wpa_debug_show_keys;
5558 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5559 params->wpa_debug_timestamp;
5560
5561 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5562
5563 if (eloop_init()) {
5564 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5565 wpa_supplicant_deinit(global);
5566 return NULL;
5567 }
5568
Jouni Malinen75ecf522011-06-27 15:19:46 -07005569 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005570
5571 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5572 if (global->ctrl_iface == NULL) {
5573 wpa_supplicant_deinit(global);
5574 return NULL;
5575 }
5576
5577 if (wpas_notify_supplicant_initialized(global)) {
5578 wpa_supplicant_deinit(global);
5579 return NULL;
5580 }
5581
5582 for (i = 0; wpa_drivers[i]; i++)
5583 global->drv_count++;
5584 if (global->drv_count == 0) {
5585 wpa_printf(MSG_ERROR, "No drivers enabled");
5586 wpa_supplicant_deinit(global);
5587 return NULL;
5588 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005589 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005590 if (global->drv_priv == NULL) {
5591 wpa_supplicant_deinit(global);
5592 return NULL;
5593 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005594
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005595#ifdef CONFIG_WIFI_DISPLAY
5596 if (wifi_display_init(global) < 0) {
5597 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5598 wpa_supplicant_deinit(global);
5599 return NULL;
5600 }
5601#endif /* CONFIG_WIFI_DISPLAY */
5602
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005603 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5604 wpas_periodic, global, NULL);
5605
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005606 return global;
5607}
5608
5609
5610/**
5611 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5612 * @global: Pointer to global data from wpa_supplicant_init()
5613 * Returns: 0 after successful event loop run, -1 on failure
5614 *
5615 * This function starts the main event loop and continues running as long as
5616 * there are any remaining events. In most cases, this function is running as
5617 * long as the %wpa_supplicant process in still in use.
5618 */
5619int wpa_supplicant_run(struct wpa_global *global)
5620{
5621 struct wpa_supplicant *wpa_s;
5622
5623 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005624 (wpa_supplicant_daemon(global->params.pid_file) ||
5625 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005626 return -1;
5627
Dmitry Shmidte4663042016-04-04 10:07:49 -07005628#ifdef CONFIG_MATCH_IFACE
5629 if (wpa_supplicant_match_existing(global))
5630 return -1;
5631#endif
5632
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005633 if (global->params.wait_for_monitor) {
5634 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005635 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005636 wpa_supplicant_ctrl_iface_wait(
5637 wpa_s->ctrl_iface);
5638 }
5639
5640 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5641 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5642
5643 eloop_run();
5644
5645 return 0;
5646}
5647
5648
5649/**
5650 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5651 * @global: Pointer to global data from wpa_supplicant_init()
5652 *
5653 * This function is called to deinitialize %wpa_supplicant and to free all
5654 * allocated resources. Remaining network interfaces will also be removed.
5655 */
5656void wpa_supplicant_deinit(struct wpa_global *global)
5657{
5658 int i;
5659
5660 if (global == NULL)
5661 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005662
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005663 eloop_cancel_timeout(wpas_periodic, global, NULL);
5664
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005665#ifdef CONFIG_WIFI_DISPLAY
5666 wifi_display_deinit(global);
5667#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005668
5669 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005670 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005671
5672 if (global->ctrl_iface)
5673 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5674
5675 wpas_notify_supplicant_deinitialized(global);
5676
5677 eap_peer_unregister_methods();
5678#ifdef CONFIG_AP
5679 eap_server_unregister_methods();
5680#endif /* CONFIG_AP */
5681
5682 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5683 if (!global->drv_priv[i])
5684 continue;
5685 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5686 }
5687 os_free(global->drv_priv);
5688
5689 random_deinit();
5690
5691 eloop_destroy();
5692
5693 if (global->params.pid_file) {
5694 os_daemonize_terminate(global->params.pid_file);
5695 os_free(global->params.pid_file);
5696 }
5697 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005698 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005699 os_free(global->params.override_driver);
5700 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005701#ifdef CONFIG_MATCH_IFACE
5702 os_free(global->params.match_ifaces);
5703#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005704#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005705 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005706#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005707
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005708 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005709 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005710 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005711
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005712 os_free(global);
5713 wpa_debug_close_syslog();
5714 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005715 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005716}
5717
5718
5719void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5720{
5721 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5722 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5723 char country[3];
5724 country[0] = wpa_s->conf->country[0];
5725 country[1] = wpa_s->conf->country[1];
5726 country[2] = '\0';
5727 if (wpa_drv_set_country(wpa_s, country) < 0) {
5728 wpa_printf(MSG_ERROR, "Failed to set country code "
5729 "'%s'", country);
5730 }
5731 }
5732
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005733 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5734 wpas_init_ext_pw(wpa_s);
5735
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005736 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5737 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5738
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005739#ifdef CONFIG_WPS
5740 wpas_wps_update_config(wpa_s);
5741#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005742 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005743 wpa_s->conf->changed_parameters = 0;
5744}
5745
5746
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005747void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005748{
5749 int i;
5750
5751 for (i = 0; i < *num_freqs; i++) {
5752 if (freqs[i] == freq)
5753 return;
5754 }
5755
5756 freqs[*num_freqs] = freq;
5757 (*num_freqs)++;
5758}
5759
5760
5761static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5762{
5763 struct wpa_bss *bss, *cbss;
5764 const int max_freqs = 10;
5765 int *freqs;
5766 int num_freqs = 0;
5767
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005768 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005769 if (freqs == NULL)
5770 return NULL;
5771
5772 cbss = wpa_s->current_bss;
5773
5774 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5775 if (bss == cbss)
5776 continue;
5777 if (bss->ssid_len == cbss->ssid_len &&
5778 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5779 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5780 add_freq(freqs, &num_freqs, bss->freq);
5781 if (num_freqs == max_freqs)
5782 break;
5783 }
5784 }
5785
5786 if (num_freqs == 0) {
5787 os_free(freqs);
5788 freqs = NULL;
5789 }
5790
5791 return freqs;
5792}
5793
5794
5795void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5796{
5797 int timeout;
5798 int count;
5799 int *freqs = NULL;
5800
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005801 wpas_connect_work_done(wpa_s);
5802
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005803 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005804 * Remove possible authentication timeout since the connection failed.
5805 */
5806 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5807
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005808 /*
5809 * There is no point in blacklisting the AP if this event is
5810 * generated based on local request to disconnect.
5811 */
5812 if (wpa_s->own_disconnect_req) {
5813 wpa_s->own_disconnect_req = 0;
5814 wpa_dbg(wpa_s, MSG_DEBUG,
5815 "Ignore connection failure due to local request to disconnect");
5816 return;
5817 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005818 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005819 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5820 "indication since interface has been put into "
5821 "disconnected state");
5822 return;
5823 }
5824
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005825 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005826 * Add the failed BSSID into the blacklist and speed up next scan
5827 * attempt if there could be other APs that could accept association.
5828 * The current blacklist count indicates how many times we have tried
5829 * connecting to this AP and multiple attempts mean that other APs are
5830 * either not available or has already been tried, so that we can start
5831 * increasing the delay here to avoid constant scanning.
5832 */
5833 count = wpa_blacklist_add(wpa_s, bssid);
5834 if (count == 1 && wpa_s->current_bss) {
5835 /*
5836 * This BSS was not in the blacklist before. If there is
5837 * another BSS available for the same ESS, we should try that
5838 * next. Otherwise, we may as well try this one once more
5839 * before allowing other, likely worse, ESSes to be considered.
5840 */
5841 freqs = get_bss_freqs_in_ess(wpa_s);
5842 if (freqs) {
5843 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5844 "has been seen; try it next");
5845 wpa_blacklist_add(wpa_s, bssid);
5846 /*
5847 * On the next scan, go through only the known channels
5848 * used in this ESS based on previous scans to speed up
5849 * common load balancing use case.
5850 */
5851 os_free(wpa_s->next_scan_freqs);
5852 wpa_s->next_scan_freqs = freqs;
5853 }
5854 }
5855
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005856 /*
5857 * Add previous failure count in case the temporary blacklist was
5858 * cleared due to no other BSSes being available.
5859 */
5860 count += wpa_s->extra_blacklist_count;
5861
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005862 if (count > 3 && wpa_s->current_ssid) {
5863 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5864 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005865 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005866 }
5867
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005868 switch (count) {
5869 case 1:
5870 timeout = 100;
5871 break;
5872 case 2:
5873 timeout = 500;
5874 break;
5875 case 3:
5876 timeout = 1000;
5877 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005878 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005879 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005880 break;
5881 default:
5882 timeout = 10000;
5883 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005884 }
5885
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005886 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5887 "ms", count, timeout);
5888
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005889 /*
5890 * TODO: if more than one possible AP is available in scan results,
5891 * could try the other ones before requesting a new scan.
5892 */
5893 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5894 1000 * (timeout % 1000));
5895}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005896
5897
5898int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5899{
5900 return wpa_s->conf->ap_scan == 2 ||
5901 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5902}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005903
Dmitry Shmidt04949592012-07-19 12:16:46 -07005904
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005905#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005906int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5907 struct wpa_ssid *ssid,
5908 const char *field,
5909 const char *value)
5910{
5911#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005912 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005913
5914 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5915 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5916 (const u8 *) value, os_strlen(value));
5917
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005918 rtype = wpa_supplicant_ctrl_req_from_string(field);
5919 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
5920#else /* IEEE8021X_EAPOL */
5921 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5922 return -1;
5923#endif /* IEEE8021X_EAPOL */
5924}
5925
5926int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5927 struct wpa_ssid *ssid,
5928 enum wpa_ctrl_req_type rtype,
5929 const char *value)
5930{
5931#ifdef IEEE8021X_EAPOL
5932 struct eap_peer_config *eap = &ssid->eap;
5933
5934 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005935 case WPA_CTRL_REQ_EAP_IDENTITY:
5936 os_free(eap->identity);
5937 eap->identity = (u8 *) os_strdup(value);
5938 eap->identity_len = os_strlen(value);
5939 eap->pending_req_identity = 0;
5940 if (ssid == wpa_s->current_ssid)
5941 wpa_s->reassociate = 1;
5942 break;
5943 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005944 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005945 eap->password = (u8 *) os_strdup(value);
5946 eap->password_len = os_strlen(value);
5947 eap->pending_req_password = 0;
5948 if (ssid == wpa_s->current_ssid)
5949 wpa_s->reassociate = 1;
5950 break;
5951 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005952 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005953 eap->new_password = (u8 *) os_strdup(value);
5954 eap->new_password_len = os_strlen(value);
5955 eap->pending_req_new_password = 0;
5956 if (ssid == wpa_s->current_ssid)
5957 wpa_s->reassociate = 1;
5958 break;
5959 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005960 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005961 eap->pin = os_strdup(value);
5962 eap->pending_req_pin = 0;
5963 if (ssid == wpa_s->current_ssid)
5964 wpa_s->reassociate = 1;
5965 break;
5966 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005967 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005968 eap->otp = (u8 *) os_strdup(value);
5969 eap->otp_len = os_strlen(value);
5970 os_free(eap->pending_req_otp);
5971 eap->pending_req_otp = NULL;
5972 eap->pending_req_otp_len = 0;
5973 break;
5974 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005975 str_clear_free(eap->private_key_passwd);
5976 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005977 eap->pending_req_passphrase = 0;
5978 if (ssid == wpa_s->current_ssid)
5979 wpa_s->reassociate = 1;
5980 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005981 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005982 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005983 eap->external_sim_resp = os_strdup(value);
5984 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005985 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5986 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5987 return -1;
5988 ssid->mem_only_psk = 1;
5989 if (ssid->passphrase)
5990 wpa_config_update_psk(ssid);
5991 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5992 wpa_supplicant_req_scan(wpa_s, 0, 0);
5993 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005994 case WPA_CTRL_REQ_EXT_CERT_CHECK:
5995 if (eap->pending_ext_cert_check != PENDING_CHECK)
5996 return -1;
5997 if (os_strcmp(value, "good") == 0)
5998 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
5999 else if (os_strcmp(value, "bad") == 0)
6000 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
6001 else
6002 return -1;
6003 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006004 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07006005 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006006 return -1;
6007 }
6008
6009 return 0;
6010#else /* IEEE8021X_EAPOL */
6011 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6012 return -1;
6013#endif /* IEEE8021X_EAPOL */
6014}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006015#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006016
6017
6018int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6019{
6020 int i;
6021 unsigned int drv_enc;
6022
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006023 if (wpa_s->p2p_mgmt)
6024 return 1; /* no normal network profiles on p2p_mgmt interface */
6025
Dmitry Shmidt04949592012-07-19 12:16:46 -07006026 if (ssid == NULL)
6027 return 1;
6028
6029 if (ssid->disabled)
6030 return 1;
6031
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006032 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006033 drv_enc = wpa_s->drv_enc;
6034 else
6035 drv_enc = (unsigned int) -1;
6036
6037 for (i = 0; i < NUM_WEP_KEYS; i++) {
6038 size_t len = ssid->wep_key_len[i];
6039 if (len == 0)
6040 continue;
6041 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
6042 continue;
6043 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
6044 continue;
6045 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
6046 continue;
6047 return 1; /* invalid WEP key */
6048 }
6049
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006050 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006051 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
6052 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006053 return 1;
6054
Dmitry Shmidt04949592012-07-19 12:16:46 -07006055 return 0;
6056}
6057
6058
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006059int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6060{
6061#ifdef CONFIG_IEEE80211W
6062 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6063 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6064 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6065 /*
6066 * Driver does not support BIP -- ignore pmf=1 default
6067 * since the connection with PMF would fail and the
6068 * configuration does not require PMF to be enabled.
6069 */
6070 return NO_MGMT_FRAME_PROTECTION;
6071 }
6072
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006073 if (ssid &&
6074 (ssid->key_mgmt &
6075 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6076 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6077 /*
6078 * Do not use the default PMF value for non-RSN networks
6079 * since PMF is available only with RSN and pmf=2
6080 * configuration would otherwise prevent connections to
6081 * all open networks.
6082 */
6083 return NO_MGMT_FRAME_PROTECTION;
6084 }
6085
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006086 return wpa_s->conf->pmf;
6087 }
6088
6089 return ssid->ieee80211w;
6090#else /* CONFIG_IEEE80211W */
6091 return NO_MGMT_FRAME_PROTECTION;
6092#endif /* CONFIG_IEEE80211W */
6093}
6094
6095
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006096int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006097{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006098 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006099 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006100 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006101 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006102 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006103}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006104
6105
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006106void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006107{
6108 struct wpa_ssid *ssid = wpa_s->current_ssid;
6109 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006110 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006111
6112 if (ssid == NULL) {
6113 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6114 "SSID block");
6115 return;
6116 }
6117
6118 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6119 return;
6120
6121 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006122
6123#ifdef CONFIG_P2P
6124 if (ssid->p2p_group &&
6125 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6126 /*
6127 * Skip the wait time since there is a short timeout on the
6128 * connection to a P2P group.
6129 */
6130 return;
6131 }
6132#endif /* CONFIG_P2P */
6133
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006134 if (ssid->auth_failures > 50)
6135 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006136 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006137 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006138 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006139 dur = 90;
6140 else if (ssid->auth_failures > 3)
6141 dur = 60;
6142 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006143 dur = 30;
6144 else if (ssid->auth_failures > 1)
6145 dur = 20;
6146 else
6147 dur = 10;
6148
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006149 if (ssid->auth_failures > 1 &&
6150 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6151 dur += os_random() % (ssid->auth_failures * 10);
6152
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006153 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006154 if (now.sec + dur <= ssid->disabled_until.sec)
6155 return;
6156
6157 ssid->disabled_until.sec = now.sec + dur;
6158
6159 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006160 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006161 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006162 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006163}
6164
6165
6166void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6167 struct wpa_ssid *ssid, int clear_failures)
6168{
6169 if (ssid == NULL)
6170 return;
6171
6172 if (ssid->disabled_until.sec) {
6173 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6174 "id=%d ssid=\"%s\"",
6175 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6176 }
6177 ssid->disabled_until.sec = 0;
6178 ssid->disabled_until.usec = 0;
6179 if (clear_failures)
6180 ssid->auth_failures = 0;
6181}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006182
6183
6184int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6185{
6186 size_t i;
6187
6188 if (wpa_s->disallow_aps_bssid == NULL)
6189 return 0;
6190
6191 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6192 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6193 bssid, ETH_ALEN) == 0)
6194 return 1;
6195 }
6196
6197 return 0;
6198}
6199
6200
6201int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6202 size_t ssid_len)
6203{
6204 size_t i;
6205
6206 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6207 return 0;
6208
6209 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6210 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6211 if (ssid_len == s->ssid_len &&
6212 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6213 return 1;
6214 }
6215
6216 return 0;
6217}
6218
6219
6220/**
6221 * wpas_request_connection - Request a new connection
6222 * @wpa_s: Pointer to the network interface
6223 *
6224 * This function is used to request a new connection to be found. It will mark
6225 * the interface to allow reassociation and request a new scan to find a
6226 * suitable network to connect to.
6227 */
6228void wpas_request_connection(struct wpa_supplicant *wpa_s)
6229{
6230 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006231 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006232 wpa_supplicant_reinit_autoscan(wpa_s);
6233 wpa_s->extra_blacklist_count = 0;
6234 wpa_s->disconnected = 0;
6235 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006236
6237 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6238 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006239 else
6240 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006241}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006242
Roshan Pius02242d72016-08-09 15:31:48 -07006243/**
6244 * wpas_request_disconnection - Request disconnection
6245 * @wpa_s: Pointer to the network interface
6246 *
6247 * This function is used to request disconnection from the currently connected
6248 * network. This will stop any ongoing scans and initiate deauthentication.
6249 */
6250void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6251{
6252#ifdef CONFIG_SME
6253 wpa_s->sme.prev_bssid_set = 0;
6254#endif /* CONFIG_SME */
6255 wpa_s->reassociate = 0;
6256 wpa_s->disconnected = 1;
6257 wpa_supplicant_cancel_sched_scan(wpa_s);
6258 wpa_supplicant_cancel_scan(wpa_s);
6259 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6260 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6261}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006262
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006263/**
6264 * wpas_request_disconnection - Request disconnection
6265 * @wpa_s: Pointer to the network interface
6266 *
6267 * This function is used to request disconnection from the currently connected
6268 * network. This will stop any ongoing scans and initiate deauthentication.
6269 */
6270void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6271{
6272#ifdef CONFIG_SME
6273 wpa_s->sme.prev_bssid_set = 0;
6274#endif /* CONFIG_SME */
6275 wpa_s->reassociate = 0;
6276 wpa_s->disconnected = 1;
6277 wpa_supplicant_cancel_sched_scan(wpa_s);
6278 wpa_supplicant_cancel_scan(wpa_s);
6279 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6280 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6281}
6282
6283
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006284void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6285 struct wpa_used_freq_data *freqs_data,
6286 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006287{
6288 unsigned int i;
6289
6290 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6291 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006292 for (i = 0; i < len; i++) {
6293 struct wpa_used_freq_data *cur = &freqs_data[i];
6294 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6295 i, cur->freq, cur->flags);
6296 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006297}
6298
6299
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006300/*
6301 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006302 * are using the same radio as the current interface, and in addition, get
6303 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006304 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006305int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6306 struct wpa_used_freq_data *freqs_data,
6307 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006308{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006309 struct wpa_supplicant *ifs;
6310 u8 bssid[ETH_ALEN];
6311 int freq;
6312 unsigned int idx = 0, i;
6313
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006314 wpa_dbg(wpa_s, MSG_DEBUG,
6315 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006316 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006317
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006318 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6319 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006320 if (idx == len)
6321 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006322
6323 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6324 continue;
6325
6326 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006327 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6328 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006329 freq = ifs->current_ssid->frequency;
6330 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6331 freq = ifs->assoc_freq;
6332 else
6333 continue;
6334
6335 /* Hold only distinct freqs */
6336 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006337 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006338 break;
6339
6340 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006341 freqs_data[idx++].freq = freq;
6342
6343 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006344 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006345 WPA_FREQ_USED_BY_P2P_CLIENT :
6346 WPA_FREQ_USED_BY_INFRA_STATION;
6347 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006348 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006349
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006350 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006351 return idx;
6352}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006353
6354
6355/*
6356 * Find the operating frequencies of any of the virtual interfaces that
6357 * are using the same radio as the current interface.
6358 */
6359int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6360 int *freq_array, unsigned int len)
6361{
6362 struct wpa_used_freq_data *freqs_data;
6363 int num, i;
6364
6365 os_memset(freq_array, 0, sizeof(int) * len);
6366
6367 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6368 if (!freqs_data)
6369 return -1;
6370
6371 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6372 for (i = 0; i < num; i++)
6373 freq_array[i] = freqs_data[i].freq;
6374
6375 os_free(freqs_data);
6376
6377 return num;
6378}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006379
6380
6381static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
6382{
6383 struct rrm_data *rrm = data;
6384
6385 if (!rrm->notify_neighbor_rep) {
6386 wpa_printf(MSG_ERROR,
6387 "RRM: Unexpected neighbor report timeout");
6388 return;
6389 }
6390
6391 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
6392 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
6393
6394 rrm->notify_neighbor_rep = NULL;
6395 rrm->neighbor_rep_cb_ctx = NULL;
6396}
6397
6398
6399/*
6400 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
6401 * @wpa_s: Pointer to wpa_supplicant
6402 */
6403void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
6404{
6405 wpa_s->rrm.rrm_used = 0;
6406
6407 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6408 NULL);
6409 if (wpa_s->rrm.notify_neighbor_rep)
6410 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
6411 wpa_s->rrm.next_neighbor_rep_token = 1;
6412}
6413
6414
6415/*
6416 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
6417 * @wpa_s: Pointer to wpa_supplicant
6418 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
6419 * @report_len: Length of neighbor report buffer
6420 */
6421void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
6422 const u8 *report, size_t report_len)
6423{
6424 struct wpabuf *neighbor_rep;
6425
6426 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
6427 if (report_len < 1)
6428 return;
6429
6430 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
6431 wpa_printf(MSG_DEBUG,
6432 "RRM: Discarding neighbor report with token %d (expected %d)",
6433 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
6434 return;
6435 }
6436
6437 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
6438 NULL);
6439
6440 if (!wpa_s->rrm.notify_neighbor_rep) {
6441 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
6442 return;
6443 }
6444
6445 /* skipping the first byte, which is only an id (dialog token) */
6446 neighbor_rep = wpabuf_alloc(report_len - 1);
6447 if (neighbor_rep == NULL)
6448 return;
6449 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
6450 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
6451 report[0]);
6452 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
6453 neighbor_rep);
6454 wpa_s->rrm.notify_neighbor_rep = NULL;
6455 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
6456}
6457
6458
Dmitry Shmidtff787d52015-01-12 13:01:47 -08006459#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
6460/* Workaround different, undefined for Windows, error codes used here */
6461#define ENOTCONN -1
6462#define EOPNOTSUPP -1
6463#define ECANCELED -1
6464#endif
6465
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006466/* Measurement Request element + Location Subject + Maximum Age subelement */
6467#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
6468/* Measurement Request element + Location Civic Request */
6469#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
6470
6471
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006472/**
6473 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
6474 * @wpa_s: Pointer to wpa_supplicant
6475 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
6476 * is sent in the request.
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006477 * @lci: if set, neighbor request will include LCI request
6478 * @civic: if set, neighbor request will include civic location request
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006479 * @cb: Callback function to be called once the requested report arrives, or
6480 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
6481 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
6482 * the requester's responsibility to free it.
6483 * In the latter case NULL will be sent in 'neighbor_rep'.
6484 * @cb_ctx: Context value to send the callback function
6485 * Returns: 0 in case of success, negative error code otherwise
6486 *
6487 * In case there is a previous request which has not been answered yet, the
6488 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
6489 * Request must contain a callback function.
6490 */
6491int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006492 const struct wpa_ssid_value *ssid,
6493 int lci, int civic,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006494 void (*cb)(void *ctx,
6495 struct wpabuf *neighbor_rep),
6496 void *cb_ctx)
6497{
6498 struct wpabuf *buf;
6499 const u8 *rrm_ie;
6500
6501 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
6502 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
6503 return -ENOTCONN;
6504 }
6505
6506 if (!wpa_s->rrm.rrm_used) {
6507 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
6508 return -EOPNOTSUPP;
6509 }
6510
6511 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
6512 WLAN_EID_RRM_ENABLED_CAPABILITIES);
6513 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
6514 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
6515 wpa_printf(MSG_DEBUG,
6516 "RRM: No network support for Neighbor Report.");
6517 return -EOPNOTSUPP;
6518 }
6519
6520 if (!cb) {
6521 wpa_printf(MSG_DEBUG,
6522 "RRM: Neighbor Report request must provide a callback.");
6523 return -EINVAL;
6524 }
6525
6526 /* Refuse if there's a live request */
6527 if (wpa_s->rrm.notify_neighbor_rep) {
6528 wpa_printf(MSG_DEBUG,
6529 "RRM: Currently handling previous Neighbor Report.");
6530 return -EBUSY;
6531 }
6532
6533 /* 3 = action category + action code + dialog token */
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006534 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
6535 (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
6536 (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006537 if (buf == NULL) {
6538 wpa_printf(MSG_DEBUG,
6539 "RRM: Failed to allocate Neighbor Report Request");
6540 return -ENOMEM;
6541 }
6542
6543 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
6544 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
6545 wpa_s->rrm.next_neighbor_rep_token);
6546
6547 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6548 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
6549 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
6550 if (ssid) {
6551 wpabuf_put_u8(buf, WLAN_EID_SSID);
6552 wpabuf_put_u8(buf, ssid->ssid_len);
6553 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
6554 }
6555
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006556 if (lci) {
6557 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6558 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6559 wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
6560
6561 /*
6562 * Measurement token; nonzero number that is unique among the
6563 * Measurement Request elements in a particular frame.
6564 */
6565 wpabuf_put_u8(buf, 1); /* Measurement Token */
6566
6567 /*
6568 * Parallel, Enable, Request, and Report bits are 0, Duration is
6569 * reserved.
6570 */
6571 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6572 wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
6573
6574 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
6575 /* Location Subject */
6576 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6577
6578 /* Optional Subelements */
6579 /*
6580 * IEEE P802.11-REVmc/D5.0 Figure 9-170
6581 * The Maximum Age subelement is required, otherwise the AP can
6582 * send only data that was determined after receiving the
6583 * request. Setting it here to unlimited age.
6584 */
6585 wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
6586 wpabuf_put_u8(buf, 2);
6587 wpabuf_put_le16(buf, 0xffff);
6588 }
6589
6590 if (civic) {
6591 /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
6592 wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
6593 wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
6594
6595 /*
6596 * Measurement token; nonzero number that is unique among the
6597 * Measurement Request elements in a particular frame.
6598 */
6599 wpabuf_put_u8(buf, 2); /* Measurement Token */
6600
6601 /*
6602 * Parallel, Enable, Request, and Report bits are 0, Duration is
6603 * reserved.
6604 */
6605 wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
6606 /* Measurement Type */
6607 wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
6608
6609 /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
6610 * Location Civic request */
6611 /* Location Subject */
6612 wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
6613 wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
6614 /* Location Service Interval Units: Seconds */
6615 wpabuf_put_u8(buf, 0);
6616 /* Location Service Interval: 0 - Only one report is requested
6617 */
6618 wpabuf_put_le16(buf, 0);
6619 /* No optional subelements */
6620 }
6621
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006622 wpa_s->rrm.next_neighbor_rep_token++;
6623
6624 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
6625 wpa_s->own_addr, wpa_s->bssid,
6626 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
6627 wpa_printf(MSG_DEBUG,
6628 "RRM: Failed to send Neighbor Report Request");
6629 wpabuf_free(buf);
6630 return -ECANCELED;
6631 }
6632
6633 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
6634 wpa_s->rrm.notify_neighbor_rep = cb;
6635 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
6636 wpas_rrm_neighbor_rep_timeout_handler,
6637 &wpa_s->rrm, NULL);
6638
6639 wpabuf_free(buf);
6640 return 0;
6641}
6642
6643
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006644static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
6645 const u8 *request, size_t len,
6646 struct wpabuf *report)
6647{
6648 u8 token, type, subject;
6649 u16 max_age = 0;
6650 struct os_reltime t, diff;
6651 unsigned long diff_l;
6652 u8 *ptoken;
6653 const u8 *subelem;
6654
6655 if (!wpa_s->lci || len < 3 + 4)
6656 return report;
6657
6658 token = *request++;
6659 /* Measurement request mode isn't used */
6660 request++;
6661 type = *request++;
6662 subject = *request++;
6663
6664 wpa_printf(MSG_DEBUG,
6665 "Measurement request token %u type %u location subject %u",
6666 token, type, subject);
6667
6668 if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
6669 wpa_printf(MSG_INFO,
6670 "Not building LCI report - bad type or location subject");
6671 return report;
6672 }
6673
6674 /* Subelements are formatted exactly like elements */
6675 subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
6676 if (subelem && subelem[1] == 2)
6677 max_age = WPA_GET_LE16(subelem + 2);
6678
6679 if (os_get_reltime(&t))
6680 return report;
6681
6682 os_reltime_sub(&t, &wpa_s->lci_time, &diff);
6683 /* LCI age is calculated in 10th of a second units. */
6684 diff_l = diff.sec * 10 + diff.usec / 100000;
6685
6686 if (max_age != 0xffff && max_age < diff_l)
6687 return report;
6688
6689 if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
6690 return report;
6691
6692 wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
6693 wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
6694 /* We'll override user's measurement token */
6695 ptoken = wpabuf_put(report, 0);
6696 wpabuf_put_buf(report, wpa_s->lci);
6697 *ptoken = token;
6698
6699 return report;
6700}
6701
6702
6703void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
6704 const u8 *src,
6705 const u8 *frame, size_t len)
6706{
6707 struct wpabuf *buf, *report;
6708 u8 token;
6709 const u8 *ie, *end;
6710
6711 if (wpa_s->wpa_state != WPA_COMPLETED) {
6712 wpa_printf(MSG_INFO,
6713 "RRM: Ignoring radio measurement request: Not associated");
6714 return;
6715 }
6716
6717 if (!wpa_s->rrm.rrm_used) {
6718 wpa_printf(MSG_INFO,
6719 "RRM: Ignoring radio measurement request: Not RRM network");
6720 return;
6721 }
6722
6723 if (len < 3) {
6724 wpa_printf(MSG_INFO,
6725 "RRM: Ignoring too short radio measurement request");
6726 return;
6727 }
6728
6729 end = frame + len;
6730
6731 token = *frame++;
6732
6733 /* Ignore number of repetitions because it's not used in LCI request */
6734 frame += 2;
6735
6736 report = NULL;
6737 while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
6738 ie[1] >= 3) {
6739 u8 msmt_type;
6740
6741 msmt_type = ie[4];
6742 wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
6743
6744 switch (msmt_type) {
6745 case MEASURE_TYPE_LCI:
6746 report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
6747 report);
6748 break;
6749 default:
6750 wpa_printf(MSG_INFO,
6751 "RRM: Unsupported radio measurement request %d",
6752 msmt_type);
6753 break;
6754 }
6755
6756 frame = ie + ie[1] + 2;
6757 }
6758
6759 if (!report)
6760 return;
6761
6762 buf = wpabuf_alloc(3 + wpabuf_len(report));
6763 if (!buf) {
6764 wpabuf_free(report);
6765 return;
6766 }
6767
6768 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6769 wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
6770 wpabuf_put_u8(buf, token);
6771
6772 wpabuf_put_buf(buf, report);
6773 wpabuf_free(report);
6774
6775 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6776 wpa_s->own_addr, wpa_s->bssid,
6777 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6778 wpa_printf(MSG_ERROR,
6779 "RRM: Radio measurement report failed: Sending Action frame failed");
6780 }
6781 wpabuf_free(buf);
6782}
6783
6784
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006785void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
6786 const u8 *src,
6787 const u8 *frame, size_t len,
6788 int rssi)
6789{
6790 struct wpabuf *buf;
6791 const struct rrm_link_measurement_request *req;
6792 struct rrm_link_measurement_report report;
6793
6794 if (wpa_s->wpa_state != WPA_COMPLETED) {
6795 wpa_printf(MSG_INFO,
6796 "RRM: Ignoring link measurement request. Not associated");
6797 return;
6798 }
6799
6800 if (!wpa_s->rrm.rrm_used) {
6801 wpa_printf(MSG_INFO,
6802 "RRM: Ignoring link measurement request. Not RRM network");
6803 return;
6804 }
6805
6806 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
6807 wpa_printf(MSG_INFO,
6808 "RRM: Measurement report failed. TX power insertion not supported");
6809 return;
6810 }
6811
6812 req = (const struct rrm_link_measurement_request *) frame;
6813 if (len < sizeof(*req)) {
6814 wpa_printf(MSG_INFO,
6815 "RRM: Link measurement report failed. Request too short");
6816 return;
6817 }
6818
6819 os_memset(&report, 0, sizeof(report));
6820 report.tpc.eid = WLAN_EID_TPC_REPORT;
6821 report.tpc.len = 2;
6822 report.rsni = 255; /* 255 indicates that RSNI is not available */
6823 report.dialog_token = req->dialog_token;
6824
6825 /*
6826 * It's possible to estimate RCPI based on RSSI in dBm. This
6827 * calculation will not reflect the correct value for high rates,
6828 * but it's good enough for Action frames which are transmitted
6829 * with up to 24 Mbps rates.
6830 */
6831 if (!rssi)
6832 report.rcpi = 255; /* not available */
6833 else if (rssi < -110)
6834 report.rcpi = 0;
6835 else if (rssi > 0)
6836 report.rcpi = 220;
6837 else
6838 report.rcpi = (rssi + 110) * 2;
6839
6840 /* action_category + action_code */
6841 buf = wpabuf_alloc(2 + sizeof(report));
6842 if (buf == NULL) {
6843 wpa_printf(MSG_ERROR,
6844 "RRM: Link measurement report failed. Buffer allocation failed");
6845 return;
6846 }
6847
6848 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6849 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
6850 wpabuf_put_data(buf, &report, sizeof(report));
6851 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
6852 wpabuf_head(buf), wpabuf_len(buf));
6853
6854 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6855 wpa_s->own_addr, wpa_s->bssid,
6856 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6857 wpa_printf(MSG_ERROR,
6858 "RRM: Link measurement report failed. Send action failed");
6859 }
6860 wpabuf_free(buf);
6861}
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006862
6863
6864struct wpa_supplicant *
6865wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6866{
6867 switch (frame) {
6868#ifdef CONFIG_P2P
6869 case VENDOR_ELEM_PROBE_REQ_P2P:
6870 case VENDOR_ELEM_PROBE_RESP_P2P:
6871 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6872 case VENDOR_ELEM_BEACON_P2P_GO:
6873 case VENDOR_ELEM_P2P_PD_REQ:
6874 case VENDOR_ELEM_P2P_PD_RESP:
6875 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6876 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6877 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6878 case VENDOR_ELEM_P2P_INV_REQ:
6879 case VENDOR_ELEM_P2P_INV_RESP:
6880 case VENDOR_ELEM_P2P_ASSOC_REQ:
6881 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006882 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006883#endif /* CONFIG_P2P */
6884 default:
6885 return wpa_s;
6886 }
6887}
6888
6889
6890void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6891{
6892 unsigned int i;
6893 char buf[30];
6894
6895 wpa_printf(MSG_DEBUG, "Update vendor elements");
6896
6897 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6898 if (wpa_s->vendor_elem[i]) {
6899 int res;
6900
6901 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6902 if (!os_snprintf_error(sizeof(buf), res)) {
6903 wpa_hexdump_buf(MSG_DEBUG, buf,
6904 wpa_s->vendor_elem[i]);
6905 }
6906 }
6907 }
6908
6909#ifdef CONFIG_P2P
6910 if (wpa_s->parent == wpa_s &&
6911 wpa_s->global->p2p &&
6912 !wpa_s->global->p2p_disabled)
6913 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6914#endif /* CONFIG_P2P */
6915}
6916
6917
6918int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6919 const u8 *elem, size_t len)
6920{
6921 u8 *ie, *end;
6922
6923 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6924 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6925
6926 for (; ie + 1 < end; ie += 2 + ie[1]) {
6927 if (ie + len > end)
6928 break;
6929 if (os_memcmp(ie, elem, len) != 0)
6930 continue;
6931
6932 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6933 wpabuf_free(wpa_s->vendor_elem[frame]);
6934 wpa_s->vendor_elem[frame] = NULL;
6935 } else {
6936 os_memmove(ie, ie + len, end - (ie + len));
6937 wpa_s->vendor_elem[frame]->used -= len;
6938 }
6939 wpas_vendor_elem_update(wpa_s);
6940 return 0;
6941 }
6942
6943 return -1;
6944}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006945
6946
6947struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6948 u16 num_modes, enum hostapd_hw_mode mode)
6949{
6950 u16 i;
6951
6952 for (i = 0; i < num_modes; i++) {
6953 if (modes[i].mode == mode)
6954 return &modes[i];
6955 }
6956
6957 return NULL;
6958}
6959
6960
6961static struct
6962wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6963 const u8 *bssid)
6964{
6965 struct wpa_bss_tmp_disallowed *bss;
6966
6967 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6968 struct wpa_bss_tmp_disallowed, list) {
6969 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6970 return bss;
6971 }
6972
6973 return NULL;
6974}
6975
6976
6977void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6978 unsigned int sec)
6979{
6980 struct wpa_bss_tmp_disallowed *bss;
6981 struct os_reltime until;
6982
6983 os_get_reltime(&until);
6984 until.sec += sec;
6985
6986 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6987 if (bss) {
6988 bss->disallowed_until = until;
6989 return;
6990 }
6991
6992 bss = os_malloc(sizeof(*bss));
6993 if (!bss) {
6994 wpa_printf(MSG_DEBUG,
6995 "Failed to allocate memory for temp disallow BSS");
6996 return;
6997 }
6998
6999 bss->disallowed_until = until;
7000 os_memcpy(bss->bssid, bssid, ETH_ALEN);
7001 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
7002}
7003
7004
7005int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
7006{
7007 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
7008 struct os_reltime now, age;
7009
7010 os_get_reltime(&now);
7011
7012 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
7013 struct wpa_bss_tmp_disallowed, list) {
7014 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
7015 /* This BSS is not disallowed anymore */
7016 dl_list_del(&tmp->list);
7017 os_free(tmp);
7018 continue;
7019 }
7020 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
7021 bss = tmp;
7022 break;
7023 }
7024 }
7025 if (!bss)
7026 return 0;
7027
7028 os_reltime_sub(&bss->disallowed_until, &now, &age);
7029 wpa_printf(MSG_DEBUG,
7030 "BSS " MACSTR " disabled for %ld.%0ld seconds",
7031 MAC2STR(bss->bssid), age.sec, age.usec);
7032 return 1;
7033}