blob: abb033d11d9949d30329b4bf9a163f01b747bffe [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidt29333592017-01-09 12:27:11 -08003 * Copyright (c) 2003-2017, 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 Shmidt29333592017-01-09 12:27:11 -080065"Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070066
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070067const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080068"This software may be distributed under the terms of the BSD license.\n"
69"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070#ifdef EAP_TLS_OPENSSL
71"\nThis product includes software developed by the OpenSSL Project\n"
72"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
73#endif /* EAP_TLS_OPENSSL */
74;
75
76#ifndef CONFIG_NO_STDOUT_DEBUG
77/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070078const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080079"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070080const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080081"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082"\n"
83"Redistribution and use in source and binary forms, with or without\n"
84"modification, are permitted provided that the following conditions are\n"
85"met:\n"
86"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070087const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088"1. Redistributions of source code must retain the above copyright\n"
89" notice, this list of conditions and the following disclaimer.\n"
90"\n"
91"2. Redistributions in binary form must reproduce the above copyright\n"
92" notice, this list of conditions and the following disclaimer in the\n"
93" documentation and/or other materials provided with the distribution.\n"
94"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070095const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
97" names of its contributors may be used to endorse or promote products\n"
98" derived from this software without specific prior written permission.\n"
99"\n"
100"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
101"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
102"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
103"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700104const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
106"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
107"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
108"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
109"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
110"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
111"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
112"\n";
113#endif /* CONFIG_NO_STDOUT_DEBUG */
114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700115/* Configure default/group WEP keys for static WEP */
116int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
117{
118 int i, set = 0;
119
120 for (i = 0; i < NUM_WEP_KEYS; i++) {
121 if (ssid->wep_key_len[i] == 0)
122 continue;
123
124 set = 1;
125 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
126 i, i == ssid->wep_tx_keyidx, NULL, 0,
127 ssid->wep_key[i], ssid->wep_key_len[i]);
128 }
129
130 return set;
131}
132
133
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700134int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
135 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136{
137 u8 key[32];
138 size_t keylen;
139 enum wpa_alg alg;
140 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800141 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700142
143 /* IBSS/WPA-None uses only one key (Group) for both receiving and
144 * sending unicast and multicast packets. */
145
146 if (ssid->mode != WPAS_MODE_IBSS) {
147 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
148 "IBSS/ad-hoc) for WPA-None", ssid->mode);
149 return -1;
150 }
151
152 if (!ssid->psk_set) {
153 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
154 "WPA-None");
155 return -1;
156 }
157
158 switch (wpa_s->group_cipher) {
159 case WPA_CIPHER_CCMP:
160 os_memcpy(key, ssid->psk, 16);
161 keylen = 16;
162 alg = WPA_ALG_CCMP;
163 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700164 case WPA_CIPHER_GCMP:
165 os_memcpy(key, ssid->psk, 16);
166 keylen = 16;
167 alg = WPA_ALG_GCMP;
168 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700169 case WPA_CIPHER_TKIP:
170 /* WPA-None uses the same Michael MIC key for both TX and RX */
171 os_memcpy(key, ssid->psk, 16 + 8);
172 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
173 keylen = 32;
174 alg = WPA_ALG_TKIP;
175 break;
176 default:
177 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
178 "WPA-None", wpa_s->group_cipher);
179 return -1;
180 }
181
182 /* TODO: should actually remember the previously used seq#, both for TX
183 * and RX from each STA.. */
184
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800185 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
186 os_memset(key, 0, sizeof(key));
187 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700188}
189
190
191static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
192{
193 struct wpa_supplicant *wpa_s = eloop_ctx;
194 const u8 *bssid = wpa_s->bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -0700195 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
196 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
197 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700198 bssid = wpa_s->pending_bssid;
199 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
200 MAC2STR(bssid));
201 wpa_blacklist_add(wpa_s, bssid);
202 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800203 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700204 wpa_s->reassociate = 1;
Roshan Pius38e96762017-01-23 14:52:00 -0800205 wpas_notify_auth_timeout(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700206
207 /*
208 * If we timed out, the AP or the local radio may be busy.
209 * So, wait a second until scanning again.
210 */
211 wpa_supplicant_req_scan(wpa_s, 1, 0);
212}
213
214
215/**
216 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
217 * @wpa_s: Pointer to wpa_supplicant data
218 * @sec: Number of seconds after which to time out authentication
219 * @usec: Number of microseconds after which to time out authentication
220 *
221 * This function is used to schedule a timeout for the current authentication
222 * attempt.
223 */
224void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
225 int sec, int usec)
226{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700227 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
229 return;
230
231 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
232 "%d usec", sec, usec);
233 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
234 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
235}
236
237
238/**
239 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
240 * @wpa_s: Pointer to wpa_supplicant data
241 *
242 * This function is used to cancel authentication timeout scheduled with
243 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
244 * been completed.
245 */
246void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
247{
248 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
249 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
250 wpa_blacklist_del(wpa_s, wpa_s->bssid);
251}
252
253
254/**
255 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
256 * @wpa_s: Pointer to wpa_supplicant data
257 *
258 * This function is used to configure EAPOL state machine based on the selected
259 * authentication mode.
260 */
261void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
262{
263#ifdef IEEE8021X_EAPOL
264 struct eapol_config eapol_conf;
265 struct wpa_ssid *ssid = wpa_s->current_ssid;
266
267#ifdef CONFIG_IBSS_RSN
268 if (ssid->mode == WPAS_MODE_IBSS &&
269 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
270 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
271 /*
272 * RSN IBSS authentication is per-STA and we can disable the
273 * per-BSSID EAPOL authentication.
274 */
275 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
276 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
277 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
278 return;
279 }
280#endif /* CONFIG_IBSS_RSN */
281
282 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
283 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
284
285 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
286 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
287 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
288 else
289 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
290
291 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
292 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
293 eapol_conf.accept_802_1x_keys = 1;
294 eapol_conf.required_keys = 0;
295 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
296 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
297 }
298 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
299 eapol_conf.required_keys |=
300 EAPOL_REQUIRE_KEY_BROADCAST;
301 }
302
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700303 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700304 eapol_conf.required_keys = 0;
305 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700306 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700307 eapol_conf.workaround = ssid->eap_workaround;
308 eapol_conf.eap_disabled =
309 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
310 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
311 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700312 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800313
314#ifdef CONFIG_WPS
315 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
316 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
317 if (wpa_s->current_bss) {
318 struct wpabuf *ie;
319 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
320 WPS_IE_VENDOR_TYPE);
321 if (ie) {
322 if (wps_is_20(ie))
323 eapol_conf.wps |=
324 EAPOL_PEER_IS_WPS20_AP;
325 wpabuf_free(ie);
326 }
327 }
328 }
329#endif /* CONFIG_WPS */
330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700331 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700332
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800333#ifdef CONFIG_MACSEC
334 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set)
335 ieee802_1x_create_preshared_mka(wpa_s, ssid);
336 else
337 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
338#endif /* CONFIG_MACSEC */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800339#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700340}
341
342
343/**
344 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
345 * @wpa_s: Pointer to wpa_supplicant data
346 * @ssid: Configuration data for the network
347 *
348 * This function is used to configure WPA state machine and related parameters
349 * to a mode where WPA is not enabled. This is called as part of the
350 * authentication configuration when the selected network does not use WPA.
351 */
352void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
353 struct wpa_ssid *ssid)
354{
355 int i;
356
357 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
358 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
359 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
360 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
361 else
362 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
363 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
364 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
365 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
366 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
367 wpa_s->group_cipher = WPA_CIPHER_NONE;
368 wpa_s->mgmt_group_cipher = 0;
369
370 for (i = 0; i < NUM_WEP_KEYS; i++) {
371 if (ssid->wep_key_len[i] > 5) {
372 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
373 wpa_s->group_cipher = WPA_CIPHER_WEP104;
374 break;
375 } else if (ssid->wep_key_len[i] > 0) {
376 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
377 wpa_s->group_cipher = WPA_CIPHER_WEP40;
378 break;
379 }
380 }
381
382 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
383 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
384 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
385 wpa_s->pairwise_cipher);
386 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
387#ifdef CONFIG_IEEE80211W
388 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
389 wpa_s->mgmt_group_cipher);
390#endif /* CONFIG_IEEE80211W */
391
392 pmksa_cache_clear_current(wpa_s->wpa);
393}
394
395
Dmitry Shmidt04949592012-07-19 12:16:46 -0700396void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800397{
398 int i;
399 if (wpa_s->hw.modes == NULL)
400 return;
401
402 for (i = 0; i < wpa_s->hw.num_modes; i++) {
403 os_free(wpa_s->hw.modes[i].channels);
404 os_free(wpa_s->hw.modes[i].rates);
405 }
406
407 os_free(wpa_s->hw.modes);
408 wpa_s->hw.modes = NULL;
409}
410
411
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800412static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
413{
414 struct wpa_bss_tmp_disallowed *bss, *prev;
415
416 dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
417 struct wpa_bss_tmp_disallowed, list) {
418 dl_list_del(&bss->list);
419 os_free(bss);
420 }
421}
422
423
Paul Stewart092955c2017-02-06 09:13:09 -0800424void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
425{
426 struct fils_hlp_req *req;
427
428 while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
429 list)) != NULL) {
430 dl_list_del(&req->list);
431 wpabuf_free(req->pkt);
432 os_free(req);
433 }
434}
435
436
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700437static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
438{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700439 int i;
440
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700441 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700442 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 scard_deinit(wpa_s->scard);
444 wpa_s->scard = NULL;
445 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
446 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
447 l2_packet_deinit(wpa_s->l2);
448 wpa_s->l2 = NULL;
449 if (wpa_s->l2_br) {
450 l2_packet_deinit(wpa_s->l2_br);
451 wpa_s->l2_br = NULL;
452 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800453#ifdef CONFIG_TESTING_OPTIONS
454 l2_packet_deinit(wpa_s->l2_test);
455 wpa_s->l2_test = NULL;
456#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700458 if (wpa_s->conf != NULL) {
459 struct wpa_ssid *ssid;
460 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
461 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700462 }
463
464 os_free(wpa_s->confname);
465 wpa_s->confname = NULL;
466
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700467 os_free(wpa_s->confanother);
468 wpa_s->confanother = NULL;
469
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700470 wpa_sm_set_eapol(wpa_s->wpa, NULL);
471 eapol_sm_deinit(wpa_s->eapol);
472 wpa_s->eapol = NULL;
473
474 rsn_preauth_deinit(wpa_s->wpa);
475
476#ifdef CONFIG_TDLS
477 wpa_tdls_deinit(wpa_s->wpa);
478#endif /* CONFIG_TDLS */
479
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800480 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700481 pmksa_candidate_free(wpa_s->wpa);
482 wpa_sm_deinit(wpa_s->wpa);
483 wpa_s->wpa = NULL;
484 wpa_blacklist_clear(wpa_s);
485
486 wpa_bss_deinit(wpa_s);
487
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700488 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700489 wpa_supplicant_cancel_scan(wpa_s);
490 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800491 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
492#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
493 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
494 wpa_s, NULL);
495#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700496
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700497 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
498
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700499 wpas_wps_deinit(wpa_s);
500
501 wpabuf_free(wpa_s->pending_eapol_rx);
502 wpa_s->pending_eapol_rx = NULL;
503
504#ifdef CONFIG_IBSS_RSN
505 ibss_rsn_deinit(wpa_s->ibss_rsn);
506 wpa_s->ibss_rsn = NULL;
507#endif /* CONFIG_IBSS_RSN */
508
509 sme_deinit(wpa_s);
510
511#ifdef CONFIG_AP
512 wpa_supplicant_ap_deinit(wpa_s);
513#endif /* CONFIG_AP */
514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700516
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800517#ifdef CONFIG_OFFCHANNEL
518 offchannel_deinit(wpa_s);
519#endif /* CONFIG_OFFCHANNEL */
520
521 wpa_supplicant_cancel_sched_scan(wpa_s);
522
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700523 os_free(wpa_s->next_scan_freqs);
524 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800525
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800526 os_free(wpa_s->manual_scan_freqs);
527 wpa_s->manual_scan_freqs = NULL;
528
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700529 os_free(wpa_s->manual_sched_scan_freqs);
530 wpa_s->manual_sched_scan_freqs = NULL;
531
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800532 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
533
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700534 /*
535 * Need to remove any pending gas-query radio work before the
536 * gas_query_deinit() call because gas_query::work has not yet been set
537 * for works that have not been started. gas_query_free() will be unable
538 * to cancel such pending radio works and once the pending gas-query
539 * radio work eventually gets removed, the deinit notification call to
540 * gas_query_start_cb() would result in dereferencing freed memory.
541 */
542 if (wpa_s->radio)
543 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800544 gas_query_deinit(wpa_s->gas);
545 wpa_s->gas = NULL;
546
547 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700548
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700549 ieee802_1x_dealloc_kay_sm(wpa_s);
550
Dmitry Shmidt04949592012-07-19 12:16:46 -0700551 os_free(wpa_s->bssid_filter);
552 wpa_s->bssid_filter = NULL;
553
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800554 os_free(wpa_s->disallow_aps_bssid);
555 wpa_s->disallow_aps_bssid = NULL;
556 os_free(wpa_s->disallow_aps_ssid);
557 wpa_s->disallow_aps_ssid = NULL;
558
Dmitry Shmidt04949592012-07-19 12:16:46 -0700559 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700560#ifdef CONFIG_WNM
561 wnm_deallocate_memory(wpa_s);
562#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700563
564 ext_password_deinit(wpa_s->ext_pw);
565 wpa_s->ext_pw = NULL;
566
567 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800568 wpa_s->last_gas_resp = NULL;
569 wpabuf_free(wpa_s->prev_gas_resp);
570 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700571
572 os_free(wpa_s->last_scan_res);
573 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800574
575#ifdef CONFIG_HS20
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700576 if (wpa_s->drv_priv)
577 wpa_drv_configure_frame_filters(wpa_s, 0);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700578 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800579#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700580
581 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
582 wpabuf_free(wpa_s->vendor_elem[i]);
583 wpa_s->vendor_elem[i] = NULL;
584 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800585
586 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800587
588 wpa_s->sched_scan_plans_num = 0;
589 os_free(wpa_s->sched_scan_plans);
590 wpa_s->sched_scan_plans = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800591
592#ifdef CONFIG_MBO
593 wpa_s->non_pref_chan_num = 0;
594 os_free(wpa_s->non_pref_chan);
595 wpa_s->non_pref_chan = NULL;
596#endif /* CONFIG_MBO */
597
598 free_bss_tmp_disallowed(wpa_s);
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700599
600 wpabuf_free(wpa_s->lci);
601 wpa_s->lci = NULL;
Dmitry Shmidt29333592017-01-09 12:27:11 -0800602 wpas_clear_beacon_rep_data(wpa_s);
Paul Stewart092955c2017-02-06 09:13:09 -0800603
604#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
605#ifdef CONFIG_MESH
606 {
607 struct external_pmksa_cache *entry;
608
609 while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
610 struct external_pmksa_cache,
611 list)) != NULL) {
612 dl_list_del(&entry->list);
613 os_free(entry->pmksa_cache);
614 os_free(entry);
615 }
616 }
617#endif /* CONFIG_MESH */
618#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
619
620 wpas_flush_fils_hlp_req(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700621}
622
623
624/**
625 * wpa_clear_keys - Clear keys configured for the driver
626 * @wpa_s: Pointer to wpa_supplicant data
627 * @addr: Previously used BSSID or %NULL if not available
628 *
629 * This function clears the encryption keys that has been previously configured
630 * for the driver.
631 */
632void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
633{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800634 int i, max;
635
636#ifdef CONFIG_IEEE80211W
637 max = 6;
638#else /* CONFIG_IEEE80211W */
639 max = 4;
640#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700641
642 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800643 for (i = 0; i < max; i++) {
644 if (wpa_s->keys_cleared & BIT(i))
645 continue;
646 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
647 NULL, 0);
648 }
649 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
650 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700651 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
652 0);
653 /* MLME-SETPROTECTION.request(None) */
654 wpa_drv_mlme_setprotection(
655 wpa_s, addr,
656 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
657 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
658 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800659 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700660}
661
662
663/**
664 * wpa_supplicant_state_txt - Get the connection state name as a text string
665 * @state: State (wpa_state; WPA_*)
666 * Returns: The state name as a printable text string
667 */
668const char * wpa_supplicant_state_txt(enum wpa_states state)
669{
670 switch (state) {
671 case WPA_DISCONNECTED:
672 return "DISCONNECTED";
673 case WPA_INACTIVE:
674 return "INACTIVE";
675 case WPA_INTERFACE_DISABLED:
676 return "INTERFACE_DISABLED";
677 case WPA_SCANNING:
678 return "SCANNING";
679 case WPA_AUTHENTICATING:
680 return "AUTHENTICATING";
681 case WPA_ASSOCIATING:
682 return "ASSOCIATING";
683 case WPA_ASSOCIATED:
684 return "ASSOCIATED";
685 case WPA_4WAY_HANDSHAKE:
686 return "4WAY_HANDSHAKE";
687 case WPA_GROUP_HANDSHAKE:
688 return "GROUP_HANDSHAKE";
689 case WPA_COMPLETED:
690 return "COMPLETED";
691 default:
692 return "UNKNOWN";
693 }
694}
695
696
697#ifdef CONFIG_BGSCAN
698
699static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
700{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800701 const char *name;
702
703 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
704 name = wpa_s->current_ssid->bgscan;
705 else
706 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800707 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800708 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800709 if (wpas_driver_bss_selection(wpa_s))
710 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700711 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
712 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800713#ifdef CONFIG_P2P
714 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
715 return;
716#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700717
718 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800719 if (wpa_s->current_ssid) {
720 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700721 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
722 "bgscan");
723 /*
724 * Live without bgscan; it is only used as a roaming
725 * optimization, so the initial connection is not
726 * affected.
727 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700728 } else {
729 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700731 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
732 0);
733 if (scan_res) {
734 bgscan_notify_scan(wpa_s, scan_res);
735 wpa_scan_results_free(scan_res);
736 }
737 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700738 } else
739 wpa_s->bgscan_ssid = NULL;
740}
741
742
743static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
744{
745 if (wpa_s->bgscan_ssid != NULL) {
746 bgscan_deinit(wpa_s);
747 wpa_s->bgscan_ssid = NULL;
748 }
749}
750
751#endif /* CONFIG_BGSCAN */
752
753
Dmitry Shmidt04949592012-07-19 12:16:46 -0700754static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
755{
756 if (autoscan_init(wpa_s, 0))
757 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
758}
759
760
761static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
762{
763 autoscan_deinit(wpa_s);
764}
765
766
767void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
768{
769 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
770 wpa_s->wpa_state == WPA_SCANNING) {
771 autoscan_deinit(wpa_s);
772 wpa_supplicant_start_autoscan(wpa_s);
773 }
774}
775
776
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700777/**
778 * wpa_supplicant_set_state - Set current connection state
779 * @wpa_s: Pointer to wpa_supplicant data
780 * @state: The new connection state
781 *
782 * This function is called whenever the connection state changes, e.g.,
783 * association is completed for WPA/WPA2 4-Way Handshake is started.
784 */
785void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
786 enum wpa_states state)
787{
788 enum wpa_states old_state = wpa_s->wpa_state;
789
790 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
791 wpa_supplicant_state_txt(wpa_s->wpa_state),
792 wpa_supplicant_state_txt(state));
793
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800794 if (state == WPA_INTERFACE_DISABLED) {
795 /* Assure normal scan when interface is restored */
796 wpa_s->normal_scans = 0;
797 }
798
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700799 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800800 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700801 /* Reinitialize normal_scan counter */
802 wpa_s->normal_scans = 0;
803 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800804
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700805#ifdef CONFIG_P2P
806 /*
807 * P2PS client has to reply to Probe Request frames received on the
808 * group operating channel. Enable Probe Request frame reporting for
809 * P2P connected client in case p2p_cli_probe configuration property is
810 * set to 1.
811 */
812 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
813 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
814 wpa_s->current_ssid->p2p_group) {
815 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
816 wpa_dbg(wpa_s, MSG_DEBUG,
817 "P2P: Enable CLI Probe Request RX reporting");
818 wpa_s->p2p_cli_probe =
819 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
820 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
821 wpa_dbg(wpa_s, MSG_DEBUG,
822 "P2P: Disable CLI Probe Request RX reporting");
823 wpa_s->p2p_cli_probe = 0;
824 wpa_drv_probe_req_report(wpa_s, 0);
825 }
826 }
827#endif /* CONFIG_P2P */
828
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700829 if (state != WPA_SCANNING)
830 wpa_supplicant_notify_scanning(wpa_s, 0);
831
832 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700833 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700834#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700835 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800836 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800837 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700838 ssid ? ssid->id : -1,
839 ssid && ssid->id_str ? ssid->id_str : "");
840#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700841 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700842 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800843 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700844 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700845 wpa_drv_set_operstate(wpa_s, 1);
846#ifndef IEEE8021X_EAPOL
847 wpa_drv_set_supp_port(wpa_s, 1);
848#endif /* IEEE8021X_EAPOL */
849 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700850 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700851 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700852
853 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
855 state == WPA_ASSOCIATED) {
856 wpa_s->new_connection = 1;
857 wpa_drv_set_operstate(wpa_s, 0);
858#ifndef IEEE8021X_EAPOL
859 wpa_drv_set_supp_port(wpa_s, 0);
860#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700861 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700862 }
863 wpa_s->wpa_state = state;
864
865#ifdef CONFIG_BGSCAN
866 if (state == WPA_COMPLETED)
867 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800868 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700869 wpa_supplicant_stop_bgscan(wpa_s);
870#endif /* CONFIG_BGSCAN */
871
Dmitry Shmidt04949592012-07-19 12:16:46 -0700872 if (state == WPA_AUTHENTICATING)
873 wpa_supplicant_stop_autoscan(wpa_s);
874
875 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
876 wpa_supplicant_start_autoscan(wpa_s);
877
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800878 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
879 wmm_ac_notify_disassoc(wpa_s);
880
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700881 if (wpa_s->wpa_state != old_state) {
882 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
883
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700884 /*
885 * Notify the P2P Device interface about a state change in one
886 * of the interfaces.
887 */
888 wpas_p2p_indicate_state_change(wpa_s);
889
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700890 if (wpa_s->wpa_state == WPA_COMPLETED ||
891 old_state == WPA_COMPLETED)
892 wpas_notify_auth_changed(wpa_s);
893 }
894}
895
896
897void wpa_supplicant_terminate_proc(struct wpa_global *global)
898{
899 int pending = 0;
900#ifdef CONFIG_WPS
901 struct wpa_supplicant *wpa_s = global->ifaces;
902 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800903 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700904 if (wpas_wps_terminate_pending(wpa_s) == 1)
905 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700906#ifdef CONFIG_P2P
907 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
908 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
909 wpas_p2p_disconnect(wpa_s);
910#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800911 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700912 }
913#endif /* CONFIG_WPS */
914 if (pending)
915 return;
916 eloop_terminate();
917}
918
919
920static void wpa_supplicant_terminate(int sig, void *signal_ctx)
921{
922 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700923 wpa_supplicant_terminate_proc(global);
924}
925
926
927void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
928{
929 enum wpa_states old_state = wpa_s->wpa_state;
930
931 wpa_s->pairwise_cipher = 0;
932 wpa_s->group_cipher = 0;
933 wpa_s->mgmt_group_cipher = 0;
934 wpa_s->key_mgmt = 0;
935 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700936 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700937
938 if (wpa_s->wpa_state != old_state)
939 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
940}
941
942
943/**
944 * wpa_supplicant_reload_configuration - Reload configuration data
945 * @wpa_s: Pointer to wpa_supplicant data
946 * Returns: 0 on success or -1 if configuration parsing failed
947 *
948 * This function can be used to request that the configuration data is reloaded
949 * (e.g., after configuration file change). This function is reloading
950 * configuration only for one interface, so this may need to be called multiple
951 * times if %wpa_supplicant is controlling multiple interfaces and all
952 * interfaces need reconfiguration.
953 */
954int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
955{
956 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700957 int reconf_ctrl;
958 int old_ap_scan;
959
960 if (wpa_s->confname == NULL)
961 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700962 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700963 if (conf == NULL) {
964 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
965 "file '%s' - exiting", wpa_s->confname);
966 return -1;
967 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700968 wpa_config_read(wpa_s->confanother, conf);
969
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700970 conf->changed_parameters = (unsigned int) -1;
971
972 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
973 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
974 os_strcmp(conf->ctrl_interface,
975 wpa_s->conf->ctrl_interface) != 0);
976
977 if (reconf_ctrl && wpa_s->ctrl_iface) {
978 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
979 wpa_s->ctrl_iface = NULL;
980 }
981
982 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800983 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700984 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
985 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800986 wpa_supplicant_deauthenticate(wpa_s,
987 WLAN_REASON_DEAUTH_LEAVING);
988 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989
990 /*
991 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800992 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 */
994 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
995 /*
996 * Clear forced success to clear EAP state for next
997 * authentication.
998 */
999 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1000 }
1001 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1002 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001003 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001004 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
1005 rsn_preauth_deinit(wpa_s->wpa);
1006
1007 old_ap_scan = wpa_s->conf->ap_scan;
1008 wpa_config_free(wpa_s->conf);
1009 wpa_s->conf = conf;
1010 if (old_ap_scan != wpa_s->conf->ap_scan)
1011 wpas_notify_ap_scan_changed(wpa_s);
1012
1013 if (reconf_ctrl)
1014 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
1015
1016 wpa_supplicant_update_config(wpa_s);
1017
1018 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001019 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001020 wpa_s->reassociate = 1;
1021 wpa_supplicant_req_scan(wpa_s, 0, 0);
1022 }
1023 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
1024 return 0;
1025}
1026
1027
1028static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
1029{
1030 struct wpa_global *global = signal_ctx;
1031 struct wpa_supplicant *wpa_s;
1032 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
1033 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
1034 sig);
1035 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
1036 wpa_supplicant_terminate_proc(global);
1037 }
1038 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001039
1040 if (wpa_debug_reopen_file() < 0) {
1041 /* Ignore errors since we cannot really do much to fix this */
1042 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
1043 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001044}
1045
1046
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
1048 struct wpa_ssid *ssid,
1049 struct wpa_ie_data *ie)
1050{
1051 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
1052 if (ret) {
1053 if (ret == -2) {
1054 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
1055 "from association info");
1056 }
1057 return -1;
1058 }
1059
1060 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
1061 "cipher suites");
1062 if (!(ie->group_cipher & ssid->group_cipher)) {
1063 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
1064 "cipher 0x%x (mask 0x%x) - reject",
1065 ie->group_cipher, ssid->group_cipher);
1066 return -1;
1067 }
1068 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
1069 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
1070 "cipher 0x%x (mask 0x%x) - reject",
1071 ie->pairwise_cipher, ssid->pairwise_cipher);
1072 return -1;
1073 }
1074 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1075 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1076 "management 0x%x (mask 0x%x) - reject",
1077 ie->key_mgmt, ssid->key_mgmt);
1078 return -1;
1079 }
1080
1081#ifdef CONFIG_IEEE80211W
1082 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001083 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001084 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1085 "that does not support management frame protection - "
1086 "reject");
1087 return -1;
1088 }
1089#endif /* CONFIG_IEEE80211W */
1090
1091 return 0;
1092}
1093
1094
1095/**
1096 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1097 * @wpa_s: Pointer to wpa_supplicant data
1098 * @bss: Scan results for the selected BSS, or %NULL if not available
1099 * @ssid: Configuration data for the selected network
1100 * @wpa_ie: Buffer for the WPA/RSN IE
1101 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1102 * used buffer length in case the functions returns success.
1103 * Returns: 0 on success or -1 on failure
1104 *
1105 * This function is used to configure authentication and encryption parameters
1106 * based on the network configuration and scan result for the selected BSS (if
1107 * available).
1108 */
1109int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1110 struct wpa_bss *bss, struct wpa_ssid *ssid,
1111 u8 *wpa_ie, size_t *wpa_ie_len)
1112{
1113 struct wpa_ie_data ie;
1114 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001115 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001116
1117 if (bss) {
1118 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1119 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001120 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001122 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001123
1124 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1125 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1126 (ie.group_cipher & ssid->group_cipher) &&
1127 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1128 (ie.key_mgmt & ssid->key_mgmt)) {
1129 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1130 proto = WPA_PROTO_RSN;
1131 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001132 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001133 (ie.group_cipher & ssid->group_cipher) &&
1134 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1135 (ie.key_mgmt & ssid->key_mgmt)) {
1136 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1137 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001138#ifdef CONFIG_HS20
1139 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1140 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1141 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001142 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001143 ie.group_cipher = WPA_CIPHER_CCMP;
1144 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1145 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1146 proto = WPA_PROTO_OSEN;
1147#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001148 } else if (bss) {
1149 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001150 wpa_dbg(wpa_s, MSG_DEBUG,
1151 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1152 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1153 ssid->key_mgmt);
1154 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1155 MAC2STR(bss->bssid),
1156 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1157 bss_wpa ? " WPA" : "",
1158 bss_rsn ? " RSN" : "",
1159 bss_osen ? " OSEN" : "");
1160 if (bss_rsn) {
1161 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1162 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1163 wpa_dbg(wpa_s, MSG_DEBUG,
1164 "Could not parse RSN element");
1165 } else {
1166 wpa_dbg(wpa_s, MSG_DEBUG,
1167 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1168 ie.pairwise_cipher, ie.group_cipher,
1169 ie.key_mgmt);
1170 }
1171 }
1172 if (bss_wpa) {
1173 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1174 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1175 wpa_dbg(wpa_s, MSG_DEBUG,
1176 "Could not parse WPA element");
1177 } else {
1178 wpa_dbg(wpa_s, MSG_DEBUG,
1179 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1180 ie.pairwise_cipher, ie.group_cipher,
1181 ie.key_mgmt);
1182 }
1183 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 return -1;
1185 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001186 if (ssid->proto & WPA_PROTO_OSEN)
1187 proto = WPA_PROTO_OSEN;
1188 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001189 proto = WPA_PROTO_RSN;
1190 else
1191 proto = WPA_PROTO_WPA;
1192 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1193 os_memset(&ie, 0, sizeof(ie));
1194 ie.group_cipher = ssid->group_cipher;
1195 ie.pairwise_cipher = ssid->pairwise_cipher;
1196 ie.key_mgmt = ssid->key_mgmt;
1197#ifdef CONFIG_IEEE80211W
1198 ie.mgmt_group_cipher =
1199 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1200 WPA_CIPHER_AES_128_CMAC : 0;
1201#endif /* CONFIG_IEEE80211W */
1202 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1203 "based on configuration");
1204 } else
1205 proto = ie.proto;
1206 }
1207
1208 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1209 "pairwise %d key_mgmt %d proto %d",
1210 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1211#ifdef CONFIG_IEEE80211W
1212 if (ssid->ieee80211w) {
1213 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1214 ie.mgmt_group_cipher);
1215 }
1216#endif /* CONFIG_IEEE80211W */
1217
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001218 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001219 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1220 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001221 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001222
1223 if (bss || !wpa_s->ap_ies_from_associnfo) {
1224 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1225 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1226 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1227 bss_rsn ? 2 + bss_rsn[1] : 0))
1228 return -1;
1229 }
1230
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001231#ifdef CONFIG_NO_WPA
1232 wpa_s->group_cipher = WPA_CIPHER_NONE;
1233 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1234#else /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001236 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1237 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001238 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1239 "cipher");
1240 return -1;
1241 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001242 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1243 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001244
1245 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001246 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1247 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001248 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1249 "cipher");
1250 return -1;
1251 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001252 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1253 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001254#endif /* CONFIG_NO_WPA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001255
1256 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001257#ifdef CONFIG_SAE
1258 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1259 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1260#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001261 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001262#ifdef CONFIG_SUITEB192
1263 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1264 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1265 wpa_dbg(wpa_s, MSG_DEBUG,
1266 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1267#endif /* CONFIG_SUITEB192 */
1268#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001269 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1270 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1271 wpa_dbg(wpa_s, MSG_DEBUG,
1272 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001273#endif /* CONFIG_SUITEB */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001274#ifdef CONFIG_FILS
1275#ifdef CONFIG_IEEE80211R
1276 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) {
1277 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
1278 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384");
1279 } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) {
1280 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
1281 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256");
1282#endif /* CONFIG_IEEE80211R */
1283 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
1284 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
1285 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384");
1286 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
1287 wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
1288 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256");
1289#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001290#ifdef CONFIG_IEEE80211R
1291 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1292 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1293 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1294 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1295 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1296 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1297#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001298#ifdef CONFIG_SAE
1299 } else if (sel & WPA_KEY_MGMT_SAE) {
1300 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1301 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1302 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1303 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1304 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1305#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001306#ifdef CONFIG_IEEE80211W
1307 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1308 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1309 wpa_dbg(wpa_s, MSG_DEBUG,
1310 "WPA: using KEY_MGMT 802.1X with SHA256");
1311 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1312 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1313 wpa_dbg(wpa_s, MSG_DEBUG,
1314 "WPA: using KEY_MGMT PSK with SHA256");
1315#endif /* CONFIG_IEEE80211W */
1316 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1317 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1318 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1319 } else if (sel & WPA_KEY_MGMT_PSK) {
1320 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1321 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1322 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1323 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1324 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001325#ifdef CONFIG_HS20
1326 } else if (sel & WPA_KEY_MGMT_OSEN) {
1327 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1328 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1329#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 } else {
1331 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1332 "authenticated key management type");
1333 return -1;
1334 }
1335
1336 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1337 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1338 wpa_s->pairwise_cipher);
1339 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1340
1341#ifdef CONFIG_IEEE80211W
1342 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001343 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001344 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1345 sel = 0;
1346 if (sel & WPA_CIPHER_AES_128_CMAC) {
1347 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1348 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1349 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001350 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1351 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1352 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1353 "BIP-GMAC-128");
1354 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1355 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1356 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1357 "BIP-GMAC-256");
1358 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1359 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1360 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1361 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001362 } else {
1363 wpa_s->mgmt_group_cipher = 0;
1364 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1365 }
1366 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1367 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001368 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001369 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370#endif /* CONFIG_IEEE80211W */
1371
1372 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1373 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1374 return -1;
1375 }
1376
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001377 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001378 int psk_set = 0;
1379
1380 if (ssid->psk_set) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001381 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
1382 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001383 psk_set = 1;
1384 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001385#ifndef CONFIG_NO_PBKDF2
1386 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1387 ssid->passphrase) {
1388 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001389 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1390 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001391 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1392 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001393 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001394 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001395 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001396 }
1397#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001398#ifdef CONFIG_EXT_PASSWORD
1399 if (ssid->ext_psk) {
1400 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1401 ssid->ext_psk);
1402 char pw_str[64 + 1];
1403 u8 psk[PMK_LEN];
1404
1405 if (pw == NULL) {
1406 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1407 "found from external storage");
1408 return -1;
1409 }
1410
1411 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1412 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1413 "PSK length %d in external storage",
1414 (int) wpabuf_len(pw));
1415 ext_password_free(pw);
1416 return -1;
1417 }
1418
1419 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1420 pw_str[wpabuf_len(pw)] = '\0';
1421
1422#ifndef CONFIG_NO_PBKDF2
1423 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1424 {
1425 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1426 4096, psk, PMK_LEN);
1427 os_memset(pw_str, 0, sizeof(pw_str));
1428 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1429 "external passphrase)",
1430 psk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001431 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1432 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001433 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001434 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001435 } else
1436#endif /* CONFIG_NO_PBKDF2 */
1437 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1438 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1439 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1440 "Invalid PSK hex string");
1441 os_memset(pw_str, 0, sizeof(pw_str));
1442 ext_password_free(pw);
1443 return -1;
1444 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001445 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
1446 NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001447 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001448 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001449 } else {
1450 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1451 "PSK available");
1452 os_memset(pw_str, 0, sizeof(pw_str));
1453 ext_password_free(pw);
1454 return -1;
1455 }
1456
1457 os_memset(pw_str, 0, sizeof(pw_str));
1458 ext_password_free(pw);
1459 }
1460#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001461
1462 if (!psk_set) {
1463 wpa_msg(wpa_s, MSG_INFO,
1464 "No PSK available for association");
1465 return -1;
1466 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001467 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001468 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1469
1470 return 0;
1471}
1472
1473
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001474static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1475{
1476 *pos = 0x00;
1477
1478 switch (idx) {
1479 case 0: /* Bits 0-7 */
1480 break;
1481 case 1: /* Bits 8-15 */
1482 break;
1483 case 2: /* Bits 16-23 */
1484#ifdef CONFIG_WNM
1485 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1486 *pos |= 0x08; /* Bit 19 - BSS Transition */
1487#endif /* CONFIG_WNM */
1488 break;
1489 case 3: /* Bits 24-31 */
1490#ifdef CONFIG_WNM
1491 *pos |= 0x02; /* Bit 25 - SSID List */
1492#endif /* CONFIG_WNM */
1493#ifdef CONFIG_INTERWORKING
1494 if (wpa_s->conf->interworking)
1495 *pos |= 0x80; /* Bit 31 - Interworking */
1496#endif /* CONFIG_INTERWORKING */
1497 break;
1498 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001499#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001500 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1501 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001502#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001503 break;
1504 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001505#ifdef CONFIG_HS20
1506 if (wpa_s->conf->hs20)
1507 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1508#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001509#ifdef CONFIG_MBO
1510 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1511#endif /* CONFIG_MBO */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001512 break;
1513 case 6: /* Bits 48-55 */
1514 break;
Dmitry Shmidt7d175302016-09-06 13:11:34 -07001515 case 7: /* Bits 56-63 */
1516 break;
1517 case 8: /* Bits 64-71 */
1518 if (wpa_s->conf->ftm_responder)
1519 *pos |= 0x40; /* Bit 70 - FTM responder */
1520 if (wpa_s->conf->ftm_initiator)
1521 *pos |= 0x80; /* Bit 71 - FTM initiator */
1522 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001523 case 9: /* Bits 72-79 */
1524#ifdef CONFIG_FILS
1525 *pos |= 0x01;
1526#endif /* CONFIG_FILS */
1527 break;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001528 }
1529}
1530
1531
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001532int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001533{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001534 u8 *pos = buf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001535 u8 len = 10, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001536
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001537 if (len < wpa_s->extended_capa_len)
1538 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001539 if (buflen < (size_t) len + 2) {
1540 wpa_printf(MSG_INFO,
1541 "Not enough room for building extended capabilities element");
1542 return -1;
1543 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001544
1545 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001546 *pos++ = len;
1547 for (i = 0; i < len; i++, pos++) {
1548 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001549
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001550 if (i < wpa_s->extended_capa_len) {
1551 *pos &= ~wpa_s->extended_capa_mask[i];
1552 *pos |= wpa_s->extended_capa[i];
1553 }
1554 }
1555
1556 while (len > 0 && buf[1 + len] == 0) {
1557 len--;
1558 buf[1] = len;
1559 }
1560 if (len == 0)
1561 return 0;
1562
1563 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001564}
1565
1566
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001567static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1568 struct wpa_bss *test_bss)
1569{
1570 struct wpa_bss *bss;
1571
1572 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1573 if (bss == test_bss)
1574 return 1;
1575 }
1576
1577 return 0;
1578}
1579
1580
1581static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1582 struct wpa_ssid *test_ssid)
1583{
1584 struct wpa_ssid *ssid;
1585
1586 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1587 if (ssid == test_ssid)
1588 return 1;
1589 }
1590
1591 return 0;
1592}
1593
1594
1595int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1596 struct wpa_ssid *test_ssid)
1597{
1598 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1599 return 0;
1600
1601 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1602}
1603
1604
1605void wpas_connect_work_free(struct wpa_connect_work *cwork)
1606{
1607 if (cwork == NULL)
1608 return;
1609 os_free(cwork);
1610}
1611
1612
1613void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1614{
1615 struct wpa_connect_work *cwork;
1616 struct wpa_radio_work *work = wpa_s->connect_work;
1617
1618 if (!work)
1619 return;
1620
1621 wpa_s->connect_work = NULL;
1622 cwork = work->ctx;
1623 work->ctx = NULL;
1624 wpas_connect_work_free(cwork);
1625 radio_work_done(work);
1626}
1627
1628
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001629int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1630{
1631 struct os_reltime now;
1632 u8 addr[ETH_ALEN];
1633
1634 os_get_reltime(&now);
1635 if (wpa_s->last_mac_addr_style == style &&
1636 wpa_s->last_mac_addr_change.sec != 0 &&
1637 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1638 wpa_s->conf->rand_addr_lifetime)) {
1639 wpa_msg(wpa_s, MSG_DEBUG,
1640 "Previously selected random MAC address has not yet expired");
1641 return 0;
1642 }
1643
1644 switch (style) {
1645 case 1:
1646 if (random_mac_addr(addr) < 0)
1647 return -1;
1648 break;
1649 case 2:
1650 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1651 if (random_mac_addr_keep_oui(addr) < 0)
1652 return -1;
1653 break;
1654 default:
1655 return -1;
1656 }
1657
1658 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1659 wpa_msg(wpa_s, MSG_INFO,
1660 "Failed to set random MAC address");
1661 return -1;
1662 }
1663
1664 os_get_reltime(&wpa_s->last_mac_addr_change);
1665 wpa_s->mac_addr_changed = 1;
1666 wpa_s->last_mac_addr_style = style;
1667
1668 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1669 wpa_msg(wpa_s, MSG_INFO,
1670 "Could not update MAC address information");
1671 return -1;
1672 }
1673
1674 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1675 MAC2STR(addr));
1676
1677 return 0;
1678}
1679
1680
1681int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1682{
1683 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1684 !wpa_s->conf->preassoc_mac_addr)
1685 return 0;
1686
1687 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1688}
1689
1690
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001691static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1692
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001693/**
1694 * wpa_supplicant_associate - Request association
1695 * @wpa_s: Pointer to wpa_supplicant data
1696 * @bss: Scan results for the selected BSS, or %NULL if not available
1697 * @ssid: Configuration data for the selected network
1698 *
1699 * This function is used to request %wpa_supplicant to associate with a BSS.
1700 */
1701void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1702 struct wpa_bss *bss, struct wpa_ssid *ssid)
1703{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001704 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001705 int rand_style;
1706
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001707 wpa_s->own_disconnect_req = 0;
1708
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001709 /*
1710 * If we are starting a new connection, any previously pending EAPOL
1711 * RX cannot be valid anymore.
1712 */
1713 wpabuf_free(wpa_s->pending_eapol_rx);
1714 wpa_s->pending_eapol_rx = NULL;
1715
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001716 if (ssid->mac_addr == -1)
1717 rand_style = wpa_s->conf->mac_addr;
1718 else
1719 rand_style = ssid->mac_addr;
1720
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001721 wmm_ac_clear_saved_tspecs(wpa_s);
1722 wpa_s->reassoc_same_bss = 0;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001723 wpa_s->reassoc_same_ess = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001724
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001725 if (wpa_s->last_ssid == ssid) {
1726 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidte4663042016-04-04 10:07:49 -07001727 wpa_s->reassoc_same_ess = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001728 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1729 wmm_ac_save_tspecs(wpa_s);
1730 wpa_s->reassoc_same_bss = 1;
1731 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001732 }
1733
1734 if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001735 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1736 return;
1737 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001738 } else if (rand_style == 0 && wpa_s->mac_addr_changed) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001739 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1740 wpa_msg(wpa_s, MSG_INFO,
1741 "Could not restore permanent MAC address");
1742 return;
1743 }
1744 wpa_s->mac_addr_changed = 0;
1745 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1746 wpa_msg(wpa_s, MSG_INFO,
1747 "Could not update MAC address information");
1748 return;
1749 }
1750 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1751 }
1752 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753
1754#ifdef CONFIG_IBSS_RSN
1755 ibss_rsn_deinit(wpa_s->ibss_rsn);
1756 wpa_s->ibss_rsn = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001757#else /* CONFIG_IBSS_RSN */
1758 if (ssid->mode == WPAS_MODE_IBSS &&
1759 !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) {
1760 wpa_msg(wpa_s, MSG_INFO,
1761 "IBSS RSN not supported in the build");
1762 return;
1763 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001764#endif /* CONFIG_IBSS_RSN */
1765
1766 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1767 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1768#ifdef CONFIG_AP
1769 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1770 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1771 "mode");
1772 return;
1773 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001774 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1775 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001776 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1777 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001778 return;
1779 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780 wpa_s->current_bss = bss;
1781#else /* CONFIG_AP */
1782 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1783 "the build");
1784#endif /* CONFIG_AP */
1785 return;
1786 }
1787
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001788 if (ssid->mode == WPAS_MODE_MESH) {
1789#ifdef CONFIG_MESH
1790 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1791 wpa_msg(wpa_s, MSG_INFO,
1792 "Driver does not support mesh mode");
1793 return;
1794 }
1795 if (bss)
1796 ssid->frequency = bss->freq;
1797 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1798 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1799 return;
1800 }
1801 wpa_s->current_bss = bss;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001802 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
1803 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1804 ssid->id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001805#else /* CONFIG_MESH */
1806 wpa_msg(wpa_s, MSG_ERROR,
1807 "mesh mode support not included in the build");
1808#endif /* CONFIG_MESH */
1809 return;
1810 }
1811
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001812#ifdef CONFIG_TDLS
1813 if (bss)
1814 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1815 bss->ie_len);
1816#endif /* CONFIG_TDLS */
1817
1818 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1819 ssid->mode == IEEE80211_MODE_INFRA) {
1820 sme_authenticate(wpa_s, bss, ssid);
1821 return;
1822 }
1823
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001824 if (wpa_s->connect_work) {
1825 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1826 return;
1827 }
1828
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001829 if (radio_work_pending(wpa_s, "connect")) {
1830 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1831 return;
1832 }
1833
Dmitry Shmidt29333592017-01-09 12:27:11 -08001834#ifdef CONFIG_SME
1835 if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) {
1836 /* Clear possibly set auth_alg, if any, from last attempt. */
1837 wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN;
1838 }
1839#endif /* CONFIG_SME */
1840
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001841 wpas_abort_ongoing_scan(wpa_s);
1842
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001843 cwork = os_zalloc(sizeof(*cwork));
1844 if (cwork == NULL)
1845 return;
1846
1847 cwork->bss = bss;
1848 cwork->ssid = ssid;
1849
1850 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1851 wpas_start_assoc_cb, cwork) < 0) {
1852 os_free(cwork);
1853 }
1854}
1855
1856
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001857static int bss_is_ibss(struct wpa_bss *bss)
1858{
1859 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1860 IEEE80211_CAP_IBSS;
1861}
1862
1863
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001864static int drv_supports_vht(struct wpa_supplicant *wpa_s,
1865 const struct wpa_ssid *ssid)
1866{
1867 enum hostapd_hw_mode hw_mode;
1868 struct hostapd_hw_modes *mode = NULL;
1869 u8 channel;
1870 int i;
1871
1872#ifdef CONFIG_HT_OVERRIDES
1873 if (ssid->disable_ht)
1874 return 0;
1875#endif /* CONFIG_HT_OVERRIDES */
1876
1877 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1878 if (hw_mode == NUM_HOSTAPD_MODES)
1879 return 0;
1880 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1881 if (wpa_s->hw.modes[i].mode == hw_mode) {
1882 mode = &wpa_s->hw.modes[i];
1883 break;
1884 }
1885 }
1886
1887 if (!mode)
1888 return 0;
1889
1890 return mode->vht_capab != 0;
1891}
1892
1893
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001894void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1895 const struct wpa_ssid *ssid,
1896 struct hostapd_freq_params *freq)
1897{
1898 enum hostapd_hw_mode hw_mode;
1899 struct hostapd_hw_modes *mode = NULL;
1900 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1901 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001902 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001903 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1904 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001905 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001906 unsigned int j, k;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001907 struct hostapd_freq_params vht_freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001908 int chwidth, seg0, seg1;
1909 u32 vht_caps = 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001910
1911 freq->freq = ssid->frequency;
1912
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001913 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1914 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1915
1916 if (ssid->mode != WPAS_MODE_IBSS)
1917 break;
1918
1919 /* Don't adjust control freq in case of fixed_freq */
1920 if (ssid->fixed_freq)
1921 break;
1922
1923 if (!bss_is_ibss(bss))
1924 continue;
1925
1926 if (ssid->ssid_len == bss->ssid_len &&
1927 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1928 wpa_printf(MSG_DEBUG,
1929 "IBSS already found in scan results, adjust control freq: %d",
1930 bss->freq);
1931 freq->freq = bss->freq;
1932 obss_scan = 0;
1933 break;
1934 }
1935 }
1936
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001937 /* For IBSS check HT_IBSS flag */
1938 if (ssid->mode == WPAS_MODE_IBSS &&
1939 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1940 return;
1941
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001942 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1943 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1944 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1945 wpa_printf(MSG_DEBUG,
1946 "IBSS: WEP/TKIP detected, do not try to enable HT");
1947 return;
1948 }
1949
1950 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001951 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1952 if (wpa_s->hw.modes[i].mode == hw_mode) {
1953 mode = &wpa_s->hw.modes[i];
1954 break;
1955 }
1956 }
1957
1958 if (!mode)
1959 return;
1960
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001961#ifdef CONFIG_HT_OVERRIDES
1962 if (ssid->disable_ht) {
1963 freq->ht_enabled = 0;
1964 return;
1965 }
1966#endif /* CONFIG_HT_OVERRIDES */
1967
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001968 freq->ht_enabled = ht_supported(mode);
1969 if (!freq->ht_enabled)
1970 return;
1971
1972 /* Setup higher BW only for 5 GHz */
1973 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1974 return;
1975
1976 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1977 pri_chan = &mode->channels[chan_idx];
1978 if (pri_chan->chan == channel)
1979 break;
1980 pri_chan = NULL;
1981 }
1982 if (!pri_chan)
1983 return;
1984
1985 /* Check primary channel flags */
1986 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1987 return;
1988
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07001989#ifdef CONFIG_HT_OVERRIDES
1990 if (ssid->disable_ht40)
1991 return;
1992#endif /* CONFIG_HT_OVERRIDES */
1993
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001994 /* Check/setup HT40+/HT40- */
1995 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1996 if (ht40plus[j] == channel) {
1997 ht40 = 1;
1998 break;
1999 }
2000 }
2001
2002 /* Find secondary channel */
2003 for (i = 0; i < mode->num_channels; i++) {
2004 sec_chan = &mode->channels[i];
2005 if (sec_chan->chan == channel + ht40 * 4)
2006 break;
2007 sec_chan = NULL;
2008 }
2009 if (!sec_chan)
2010 return;
2011
2012 /* Check secondary channel flags */
2013 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2014 return;
2015
2016 freq->channel = pri_chan->chan;
2017
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002018 if (ht40 == -1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002019 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
2020 return;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002021 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002022 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
2023 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002024 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002025 freq->sec_channel_offset = ht40;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002026
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002027 if (obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002028 struct wpa_scan_results *scan_res;
2029
2030 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
2031 if (scan_res == NULL) {
2032 /* Back to HT20 */
2033 freq->sec_channel_offset = 0;
2034 return;
2035 }
2036
2037 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
2038 sec_chan->chan);
2039 switch (res) {
2040 case 0:
2041 /* Back to HT20 */
2042 freq->sec_channel_offset = 0;
2043 break;
2044 case 1:
2045 /* Configuration allowed */
2046 break;
2047 case 2:
2048 /* Switch pri/sec channels */
2049 freq->freq = hw_get_freq(mode, sec_chan->chan);
2050 freq->sec_channel_offset = -freq->sec_channel_offset;
2051 freq->channel = sec_chan->chan;
2052 break;
2053 default:
2054 freq->sec_channel_offset = 0;
2055 break;
2056 }
2057
2058 wpa_scan_results_free(scan_res);
2059 }
2060
2061 wpa_printf(MSG_DEBUG,
2062 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
2063 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002064
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002065 if (!drv_supports_vht(wpa_s, ssid))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002066 return;
2067
2068 /* For IBSS check VHT_IBSS flag */
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002069 if (ssid->mode == WPAS_MODE_IBSS &&
2070 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002071 return;
2072
2073 vht_freq = *freq;
2074
Paul Stewart092955c2017-02-06 09:13:09 -08002075#ifdef CONFIG_VHT_OVERRIDES
2076 if (ssid->disable_vht) {
2077 freq->vht_enabled = 0;
2078 return;
2079 }
2080#endif /* CONFIG_VHT_OVERRIDES */
2081
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002082 vht_freq.vht_enabled = vht_supported(mode);
2083 if (!vht_freq.vht_enabled)
2084 return;
2085
2086 /* setup center_freq1, bandwidth */
2087 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
2088 if (freq->channel >= vht80[j] &&
2089 freq->channel < vht80[j] + 16)
2090 break;
2091 }
2092
2093 if (j == ARRAY_SIZE(vht80))
2094 return;
2095
2096 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
2097 struct hostapd_channel_data *chan;
2098
2099 chan = hw_get_channel_chan(mode, i, NULL);
2100 if (!chan)
2101 return;
2102
2103 /* Back to HT configuration if channel not usable */
2104 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
2105 return;
2106 }
2107
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002108 chwidth = VHT_CHANWIDTH_80MHZ;
2109 seg0 = vht80[j] + 6;
2110 seg1 = 0;
2111
2112 if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
2113 /* setup center_freq2, bandwidth */
2114 for (k = 0; k < ARRAY_SIZE(vht80); k++) {
2115 /* Only accept 80 MHz segments separated by a gap */
2116 if (j == k || abs(vht80[j] - vht80[k]) == 16)
2117 continue;
2118 for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
2119 struct hostapd_channel_data *chan;
2120
2121 chan = hw_get_channel_chan(mode, i, NULL);
2122 if (!chan)
2123 continue;
2124
2125 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2126 HOSTAPD_CHAN_NO_IR |
2127 HOSTAPD_CHAN_RADAR))
2128 continue;
2129
2130 /* Found a suitable second segment for 80+80 */
2131 chwidth = VHT_CHANWIDTH_80P80MHZ;
2132 vht_caps |=
2133 VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
2134 seg1 = vht80[k] + 6;
2135 }
2136
2137 if (chwidth == VHT_CHANWIDTH_80P80MHZ)
2138 break;
2139 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002140 } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
2141 if (freq->freq == 5180) {
2142 chwidth = VHT_CHANWIDTH_160MHZ;
2143 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2144 seg0 = 50;
2145 } else if (freq->freq == 5520) {
2146 chwidth = VHT_CHANWIDTH_160MHZ;
2147 vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
2148 seg0 = 114;
2149 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002150 }
2151
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002152 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
2153 freq->channel, freq->ht_enabled,
2154 vht_freq.vht_enabled,
2155 freq->sec_channel_offset,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002156 chwidth, seg0, seg1, vht_caps) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002157 return;
2158
2159 *freq = vht_freq;
2160
2161 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
2162 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002163}
2164
2165
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002166static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
2167{
2168 struct wpa_connect_work *cwork = work->ctx;
2169 struct wpa_bss *bss = cwork->bss;
2170 struct wpa_ssid *ssid = cwork->ssid;
2171 struct wpa_supplicant *wpa_s = work->wpa_s;
2172 u8 wpa_ie[200];
2173 size_t wpa_ie_len;
2174 int use_crypt, ret, i, bssid_changed;
2175 int algs = WPA_AUTH_ALG_OPEN;
2176 unsigned int cipher_pairwise, cipher_group;
2177 struct wpa_driver_associate_params params;
2178 int wep_keys_set = 0;
2179 int assoc_failed = 0;
2180 struct wpa_ssid *old_ssid;
Dmitry Shmidte4663042016-04-04 10:07:49 -07002181 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002182#ifdef CONFIG_HT_OVERRIDES
2183 struct ieee80211_ht_capabilities htcaps;
2184 struct ieee80211_ht_capabilities htcaps_mask;
2185#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002186#ifdef CONFIG_VHT_OVERRIDES
2187 struct ieee80211_vht_capabilities vhtcaps;
2188 struct ieee80211_vht_capabilities vhtcaps_mask;
2189#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002190
2191 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002192 if (work->started) {
2193 wpa_s->connect_work = NULL;
2194
2195 /* cancel possible auth. timeout */
2196 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
2197 NULL);
2198 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002199 wpas_connect_work_free(cwork);
2200 return;
2201 }
2202
2203 wpa_s->connect_work = work;
2204
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002205 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
2206 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002207 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
2208 wpas_connect_work_done(wpa_s);
2209 return;
2210 }
2211
Dmitry Shmidte4663042016-04-04 10:07:49 -07002212 os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002213 os_memset(&params, 0, sizeof(params));
2214 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002215 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002216 if (bss &&
2217 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002218#ifdef CONFIG_IEEE80211R
2219 const u8 *ie, *md = NULL;
2220#endif /* CONFIG_IEEE80211R */
2221 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2222 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
2223 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
2224 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2225 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2226 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2227 if (bssid_changed)
2228 wpas_notify_bssid_changed(wpa_s);
2229#ifdef CONFIG_IEEE80211R
2230 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2231 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2232 md = ie + 2;
2233 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2234 if (md) {
2235 /* Prepare for the next transition */
2236 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2237 }
2238#endif /* CONFIG_IEEE80211R */
2239#ifdef CONFIG_WPS
2240 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2241 wpa_s->conf->ap_scan == 2 &&
2242 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2243 /* Use ap_scan==1 style network selection to find the network
2244 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002245 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002246 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002247 wpa_s->reassociate = 1;
2248 wpa_supplicant_req_scan(wpa_s, 0, 0);
2249 return;
2250#endif /* CONFIG_WPS */
2251 } else {
2252 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2253 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002254 if (bss)
2255 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
2256 else
2257 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002259 if (!wpa_s->pno)
2260 wpa_supplicant_cancel_sched_scan(wpa_s);
2261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002262 wpa_supplicant_cancel_scan(wpa_s);
2263
2264 /* Starting new association, so clear the possibly used WPA IE from the
2265 * previous association. */
2266 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2267
2268#ifdef IEEE8021X_EAPOL
2269 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2270 if (ssid->leap) {
2271 if (ssid->non_leap == 0)
2272 algs = WPA_AUTH_ALG_LEAP;
2273 else
2274 algs |= WPA_AUTH_ALG_LEAP;
2275 }
2276 }
2277#endif /* IEEE8021X_EAPOL */
2278 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2279 if (ssid->auth_alg) {
2280 algs = ssid->auth_alg;
2281 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2282 "0x%x", algs);
2283 }
2284
2285 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2286 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002287 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002288 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002289 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2290 wpa_s->conf->okc :
2291 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002292 (ssid->proto & WPA_PROTO_RSN);
2293 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002294 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002295 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296 wpa_ie_len = sizeof(wpa_ie);
2297 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2298 wpa_ie, &wpa_ie_len)) {
2299 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2300 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002301 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002302 return;
2303 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002304 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2305 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2306 /*
2307 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2308 * use non-WPA since the scan results did not indicate that the
2309 * AP is using WPA or WPA2.
2310 */
2311 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2312 wpa_ie_len = 0;
2313 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002314 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002315 wpa_ie_len = sizeof(wpa_ie);
2316 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2317 wpa_ie, &wpa_ie_len)) {
2318 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2319 "key management and encryption suites (no "
2320 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002321 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002322 return;
2323 }
2324#ifdef CONFIG_WPS
2325 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2326 struct wpabuf *wps_ie;
2327 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2328 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2329 wpa_ie_len = wpabuf_len(wps_ie);
2330 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2331 } else
2332 wpa_ie_len = 0;
2333 wpabuf_free(wps_ie);
2334 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2335 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2336 params.wps = WPS_MODE_PRIVACY;
2337 else
2338 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002339 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340#endif /* CONFIG_WPS */
2341 } else {
2342 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2343 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002344 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002345 }
2346
2347#ifdef CONFIG_P2P
2348 if (wpa_s->global->p2p) {
2349 u8 *pos;
2350 size_t len;
2351 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002352 pos = wpa_ie + wpa_ie_len;
2353 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002354 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2355 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002356 if (res >= 0)
2357 wpa_ie_len += res;
2358 }
2359
2360 wpa_s->cross_connect_disallowed = 0;
2361 if (bss) {
2362 struct wpabuf *p2p;
2363 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2364 if (p2p) {
2365 wpa_s->cross_connect_disallowed =
2366 p2p_get_cross_connect_disallowed(p2p);
2367 wpabuf_free(p2p);
2368 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2369 "connection",
2370 wpa_s->cross_connect_disallowed ?
2371 "disallows" : "allows");
2372 }
2373 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002374
2375 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376#endif /* CONFIG_P2P */
2377
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002378 if (bss) {
Dmitry Shmidt29333592017-01-09 12:27:11 -08002379 wpa_ie_len += wpas_supp_op_class_ie(wpa_s, bss->freq,
2380 wpa_ie + wpa_ie_len,
2381 sizeof(wpa_ie) -
2382 wpa_ie_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002383 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002384
Dmitry Shmidt56052862013-10-04 10:23:25 -07002385 /*
2386 * Workaround: Add Extended Capabilities element only if the AP
2387 * included this element in Beacon/Probe Response frames. Some older
2388 * APs seem to have interoperability issues if this element is
2389 * included, so while the standard may require us to include the
2390 * element in all cases, it is justifiable to skip it to avoid
2391 * interoperability issues.
2392 */
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002393 if (ssid->p2p_group)
2394 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
2395 else
2396 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
2397
Dmitry Shmidt56052862013-10-04 10:23:25 -07002398 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002399 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002400 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002401 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2402 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002403 if (ext_capab_len > 0) {
2404 u8 *pos = wpa_ie;
2405 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2406 pos += 2 + pos[1];
2407 os_memmove(pos + ext_capab_len, pos,
2408 wpa_ie_len - (pos - wpa_ie));
2409 wpa_ie_len += ext_capab_len;
2410 os_memcpy(pos, ext_capab, ext_capab_len);
2411 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002412 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002413
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002414#ifdef CONFIG_HS20
2415 if (is_hs20_network(wpa_s, ssid, bss)) {
2416 struct wpabuf *hs20;
2417
2418 hs20 = wpabuf_alloc(20);
2419 if (hs20) {
2420 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
2421 size_t len;
2422
2423 wpas_hs20_add_indication(hs20, pps_mo_id);
2424 len = sizeof(wpa_ie) - wpa_ie_len;
2425 if (wpabuf_len(hs20) <= len) {
2426 os_memcpy(wpa_ie + wpa_ie_len,
2427 wpabuf_head(hs20), wpabuf_len(hs20));
2428 wpa_ie_len += wpabuf_len(hs20);
2429 }
2430 wpabuf_free(hs20);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002431
2432 hs20_configure_frame_filters(wpa_s);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002433 }
2434 }
2435#endif /* CONFIG_HS20 */
2436
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002437 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2438 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2439 size_t len;
2440
2441 len = sizeof(wpa_ie) - wpa_ie_len;
2442 if (wpabuf_len(buf) <= len) {
2443 os_memcpy(wpa_ie + wpa_ie_len,
2444 wpabuf_head(buf), wpabuf_len(buf));
2445 wpa_ie_len += wpabuf_len(buf);
2446 }
2447 }
2448
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002449#ifdef CONFIG_FST
2450 if (wpa_s->fst_ies) {
2451 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2452
2453 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2454 os_memcpy(wpa_ie + wpa_ie_len,
2455 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2456 wpa_ie_len += fst_ies_len;
2457 }
2458 }
2459#endif /* CONFIG_FST */
2460
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002461#ifdef CONFIG_MBO
Dmitry Shmidt29333592017-01-09 12:27:11 -08002462 if (bss && wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002463 int len;
2464
2465 len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
2466 sizeof(wpa_ie) - wpa_ie_len);
2467 if (len >= 0)
2468 wpa_ie_len += len;
2469 }
2470#endif /* CONFIG_MBO */
2471
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002472 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2473 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002474 cipher_pairwise = wpa_s->pairwise_cipher;
2475 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2477 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2478 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2479 use_crypt = 0;
2480 if (wpa_set_wep_keys(wpa_s, ssid)) {
2481 use_crypt = 1;
2482 wep_keys_set = 1;
2483 }
2484 }
2485 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2486 use_crypt = 0;
2487
2488#ifdef IEEE8021X_EAPOL
2489 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2490 if ((ssid->eapol_flags &
2491 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2492 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2493 !wep_keys_set) {
2494 use_crypt = 0;
2495 } else {
2496 /* Assume that dynamic WEP-104 keys will be used and
2497 * set cipher suites in order for drivers to expect
2498 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002499 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002500 }
2501 }
2502#endif /* IEEE8021X_EAPOL */
2503
2504 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2505 /* Set the key before (and later after) association */
2506 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2507 }
2508
2509 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2510 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 params.ssid = bss->ssid;
2512 params.ssid_len = bss->ssid_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002513 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set ||
2514 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002515 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2516 MACSTR " freq=%u MHz based on scan results "
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002517 "(bssid_set=%d wps=%d)",
Dmitry Shmidt04949592012-07-19 12:16:46 -07002518 MAC2STR(bss->bssid), bss->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002519 ssid->bssid_set,
2520 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002521 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002522 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002523 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002524 params.bssid_hint = bss->bssid;
2525 params.freq_hint = bss->freq;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002526 params.pbss = bss_is_pbss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 } else {
2528 params.ssid = ssid->ssid;
2529 params.ssid_len = ssid->ssid_len;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002530 params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002532
2533 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2534 wpa_s->conf->ap_scan == 2) {
2535 params.bssid = ssid->bssid;
2536 params.fixed_bssid = 1;
2537 }
2538
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002539 /* Initial frequency for IBSS/mesh */
2540 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002541 ssid->frequency > 0 && params.freq.freq == 0)
2542 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002543
2544 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002545 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002546 if (ssid->beacon_int)
2547 params.beacon_int = ssid->beacon_int;
2548 else
2549 params.beacon_int = wpa_s->conf->beacon_int;
2550 }
2551
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 params.wpa_ie = wpa_ie;
2553 params.wpa_ie_len = wpa_ie_len;
2554 params.pairwise_suite = cipher_pairwise;
2555 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002556 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002557 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 params.auth_alg = algs;
2559 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002560 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 for (i = 0; i < NUM_WEP_KEYS; i++) {
2562 if (ssid->wep_key_len[i])
2563 params.wep_key[i] = ssid->wep_key[i];
2564 params.wep_key_len[i] = ssid->wep_key_len[i];
2565 }
2566 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2567
2568 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002569 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2570 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002571 params.passphrase = ssid->passphrase;
2572 if (ssid->psk_set)
2573 params.psk = ssid->psk;
2574 }
2575
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002576 if (wpa_s->conf->key_mgmt_offload) {
2577 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2578 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002579 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2580 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002581 params.req_key_mgmt_offload =
2582 ssid->proactive_key_caching < 0 ?
2583 wpa_s->conf->okc : ssid->proactive_key_caching;
2584 else
2585 params.req_key_mgmt_offload = 1;
2586
2587 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2588 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2589 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2590 ssid->psk_set)
2591 params.psk = ssid->psk;
2592 }
2593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002594 params.drop_unencrypted = use_crypt;
2595
2596#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002597 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002598 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2600 struct wpa_ie_data ie;
2601 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2602 ie.capabilities &
2603 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2604 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2605 "MFP: require MFP");
2606 params.mgmt_frame_protection =
2607 MGMT_FRAME_PROTECTION_REQUIRED;
2608 }
2609 }
2610#endif /* CONFIG_IEEE80211W */
2611
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002612 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002613
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002614 if (wpa_s->p2pdev->set_sta_uapsd)
2615 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616 else
2617 params.uapsd = -1;
2618
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002619#ifdef CONFIG_HT_OVERRIDES
2620 os_memset(&htcaps, 0, sizeof(htcaps));
2621 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2622 params.htcaps = (u8 *) &htcaps;
2623 params.htcaps_mask = (u8 *) &htcaps_mask;
2624 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2625#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002626#ifdef CONFIG_VHT_OVERRIDES
2627 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2628 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2629 params.vhtcaps = &vhtcaps;
2630 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002631 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002632#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002633
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002634#ifdef CONFIG_P2P
2635 /*
2636 * If multi-channel concurrency is not supported, check for any
2637 * frequency conflict. In case of any frequency conflict, remove the
2638 * least prioritized connection.
2639 */
2640 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002641 int freq, num;
2642 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002643 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002644 wpa_printf(MSG_DEBUG,
2645 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002646 freq, params.freq.freq);
2647 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002648 wpa_s, params.freq.freq, ssid) < 0) {
2649 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002650 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002651 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002652 }
2653 }
2654#endif /* CONFIG_P2P */
2655
Dmitry Shmidte4663042016-04-04 10:07:49 -07002656 if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
2657 wpa_s->current_ssid)
2658 params.prev_bssid = prev_bssid;
2659
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002660 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 if (ret < 0) {
2662 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2663 "failed");
2664 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2665 /*
2666 * The driver is known to mean what is saying, so we
2667 * can stop right here; the association will not
2668 * succeed.
2669 */
2670 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002671 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2673 return;
2674 }
2675 /* try to continue anyway; new association will be tried again
2676 * after timeout */
2677 assoc_failed = 1;
2678 }
2679
2680 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2681 /* Set the key after the association just in case association
2682 * cleared the previously configured key. */
2683 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2684 /* No need to timeout authentication since there is no key
2685 * management. */
2686 wpa_supplicant_cancel_auth_timeout(wpa_s);
2687 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2688#ifdef CONFIG_IBSS_RSN
2689 } else if (ssid->mode == WPAS_MODE_IBSS &&
2690 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2691 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2692 /*
2693 * RSN IBSS authentication is per-STA and we can disable the
2694 * per-BSSID authentication.
2695 */
2696 wpa_supplicant_cancel_auth_timeout(wpa_s);
2697#endif /* CONFIG_IBSS_RSN */
2698 } else {
2699 /* Timeout for IEEE 802.11 authentication and association */
2700 int timeout = 60;
2701
2702 if (assoc_failed) {
2703 /* give IBSS a bit more time */
2704 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2705 } else if (wpa_s->conf->ap_scan == 1) {
2706 /* give IBSS a bit more time */
2707 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2708 }
2709 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2710 }
2711
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002712 if (wep_keys_set &&
2713 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 /* Set static WEP keys again */
2715 wpa_set_wep_keys(wpa_s, ssid);
2716 }
2717
2718 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2719 /*
2720 * Do not allow EAP session resumption between different
2721 * network configurations.
2722 */
2723 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2724 }
2725 old_ssid = wpa_s->current_ssid;
2726 wpa_s->current_ssid = ssid;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002727
2728 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002729 wpa_s->current_bss = bss;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002730#ifdef CONFIG_HS20
2731 hs20_configure_frame_filters(wpa_s);
2732#endif /* CONFIG_HS20 */
2733 }
2734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2736 wpa_supplicant_initiate_eapol(wpa_s);
2737 if (old_ssid != wpa_s->current_ssid)
2738 wpas_notify_network_changed(wpa_s);
2739}
2740
2741
2742static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2743 const u8 *addr)
2744{
2745 struct wpa_ssid *old_ssid;
2746
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002747 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002749 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002751 wpa_sm_set_config(wpa_s->wpa, NULL);
2752 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2753 if (old_ssid != wpa_s->current_ssid)
2754 wpas_notify_network_changed(wpa_s);
2755 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2756}
2757
2758
2759/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002760 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2761 * @wpa_s: Pointer to wpa_supplicant data
2762 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2763 *
2764 * This function is used to request %wpa_supplicant to deauthenticate from the
2765 * current AP.
2766 */
2767void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2768 int reason_code)
2769{
2770 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002771 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002772 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002773
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002774 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2775 " pending_bssid=" MACSTR " reason=%d state=%s",
2776 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2777 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2778
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002779 if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2780 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2781 wpa_s->wpa_state == WPA_ASSOCIATING))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002782 addr = wpa_s->pending_bssid;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002783 else if (!is_zero_ether_addr(wpa_s->bssid))
2784 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002785 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2786 /*
2787 * When using driver-based BSS selection, we may not know the
2788 * BSSID with which we are currently trying to associate. We
2789 * need to notify the driver of this disconnection even in such
2790 * a case, so use the all zeros address here.
2791 */
2792 addr = wpa_s->bssid;
2793 zero_addr = 1;
2794 }
2795
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002796#ifdef CONFIG_TDLS
2797 wpa_tdls_teardown_peers(wpa_s->wpa);
2798#endif /* CONFIG_TDLS */
2799
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002800#ifdef CONFIG_MESH
2801 if (wpa_s->ifmsh) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002802 wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2803 wpa_s->ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002804 wpa_supplicant_leave_mesh(wpa_s);
2805 }
2806#endif /* CONFIG_MESH */
2807
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002808 if (addr) {
2809 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002810 os_memset(&event, 0, sizeof(event));
2811 event.deauth_info.reason_code = (u16) reason_code;
2812 event.deauth_info.locally_generated = 1;
2813 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002814 if (zero_addr)
2815 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002816 }
2817
2818 wpa_supplicant_clear_connection(wpa_s, addr);
2819}
2820
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002821static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2822 struct wpa_ssid *ssid)
2823{
2824 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2825 return;
2826
2827 ssid->disabled = 0;
2828 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2829 wpas_notify_network_enabled_changed(wpa_s, ssid);
2830
2831 /*
2832 * Try to reassociate since there is no current configuration and a new
2833 * network was made available.
2834 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002835 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002836 wpa_s->reassociate = 1;
2837}
2838
Roshan Pius950bec92016-07-19 09:49:24 -07002839/**
2840 * wpa_supplicant_add_network - Add a new network.
2841 * @wpa_s: wpa_supplicant structure for a network interface
2842 * Returns: The new network configuration or %NULL if operation failed
2843 *
2844 * This function performs the following operations:
2845 * 1. Adds a new network.
2846 * 2. Send network addition notification.
2847 * 3. Marks the network disabled.
2848 * 4. Set network default parameters.
2849 */
2850struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
2851{
2852 struct wpa_ssid *ssid;
2853
2854 ssid = wpa_config_add_network(wpa_s->conf);
2855 if (!ssid) {
2856 return NULL;
2857 }
2858 wpas_notify_network_added(wpa_s, ssid);
2859 ssid->disabled = 1;
2860 wpa_config_set_network_defaults(ssid);
2861
2862 return ssid;
2863}
2864
2865/**
2866 * wpa_supplicant_remove_network - Remove a configured network based on id
2867 * @wpa_s: wpa_supplicant structure for a network interface
2868 * @id: Unique network id to search for
2869 * Returns: 0 on success, or -1 if the network was not found, -2 if the network
2870 * could not be removed
2871 *
2872 * This function performs the following operations:
2873 * 1. Removes the network.
2874 * 2. Send network removal notification.
2875 * 3. Update internal state machines.
2876 * 4. Stop any running sched scans.
2877 */
2878int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
2879{
2880 struct wpa_ssid *ssid;
2881 int was_disabled;
2882
2883 ssid = wpa_config_get_network(wpa_s->conf, id);
2884 if (ssid)
2885 wpas_notify_network_removed(wpa_s, ssid);
2886 if (ssid == NULL) {
2887 return -1;
2888 }
2889
2890 if (wpa_s->last_ssid == ssid)
2891 wpa_s->last_ssid = NULL;
2892
2893 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
2894#ifdef CONFIG_SME
2895 wpa_s->sme.prev_bssid_set = 0;
2896#endif /* CONFIG_SME */
2897 /*
2898 * Invalidate the EAP session cache if the current or
2899 * previously used network is removed.
2900 */
2901 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2902 }
2903
2904 if (ssid == wpa_s->current_ssid) {
2905 wpa_sm_set_config(wpa_s->wpa, NULL);
2906 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2907
2908 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2909 wpa_s->own_disconnect_req = 1;
2910 wpa_supplicant_deauthenticate(wpa_s,
2911 WLAN_REASON_DEAUTH_LEAVING);
2912 }
2913
2914 was_disabled = ssid->disabled;
2915
2916 if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
2917 return -2;
2918 }
2919
2920 if (!was_disabled && wpa_s->sched_scanning) {
2921 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
2922 "network from filters");
2923 wpa_supplicant_cancel_sched_scan(wpa_s);
2924 wpa_supplicant_req_scan(wpa_s, 0, 0);
2925 }
2926 return 0;
2927}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928
2929/**
2930 * wpa_supplicant_enable_network - Mark a configured network as enabled
2931 * @wpa_s: wpa_supplicant structure for a network interface
2932 * @ssid: wpa_ssid structure for a configured network or %NULL
2933 *
2934 * Enables the specified network or all networks if no network specified.
2935 */
2936void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2937 struct wpa_ssid *ssid)
2938{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002939 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002940 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2941 wpa_supplicant_enable_one_network(wpa_s, ssid);
2942 } else
2943 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002944
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002945 if (wpa_s->reassociate && !wpa_s->disconnected &&
2946 (!wpa_s->current_ssid ||
2947 wpa_s->wpa_state == WPA_DISCONNECTED ||
2948 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002949 if (wpa_s->sched_scanning) {
2950 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2951 "new network to scan filters");
2952 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002953 }
2954
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002955 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2956 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002957 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002958 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959 }
2960}
2961
2962
2963/**
2964 * wpa_supplicant_disable_network - Mark a configured network as disabled
2965 * @wpa_s: wpa_supplicant structure for a network interface
2966 * @ssid: wpa_ssid structure for a configured network or %NULL
2967 *
2968 * Disables the specified network or all networks if no network specified.
2969 */
2970void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2971 struct wpa_ssid *ssid)
2972{
2973 struct wpa_ssid *other_ssid;
2974 int was_disabled;
2975
2976 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002977 if (wpa_s->sched_scanning)
2978 wpa_supplicant_cancel_sched_scan(wpa_s);
2979
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2981 other_ssid = other_ssid->next) {
2982 was_disabled = other_ssid->disabled;
2983 if (was_disabled == 2)
2984 continue; /* do not change persistent P2P group
2985 * data */
2986
2987 other_ssid->disabled = 1;
2988
2989 if (was_disabled != other_ssid->disabled)
2990 wpas_notify_network_enabled_changed(
2991 wpa_s, other_ssid);
2992 }
2993 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002994 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2996 } else if (ssid->disabled != 2) {
2997 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002998 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002999 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3000
3001 was_disabled = ssid->disabled;
3002
3003 ssid->disabled = 1;
3004
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003005 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003006 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003007 if (wpa_s->sched_scanning) {
3008 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
3009 "to remove network from filters");
3010 wpa_supplicant_cancel_sched_scan(wpa_s);
3011 wpa_supplicant_req_scan(wpa_s, 0, 0);
3012 }
3013 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003014 }
3015}
3016
3017
3018/**
3019 * wpa_supplicant_select_network - Attempt association with a network
3020 * @wpa_s: wpa_supplicant structure for a network interface
3021 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
3022 */
3023void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
3024 struct wpa_ssid *ssid)
3025{
3026
3027 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003028 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003029
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003030 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07003031 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
3032 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003033 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003034 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003035 disconnected = 1;
3036 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003037
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003038 if (ssid)
3039 wpas_clear_temp_disabled(wpa_s, ssid, 1);
3040
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003041 /*
3042 * Mark all other networks disabled or mark all networks enabled if no
3043 * network specified.
3044 */
3045 for (other_ssid = wpa_s->conf->ssid; other_ssid;
3046 other_ssid = other_ssid->next) {
3047 int was_disabled = other_ssid->disabled;
3048 if (was_disabled == 2)
3049 continue; /* do not change persistent P2P group data */
3050
3051 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003052 if (was_disabled && !other_ssid->disabled)
3053 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003054
3055 if (was_disabled != other_ssid->disabled)
3056 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
3057 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003058
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003059 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
3060 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003061 /* We are already associated with the selected network */
3062 wpa_printf(MSG_DEBUG, "Already associated with the "
3063 "selected network - do nothing");
3064 return;
3065 }
3066
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003067 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003068 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003069 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003070 wpa_s->connect_without_scan =
3071 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003072
3073 /*
3074 * Don't optimize next scan freqs since a new ESS has been
3075 * selected.
3076 */
3077 os_free(wpa_s->next_scan_freqs);
3078 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003079 } else {
3080 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003081 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003083 wpa_s->disconnected = 0;
3084 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003085
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003086 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003087 wpa_supplicant_fast_associate(wpa_s) != 1) {
3088 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003089 wpas_scan_reset_sched_scan(wpa_s);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003090 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003091 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003092
3093 if (ssid)
3094 wpas_notify_network_selected(wpa_s, ssid);
3095}
3096
3097
3098/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003099 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
3100 * @wpa_s: wpa_supplicant structure for a network interface
3101 * @pkcs11_engine_path: PKCS #11 engine path or NULL
3102 * @pkcs11_module_path: PKCS #11 module path or NULL
3103 * Returns: 0 on success; -1 on failure
3104 *
3105 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
3106 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
3107 * module path fails the paths will be reset to the default value (NULL).
3108 */
3109int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
3110 const char *pkcs11_engine_path,
3111 const char *pkcs11_module_path)
3112{
3113 char *pkcs11_engine_path_copy = NULL;
3114 char *pkcs11_module_path_copy = NULL;
3115
3116 if (pkcs11_engine_path != NULL) {
3117 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
3118 if (pkcs11_engine_path_copy == NULL)
3119 return -1;
3120 }
3121 if (pkcs11_module_path != NULL) {
3122 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08003123 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003124 os_free(pkcs11_engine_path_copy);
3125 return -1;
3126 }
3127 }
3128
3129 os_free(wpa_s->conf->pkcs11_engine_path);
3130 os_free(wpa_s->conf->pkcs11_module_path);
3131 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
3132 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
3133
3134 wpa_sm_set_eapol(wpa_s->wpa, NULL);
3135 eapol_sm_deinit(wpa_s->eapol);
3136 wpa_s->eapol = NULL;
3137 if (wpa_supplicant_init_eapol(wpa_s)) {
3138 /* Error -> Reset paths to the default value (NULL) once. */
3139 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
3140 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
3141 NULL);
3142
3143 return -1;
3144 }
3145 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3146
3147 return 0;
3148}
3149
3150
3151/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003152 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
3153 * @wpa_s: wpa_supplicant structure for a network interface
3154 * @ap_scan: AP scan mode
3155 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
3156 *
3157 */
3158int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
3159{
3160
3161 int old_ap_scan;
3162
3163 if (ap_scan < 0 || ap_scan > 2)
3164 return -1;
3165
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003166 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3167 wpa_printf(MSG_INFO,
3168 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3169 }
3170
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003171#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003172 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
3173 wpa_s->wpa_state >= WPA_ASSOCIATING &&
3174 wpa_s->wpa_state < WPA_COMPLETED) {
3175 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
3176 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003177 return 0;
3178 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003179#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07003180
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003181 old_ap_scan = wpa_s->conf->ap_scan;
3182 wpa_s->conf->ap_scan = ap_scan;
3183
3184 if (old_ap_scan != wpa_s->conf->ap_scan)
3185 wpas_notify_ap_scan_changed(wpa_s);
3186
3187 return 0;
3188}
3189
3190
3191/**
3192 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
3193 * @wpa_s: wpa_supplicant structure for a network interface
3194 * @expire_age: Expiration age in seconds
3195 * Returns: 0 if succeed or -1 if expire_age has an invalid value
3196 *
3197 */
3198int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
3199 unsigned int bss_expire_age)
3200{
3201 if (bss_expire_age < 10) {
3202 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
3203 bss_expire_age);
3204 return -1;
3205 }
3206 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
3207 bss_expire_age);
3208 wpa_s->conf->bss_expiration_age = bss_expire_age;
3209
3210 return 0;
3211}
3212
3213
3214/**
3215 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
3216 * @wpa_s: wpa_supplicant structure for a network interface
3217 * @expire_count: number of scans after which an unseen BSS is reclaimed
3218 * Returns: 0 if succeed or -1 if expire_count has an invalid value
3219 *
3220 */
3221int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
3222 unsigned int bss_expire_count)
3223{
3224 if (bss_expire_count < 1) {
3225 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
3226 bss_expire_count);
3227 return -1;
3228 }
3229 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
3230 bss_expire_count);
3231 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
3232
3233 return 0;
3234}
3235
3236
3237/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07003238 * wpa_supplicant_set_scan_interval - Set scan interval
3239 * @wpa_s: wpa_supplicant structure for a network interface
3240 * @scan_interval: scan interval in seconds
3241 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
3242 *
3243 */
3244int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
3245 int scan_interval)
3246{
3247 if (scan_interval < 0) {
3248 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
3249 scan_interval);
3250 return -1;
3251 }
3252 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
3253 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003254 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003255
3256 return 0;
3257}
3258
3259
3260/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003261 * wpa_supplicant_set_debug_params - Set global debug params
3262 * @global: wpa_global structure
3263 * @debug_level: debug level
3264 * @debug_timestamp: determines if show timestamp in debug data
3265 * @debug_show_keys: determines if show keys in debug data
3266 * Returns: 0 if succeed or -1 if debug_level has wrong value
3267 */
3268int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
3269 int debug_timestamp, int debug_show_keys)
3270{
3271
3272 int old_level, old_timestamp, old_show_keys;
3273
3274 /* check for allowed debuglevels */
3275 if (debug_level != MSG_EXCESSIVE &&
3276 debug_level != MSG_MSGDUMP &&
3277 debug_level != MSG_DEBUG &&
3278 debug_level != MSG_INFO &&
3279 debug_level != MSG_WARNING &&
3280 debug_level != MSG_ERROR)
3281 return -1;
3282
3283 old_level = wpa_debug_level;
3284 old_timestamp = wpa_debug_timestamp;
3285 old_show_keys = wpa_debug_show_keys;
3286
3287 wpa_debug_level = debug_level;
3288 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
3289 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
3290
3291 if (wpa_debug_level != old_level)
3292 wpas_notify_debug_level_changed(global);
3293 if (wpa_debug_timestamp != old_timestamp)
3294 wpas_notify_debug_timestamp_changed(global);
3295 if (wpa_debug_show_keys != old_show_keys)
3296 wpas_notify_debug_show_keys_changed(global);
3297
3298 return 0;
3299}
3300
3301
3302/**
3303 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
3304 * @wpa_s: Pointer to wpa_supplicant data
3305 * Returns: A pointer to the current network structure or %NULL on failure
3306 */
3307struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
3308{
3309 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003310 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311 int res;
3312 size_t ssid_len;
3313 u8 bssid[ETH_ALEN];
3314 int wired;
3315
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003316 res = wpa_drv_get_ssid(wpa_s, ssid);
3317 if (res < 0) {
3318 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
3319 "driver");
3320 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003321 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003322 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003323
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003324 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003325 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
3326 "driver");
3327 return NULL;
3328 }
3329
3330 wired = wpa_s->conf->ap_scan == 0 &&
3331 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
3332
3333 entry = wpa_s->conf->ssid;
3334 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003335 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003336 ((ssid_len == entry->ssid_len &&
3337 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
3338 (!entry->bssid_set ||
3339 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3340 return entry;
3341#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07003342 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003343 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
3344 (entry->ssid == NULL || entry->ssid_len == 0) &&
3345 (!entry->bssid_set ||
3346 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
3347 return entry;
3348#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003349
Dmitry Shmidt04949592012-07-19 12:16:46 -07003350 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003351 entry->ssid_len == 0 &&
3352 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
3353 return entry;
3354
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003355 entry = entry->next;
3356 }
3357
3358 return NULL;
3359}
3360
3361
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003362static int select_driver(struct wpa_supplicant *wpa_s, int i)
3363{
3364 struct wpa_global *global = wpa_s->global;
3365
3366 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
Dmitry Shmidte4663042016-04-04 10:07:49 -07003367 global->drv_priv[i] = wpa_drivers[i]->global_init(global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003368 if (global->drv_priv[i] == NULL) {
3369 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3370 "'%s'", wpa_drivers[i]->name);
3371 return -1;
3372 }
3373 }
3374
3375 wpa_s->driver = wpa_drivers[i];
3376 wpa_s->global_drv_priv = global->drv_priv[i];
3377
3378 return 0;
3379}
3380
3381
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003382static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3383 const char *name)
3384{
3385 int i;
3386 size_t len;
3387 const char *pos, *driver = name;
3388
3389 if (wpa_s == NULL)
3390 return -1;
3391
3392 if (wpa_drivers[0] == NULL) {
3393 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3394 "wpa_supplicant");
3395 return -1;
3396 }
3397
3398 if (name == NULL) {
3399 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003400 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401 }
3402
3403 do {
3404 pos = os_strchr(driver, ',');
3405 if (pos)
3406 len = pos - driver;
3407 else
3408 len = os_strlen(driver);
3409
3410 for (i = 0; wpa_drivers[i]; i++) {
3411 if (os_strlen(wpa_drivers[i]->name) == len &&
3412 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003413 0) {
3414 /* First driver that succeeds wins */
3415 if (select_driver(wpa_s, i) == 0)
3416 return 0;
3417 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003418 }
3419
3420 driver = pos + 1;
3421 } while (pos);
3422
3423 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3424 return -1;
3425}
3426
3427
3428/**
3429 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3430 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3431 * with struct wpa_driver_ops::init()
3432 * @src_addr: Source address of the EAPOL frame
3433 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3434 * @len: Length of the EAPOL data
3435 *
3436 * This function is called for each received EAPOL frame. Most driver
3437 * interfaces rely on more generic OS mechanism for receiving frames through
3438 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3439 * take care of received EAPOL frames and deliver them to the core supplicant
3440 * code by calling this function.
3441 */
3442void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3443 const u8 *buf, size_t len)
3444{
3445 struct wpa_supplicant *wpa_s = ctx;
3446
3447 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3448 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3449
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003450#ifdef CONFIG_TESTING_OPTIONS
3451 if (wpa_s->ignore_auth_resp) {
3452 wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
3453 return;
3454 }
3455#endif /* CONFIG_TESTING_OPTIONS */
3456
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003457#ifdef CONFIG_PEERKEY
3458 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3459 wpa_s->current_ssid->peerkey &&
3460 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3461 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3462 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3463 return;
3464 }
3465#endif /* CONFIG_PEERKEY */
3466
Jouni Malinena05074c2012-12-21 21:35:35 +02003467 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3468 (wpa_s->last_eapol_matches_bssid &&
3469#ifdef CONFIG_AP
3470 !wpa_s->ap_iface &&
3471#endif /* CONFIG_AP */
3472 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003473 /*
3474 * There is possible race condition between receiving the
3475 * association event and the EAPOL frame since they are coming
3476 * through different paths from the driver. In order to avoid
3477 * issues in trying to process the EAPOL frame before receiving
3478 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003479 * the association event is received. This may also be needed in
3480 * driver-based roaming case, so also use src_addr != BSSID as a
3481 * trigger if we have previously confirmed that the
3482 * Authenticator uses BSSID as the src_addr (which is not the
3483 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003484 */
3485 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003486 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3487 wpa_supplicant_state_txt(wpa_s->wpa_state),
3488 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 wpabuf_free(wpa_s->pending_eapol_rx);
3490 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3491 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003492 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003493 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3494 ETH_ALEN);
3495 }
3496 return;
3497 }
3498
Jouni Malinena05074c2012-12-21 21:35:35 +02003499 wpa_s->last_eapol_matches_bssid =
3500 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3501
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003502#ifdef CONFIG_AP
3503 if (wpa_s->ap_iface) {
3504 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3505 return;
3506 }
3507#endif /* CONFIG_AP */
3508
3509 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3510 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3511 "no key management is configured");
3512 return;
3513 }
3514
3515 if (wpa_s->eapol_received == 0 &&
3516 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3517 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3518 wpa_s->wpa_state != WPA_COMPLETED) &&
3519 (wpa_s->current_ssid == NULL ||
3520 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3521 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003522 int timeout = 10;
3523
3524 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3525 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3526 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3527 /* Use longer timeout for IEEE 802.1X/EAP */
3528 timeout = 70;
3529 }
3530
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003531#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003532 if (wpa_s->current_ssid && wpa_s->current_bss &&
3533 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3534 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3535 /*
3536 * Use shorter timeout if going through WPS AP iteration
3537 * for PIN config method with an AP that does not
3538 * advertise Selected Registrar.
3539 */
3540 struct wpabuf *wps_ie;
3541
3542 wps_ie = wpa_bss_get_vendor_ie_multi(
3543 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3544 if (wps_ie &&
3545 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3546 timeout = 10;
3547 wpabuf_free(wps_ie);
3548 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003549#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003550
3551 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003552 }
3553 wpa_s->eapol_received++;
3554
3555 if (wpa_s->countermeasures) {
3556 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3557 "EAPOL packet");
3558 return;
3559 }
3560
3561#ifdef CONFIG_IBSS_RSN
3562 if (wpa_s->current_ssid &&
3563 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3564 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3565 return;
3566 }
3567#endif /* CONFIG_IBSS_RSN */
3568
3569 /* Source address of the incoming EAPOL frame could be compared to the
3570 * current BSSID. However, it is possible that a centralized
3571 * Authenticator could be using another MAC address than the BSSID of
3572 * an AP, so just allow any address to be used for now. The replies are
3573 * still sent to the current BSSID (if available), though. */
3574
3575 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3576 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3577 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3578 return;
3579 wpa_drv_poll(wpa_s);
3580 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3581 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3582 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3583 /*
3584 * Set portValid = TRUE here since we are going to skip 4-way
3585 * handshake processing which would normally set portValid. We
3586 * need this to allow the EAPOL state machines to be completed
3587 * without going through EAPOL-Key handshake.
3588 */
3589 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3590 }
3591}
3592
3593
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003594int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003595{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003596 if ((!wpa_s->p2p_mgmt ||
3597 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3598 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003599 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003600 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3601 wpa_drv_get_mac_addr(wpa_s),
3602 ETH_P_EAPOL,
3603 wpa_supplicant_rx_eapol, wpa_s, 0);
3604 if (wpa_s->l2 == NULL)
3605 return -1;
3606 } else {
3607 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3608 if (addr)
3609 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3610 }
3611
3612 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3613 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3614 return -1;
3615 }
3616
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003617 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3618
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003619 return 0;
3620}
3621
3622
Dmitry Shmidt04949592012-07-19 12:16:46 -07003623static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3624 const u8 *buf, size_t len)
3625{
3626 struct wpa_supplicant *wpa_s = ctx;
3627 const struct l2_ethhdr *eth;
3628
3629 if (len < sizeof(*eth))
3630 return;
3631 eth = (const struct l2_ethhdr *) buf;
3632
3633 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3634 !(eth->h_dest[0] & 0x01)) {
3635 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3636 " (bridge - not for this interface - ignore)",
3637 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3638 return;
3639 }
3640
3641 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3642 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3643 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3644 len - sizeof(*eth));
3645}
3646
3647
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003648/**
3649 * wpa_supplicant_driver_init - Initialize driver interface parameters
3650 * @wpa_s: Pointer to wpa_supplicant data
3651 * Returns: 0 on success, -1 on failure
3652 *
3653 * This function is called to initialize driver interface parameters.
3654 * wpa_drv_init() must have been called before this function to initialize the
3655 * driver interface.
3656 */
3657int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3658{
3659 static int interface_count = 0;
3660
3661 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3662 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003663
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003664 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3665 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003666 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003667 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3668
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669 if (wpa_s->bridge_ifname[0]) {
3670 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3671 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003672 wpa_s->l2_br = l2_packet_init_bridge(
3673 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3674 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675 if (wpa_s->l2_br == NULL) {
3676 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3677 "connection for the bridge interface '%s'",
3678 wpa_s->bridge_ifname);
3679 return -1;
3680 }
3681 }
3682
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003683 if (wpa_s->conf->ap_scan == 2 &&
3684 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3685 wpa_printf(MSG_INFO,
3686 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3687 }
3688
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003689 wpa_clear_keys(wpa_s, NULL);
3690
3691 /* Make sure that TKIP countermeasures are not left enabled (could
3692 * happen if wpa_supplicant is killed during countermeasures. */
3693 wpa_drv_set_countermeasures(wpa_s, 0);
3694
3695 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3696 wpa_drv_flush_pmkid(wpa_s);
3697
3698 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003699 wpa_s->prev_scan_wildcard = 0;
3700
Dmitry Shmidt04949592012-07-19 12:16:46 -07003701 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003702 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3703 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3704 interface_count = 0;
3705 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003706#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003707 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003708 wpa_supplicant_delayed_sched_scan(wpa_s,
3709 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003710 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003711 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003712 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003713#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003714 interface_count++;
3715 } else
3716 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3717
3718 return 0;
3719}
3720
3721
3722static int wpa_supplicant_daemon(const char *pid_file)
3723{
3724 wpa_printf(MSG_DEBUG, "Daemonize..");
3725 return os_daemonize(pid_file);
3726}
3727
3728
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003729static struct wpa_supplicant *
3730wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003731{
3732 struct wpa_supplicant *wpa_s;
3733
3734 wpa_s = os_zalloc(sizeof(*wpa_s));
3735 if (wpa_s == NULL)
3736 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003737 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003738 wpa_s->scan_interval = 5;
3739 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003740 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003741 wpa_s->p2pdev = wpa_s->parent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003742 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003744 dl_list_init(&wpa_s->bss_tmp_disallowed);
Paul Stewart092955c2017-02-06 09:13:09 -08003745 dl_list_init(&wpa_s->fils_hlp_req);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747 return wpa_s;
3748}
3749
3750
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003751#ifdef CONFIG_HT_OVERRIDES
3752
3753static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3754 struct ieee80211_ht_capabilities *htcaps,
3755 struct ieee80211_ht_capabilities *htcaps_mask,
3756 const char *ht_mcs)
3757{
3758 /* parse ht_mcs into hex array */
3759 int i;
3760 const char *tmp = ht_mcs;
3761 char *end = NULL;
3762
3763 /* If ht_mcs is null, do not set anything */
3764 if (!ht_mcs)
3765 return 0;
3766
3767 /* This is what we are setting in the kernel */
3768 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3769
3770 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3771
3772 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
Paul Stewart092955c2017-02-06 09:13:09 -08003773 long v;
3774
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003775 errno = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08003776 v = strtol(tmp, &end, 16);
3777
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003778 if (errno == 0) {
3779 wpa_msg(wpa_s, MSG_DEBUG,
3780 "htcap value[%i]: %ld end: %p tmp: %p",
3781 i, v, end, tmp);
3782 if (end == tmp)
3783 break;
3784
3785 htcaps->supported_mcs_set[i] = v;
3786 tmp = end;
3787 } else {
3788 wpa_msg(wpa_s, MSG_ERROR,
3789 "Failed to parse ht-mcs: %s, error: %s\n",
3790 ht_mcs, strerror(errno));
3791 return -1;
3792 }
3793 }
3794
3795 /*
3796 * If we were able to parse any values, then set mask for the MCS set.
3797 */
3798 if (i) {
3799 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3800 IEEE80211_HT_MCS_MASK_LEN - 1);
3801 /* skip the 3 reserved bits */
3802 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3803 0x1f;
3804 }
3805
3806 return 0;
3807}
3808
3809
3810static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3811 struct ieee80211_ht_capabilities *htcaps,
3812 struct ieee80211_ht_capabilities *htcaps_mask,
3813 int disabled)
3814{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003815 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003816
3817 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3818
3819 if (disabled == -1)
3820 return 0;
3821
3822 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3823 htcaps_mask->ht_capabilities_info |= msk;
3824 if (disabled)
3825 htcaps->ht_capabilities_info &= msk;
3826 else
3827 htcaps->ht_capabilities_info |= msk;
3828
3829 return 0;
3830}
3831
3832
3833static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3834 struct ieee80211_ht_capabilities *htcaps,
3835 struct ieee80211_ht_capabilities *htcaps_mask,
3836 int factor)
3837{
3838 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3839
3840 if (factor == -1)
3841 return 0;
3842
3843 if (factor < 0 || factor > 3) {
3844 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3845 "Must be 0-3 or -1", factor);
3846 return -EINVAL;
3847 }
3848
3849 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3850 htcaps->a_mpdu_params &= ~0x3;
3851 htcaps->a_mpdu_params |= factor & 0x3;
3852
3853 return 0;
3854}
3855
3856
3857static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3858 struct ieee80211_ht_capabilities *htcaps,
3859 struct ieee80211_ht_capabilities *htcaps_mask,
3860 int density)
3861{
3862 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3863
3864 if (density == -1)
3865 return 0;
3866
3867 if (density < 0 || density > 7) {
3868 wpa_msg(wpa_s, MSG_ERROR,
3869 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3870 density);
3871 return -EINVAL;
3872 }
3873
3874 htcaps_mask->a_mpdu_params |= 0x1C;
3875 htcaps->a_mpdu_params &= ~(0x1C);
3876 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3877
3878 return 0;
3879}
3880
3881
3882static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3883 struct ieee80211_ht_capabilities *htcaps,
3884 struct ieee80211_ht_capabilities *htcaps_mask,
3885 int disabled)
3886{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003887 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3888
Paul Stewart092955c2017-02-06 09:13:09 -08003889 set_disable_ht40(htcaps, disabled);
3890 set_disable_ht40(htcaps_mask, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003891
3892 return 0;
3893}
3894
3895
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003896static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3897 struct ieee80211_ht_capabilities *htcaps,
3898 struct ieee80211_ht_capabilities *htcaps_mask,
3899 int disabled)
3900{
3901 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003902 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3903 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003904
3905 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3906
3907 if (disabled)
3908 htcaps->ht_capabilities_info &= ~msk;
3909 else
3910 htcaps->ht_capabilities_info |= msk;
3911
3912 htcaps_mask->ht_capabilities_info |= msk;
3913
3914 return 0;
3915}
3916
3917
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003918static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3919 struct ieee80211_ht_capabilities *htcaps,
3920 struct ieee80211_ht_capabilities *htcaps_mask,
3921 int disabled)
3922{
3923 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003924 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003925
3926 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3927
3928 if (disabled)
3929 htcaps->ht_capabilities_info &= ~msk;
3930 else
3931 htcaps->ht_capabilities_info |= msk;
3932
3933 htcaps_mask->ht_capabilities_info |= msk;
3934
3935 return 0;
3936}
3937
3938
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003939void wpa_supplicant_apply_ht_overrides(
3940 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3941 struct wpa_driver_associate_params *params)
3942{
3943 struct ieee80211_ht_capabilities *htcaps;
3944 struct ieee80211_ht_capabilities *htcaps_mask;
3945
3946 if (!ssid)
3947 return;
3948
3949 params->disable_ht = ssid->disable_ht;
3950 if (!params->htcaps || !params->htcaps_mask)
3951 return;
3952
3953 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3954 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3955 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3956 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3957 ssid->disable_max_amsdu);
3958 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3959 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3960 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003961 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003962 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003963
3964 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003965 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003966 htcaps->ht_capabilities_info |= bit;
3967 htcaps_mask->ht_capabilities_info |= bit;
3968 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003969}
3970
3971#endif /* CONFIG_HT_OVERRIDES */
3972
3973
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003974#ifdef CONFIG_VHT_OVERRIDES
3975void wpa_supplicant_apply_vht_overrides(
3976 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3977 struct wpa_driver_associate_params *params)
3978{
3979 struct ieee80211_vht_capabilities *vhtcaps;
3980 struct ieee80211_vht_capabilities *vhtcaps_mask;
3981
3982 if (!ssid)
3983 return;
3984
3985 params->disable_vht = ssid->disable_vht;
3986
3987 vhtcaps = (void *) params->vhtcaps;
3988 vhtcaps_mask = (void *) params->vhtcaps_mask;
3989
3990 if (!vhtcaps || !vhtcaps_mask)
3991 return;
3992
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07003993 vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
3994 vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003995
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003996#ifdef CONFIG_HT_OVERRIDES
3997 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003998 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3999 int max_ampdu;
4000
4001 max_ampdu = (ssid->vht_capa &
4002 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
4003 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004004
4005 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
4006 wpa_set_ampdu_factor(wpa_s,
4007 (void *) params->htcaps,
4008 (void *) params->htcaps_mask,
4009 max_ampdu);
4010 }
4011#endif /* CONFIG_HT_OVERRIDES */
4012
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004013#define OVERRIDE_MCS(i) \
4014 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
4015 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004016 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004017 vhtcaps->vht_supported_mcs_set.tx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004018 host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
4019 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004020 } \
4021 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
4022 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004023 host_to_le16(3 << 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004024 vhtcaps->vht_supported_mcs_set.rx_map |= \
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004025 host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
4026 2 * (i - 1)); \
Dmitry Shmidt2f023192013-03-12 12:44:17 -07004027 }
4028
4029 OVERRIDE_MCS(1);
4030 OVERRIDE_MCS(2);
4031 OVERRIDE_MCS(3);
4032 OVERRIDE_MCS(4);
4033 OVERRIDE_MCS(5);
4034 OVERRIDE_MCS(6);
4035 OVERRIDE_MCS(7);
4036 OVERRIDE_MCS(8);
4037}
4038#endif /* CONFIG_VHT_OVERRIDES */
4039
4040
Dmitry Shmidt04949592012-07-19 12:16:46 -07004041static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
4042{
4043#ifdef PCSC_FUNCS
4044 size_t len;
4045
4046 if (!wpa_s->conf->pcsc_reader)
4047 return 0;
4048
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004049 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004050 if (!wpa_s->scard)
4051 return 1;
4052
4053 if (wpa_s->conf->pcsc_pin &&
4054 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
4055 scard_deinit(wpa_s->scard);
4056 wpa_s->scard = NULL;
4057 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
4058 return -1;
4059 }
4060
4061 len = sizeof(wpa_s->imsi) - 1;
4062 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
4063 scard_deinit(wpa_s->scard);
4064 wpa_s->scard = NULL;
4065 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
4066 return -1;
4067 }
4068 wpa_s->imsi[len] = '\0';
4069
4070 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
4071
4072 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
4073 wpa_s->imsi, wpa_s->mnc_len);
4074
4075 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
4076 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
4077#endif /* PCSC_FUNCS */
4078
4079 return 0;
4080}
4081
4082
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004083int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
4084{
4085 char *val, *pos;
4086
4087 ext_password_deinit(wpa_s->ext_pw);
4088 wpa_s->ext_pw = NULL;
4089 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
4090
4091 if (!wpa_s->conf->ext_password_backend)
4092 return 0;
4093
4094 val = os_strdup(wpa_s->conf->ext_password_backend);
4095 if (val == NULL)
4096 return -1;
4097 pos = os_strchr(val, ':');
4098 if (pos)
4099 *pos++ = '\0';
4100
4101 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
4102
4103 wpa_s->ext_pw = ext_password_init(val, pos);
4104 os_free(val);
4105 if (wpa_s->ext_pw == NULL) {
4106 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
4107 return -1;
4108 }
4109 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
4110
4111 return 0;
4112}
4113
4114
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004115#ifdef CONFIG_FST
4116
4117static const u8 * wpas_fst_get_bssid_cb(void *ctx)
4118{
4119 struct wpa_supplicant *wpa_s = ctx;
4120
4121 return (is_zero_ether_addr(wpa_s->bssid) ||
4122 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
4123}
4124
4125
4126static void wpas_fst_get_channel_info_cb(void *ctx,
4127 enum hostapd_hw_mode *hw_mode,
4128 u8 *channel)
4129{
4130 struct wpa_supplicant *wpa_s = ctx;
4131
4132 if (wpa_s->current_bss) {
4133 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
4134 channel);
4135 } else if (wpa_s->hw.num_modes) {
4136 *hw_mode = wpa_s->hw.modes[0].mode;
4137 } else {
4138 WPA_ASSERT(0);
4139 *hw_mode = 0;
4140 }
4141}
4142
4143
4144static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
4145{
4146 struct wpa_supplicant *wpa_s = ctx;
4147
4148 *modes = wpa_s->hw.modes;
4149 return wpa_s->hw.num_modes;
4150}
4151
4152
4153static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
4154{
4155 struct wpa_supplicant *wpa_s = ctx;
4156
4157 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
4158 wpa_s->fst_ies = fst_ies;
4159}
4160
4161
4162static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
4163{
4164 struct wpa_supplicant *wpa_s = ctx;
4165
Paul Stewart092955c2017-02-06 09:13:09 -08004166 if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
4167 wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
4168 __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
4169 return -1;
4170 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004171 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
Paul Stewart092955c2017-02-06 09:13:09 -08004172 wpa_s->own_addr, wpa_s->bssid,
4173 wpabuf_head(data), wpabuf_len(data),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004174 0);
4175}
4176
4177
4178static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
4179{
4180 struct wpa_supplicant *wpa_s = ctx;
4181
4182 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4183 return wpa_s->received_mb_ies;
4184}
4185
4186
4187static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
4188 const u8 *buf, size_t size)
4189{
4190 struct wpa_supplicant *wpa_s = ctx;
4191 struct mb_ies_info info;
4192
4193 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
4194
4195 if (!mb_ies_info_by_ies(&info, buf, size)) {
4196 wpabuf_free(wpa_s->received_mb_ies);
4197 wpa_s->received_mb_ies = mb_ies_by_info(&info);
4198 }
4199}
4200
4201
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004202static const u8 * wpas_fst_get_peer_first(void *ctx,
4203 struct fst_get_peer_ctx **get_ctx,
4204 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004205{
4206 struct wpa_supplicant *wpa_s = ctx;
4207
4208 *get_ctx = NULL;
4209 if (!is_zero_ether_addr(wpa_s->bssid))
4210 return (wpa_s->received_mb_ies || !mb_only) ?
4211 wpa_s->bssid : NULL;
4212 return NULL;
4213}
4214
4215
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07004216static const u8 * wpas_fst_get_peer_next(void *ctx,
4217 struct fst_get_peer_ctx **get_ctx,
4218 Boolean mb_only)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004219{
4220 return NULL;
4221}
4222
4223void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
4224 struct fst_wpa_obj *iface_obj)
4225{
4226 iface_obj->ctx = wpa_s;
4227 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
4228 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
4229 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
4230 iface_obj->set_ies = wpas_fst_set_ies_cb;
4231 iface_obj->send_action = wpas_fst_send_action_cb;
4232 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
4233 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
4234 iface_obj->get_peer_first = wpas_fst_get_peer_first;
4235 iface_obj->get_peer_next = wpas_fst_get_peer_next;
4236}
4237#endif /* CONFIG_FST */
4238
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004239static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004240 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004241{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004242 struct wowlan_triggers *triggers;
4243 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004244
4245 if (!wpa_s->conf->wowlan_triggers)
4246 return 0;
4247
Dmitry Shmidt0207e232014-09-03 14:58:37 -07004248 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
4249 if (triggers) {
4250 ret = wpa_drv_wowlan(wpa_s, triggers);
4251 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004252 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004253 return ret;
4254}
4255
4256
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004257enum wpa_radio_work_band wpas_freq_to_band(int freq)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004258{
4259 if (freq < 3000)
4260 return BAND_2_4_GHZ;
4261 if (freq > 50000)
4262 return BAND_60_GHZ;
4263 return BAND_5_GHZ;
4264}
4265
4266
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004267unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004268{
4269 int i;
4270 unsigned int band = 0;
4271
4272 if (freqs) {
4273 /* freqs are specified for the radio work */
4274 for (i = 0; freqs[i]; i++)
4275 band |= wpas_freq_to_band(freqs[i]);
4276 } else {
4277 /*
4278 * freqs are not specified, implies all
4279 * the supported freqs by HW
4280 */
4281 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4282 if (wpa_s->hw.modes[i].num_channels != 0) {
4283 if (wpa_s->hw.modes[i].mode ==
4284 HOSTAPD_MODE_IEEE80211B ||
4285 wpa_s->hw.modes[i].mode ==
4286 HOSTAPD_MODE_IEEE80211G)
4287 band |= BAND_2_4_GHZ;
4288 else if (wpa_s->hw.modes[i].mode ==
4289 HOSTAPD_MODE_IEEE80211A)
4290 band |= BAND_5_GHZ;
4291 else if (wpa_s->hw.modes[i].mode ==
4292 HOSTAPD_MODE_IEEE80211AD)
4293 band |= BAND_60_GHZ;
4294 else if (wpa_s->hw.modes[i].mode ==
4295 HOSTAPD_MODE_IEEE80211ANY)
4296 band = BAND_2_4_GHZ | BAND_5_GHZ |
4297 BAND_60_GHZ;
4298 }
4299 }
4300 }
4301
4302 return band;
4303}
4304
4305
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004306static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
4307 const char *rn)
4308{
4309 struct wpa_supplicant *iface = wpa_s->global->ifaces;
4310 struct wpa_radio *radio;
4311
4312 while (rn && iface) {
4313 radio = iface->radio;
4314 if (radio && os_strcmp(rn, radio->name) == 0) {
4315 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
4316 wpa_s->ifname, rn);
4317 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4318 return radio;
4319 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08004320
4321 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004322 }
4323
4324 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
4325 wpa_s->ifname, rn ? rn : "N/A");
4326 radio = os_zalloc(sizeof(*radio));
4327 if (radio == NULL)
4328 return NULL;
4329
4330 if (rn)
4331 os_strlcpy(radio->name, rn, sizeof(radio->name));
4332 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004333 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004334 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
4335
4336 return radio;
4337}
4338
4339
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004340static void radio_work_free(struct wpa_radio_work *work)
4341{
4342 if (work->wpa_s->scan_work == work) {
4343 /* This should not really happen. */
4344 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
4345 work->type, work, work->started);
4346 work->wpa_s->scan_work = NULL;
4347 }
4348
4349#ifdef CONFIG_P2P
4350 if (work->wpa_s->p2p_scan_work == work) {
4351 /* This should not really happen. */
4352 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
4353 work->type, work, work->started);
4354 work->wpa_s->p2p_scan_work = NULL;
4355 }
4356#endif /* CONFIG_P2P */
4357
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004358 if (work->started) {
4359 work->wpa_s->radio->num_active_works--;
4360 wpa_dbg(work->wpa_s, MSG_DEBUG,
4361 "radio_work_free('%s'@%p: num_active_works --> %u",
4362 work->type, work,
4363 work->wpa_s->radio->num_active_works);
4364 }
4365
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004366 dl_list_del(&work->list);
4367 os_free(work);
4368}
4369
4370
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004371static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
4372{
4373 struct wpa_radio_work *active_work = NULL;
4374 struct wpa_radio_work *tmp;
4375
4376 /* Get the active work to know the type and band. */
4377 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4378 if (tmp->started) {
4379 active_work = tmp;
4380 break;
4381 }
4382 }
4383
4384 if (!active_work) {
4385 /* No active work, start one */
4386 radio->num_active_works = 0;
4387 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4388 list) {
4389 if (os_strcmp(tmp->type, "scan") == 0 &&
4390 radio->external_scan_running &&
4391 (((struct wpa_driver_scan_params *)
4392 tmp->ctx)->only_new_results ||
4393 tmp->wpa_s->clear_driver_scan_cache))
4394 continue;
4395 return tmp;
4396 }
4397 return NULL;
4398 }
4399
4400 if (os_strcmp(active_work->type, "sme-connect") == 0 ||
4401 os_strcmp(active_work->type, "connect") == 0) {
4402 /*
4403 * If the active work is either connect or sme-connect,
4404 * do not parallelize them with other radio works.
4405 */
4406 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4407 "Do not parallelize radio work with %s",
4408 active_work->type);
4409 return NULL;
4410 }
4411
4412 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4413 if (tmp->started)
4414 continue;
4415
4416 /*
4417 * If connect or sme-connect are enqueued, parallelize only
4418 * those operations ahead of them in the queue.
4419 */
4420 if (os_strcmp(tmp->type, "connect") == 0 ||
4421 os_strcmp(tmp->type, "sme-connect") == 0)
4422 break;
4423
4424 /*
4425 * Check that the radio works are distinct and
4426 * on different bands.
4427 */
4428 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4429 (active_work->bands != tmp->bands)) {
4430 /*
4431 * If a scan has to be scheduled through nl80211 scan
4432 * interface and if an external scan is already running,
4433 * do not schedule the scan since it is likely to get
4434 * rejected by kernel.
4435 */
4436 if (os_strcmp(tmp->type, "scan") == 0 &&
4437 radio->external_scan_running &&
4438 (((struct wpa_driver_scan_params *)
4439 tmp->ctx)->only_new_results ||
4440 tmp->wpa_s->clear_driver_scan_cache))
4441 continue;
4442
4443 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4444 "active_work:%s new_work:%s",
4445 active_work->type, tmp->type);
4446 return tmp;
4447 }
4448 }
4449
4450 /* Did not find a radio work to schedule in parallel. */
4451 return NULL;
4452}
4453
4454
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004455static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4456{
4457 struct wpa_radio *radio = eloop_ctx;
4458 struct wpa_radio_work *work;
4459 struct os_reltime now, diff;
4460 struct wpa_supplicant *wpa_s;
4461
4462 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004463 if (work == NULL) {
4464 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004465 return;
4466 }
4467
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004468 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4469 radio_list);
4470
4471 if (!(wpa_s &&
4472 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4473 if (work->started)
4474 return; /* already started and still in progress */
4475
4476 if (wpa_s && wpa_s->radio->external_scan_running) {
4477 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4478 return;
4479 }
4480 } else {
4481 work = NULL;
4482 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4483 /* get the work to schedule next */
4484 work = radio_work_get_next_work(radio);
4485 }
4486 if (!work)
4487 return;
4488 }
4489
4490 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004491 os_get_reltime(&now);
4492 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004493 wpa_dbg(wpa_s, MSG_DEBUG,
4494 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004495 work->type, work, diff.sec, diff.usec);
4496 work->started = 1;
4497 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004498 radio->num_active_works++;
4499
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004500 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004501
4502 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4503 radio->num_active_works < MAX_ACTIVE_WORKS)
4504 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004505}
4506
4507
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004508/*
4509 * This function removes both started and pending radio works running on
4510 * the provided interface's radio.
4511 * Prior to the removal of the radio work, its callback (cb) is called with
4512 * deinit set to be 1. Each work's callback is responsible for clearing its
4513 * internal data and restoring to a correct state.
4514 * @wpa_s: wpa_supplicant data
4515 * @type: type of works to be removed
4516 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4517 * this interface's works.
4518 */
4519void radio_remove_works(struct wpa_supplicant *wpa_s,
4520 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004521{
4522 struct wpa_radio_work *work, *tmp;
4523 struct wpa_radio *radio = wpa_s->radio;
4524
4525 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4526 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004527 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004528 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004529
4530 /* skip other ifaces' works */
4531 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004532 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004533
4534 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4535 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004536 work->cb(work, 1);
4537 radio_work_free(work);
4538 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004539
4540 /* in case we removed the started work */
4541 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004542}
4543
4544
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004545static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4546{
4547 struct wpa_radio *radio = wpa_s->radio;
4548
4549 if (!radio)
4550 return;
4551
4552 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4553 wpa_s->ifname, radio->name);
4554 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004555 radio_remove_works(wpa_s, NULL, 0);
4556 wpa_s->radio = NULL;
4557 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004558 return; /* Interfaces remain for this radio */
4559
4560 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004561 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004562 os_free(radio);
4563}
4564
4565
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004566void radio_work_check_next(struct wpa_supplicant *wpa_s)
4567{
4568 struct wpa_radio *radio = wpa_s->radio;
4569
4570 if (dl_list_empty(&radio->work))
4571 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004572 if (wpa_s->ext_work_in_progress) {
4573 wpa_printf(MSG_DEBUG,
4574 "External radio work in progress - delay start of pending item");
4575 return;
4576 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004577 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4578 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4579}
4580
4581
4582/**
4583 * radio_add_work - Add a radio work item
4584 * @wpa_s: Pointer to wpa_supplicant data
4585 * @freq: Frequency of the offchannel operation in MHz or 0
4586 * @type: Unique identifier for each type of work
4587 * @next: Force as the next work to be executed
4588 * @cb: Callback function for indicating when radio is available
4589 * @ctx: Context pointer for the work (work->ctx in cb())
4590 * Returns: 0 on success, -1 on failure
4591 *
4592 * This function is used to request time for an operation that requires
4593 * exclusive radio control. Once the radio is available, the registered callback
4594 * function will be called. radio_work_done() must be called once the exclusive
4595 * radio operation has been completed, so that the radio is freed for other
4596 * operations. The special case of deinit=1 is used to free the context data
4597 * during interface removal. That does not allow the callback function to start
4598 * the radio operation, i.e., it must free any resources allocated for the radio
4599 * work and return.
4600 *
4601 * The @freq parameter can be used to indicate a single channel on which the
4602 * offchannel operation will occur. This may allow multiple radio work
4603 * operations to be performed in parallel if they apply for the same channel.
4604 * Setting this to 0 indicates that the work item may use multiple channels or
4605 * requires exclusive control of the radio.
4606 */
4607int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4608 const char *type, int next,
4609 void (*cb)(struct wpa_radio_work *work, int deinit),
4610 void *ctx)
4611{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004612 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004613 struct wpa_radio_work *work;
4614 int was_empty;
4615
4616 work = os_zalloc(sizeof(*work));
4617 if (work == NULL)
4618 return -1;
4619 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4620 os_get_reltime(&work->time);
4621 work->freq = freq;
4622 work->type = type;
4623 work->wpa_s = wpa_s;
4624 work->cb = cb;
4625 work->ctx = ctx;
4626
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004627 if (freq)
4628 work->bands = wpas_freq_to_band(freq);
4629 else if (os_strcmp(type, "scan") == 0 ||
4630 os_strcmp(type, "p2p-scan") == 0)
4631 work->bands = wpas_get_bands(wpa_s,
4632 ((struct wpa_driver_scan_params *)
4633 ctx)->freqs);
4634 else
4635 work->bands = wpas_get_bands(wpa_s, NULL);
4636
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004637 was_empty = dl_list_empty(&wpa_s->radio->work);
4638 if (next)
4639 dl_list_add(&wpa_s->radio->work, &work->list);
4640 else
4641 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4642 if (was_empty) {
4643 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4644 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004645 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4646 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4647 wpa_dbg(wpa_s, MSG_DEBUG,
4648 "Try to schedule a radio work (num_active_works=%u)",
4649 radio->num_active_works);
4650 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004651 }
4652
4653 return 0;
4654}
4655
4656
4657/**
4658 * radio_work_done - Indicate that a radio work item has been completed
4659 * @work: Completed work
4660 *
4661 * This function is called once the callback function registered with
4662 * radio_add_work() has completed its work.
4663 */
4664void radio_work_done(struct wpa_radio_work *work)
4665{
4666 struct wpa_supplicant *wpa_s = work->wpa_s;
4667 struct os_reltime now, diff;
4668 unsigned int started = work->started;
4669
4670 os_get_reltime(&now);
4671 os_reltime_sub(&now, &work->time, &diff);
4672 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4673 work->type, work, started ? "done" : "canceled",
4674 diff.sec, diff.usec);
4675 radio_work_free(work);
4676 if (started)
4677 radio_work_check_next(wpa_s);
4678}
4679
4680
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004681struct wpa_radio_work *
4682radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004683{
4684 struct wpa_radio_work *work;
4685 struct wpa_radio *radio = wpa_s->radio;
4686
4687 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4688 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004689 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004690 }
4691
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004692 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004693}
4694
4695
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004696static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4697 struct wpa_interface *iface)
4698{
4699 const char *ifname, *driver, *rn;
4700
4701 driver = iface->driver;
4702next_driver:
4703 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4704 return -1;
4705
4706 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4707 if (wpa_s->drv_priv == NULL) {
4708 const char *pos;
4709 pos = driver ? os_strchr(driver, ',') : NULL;
4710 if (pos) {
4711 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4712 "driver interface - try next driver wrapper");
4713 driver = pos + 1;
4714 goto next_driver;
4715 }
4716 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4717 "interface");
4718 return -1;
4719 }
4720 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4721 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4722 "driver_param '%s'", wpa_s->conf->driver_param);
4723 return -1;
4724 }
4725
4726 ifname = wpa_drv_get_ifname(wpa_s);
4727 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4728 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4729 "interface name with '%s'", ifname);
4730 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4731 }
4732
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004733 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004734 if (rn && rn[0] == '\0')
4735 rn = NULL;
4736
4737 wpa_s->radio = radio_add_interface(wpa_s, rn);
4738 if (wpa_s->radio == NULL)
4739 return -1;
4740
4741 return 0;
4742}
4743
4744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004745static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4746 struct wpa_interface *iface)
4747{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004748 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004749 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004750
4751 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4752 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4753 iface->confname ? iface->confname : "N/A",
4754 iface->driver ? iface->driver : "default",
4755 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4756 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4757
4758 if (iface->confname) {
4759#ifdef CONFIG_BACKEND_FILE
4760 wpa_s->confname = os_rel2abs_path(iface->confname);
4761 if (wpa_s->confname == NULL) {
4762 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4763 "for configuration file '%s'.",
4764 iface->confname);
4765 return -1;
4766 }
4767 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4768 iface->confname, wpa_s->confname);
4769#else /* CONFIG_BACKEND_FILE */
4770 wpa_s->confname = os_strdup(iface->confname);
4771#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004772 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004773 if (wpa_s->conf == NULL) {
4774 wpa_printf(MSG_ERROR, "Failed to read or parse "
4775 "configuration '%s'.", wpa_s->confname);
4776 return -1;
4777 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004778 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4779 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004780
4781 /*
4782 * Override ctrl_interface and driver_param if set on command
4783 * line.
4784 */
4785 if (iface->ctrl_interface) {
4786 os_free(wpa_s->conf->ctrl_interface);
4787 wpa_s->conf->ctrl_interface =
4788 os_strdup(iface->ctrl_interface);
4789 }
4790
4791 if (iface->driver_param) {
4792 os_free(wpa_s->conf->driver_param);
4793 wpa_s->conf->driver_param =
4794 os_strdup(iface->driver_param);
4795 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004796
4797 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4798 os_free(wpa_s->conf->ctrl_interface);
4799 wpa_s->conf->ctrl_interface = NULL;
4800 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004801 } else
4802 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4803 iface->driver_param);
4804
4805 if (wpa_s->conf == NULL) {
4806 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4807 return -1;
4808 }
4809
4810 if (iface->ifname == NULL) {
4811 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4812 return -1;
4813 }
4814 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4815 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4816 iface->ifname);
4817 return -1;
4818 }
4819 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4820
4821 if (iface->bridge_ifname) {
4822 if (os_strlen(iface->bridge_ifname) >=
4823 sizeof(wpa_s->bridge_ifname)) {
4824 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4825 "name '%s'.", iface->bridge_ifname);
4826 return -1;
4827 }
4828 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4829 sizeof(wpa_s->bridge_ifname));
4830 }
4831
4832 /* RSNA Supplicant Key Management - INITIALIZE */
4833 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4834 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4835
4836 /* Initialize driver interface and register driver event handler before
4837 * L2 receive handler so that association events are processed before
4838 * EAPOL-Key packets if both become available for the same select()
4839 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004840 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004841 return -1;
4842
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004843 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4844 return -1;
4845
4846 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4847 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4848 NULL);
4849 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4850
4851 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4852 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4853 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4854 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4855 "dot11RSNAConfigPMKLifetime");
4856 return -1;
4857 }
4858
4859 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4860 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4861 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4862 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4863 "dot11RSNAConfigPMKReauthThreshold");
4864 return -1;
4865 }
4866
4867 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4868 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4869 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4870 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4871 "dot11RSNAConfigSATimeout");
4872 return -1;
4873 }
4874
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004875 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4876 &wpa_s->hw.num_modes,
4877 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004878 if (wpa_s->hw.modes) {
4879 u16 i;
4880
4881 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4882 if (wpa_s->hw.modes[i].vht_capab) {
4883 wpa_s->hw_capab = CAPAB_VHT;
4884 break;
4885 }
4886
4887 if (wpa_s->hw.modes[i].ht_capab &
4888 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4889 wpa_s->hw_capab = CAPAB_HT40;
4890 else if (wpa_s->hw.modes[i].ht_capab &&
4891 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4892 wpa_s->hw_capab = CAPAB_HT;
4893 }
4894 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004895
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004896 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4897 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004898 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004899 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004900 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004901 wpa_s->drv_smps_modes = capa.smps_modes;
4902 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004903 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004904 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004905 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004906 wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
4907 wpa_s->max_sched_scan_plan_interval =
4908 capa.max_sched_scan_plan_interval;
4909 wpa_s->max_sched_scan_plan_iterations =
4910 capa.max_sched_scan_plan_iterations;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004911 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4912 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004913 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4914 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004915 wpa_s->extended_capa = capa.extended_capa;
4916 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4917 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004918 wpa_s->num_multichan_concurrent =
4919 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004920 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4921
4922 if (capa.mac_addr_rand_scan_supported)
4923 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4924 if (wpa_s->sched_scan_supported &&
4925 capa.mac_addr_rand_sched_scan_supported)
4926 wpa_s->mac_addr_rand_supported |=
4927 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004928 }
4929 if (wpa_s->max_remain_on_chan == 0)
4930 wpa_s->max_remain_on_chan = 1000;
4931
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004932 /*
4933 * Only take p2p_mgmt parameters when P2P Device is supported.
4934 * Doing it here as it determines whether l2_packet_init() will be done
4935 * during wpa_supplicant_driver_init().
4936 */
4937 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4938 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4939 else
4940 iface->p2p_mgmt = 1;
4941
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004942 if (wpa_s->num_multichan_concurrent == 0)
4943 wpa_s->num_multichan_concurrent = 1;
4944
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004945 if (wpa_supplicant_driver_init(wpa_s) < 0)
4946 return -1;
4947
4948#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004949 if ((!iface->p2p_mgmt ||
4950 !(wpa_s->drv_flags &
4951 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4952 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004953 return -1;
4954#endif /* CONFIG_TDLS */
4955
4956 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4957 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4958 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4959 return -1;
4960 }
4961
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004962#ifdef CONFIG_FST
4963 if (wpa_s->conf->fst_group_id) {
4964 struct fst_iface_cfg cfg;
4965 struct fst_wpa_obj iface_obj;
4966
4967 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4968 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4969 sizeof(cfg.group_id));
4970 cfg.priority = wpa_s->conf->fst_priority;
4971 cfg.llt = wpa_s->conf->fst_llt;
4972
4973 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4974 &iface_obj, &cfg);
4975 if (!wpa_s->fst) {
4976 wpa_msg(wpa_s, MSG_ERROR,
4977 "FST: Cannot attach iface %s to group %s",
4978 wpa_s->ifname, cfg.group_id);
4979 return -1;
4980 }
4981 }
4982#endif /* CONFIG_FST */
4983
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004984 if (wpas_wps_init(wpa_s))
4985 return -1;
4986
4987 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4988 return -1;
4989 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4990
4991 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4992 if (wpa_s->ctrl_iface == NULL) {
4993 wpa_printf(MSG_ERROR,
4994 "Failed to initialize control interface '%s'.\n"
4995 "You may have another wpa_supplicant process "
4996 "already running or the file was\n"
4997 "left by an unclean termination of wpa_supplicant "
4998 "in which case you will need\n"
4999 "to manually remove this file before starting "
5000 "wpa_supplicant again.\n",
5001 wpa_s->conf->ctrl_interface);
5002 return -1;
5003 }
5004
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005005 wpa_s->gas = gas_query_init(wpa_s);
5006 if (wpa_s->gas == NULL) {
5007 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
5008 return -1;
5009 }
5010
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005011 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005012 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
5013 return -1;
5014 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005015
5016 if (wpa_bss_init(wpa_s) < 0)
5017 return -1;
5018
Paul Stewart092955c2017-02-06 09:13:09 -08005019#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5020#ifdef CONFIG_MESH
5021 dl_list_init(&wpa_s->mesh_external_pmksa_cache);
5022#endif /* CONFIG_MESH */
5023#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5024
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005025 /*
5026 * Set Wake-on-WLAN triggers, if configured.
5027 * Note: We don't restore/remove the triggers on shutdown (it doesn't
5028 * have effect anyway when the interface is down).
5029 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005030 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07005031 return -1;
5032
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005033#ifdef CONFIG_EAP_PROXY
5034{
5035 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005036 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
5037 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005038 if (wpa_s->mnc_len > 0) {
5039 wpa_s->imsi[len] = '\0';
5040 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
5041 wpa_s->imsi, wpa_s->mnc_len);
5042 } else {
5043 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
5044 }
5045}
5046#endif /* CONFIG_EAP_PROXY */
5047
Dmitry Shmidt04949592012-07-19 12:16:46 -07005048 if (pcsc_reader_init(wpa_s) < 0)
5049 return -1;
5050
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005051 if (wpas_init_ext_pw(wpa_s) < 0)
5052 return -1;
5053
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005054 wpas_rrm_reset(wpa_s);
5055
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005056 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5057
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005058#ifdef CONFIG_HS20
5059 hs20_init(wpa_s);
5060#endif /* CONFIG_HS20 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005061#ifdef CONFIG_MBO
5062 wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
5063#endif /* CONFIG_MBO */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08005064
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07005065 wpa_supplicant_set_default_scan_ies(wpa_s);
5066
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005067 return 0;
5068}
5069
5070
5071static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005072 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005073{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005074 struct wpa_global *global = wpa_s->global;
5075 struct wpa_supplicant *iface, *prev;
5076
5077 if (wpa_s == wpa_s->parent)
5078 wpas_p2p_group_remove(wpa_s, "*");
5079
5080 iface = global->ifaces;
5081 while (iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005082 if (iface->p2pdev == wpa_s)
5083 iface->p2pdev = iface->parent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005084 if (iface == wpa_s || iface->parent != wpa_s) {
5085 iface = iface->next;
5086 continue;
5087 }
5088 wpa_printf(MSG_DEBUG,
5089 "Remove remaining child interface %s from parent %s",
5090 iface->ifname, wpa_s->ifname);
5091 prev = iface;
5092 iface = iface->next;
5093 wpa_supplicant_remove_iface(global, prev, terminate);
5094 }
5095
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005096 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005097 if (wpa_s->drv_priv) {
5098 wpa_supplicant_deauthenticate(wpa_s,
5099 WLAN_REASON_DEAUTH_LEAVING);
5100
5101 wpa_drv_set_countermeasures(wpa_s, 0);
5102 wpa_clear_keys(wpa_s, NULL);
5103 }
5104
5105 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005106 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005107
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005108 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005109 radio_remove_interface(wpa_s);
5110
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005111#ifdef CONFIG_FST
5112 if (wpa_s->fst) {
5113 fst_detach(wpa_s->fst);
5114 wpa_s->fst = NULL;
5115 }
5116 if (wpa_s->received_mb_ies) {
5117 wpabuf_free(wpa_s->received_mb_ies);
5118 wpa_s->received_mb_ies = NULL;
5119 }
5120#endif /* CONFIG_FST */
5121
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005122 if (wpa_s->drv_priv)
5123 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005124
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005125 if (notify)
5126 wpas_notify_iface_removed(wpa_s);
5127
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005128 if (terminate)
5129 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005130
5131 if (wpa_s->ctrl_iface) {
5132 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
5133 wpa_s->ctrl_iface = NULL;
5134 }
5135
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005136#ifdef CONFIG_MESH
5137 if (wpa_s->ifmsh) {
5138 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
5139 wpa_s->ifmsh = NULL;
5140 }
5141#endif /* CONFIG_MESH */
5142
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005143 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07005144 wpa_config_free(wpa_s->conf);
5145 wpa_s->conf = NULL;
5146 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005147
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07005148 os_free(wpa_s->ssids_from_scan_req);
5149
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005150 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005151}
5152
5153
Dmitry Shmidte4663042016-04-04 10:07:49 -07005154#ifdef CONFIG_MATCH_IFACE
5155
5156/**
5157 * wpa_supplicant_match_iface - Match an interface description to a name
5158 * @global: Pointer to global data from wpa_supplicant_init()
5159 * @ifname: Name of the interface to match
5160 * Returns: Pointer to the created interface description or %NULL on failure
5161 */
5162struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
5163 const char *ifname)
5164{
5165 int i;
5166 struct wpa_interface *iface, *miface;
5167
5168 for (i = 0; i < global->params.match_iface_count; i++) {
5169 miface = &global->params.match_ifaces[i];
5170 if (!miface->ifname ||
5171 fnmatch(miface->ifname, ifname, 0) == 0) {
5172 iface = os_zalloc(sizeof(*iface));
5173 if (!iface)
5174 return NULL;
5175 *iface = *miface;
5176 iface->ifname = ifname;
5177 return iface;
5178 }
5179 }
5180
5181 return NULL;
5182}
5183
5184
5185/**
5186 * wpa_supplicant_match_existing - Match existing interfaces
5187 * @global: Pointer to global data from wpa_supplicant_init()
5188 * Returns: 0 on success, -1 on failure
5189 */
5190static int wpa_supplicant_match_existing(struct wpa_global *global)
5191{
5192 struct if_nameindex *ifi, *ifp;
5193 struct wpa_supplicant *wpa_s;
5194 struct wpa_interface *iface;
5195
5196 ifp = if_nameindex();
5197 if (!ifp) {
5198 wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
5199 return -1;
5200 }
5201
5202 for (ifi = ifp; ifi->if_name; ifi++) {
5203 wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
5204 if (wpa_s)
5205 continue;
5206 iface = wpa_supplicant_match_iface(global, ifi->if_name);
5207 if (iface) {
5208 wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
5209 os_free(iface);
5210 if (wpa_s)
5211 wpa_s->matched = 1;
5212 }
5213 }
5214
5215 if_freenameindex(ifp);
5216 return 0;
5217}
5218
5219#endif /* CONFIG_MATCH_IFACE */
5220
5221
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005222/**
5223 * wpa_supplicant_add_iface - Add a new network interface
5224 * @global: Pointer to global data from wpa_supplicant_init()
5225 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005226 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005227 * Returns: Pointer to the created interface or %NULL on failure
5228 *
5229 * This function is used to add new network interfaces for %wpa_supplicant.
5230 * This can be called before wpa_supplicant_run() to add interfaces before the
5231 * main event loop has been started. In addition, new interfaces can be added
5232 * dynamically while %wpa_supplicant is already running. This could happen,
5233 * e.g., when a hotplug network adapter is inserted.
5234 */
5235struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005236 struct wpa_interface *iface,
5237 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005238{
5239 struct wpa_supplicant *wpa_s;
5240 struct wpa_interface t_iface;
5241 struct wpa_ssid *ssid;
5242
5243 if (global == NULL || iface == NULL)
5244 return NULL;
5245
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005246 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005247 if (wpa_s == NULL)
5248 return NULL;
5249
5250 wpa_s->global = global;
5251
5252 t_iface = *iface;
5253 if (global->params.override_driver) {
5254 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
5255 "('%s' -> '%s')",
5256 iface->driver, global->params.override_driver);
5257 t_iface.driver = global->params.override_driver;
5258 }
5259 if (global->params.override_ctrl_interface) {
5260 wpa_printf(MSG_DEBUG, "Override interface parameter: "
5261 "ctrl_interface ('%s' -> '%s')",
5262 iface->ctrl_interface,
5263 global->params.override_ctrl_interface);
5264 t_iface.ctrl_interface =
5265 global->params.override_ctrl_interface;
5266 }
5267 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
5268 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
5269 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005270 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005271 return NULL;
5272 }
5273
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005274 /* Notify the control interfaces about new iface */
5275 if (wpas_notify_iface_added(wpa_s)) {
5276 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
5277 return NULL;
5278 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005279
Roshan Piusd6d8b8d2016-11-08 14:45:26 -08005280 /* Notify the control interfaces about new networks for non p2p mgmt
5281 * ifaces. */
5282 if (iface->p2p_mgmt == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005283 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
5284 wpas_notify_network_added(wpa_s, ssid);
5285 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005286
5287 wpa_s->next = global->ifaces;
5288 global->ifaces = wpa_s;
5289
5290 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005291 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005292
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005293#ifdef CONFIG_P2P
5294 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005295 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005296 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005297 wpas_p2p_add_p2pdev_interface(
5298 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005299 wpa_printf(MSG_INFO,
5300 "P2P: Failed to enable P2P Device interface");
5301 /* Try to continue without. P2P will be disabled. */
5302 }
5303#endif /* CONFIG_P2P */
5304
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005305 return wpa_s;
5306}
5307
5308
5309/**
5310 * wpa_supplicant_remove_iface - Remove a network interface
5311 * @global: Pointer to global data from wpa_supplicant_init()
5312 * @wpa_s: Pointer to the network interface to be removed
5313 * Returns: 0 if interface was removed, -1 if interface was not found
5314 *
5315 * This function can be used to dynamically remove network interfaces from
5316 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
5317 * addition, this function is used to remove all remaining interfaces when
5318 * %wpa_supplicant is terminated.
5319 */
5320int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005321 struct wpa_supplicant *wpa_s,
5322 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005323{
5324 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005325#ifdef CONFIG_MESH
5326 unsigned int mesh_if_created = wpa_s->mesh_if_created;
5327 char *ifname = NULL;
5328#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005329
5330 /* Remove interface from the global list of interfaces */
5331 prev = global->ifaces;
5332 if (prev == wpa_s) {
5333 global->ifaces = wpa_s->next;
5334 } else {
5335 while (prev && prev->next != wpa_s)
5336 prev = prev->next;
5337 if (prev == NULL)
5338 return -1;
5339 prev->next = wpa_s->next;
5340 }
5341
5342 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
5343
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005344#ifdef CONFIG_MESH
5345 if (mesh_if_created) {
5346 ifname = os_strdup(wpa_s->ifname);
5347 if (ifname == NULL) {
5348 wpa_dbg(wpa_s, MSG_ERROR,
5349 "mesh: Failed to malloc ifname");
5350 return -1;
5351 }
5352 }
5353#endif /* CONFIG_MESH */
5354
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005355 if (global->p2p_group_formation == wpa_s)
5356 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005357 if (global->p2p_invite_group == wpa_s)
5358 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005359 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005360
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005361#ifdef CONFIG_MESH
5362 if (mesh_if_created) {
Paul Stewart092955c2017-02-06 09:13:09 -08005363 wpa_drv_if_remove(wpa_s->parent, WPA_IF_MESH, ifname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005364 os_free(ifname);
5365 }
5366#endif /* CONFIG_MESH */
5367
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005368 return 0;
5369}
5370
5371
5372/**
5373 * wpa_supplicant_get_eap_mode - Get the current EAP mode
5374 * @wpa_s: Pointer to the network interface
5375 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
5376 */
5377const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
5378{
5379 const char *eapol_method;
5380
5381 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
5382 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
5383 return "NO-EAP";
5384 }
5385
5386 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
5387 if (eapol_method == NULL)
5388 return "UNKNOWN-EAP";
5389
5390 return eapol_method;
5391}
5392
5393
5394/**
5395 * wpa_supplicant_get_iface - Get a new network interface
5396 * @global: Pointer to global data from wpa_supplicant_init()
5397 * @ifname: Interface name
5398 * Returns: Pointer to the interface or %NULL if not found
5399 */
5400struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
5401 const char *ifname)
5402{
5403 struct wpa_supplicant *wpa_s;
5404
5405 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5406 if (os_strcmp(wpa_s->ifname, ifname) == 0)
5407 return wpa_s;
5408 }
5409 return NULL;
5410}
5411
5412
5413#ifndef CONFIG_NO_WPA_MSG
5414static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
5415{
5416 struct wpa_supplicant *wpa_s = ctx;
5417 if (wpa_s == NULL)
5418 return NULL;
5419 return wpa_s->ifname;
5420}
5421#endif /* CONFIG_NO_WPA_MSG */
5422
5423
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005424#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
5425#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
5426#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
5427
5428/* Periodic cleanup tasks */
5429static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
5430{
5431 struct wpa_global *global = eloop_ctx;
5432 struct wpa_supplicant *wpa_s;
5433
5434 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5435 wpas_periodic, global, NULL);
5436
5437#ifdef CONFIG_P2P
5438 if (global->p2p)
5439 p2p_expire_peers(global->p2p);
5440#endif /* CONFIG_P2P */
5441
5442 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5443 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
5444#ifdef CONFIG_AP
5445 ap_periodic(wpa_s);
5446#endif /* CONFIG_AP */
5447 }
5448}
5449
5450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005451/**
5452 * wpa_supplicant_init - Initialize %wpa_supplicant
5453 * @params: Parameters for %wpa_supplicant
5454 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
5455 *
5456 * This function is used to initialize %wpa_supplicant. After successful
5457 * initialization, the returned data pointer can be used to add and remove
5458 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
5459 */
5460struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
5461{
5462 struct wpa_global *global;
5463 int ret, i;
5464
5465 if (params == NULL)
5466 return NULL;
5467
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005468#ifdef CONFIG_DRIVER_NDIS
5469 {
5470 void driver_ndis_init_ops(void);
5471 driver_ndis_init_ops();
5472 }
5473#endif /* CONFIG_DRIVER_NDIS */
5474
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005475#ifndef CONFIG_NO_WPA_MSG
5476 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5477#endif /* CONFIG_NO_WPA_MSG */
5478
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005479 if (params->wpa_debug_file_path)
5480 wpa_debug_open_file(params->wpa_debug_file_path);
5481 else
5482 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005483 if (params->wpa_debug_syslog)
5484 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005485 if (params->wpa_debug_tracing) {
5486 ret = wpa_debug_open_linux_tracing();
5487 if (ret) {
5488 wpa_printf(MSG_ERROR,
5489 "Failed to enable trace logging");
5490 return NULL;
5491 }
5492 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005493
5494 ret = eap_register_methods();
5495 if (ret) {
5496 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5497 if (ret == -2)
5498 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5499 "the same EAP type.");
5500 return NULL;
5501 }
5502
5503 global = os_zalloc(sizeof(*global));
5504 if (global == NULL)
5505 return NULL;
5506 dl_list_init(&global->p2p_srv_bonjour);
5507 dl_list_init(&global->p2p_srv_upnp);
5508 global->params.daemonize = params->daemonize;
5509 global->params.wait_for_monitor = params->wait_for_monitor;
5510 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5511 if (params->pid_file)
5512 global->params.pid_file = os_strdup(params->pid_file);
5513 if (params->ctrl_interface)
5514 global->params.ctrl_interface =
5515 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005516 if (params->ctrl_interface_group)
5517 global->params.ctrl_interface_group =
5518 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005519 if (params->override_driver)
5520 global->params.override_driver =
5521 os_strdup(params->override_driver);
5522 if (params->override_ctrl_interface)
5523 global->params.override_ctrl_interface =
5524 os_strdup(params->override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005525#ifdef CONFIG_MATCH_IFACE
5526 global->params.match_iface_count = params->match_iface_count;
5527 if (params->match_iface_count) {
5528 global->params.match_ifaces =
5529 os_calloc(params->match_iface_count,
5530 sizeof(struct wpa_interface));
5531 os_memcpy(global->params.match_ifaces,
5532 params->match_ifaces,
5533 params->match_iface_count *
5534 sizeof(struct wpa_interface));
5535 }
5536#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005537#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005538 if (params->conf_p2p_dev)
5539 global->params.conf_p2p_dev =
5540 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005541#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005542 wpa_debug_level = global->params.wpa_debug_level =
5543 params->wpa_debug_level;
5544 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5545 params->wpa_debug_show_keys;
5546 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5547 params->wpa_debug_timestamp;
5548
5549 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5550
5551 if (eloop_init()) {
5552 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5553 wpa_supplicant_deinit(global);
5554 return NULL;
5555 }
5556
Jouni Malinen75ecf522011-06-27 15:19:46 -07005557 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005558
5559 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5560 if (global->ctrl_iface == NULL) {
5561 wpa_supplicant_deinit(global);
5562 return NULL;
5563 }
5564
5565 if (wpas_notify_supplicant_initialized(global)) {
5566 wpa_supplicant_deinit(global);
5567 return NULL;
5568 }
5569
5570 for (i = 0; wpa_drivers[i]; i++)
5571 global->drv_count++;
5572 if (global->drv_count == 0) {
5573 wpa_printf(MSG_ERROR, "No drivers enabled");
5574 wpa_supplicant_deinit(global);
5575 return NULL;
5576 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005577 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005578 if (global->drv_priv == NULL) {
5579 wpa_supplicant_deinit(global);
5580 return NULL;
5581 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005582
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005583#ifdef CONFIG_WIFI_DISPLAY
5584 if (wifi_display_init(global) < 0) {
5585 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5586 wpa_supplicant_deinit(global);
5587 return NULL;
5588 }
5589#endif /* CONFIG_WIFI_DISPLAY */
5590
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005591 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5592 wpas_periodic, global, NULL);
5593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005594 return global;
5595}
5596
5597
5598/**
5599 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5600 * @global: Pointer to global data from wpa_supplicant_init()
5601 * Returns: 0 after successful event loop run, -1 on failure
5602 *
5603 * This function starts the main event loop and continues running as long as
5604 * there are any remaining events. In most cases, this function is running as
5605 * long as the %wpa_supplicant process in still in use.
5606 */
5607int wpa_supplicant_run(struct wpa_global *global)
5608{
5609 struct wpa_supplicant *wpa_s;
5610
5611 if (global->params.daemonize &&
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08005612 (wpa_supplicant_daemon(global->params.pid_file) ||
5613 eloop_sock_requeue()))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005614 return -1;
5615
Dmitry Shmidte4663042016-04-04 10:07:49 -07005616#ifdef CONFIG_MATCH_IFACE
5617 if (wpa_supplicant_match_existing(global))
5618 return -1;
5619#endif
5620
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005621 if (global->params.wait_for_monitor) {
5622 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005623 if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005624 wpa_supplicant_ctrl_iface_wait(
5625 wpa_s->ctrl_iface);
5626 }
5627
5628 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5629 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5630
5631 eloop_run();
5632
5633 return 0;
5634}
5635
5636
5637/**
5638 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5639 * @global: Pointer to global data from wpa_supplicant_init()
5640 *
5641 * This function is called to deinitialize %wpa_supplicant and to free all
5642 * allocated resources. Remaining network interfaces will also be removed.
5643 */
5644void wpa_supplicant_deinit(struct wpa_global *global)
5645{
5646 int i;
5647
5648 if (global == NULL)
5649 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005650
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005651 eloop_cancel_timeout(wpas_periodic, global, NULL);
5652
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005653#ifdef CONFIG_WIFI_DISPLAY
5654 wifi_display_deinit(global);
5655#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005656
5657 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005658 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005659
5660 if (global->ctrl_iface)
5661 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5662
5663 wpas_notify_supplicant_deinitialized(global);
5664
5665 eap_peer_unregister_methods();
5666#ifdef CONFIG_AP
5667 eap_server_unregister_methods();
5668#endif /* CONFIG_AP */
5669
5670 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5671 if (!global->drv_priv[i])
5672 continue;
5673 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5674 }
5675 os_free(global->drv_priv);
5676
5677 random_deinit();
5678
5679 eloop_destroy();
5680
5681 if (global->params.pid_file) {
5682 os_daemonize_terminate(global->params.pid_file);
5683 os_free(global->params.pid_file);
5684 }
5685 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005686 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005687 os_free(global->params.override_driver);
5688 os_free(global->params.override_ctrl_interface);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005689#ifdef CONFIG_MATCH_IFACE
5690 os_free(global->params.match_ifaces);
5691#endif /* CONFIG_MATCH_IFACE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005692#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005693 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005694#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005695
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005696 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005697 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005698 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005699
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005700 os_free(global);
5701 wpa_debug_close_syslog();
5702 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005703 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005704}
5705
5706
5707void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5708{
5709 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5710 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5711 char country[3];
5712 country[0] = wpa_s->conf->country[0];
5713 country[1] = wpa_s->conf->country[1];
5714 country[2] = '\0';
5715 if (wpa_drv_set_country(wpa_s, country) < 0) {
5716 wpa_printf(MSG_ERROR, "Failed to set country code "
5717 "'%s'", country);
5718 }
5719 }
5720
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005721 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5722 wpas_init_ext_pw(wpa_s);
5723
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005724 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
5725 wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
5726
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005727#ifdef CONFIG_WPS
5728 wpas_wps_update_config(wpa_s);
5729#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005730 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005731 wpa_s->conf->changed_parameters = 0;
5732}
5733
5734
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005735void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005736{
5737 int i;
5738
5739 for (i = 0; i < *num_freqs; i++) {
5740 if (freqs[i] == freq)
5741 return;
5742 }
5743
5744 freqs[*num_freqs] = freq;
5745 (*num_freqs)++;
5746}
5747
5748
5749static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5750{
5751 struct wpa_bss *bss, *cbss;
5752 const int max_freqs = 10;
5753 int *freqs;
5754 int num_freqs = 0;
5755
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005756 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005757 if (freqs == NULL)
5758 return NULL;
5759
5760 cbss = wpa_s->current_bss;
5761
5762 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5763 if (bss == cbss)
5764 continue;
5765 if (bss->ssid_len == cbss->ssid_len &&
5766 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5767 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5768 add_freq(freqs, &num_freqs, bss->freq);
5769 if (num_freqs == max_freqs)
5770 break;
5771 }
5772 }
5773
5774 if (num_freqs == 0) {
5775 os_free(freqs);
5776 freqs = NULL;
5777 }
5778
5779 return freqs;
5780}
5781
5782
5783void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5784{
5785 int timeout;
5786 int count;
5787 int *freqs = NULL;
5788
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005789 wpas_connect_work_done(wpa_s);
5790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005791 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005792 * Remove possible authentication timeout since the connection failed.
5793 */
5794 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5795
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005796 /*
5797 * There is no point in blacklisting the AP if this event is
5798 * generated based on local request to disconnect.
5799 */
5800 if (wpa_s->own_disconnect_req) {
5801 wpa_s->own_disconnect_req = 0;
5802 wpa_dbg(wpa_s, MSG_DEBUG,
5803 "Ignore connection failure due to local request to disconnect");
5804 return;
5805 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005806 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005807 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5808 "indication since interface has been put into "
5809 "disconnected state");
5810 return;
5811 }
5812
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005813 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005814 * Add the failed BSSID into the blacklist and speed up next scan
5815 * attempt if there could be other APs that could accept association.
5816 * The current blacklist count indicates how many times we have tried
5817 * connecting to this AP and multiple attempts mean that other APs are
5818 * either not available or has already been tried, so that we can start
5819 * increasing the delay here to avoid constant scanning.
5820 */
5821 count = wpa_blacklist_add(wpa_s, bssid);
5822 if (count == 1 && wpa_s->current_bss) {
5823 /*
5824 * This BSS was not in the blacklist before. If there is
5825 * another BSS available for the same ESS, we should try that
5826 * next. Otherwise, we may as well try this one once more
5827 * before allowing other, likely worse, ESSes to be considered.
5828 */
5829 freqs = get_bss_freqs_in_ess(wpa_s);
5830 if (freqs) {
5831 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5832 "has been seen; try it next");
5833 wpa_blacklist_add(wpa_s, bssid);
5834 /*
5835 * On the next scan, go through only the known channels
5836 * used in this ESS based on previous scans to speed up
5837 * common load balancing use case.
5838 */
5839 os_free(wpa_s->next_scan_freqs);
5840 wpa_s->next_scan_freqs = freqs;
5841 }
5842 }
5843
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005844 /*
5845 * Add previous failure count in case the temporary blacklist was
5846 * cleared due to no other BSSes being available.
5847 */
5848 count += wpa_s->extra_blacklist_count;
5849
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005850 if (count > 3 && wpa_s->current_ssid) {
5851 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5852 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005853 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005854 }
5855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005856 switch (count) {
5857 case 1:
5858 timeout = 100;
5859 break;
5860 case 2:
5861 timeout = 500;
5862 break;
5863 case 3:
5864 timeout = 1000;
5865 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005866 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005867 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005868 break;
5869 default:
5870 timeout = 10000;
5871 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005872 }
5873
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005874 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5875 "ms", count, timeout);
5876
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005877 /*
5878 * TODO: if more than one possible AP is available in scan results,
5879 * could try the other ones before requesting a new scan.
5880 */
5881 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5882 1000 * (timeout % 1000));
5883}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005884
5885
5886int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5887{
5888 return wpa_s->conf->ap_scan == 2 ||
5889 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5890}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005891
Dmitry Shmidt04949592012-07-19 12:16:46 -07005892
Roshan Pius57ffbcf2016-09-27 09:12:46 -07005893#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW) || defined (CONFIG_CTRL_IFACE_HIDL)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005894int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5895 struct wpa_ssid *ssid,
5896 const char *field,
5897 const char *value)
5898{
5899#ifdef IEEE8021X_EAPOL
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005900 enum wpa_ctrl_req_type rtype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005901
5902 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5903 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5904 (const u8 *) value, os_strlen(value));
5905
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005906 rtype = wpa_supplicant_ctrl_req_from_string(field);
5907 return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
5908#else /* IEEE8021X_EAPOL */
5909 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5910 return -1;
5911#endif /* IEEE8021X_EAPOL */
5912}
5913
5914int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5915 struct wpa_ssid *ssid,
5916 enum wpa_ctrl_req_type rtype,
5917 const char *value)
5918{
5919#ifdef IEEE8021X_EAPOL
5920 struct eap_peer_config *eap = &ssid->eap;
5921
5922 switch (rtype) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005923 case WPA_CTRL_REQ_EAP_IDENTITY:
5924 os_free(eap->identity);
5925 eap->identity = (u8 *) os_strdup(value);
5926 eap->identity_len = os_strlen(value);
5927 eap->pending_req_identity = 0;
5928 if (ssid == wpa_s->current_ssid)
5929 wpa_s->reassociate = 1;
5930 break;
5931 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005932 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005933 eap->password = (u8 *) os_strdup(value);
5934 eap->password_len = os_strlen(value);
5935 eap->pending_req_password = 0;
5936 if (ssid == wpa_s->current_ssid)
5937 wpa_s->reassociate = 1;
5938 break;
5939 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005940 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005941 eap->new_password = (u8 *) os_strdup(value);
5942 eap->new_password_len = os_strlen(value);
5943 eap->pending_req_new_password = 0;
5944 if (ssid == wpa_s->current_ssid)
5945 wpa_s->reassociate = 1;
5946 break;
5947 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005948 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005949 eap->pin = os_strdup(value);
5950 eap->pending_req_pin = 0;
5951 if (ssid == wpa_s->current_ssid)
5952 wpa_s->reassociate = 1;
5953 break;
5954 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005955 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005956 eap->otp = (u8 *) os_strdup(value);
5957 eap->otp_len = os_strlen(value);
5958 os_free(eap->pending_req_otp);
5959 eap->pending_req_otp = NULL;
5960 eap->pending_req_otp_len = 0;
5961 break;
5962 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005963 str_clear_free(eap->private_key_passwd);
5964 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005965 eap->pending_req_passphrase = 0;
5966 if (ssid == wpa_s->current_ssid)
5967 wpa_s->reassociate = 1;
5968 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005969 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005970 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005971 eap->external_sim_resp = os_strdup(value);
5972 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005973 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5974 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5975 return -1;
5976 ssid->mem_only_psk = 1;
5977 if (ssid->passphrase)
5978 wpa_config_update_psk(ssid);
5979 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5980 wpa_supplicant_req_scan(wpa_s, 0, 0);
5981 break;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005982 case WPA_CTRL_REQ_EXT_CERT_CHECK:
5983 if (eap->pending_ext_cert_check != PENDING_CHECK)
5984 return -1;
5985 if (os_strcmp(value, "good") == 0)
5986 eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
5987 else if (os_strcmp(value, "bad") == 0)
5988 eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
5989 else
5990 return -1;
5991 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005992 default:
Roshan Pius71a6b8a2016-08-17 13:04:08 -07005993 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown type %d", rtype);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005994 return -1;
5995 }
5996
5997 return 0;
5998#else /* IEEE8021X_EAPOL */
5999 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
6000 return -1;
6001#endif /* IEEE8021X_EAPOL */
6002}
Roshan Pius57ffbcf2016-09-27 09:12:46 -07006003#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW || CONFIG_CTRL_IFACE_HIDL */
Dmitry Shmidt04949592012-07-19 12:16:46 -07006004
6005
6006int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6007{
6008 int i;
6009 unsigned int drv_enc;
6010
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006011 if (wpa_s->p2p_mgmt)
6012 return 1; /* no normal network profiles on p2p_mgmt interface */
6013
Dmitry Shmidt04949592012-07-19 12:16:46 -07006014 if (ssid == NULL)
6015 return 1;
6016
6017 if (ssid->disabled)
6018 return 1;
6019
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006020 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07006021 drv_enc = wpa_s->drv_enc;
6022 else
6023 drv_enc = (unsigned int) -1;
6024
6025 for (i = 0; i < NUM_WEP_KEYS; i++) {
6026 size_t len = ssid->wep_key_len[i];
6027 if (len == 0)
6028 continue;
6029 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
6030 continue;
6031 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
6032 continue;
6033 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
6034 continue;
6035 return 1; /* invalid WEP key */
6036 }
6037
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006038 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07006039 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
6040 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006041 return 1;
6042
Dmitry Shmidt04949592012-07-19 12:16:46 -07006043 return 0;
6044}
6045
6046
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006047int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
6048{
6049#ifdef CONFIG_IEEE80211W
6050 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
6051 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
6052 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
6053 /*
6054 * Driver does not support BIP -- ignore pmf=1 default
6055 * since the connection with PMF would fail and the
6056 * configuration does not require PMF to be enabled.
6057 */
6058 return NO_MGMT_FRAME_PROTECTION;
6059 }
6060
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006061 if (ssid &&
6062 (ssid->key_mgmt &
6063 ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
6064 WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
6065 /*
6066 * Do not use the default PMF value for non-RSN networks
6067 * since PMF is available only with RSN and pmf=2
6068 * configuration would otherwise prevent connections to
6069 * all open networks.
6070 */
6071 return NO_MGMT_FRAME_PROTECTION;
6072 }
6073
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006074 return wpa_s->conf->pmf;
6075 }
6076
6077 return ssid->ieee80211w;
6078#else /* CONFIG_IEEE80211W */
6079 return NO_MGMT_FRAME_PROTECTION;
6080#endif /* CONFIG_IEEE80211W */
6081}
6082
6083
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006084int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006085{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006086 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006087 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07006088 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006089 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07006090 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006091}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006092
6093
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006094void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006095{
6096 struct wpa_ssid *ssid = wpa_s->current_ssid;
6097 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006098 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006099
6100 if (ssid == NULL) {
6101 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
6102 "SSID block");
6103 return;
6104 }
6105
6106 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
6107 return;
6108
6109 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07006110
6111#ifdef CONFIG_P2P
6112 if (ssid->p2p_group &&
6113 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
6114 /*
6115 * Skip the wait time since there is a short timeout on the
6116 * connection to a P2P group.
6117 */
6118 return;
6119 }
6120#endif /* CONFIG_P2P */
6121
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006122 if (ssid->auth_failures > 50)
6123 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006124 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006125 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006126 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006127 dur = 90;
6128 else if (ssid->auth_failures > 3)
6129 dur = 60;
6130 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006131 dur = 30;
6132 else if (ssid->auth_failures > 1)
6133 dur = 20;
6134 else
6135 dur = 10;
6136
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006137 if (ssid->auth_failures > 1 &&
6138 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
6139 dur += os_random() % (ssid->auth_failures * 10);
6140
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006141 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006142 if (now.sec + dur <= ssid->disabled_until.sec)
6143 return;
6144
6145 ssid->disabled_until.sec = now.sec + dur;
6146
6147 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006148 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006149 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07006150 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006151}
6152
6153
6154void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
6155 struct wpa_ssid *ssid, int clear_failures)
6156{
6157 if (ssid == NULL)
6158 return;
6159
6160 if (ssid->disabled_until.sec) {
6161 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
6162 "id=%d ssid=\"%s\"",
6163 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
6164 }
6165 ssid->disabled_until.sec = 0;
6166 ssid->disabled_until.usec = 0;
6167 if (clear_failures)
6168 ssid->auth_failures = 0;
6169}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006170
6171
6172int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
6173{
6174 size_t i;
6175
6176 if (wpa_s->disallow_aps_bssid == NULL)
6177 return 0;
6178
6179 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
6180 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
6181 bssid, ETH_ALEN) == 0)
6182 return 1;
6183 }
6184
6185 return 0;
6186}
6187
6188
6189int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
6190 size_t ssid_len)
6191{
6192 size_t i;
6193
6194 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
6195 return 0;
6196
6197 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
6198 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
6199 if (ssid_len == s->ssid_len &&
6200 os_memcmp(ssid, s->ssid, ssid_len) == 0)
6201 return 1;
6202 }
6203
6204 return 0;
6205}
6206
6207
6208/**
6209 * wpas_request_connection - Request a new connection
6210 * @wpa_s: Pointer to the network interface
6211 *
6212 * This function is used to request a new connection to be found. It will mark
6213 * the interface to allow reassociation and request a new scan to find a
6214 * suitable network to connect to.
6215 */
6216void wpas_request_connection(struct wpa_supplicant *wpa_s)
6217{
6218 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006219 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006220 wpa_supplicant_reinit_autoscan(wpa_s);
6221 wpa_s->extra_blacklist_count = 0;
6222 wpa_s->disconnected = 0;
6223 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006224
6225 if (wpa_supplicant_fast_associate(wpa_s) != 1)
6226 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006227 else
6228 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006229}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006230
Roshan Pius02242d72016-08-09 15:31:48 -07006231/**
6232 * wpas_request_disconnection - Request disconnection
6233 * @wpa_s: Pointer to the network interface
6234 *
6235 * This function is used to request disconnection from the currently connected
6236 * network. This will stop any ongoing scans and initiate deauthentication.
6237 */
6238void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
6239{
6240#ifdef CONFIG_SME
6241 wpa_s->sme.prev_bssid_set = 0;
6242#endif /* CONFIG_SME */
6243 wpa_s->reassociate = 0;
6244 wpa_s->disconnected = 1;
6245 wpa_supplicant_cancel_sched_scan(wpa_s);
6246 wpa_supplicant_cancel_scan(wpa_s);
6247 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
6248 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
6249}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006250
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07006251
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006252void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
6253 struct wpa_used_freq_data *freqs_data,
6254 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006255{
6256 unsigned int i;
6257
6258 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
6259 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006260 for (i = 0; i < len; i++) {
6261 struct wpa_used_freq_data *cur = &freqs_data[i];
6262 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
6263 i, cur->freq, cur->flags);
6264 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006265}
6266
6267
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006268/*
6269 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006270 * are using the same radio as the current interface, and in addition, get
6271 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006272 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006273int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
6274 struct wpa_used_freq_data *freqs_data,
6275 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006276{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006277 struct wpa_supplicant *ifs;
6278 u8 bssid[ETH_ALEN];
6279 int freq;
6280 unsigned int idx = 0, i;
6281
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006282 wpa_dbg(wpa_s, MSG_DEBUG,
6283 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006284 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006285
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006286 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
6287 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006288 if (idx == len)
6289 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006290
6291 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
6292 continue;
6293
6294 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006295 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
6296 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006297 freq = ifs->current_ssid->frequency;
6298 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
6299 freq = ifs->assoc_freq;
6300 else
6301 continue;
6302
6303 /* Hold only distinct freqs */
6304 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006305 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006306 break;
6307
6308 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006309 freqs_data[idx++].freq = freq;
6310
6311 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006312 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006313 WPA_FREQ_USED_BY_P2P_CLIENT :
6314 WPA_FREQ_USED_BY_INFRA_STATION;
6315 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006316 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08006317
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006318 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006319 return idx;
6320}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006321
6322
6323/*
6324 * Find the operating frequencies of any of the virtual interfaces that
6325 * are using the same radio as the current interface.
6326 */
6327int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
6328 int *freq_array, unsigned int len)
6329{
6330 struct wpa_used_freq_data *freqs_data;
6331 int num, i;
6332
6333 os_memset(freq_array, 0, sizeof(int) * len);
6334
6335 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
6336 if (!freqs_data)
6337 return -1;
6338
6339 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
6340 for (i = 0; i < num; i++)
6341 freq_array[i] = freqs_data[i].freq;
6342
6343 os_free(freqs_data);
6344
6345 return num;
6346}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006347
6348
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006349struct wpa_supplicant *
6350wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
6351{
6352 switch (frame) {
6353#ifdef CONFIG_P2P
6354 case VENDOR_ELEM_PROBE_REQ_P2P:
6355 case VENDOR_ELEM_PROBE_RESP_P2P:
6356 case VENDOR_ELEM_PROBE_RESP_P2P_GO:
6357 case VENDOR_ELEM_BEACON_P2P_GO:
6358 case VENDOR_ELEM_P2P_PD_REQ:
6359 case VENDOR_ELEM_P2P_PD_RESP:
6360 case VENDOR_ELEM_P2P_GO_NEG_REQ:
6361 case VENDOR_ELEM_P2P_GO_NEG_RESP:
6362 case VENDOR_ELEM_P2P_GO_NEG_CONF:
6363 case VENDOR_ELEM_P2P_INV_REQ:
6364 case VENDOR_ELEM_P2P_INV_RESP:
6365 case VENDOR_ELEM_P2P_ASSOC_REQ:
6366 case VENDOR_ELEM_P2P_ASSOC_RESP:
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006367 return wpa_s->p2pdev;
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08006368#endif /* CONFIG_P2P */
6369 default:
6370 return wpa_s;
6371 }
6372}
6373
6374
6375void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
6376{
6377 unsigned int i;
6378 char buf[30];
6379
6380 wpa_printf(MSG_DEBUG, "Update vendor elements");
6381
6382 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
6383 if (wpa_s->vendor_elem[i]) {
6384 int res;
6385
6386 res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
6387 if (!os_snprintf_error(sizeof(buf), res)) {
6388 wpa_hexdump_buf(MSG_DEBUG, buf,
6389 wpa_s->vendor_elem[i]);
6390 }
6391 }
6392 }
6393
6394#ifdef CONFIG_P2P
6395 if (wpa_s->parent == wpa_s &&
6396 wpa_s->global->p2p &&
6397 !wpa_s->global->p2p_disabled)
6398 p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
6399#endif /* CONFIG_P2P */
6400}
6401
6402
6403int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
6404 const u8 *elem, size_t len)
6405{
6406 u8 *ie, *end;
6407
6408 ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
6409 end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
6410
6411 for (; ie + 1 < end; ie += 2 + ie[1]) {
6412 if (ie + len > end)
6413 break;
6414 if (os_memcmp(ie, elem, len) != 0)
6415 continue;
6416
6417 if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
6418 wpabuf_free(wpa_s->vendor_elem[frame]);
6419 wpa_s->vendor_elem[frame] = NULL;
6420 } else {
6421 os_memmove(ie, ie + len, end - (ie + len));
6422 wpa_s->vendor_elem[frame]->used -= len;
6423 }
6424 wpas_vendor_elem_update(wpa_s);
6425 return 0;
6426 }
6427
6428 return -1;
6429}
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006430
6431
6432struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
6433 u16 num_modes, enum hostapd_hw_mode mode)
6434{
6435 u16 i;
6436
6437 for (i = 0; i < num_modes; i++) {
6438 if (modes[i].mode == mode)
6439 return &modes[i];
6440 }
6441
6442 return NULL;
6443}
6444
6445
6446static struct
6447wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
6448 const u8 *bssid)
6449{
6450 struct wpa_bss_tmp_disallowed *bss;
6451
6452 dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
6453 struct wpa_bss_tmp_disallowed, list) {
6454 if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
6455 return bss;
6456 }
6457
6458 return NULL;
6459}
6460
6461
6462void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
6463 unsigned int sec)
6464{
6465 struct wpa_bss_tmp_disallowed *bss;
6466 struct os_reltime until;
6467
6468 os_get_reltime(&until);
6469 until.sec += sec;
6470
6471 bss = wpas_get_disallowed_bss(wpa_s, bssid);
6472 if (bss) {
6473 bss->disallowed_until = until;
6474 return;
6475 }
6476
6477 bss = os_malloc(sizeof(*bss));
6478 if (!bss) {
6479 wpa_printf(MSG_DEBUG,
6480 "Failed to allocate memory for temp disallow BSS");
6481 return;
6482 }
6483
6484 bss->disallowed_until = until;
6485 os_memcpy(bss->bssid, bssid, ETH_ALEN);
6486 dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
6487}
6488
6489
6490int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
6491{
6492 struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
6493 struct os_reltime now, age;
6494
6495 os_get_reltime(&now);
6496
6497 dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
6498 struct wpa_bss_tmp_disallowed, list) {
6499 if (!os_reltime_before(&now, &tmp->disallowed_until)) {
6500 /* This BSS is not disallowed anymore */
6501 dl_list_del(&tmp->list);
6502 os_free(tmp);
6503 continue;
6504 }
6505 if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
6506 bss = tmp;
6507 break;
6508 }
6509 }
6510 if (!bss)
6511 return 0;
6512
6513 os_reltime_sub(&bss->disallowed_until, &now, &age);
6514 wpa_printf(MSG_DEBUG,
6515 "BSS " MACSTR " disabled for %ld.%0ld seconds",
6516 MAC2STR(bss->bssid), age.sec, age.usec);
6517 return 1;
6518}