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