blob: b96fd8e72ea0f79c6e7f4809365b1000b8e517d2 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003 * Copyright (c) 2003-2015, 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"
14
15#include "common.h"
16#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080017#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018#include "eapol_supp/eapol_supp_sm.h"
19#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070020#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "eap_server/eap_methods.h"
22#include "rsn_supp/wpa.h"
23#include "eloop.h"
24#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070025#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "l2_packet/l2_packet.h"
27#include "wpa_supplicant_i.h"
28#include "driver_i.h"
29#include "ctrl_iface.h"
30#include "pcsc_funcs.h"
31#include "common/version.h"
32#include "rsn_supp/preauth.h"
33#include "rsn_supp/pmksa_cache.h"
34#include "common/wpa_ctrl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070035#include "common/ieee802_11_defs.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080036#include "common/hw_features_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037#include "p2p/p2p.h"
38#include "blacklist.h"
39#include "wpas_glue.h"
40#include "wps_supplicant.h"
41#include "ibss_rsn.h"
42#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080043#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070044#include "ap.h"
45#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070046#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070047#include "notify.h"
48#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070049#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070050#include "bss.h"
51#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080052#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070053#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070054#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070055#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080056#include "mesh.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070057
58const char *wpa_supplicant_version =
59"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidt807291d2015-01-27 13:40:23 -080060"Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070061
62const char *wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080063"This software may be distributed under the terms of the BSD license.\n"
64"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070065#ifdef EAP_TLS_OPENSSL
66"\nThis product includes software developed by the OpenSSL Project\n"
67"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
68#endif /* EAP_TLS_OPENSSL */
69;
70
71#ifndef CONFIG_NO_STDOUT_DEBUG
72/* Long text divided into parts in order to fit in C89 strings size limits. */
73const char *wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080074"";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075const char *wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080076"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070077"\n"
78"Redistribution and use in source and binary forms, with or without\n"
79"modification, are permitted provided that the following conditions are\n"
80"met:\n"
81"\n";
82const char *wpa_supplicant_full_license3 =
83"1. Redistributions of source code must retain the above copyright\n"
84" notice, this list of conditions and the following disclaimer.\n"
85"\n"
86"2. Redistributions in binary form must reproduce the above copyright\n"
87" notice, this list of conditions and the following disclaimer in the\n"
88" documentation and/or other materials provided with the distribution.\n"
89"\n";
90const char *wpa_supplicant_full_license4 =
91"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
92" names of its contributors may be used to endorse or promote products\n"
93" derived from this software without specific prior written permission.\n"
94"\n"
95"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
96"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
97"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
98"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
99const char *wpa_supplicant_full_license5 =
100"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
101"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
102"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
103"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
104"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
105"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
106"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
107"\n";
108#endif /* CONFIG_NO_STDOUT_DEBUG */
109
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700110/* Configure default/group WEP keys for static WEP */
111int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
112{
113 int i, set = 0;
114
115 for (i = 0; i < NUM_WEP_KEYS; i++) {
116 if (ssid->wep_key_len[i] == 0)
117 continue;
118
119 set = 1;
120 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
121 i, i == ssid->wep_tx_keyidx, NULL, 0,
122 ssid->wep_key[i], ssid->wep_key_len[i]);
123 }
124
125 return set;
126}
127
128
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700129int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
130 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700131{
132 u8 key[32];
133 size_t keylen;
134 enum wpa_alg alg;
135 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800136 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700137
138 /* IBSS/WPA-None uses only one key (Group) for both receiving and
139 * sending unicast and multicast packets. */
140
141 if (ssid->mode != WPAS_MODE_IBSS) {
142 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
143 "IBSS/ad-hoc) for WPA-None", ssid->mode);
144 return -1;
145 }
146
147 if (!ssid->psk_set) {
148 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
149 "WPA-None");
150 return -1;
151 }
152
153 switch (wpa_s->group_cipher) {
154 case WPA_CIPHER_CCMP:
155 os_memcpy(key, ssid->psk, 16);
156 keylen = 16;
157 alg = WPA_ALG_CCMP;
158 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700159 case WPA_CIPHER_GCMP:
160 os_memcpy(key, ssid->psk, 16);
161 keylen = 16;
162 alg = WPA_ALG_GCMP;
163 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700164 case WPA_CIPHER_TKIP:
165 /* WPA-None uses the same Michael MIC key for both TX and RX */
166 os_memcpy(key, ssid->psk, 16 + 8);
167 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
168 keylen = 32;
169 alg = WPA_ALG_TKIP;
170 break;
171 default:
172 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
173 "WPA-None", wpa_s->group_cipher);
174 return -1;
175 }
176
177 /* TODO: should actually remember the previously used seq#, both for TX
178 * and RX from each STA.. */
179
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800180 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
181 os_memset(key, 0, sizeof(key));
182 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700183}
184
185
186static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
187{
188 struct wpa_supplicant *wpa_s = eloop_ctx;
189 const u8 *bssid = wpa_s->bssid;
190 if (is_zero_ether_addr(bssid))
191 bssid = wpa_s->pending_bssid;
192 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
193 MAC2STR(bssid));
194 wpa_blacklist_add(wpa_s, bssid);
195 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800196 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700197 wpa_s->reassociate = 1;
198
199 /*
200 * If we timed out, the AP or the local radio may be busy.
201 * So, wait a second until scanning again.
202 */
203 wpa_supplicant_req_scan(wpa_s, 1, 0);
204}
205
206
207/**
208 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
209 * @wpa_s: Pointer to wpa_supplicant data
210 * @sec: Number of seconds after which to time out authentication
211 * @usec: Number of microseconds after which to time out authentication
212 *
213 * This function is used to schedule a timeout for the current authentication
214 * attempt.
215 */
216void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
217 int sec, int usec)
218{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700219 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700220 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
221 return;
222
223 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
224 "%d usec", sec, usec);
225 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
226 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
227}
228
229
230/**
231 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
232 * @wpa_s: Pointer to wpa_supplicant data
233 *
234 * This function is used to cancel authentication timeout scheduled with
235 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
236 * been completed.
237 */
238void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
239{
240 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
241 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
242 wpa_blacklist_del(wpa_s, wpa_s->bssid);
243}
244
245
246/**
247 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
248 * @wpa_s: Pointer to wpa_supplicant data
249 *
250 * This function is used to configure EAPOL state machine based on the selected
251 * authentication mode.
252 */
253void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
254{
255#ifdef IEEE8021X_EAPOL
256 struct eapol_config eapol_conf;
257 struct wpa_ssid *ssid = wpa_s->current_ssid;
258
259#ifdef CONFIG_IBSS_RSN
260 if (ssid->mode == WPAS_MODE_IBSS &&
261 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
262 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
263 /*
264 * RSN IBSS authentication is per-STA and we can disable the
265 * per-BSSID EAPOL authentication.
266 */
267 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
268 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
269 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
270 return;
271 }
272#endif /* CONFIG_IBSS_RSN */
273
274 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
275 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
276
277 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
278 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
279 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
280 else
281 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
282
283 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
284 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
285 eapol_conf.accept_802_1x_keys = 1;
286 eapol_conf.required_keys = 0;
287 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
288 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
289 }
290 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
291 eapol_conf.required_keys |=
292 EAPOL_REQUIRE_KEY_BROADCAST;
293 }
294
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700295 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700296 eapol_conf.required_keys = 0;
297 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700298 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299 eapol_conf.workaround = ssid->eap_workaround;
300 eapol_conf.eap_disabled =
301 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
302 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
303 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700304 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800305
306#ifdef CONFIG_WPS
307 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
308 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
309 if (wpa_s->current_bss) {
310 struct wpabuf *ie;
311 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
312 WPS_IE_VENDOR_TYPE);
313 if (ie) {
314 if (wps_is_20(ie))
315 eapol_conf.wps |=
316 EAPOL_PEER_IS_WPS20_AP;
317 wpabuf_free(ie);
318 }
319 }
320 }
321#endif /* CONFIG_WPS */
322
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700323 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700324
325 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800326#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700327}
328
329
330/**
331 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
332 * @wpa_s: Pointer to wpa_supplicant data
333 * @ssid: Configuration data for the network
334 *
335 * This function is used to configure WPA state machine and related parameters
336 * to a mode where WPA is not enabled. This is called as part of the
337 * authentication configuration when the selected network does not use WPA.
338 */
339void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
340 struct wpa_ssid *ssid)
341{
342 int i;
343
344 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
345 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
346 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
347 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
348 else
349 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
350 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
351 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
352 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
353 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
354 wpa_s->group_cipher = WPA_CIPHER_NONE;
355 wpa_s->mgmt_group_cipher = 0;
356
357 for (i = 0; i < NUM_WEP_KEYS; i++) {
358 if (ssid->wep_key_len[i] > 5) {
359 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
360 wpa_s->group_cipher = WPA_CIPHER_WEP104;
361 break;
362 } else if (ssid->wep_key_len[i] > 0) {
363 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
364 wpa_s->group_cipher = WPA_CIPHER_WEP40;
365 break;
366 }
367 }
368
369 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
370 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
371 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
372 wpa_s->pairwise_cipher);
373 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
374#ifdef CONFIG_IEEE80211W
375 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
376 wpa_s->mgmt_group_cipher);
377#endif /* CONFIG_IEEE80211W */
378
379 pmksa_cache_clear_current(wpa_s->wpa);
380}
381
382
Dmitry Shmidt04949592012-07-19 12:16:46 -0700383void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800384{
385 int i;
386 if (wpa_s->hw.modes == NULL)
387 return;
388
389 for (i = 0; i < wpa_s->hw.num_modes; i++) {
390 os_free(wpa_s->hw.modes[i].channels);
391 os_free(wpa_s->hw.modes[i].rates);
392 }
393
394 os_free(wpa_s->hw.modes);
395 wpa_s->hw.modes = NULL;
396}
397
398
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700399static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
400{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700401 int i;
402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700403 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700404 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700405 scard_deinit(wpa_s->scard);
406 wpa_s->scard = NULL;
407 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
408 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
409 l2_packet_deinit(wpa_s->l2);
410 wpa_s->l2 = NULL;
411 if (wpa_s->l2_br) {
412 l2_packet_deinit(wpa_s->l2_br);
413 wpa_s->l2_br = NULL;
414 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800415#ifdef CONFIG_TESTING_OPTIONS
416 l2_packet_deinit(wpa_s->l2_test);
417 wpa_s->l2_test = NULL;
418#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700420 if (wpa_s->conf != NULL) {
421 struct wpa_ssid *ssid;
422 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
423 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 }
425
426 os_free(wpa_s->confname);
427 wpa_s->confname = NULL;
428
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700429 os_free(wpa_s->confanother);
430 wpa_s->confanother = NULL;
431
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432 wpa_sm_set_eapol(wpa_s->wpa, NULL);
433 eapol_sm_deinit(wpa_s->eapol);
434 wpa_s->eapol = NULL;
435
436 rsn_preauth_deinit(wpa_s->wpa);
437
438#ifdef CONFIG_TDLS
439 wpa_tdls_deinit(wpa_s->wpa);
440#endif /* CONFIG_TDLS */
441
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800442 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 pmksa_candidate_free(wpa_s->wpa);
444 wpa_sm_deinit(wpa_s->wpa);
445 wpa_s->wpa = NULL;
446 wpa_blacklist_clear(wpa_s);
447
448 wpa_bss_deinit(wpa_s);
449
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700450 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451 wpa_supplicant_cancel_scan(wpa_s);
452 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800453 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
454#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
455 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
456 wpa_s, NULL);
457#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700458
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700459 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
460
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700461 wpas_wps_deinit(wpa_s);
462
463 wpabuf_free(wpa_s->pending_eapol_rx);
464 wpa_s->pending_eapol_rx = NULL;
465
466#ifdef CONFIG_IBSS_RSN
467 ibss_rsn_deinit(wpa_s->ibss_rsn);
468 wpa_s->ibss_rsn = NULL;
469#endif /* CONFIG_IBSS_RSN */
470
471 sme_deinit(wpa_s);
472
473#ifdef CONFIG_AP
474 wpa_supplicant_ap_deinit(wpa_s);
475#endif /* CONFIG_AP */
476
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700477 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800479#ifdef CONFIG_OFFCHANNEL
480 offchannel_deinit(wpa_s);
481#endif /* CONFIG_OFFCHANNEL */
482
483 wpa_supplicant_cancel_sched_scan(wpa_s);
484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700485 os_free(wpa_s->next_scan_freqs);
486 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800487
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800488 os_free(wpa_s->manual_scan_freqs);
489 wpa_s->manual_scan_freqs = NULL;
490
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700491 os_free(wpa_s->manual_sched_scan_freqs);
492 wpa_s->manual_sched_scan_freqs = NULL;
493
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800494 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
495
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800496 gas_query_deinit(wpa_s->gas);
497 wpa_s->gas = NULL;
498
499 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700500
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700501 ieee802_1x_dealloc_kay_sm(wpa_s);
502
Dmitry Shmidt04949592012-07-19 12:16:46 -0700503 os_free(wpa_s->bssid_filter);
504 wpa_s->bssid_filter = NULL;
505
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800506 os_free(wpa_s->disallow_aps_bssid);
507 wpa_s->disallow_aps_bssid = NULL;
508 os_free(wpa_s->disallow_aps_ssid);
509 wpa_s->disallow_aps_ssid = NULL;
510
Dmitry Shmidt04949592012-07-19 12:16:46 -0700511 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700512#ifdef CONFIG_WNM
513 wnm_deallocate_memory(wpa_s);
514#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700515
516 ext_password_deinit(wpa_s->ext_pw);
517 wpa_s->ext_pw = NULL;
518
519 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800520 wpa_s->last_gas_resp = NULL;
521 wpabuf_free(wpa_s->prev_gas_resp);
522 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700523
524 os_free(wpa_s->last_scan_res);
525 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800526
527#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700528 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800529#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700530
531 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
532 wpabuf_free(wpa_s->vendor_elem[i]);
533 wpa_s->vendor_elem[i] = NULL;
534 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800535
536 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700537}
538
539
540/**
541 * wpa_clear_keys - Clear keys configured for the driver
542 * @wpa_s: Pointer to wpa_supplicant data
543 * @addr: Previously used BSSID or %NULL if not available
544 *
545 * This function clears the encryption keys that has been previously configured
546 * for the driver.
547 */
548void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
549{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800550 int i, max;
551
552#ifdef CONFIG_IEEE80211W
553 max = 6;
554#else /* CONFIG_IEEE80211W */
555 max = 4;
556#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557
558 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800559 for (i = 0; i < max; i++) {
560 if (wpa_s->keys_cleared & BIT(i))
561 continue;
562 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
563 NULL, 0);
564 }
565 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
566 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700567 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
568 0);
569 /* MLME-SETPROTECTION.request(None) */
570 wpa_drv_mlme_setprotection(
571 wpa_s, addr,
572 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
573 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
574 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800575 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700576}
577
578
579/**
580 * wpa_supplicant_state_txt - Get the connection state name as a text string
581 * @state: State (wpa_state; WPA_*)
582 * Returns: The state name as a printable text string
583 */
584const char * wpa_supplicant_state_txt(enum wpa_states state)
585{
586 switch (state) {
587 case WPA_DISCONNECTED:
588 return "DISCONNECTED";
589 case WPA_INACTIVE:
590 return "INACTIVE";
591 case WPA_INTERFACE_DISABLED:
592 return "INTERFACE_DISABLED";
593 case WPA_SCANNING:
594 return "SCANNING";
595 case WPA_AUTHENTICATING:
596 return "AUTHENTICATING";
597 case WPA_ASSOCIATING:
598 return "ASSOCIATING";
599 case WPA_ASSOCIATED:
600 return "ASSOCIATED";
601 case WPA_4WAY_HANDSHAKE:
602 return "4WAY_HANDSHAKE";
603 case WPA_GROUP_HANDSHAKE:
604 return "GROUP_HANDSHAKE";
605 case WPA_COMPLETED:
606 return "COMPLETED";
607 default:
608 return "UNKNOWN";
609 }
610}
611
612
613#ifdef CONFIG_BGSCAN
614
615static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
616{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800617 const char *name;
618
619 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
620 name = wpa_s->current_ssid->bgscan;
621 else
622 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800623 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800624 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800625 if (wpas_driver_bss_selection(wpa_s))
626 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700627 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
628 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800629#ifdef CONFIG_P2P
630 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
631 return;
632#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700633
634 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800635 if (wpa_s->current_ssid) {
636 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
638 "bgscan");
639 /*
640 * Live without bgscan; it is only used as a roaming
641 * optimization, so the initial connection is not
642 * affected.
643 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700644 } else {
645 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700646 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700647 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
648 0);
649 if (scan_res) {
650 bgscan_notify_scan(wpa_s, scan_res);
651 wpa_scan_results_free(scan_res);
652 }
653 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700654 } else
655 wpa_s->bgscan_ssid = NULL;
656}
657
658
659static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
660{
661 if (wpa_s->bgscan_ssid != NULL) {
662 bgscan_deinit(wpa_s);
663 wpa_s->bgscan_ssid = NULL;
664 }
665}
666
667#endif /* CONFIG_BGSCAN */
668
669
Dmitry Shmidt04949592012-07-19 12:16:46 -0700670static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
671{
672 if (autoscan_init(wpa_s, 0))
673 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
674}
675
676
677static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
678{
679 autoscan_deinit(wpa_s);
680}
681
682
683void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
684{
685 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
686 wpa_s->wpa_state == WPA_SCANNING) {
687 autoscan_deinit(wpa_s);
688 wpa_supplicant_start_autoscan(wpa_s);
689 }
690}
691
692
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700693/**
694 * wpa_supplicant_set_state - Set current connection state
695 * @wpa_s: Pointer to wpa_supplicant data
696 * @state: The new connection state
697 *
698 * This function is called whenever the connection state changes, e.g.,
699 * association is completed for WPA/WPA2 4-Way Handshake is started.
700 */
701void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
702 enum wpa_states state)
703{
704 enum wpa_states old_state = wpa_s->wpa_state;
705
706 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
707 wpa_supplicant_state_txt(wpa_s->wpa_state),
708 wpa_supplicant_state_txt(state));
709
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800710 if (state == WPA_INTERFACE_DISABLED) {
711 /* Assure normal scan when interface is restored */
712 wpa_s->normal_scans = 0;
713 }
714
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700715 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800716 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700717 /* Reinitialize normal_scan counter */
718 wpa_s->normal_scans = 0;
719 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800720
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700721 if (state != WPA_SCANNING)
722 wpa_supplicant_notify_scanning(wpa_s, 0);
723
724 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700725 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700726#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700727 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800728 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800729 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730 ssid ? ssid->id : -1,
731 ssid && ssid->id_str ? ssid->id_str : "");
732#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700733 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700734 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800735 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700737 wpa_drv_set_operstate(wpa_s, 1);
738#ifndef IEEE8021X_EAPOL
739 wpa_drv_set_supp_port(wpa_s, 1);
740#endif /* IEEE8021X_EAPOL */
741 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700742 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700744
745 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
747 state == WPA_ASSOCIATED) {
748 wpa_s->new_connection = 1;
749 wpa_drv_set_operstate(wpa_s, 0);
750#ifndef IEEE8021X_EAPOL
751 wpa_drv_set_supp_port(wpa_s, 0);
752#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700753 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700754 }
755 wpa_s->wpa_state = state;
756
757#ifdef CONFIG_BGSCAN
758 if (state == WPA_COMPLETED)
759 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800760 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700761 wpa_supplicant_stop_bgscan(wpa_s);
762#endif /* CONFIG_BGSCAN */
763
Dmitry Shmidt04949592012-07-19 12:16:46 -0700764 if (state == WPA_AUTHENTICATING)
765 wpa_supplicant_stop_autoscan(wpa_s);
766
767 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
768 wpa_supplicant_start_autoscan(wpa_s);
769
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800770 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
771 wmm_ac_notify_disassoc(wpa_s);
772
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773 if (wpa_s->wpa_state != old_state) {
774 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
775
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700776 /*
777 * Notify the P2P Device interface about a state change in one
778 * of the interfaces.
779 */
780 wpas_p2p_indicate_state_change(wpa_s);
781
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700782 if (wpa_s->wpa_state == WPA_COMPLETED ||
783 old_state == WPA_COMPLETED)
784 wpas_notify_auth_changed(wpa_s);
785 }
786}
787
788
789void wpa_supplicant_terminate_proc(struct wpa_global *global)
790{
791 int pending = 0;
792#ifdef CONFIG_WPS
793 struct wpa_supplicant *wpa_s = global->ifaces;
794 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800795 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700796 if (wpas_wps_terminate_pending(wpa_s) == 1)
797 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700798#ifdef CONFIG_P2P
799 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
800 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
801 wpas_p2p_disconnect(wpa_s);
802#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800803 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 }
805#endif /* CONFIG_WPS */
806 if (pending)
807 return;
808 eloop_terminate();
809}
810
811
812static void wpa_supplicant_terminate(int sig, void *signal_ctx)
813{
814 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700815 wpa_supplicant_terminate_proc(global);
816}
817
818
819void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
820{
821 enum wpa_states old_state = wpa_s->wpa_state;
822
823 wpa_s->pairwise_cipher = 0;
824 wpa_s->group_cipher = 0;
825 wpa_s->mgmt_group_cipher = 0;
826 wpa_s->key_mgmt = 0;
827 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700828 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700829
830 if (wpa_s->wpa_state != old_state)
831 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
832}
833
834
835/**
836 * wpa_supplicant_reload_configuration - Reload configuration data
837 * @wpa_s: Pointer to wpa_supplicant data
838 * Returns: 0 on success or -1 if configuration parsing failed
839 *
840 * This function can be used to request that the configuration data is reloaded
841 * (e.g., after configuration file change). This function is reloading
842 * configuration only for one interface, so this may need to be called multiple
843 * times if %wpa_supplicant is controlling multiple interfaces and all
844 * interfaces need reconfiguration.
845 */
846int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
847{
848 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849 int reconf_ctrl;
850 int old_ap_scan;
851
852 if (wpa_s->confname == NULL)
853 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700854 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700855 if (conf == NULL) {
856 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
857 "file '%s' - exiting", wpa_s->confname);
858 return -1;
859 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700860 wpa_config_read(wpa_s->confanother, conf);
861
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700862 conf->changed_parameters = (unsigned int) -1;
863
864 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
865 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
866 os_strcmp(conf->ctrl_interface,
867 wpa_s->conf->ctrl_interface) != 0);
868
869 if (reconf_ctrl && wpa_s->ctrl_iface) {
870 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
871 wpa_s->ctrl_iface = NULL;
872 }
873
874 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800875 if (wpa_s->current_ssid) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -0800876 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800877 wpa_supplicant_deauthenticate(wpa_s,
878 WLAN_REASON_DEAUTH_LEAVING);
879 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880
881 /*
882 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800883 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884 */
885 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
886 /*
887 * Clear forced success to clear EAP state for next
888 * authentication.
889 */
890 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
891 }
892 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
893 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800894 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700895 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
896 rsn_preauth_deinit(wpa_s->wpa);
897
898 old_ap_scan = wpa_s->conf->ap_scan;
899 wpa_config_free(wpa_s->conf);
900 wpa_s->conf = conf;
901 if (old_ap_scan != wpa_s->conf->ap_scan)
902 wpas_notify_ap_scan_changed(wpa_s);
903
904 if (reconf_ctrl)
905 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
906
907 wpa_supplicant_update_config(wpa_s);
908
909 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700910 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700911 wpa_s->reassociate = 1;
912 wpa_supplicant_req_scan(wpa_s, 0, 0);
913 }
914 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
915 return 0;
916}
917
918
919static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
920{
921 struct wpa_global *global = signal_ctx;
922 struct wpa_supplicant *wpa_s;
923 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
924 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
925 sig);
926 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
927 wpa_supplicant_terminate_proc(global);
928 }
929 }
930}
931
932
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700933static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
934 struct wpa_ssid *ssid,
935 struct wpa_ie_data *ie)
936{
937 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
938 if (ret) {
939 if (ret == -2) {
940 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
941 "from association info");
942 }
943 return -1;
944 }
945
946 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
947 "cipher suites");
948 if (!(ie->group_cipher & ssid->group_cipher)) {
949 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
950 "cipher 0x%x (mask 0x%x) - reject",
951 ie->group_cipher, ssid->group_cipher);
952 return -1;
953 }
954 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
955 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
956 "cipher 0x%x (mask 0x%x) - reject",
957 ie->pairwise_cipher, ssid->pairwise_cipher);
958 return -1;
959 }
960 if (!(ie->key_mgmt & ssid->key_mgmt)) {
961 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
962 "management 0x%x (mask 0x%x) - reject",
963 ie->key_mgmt, ssid->key_mgmt);
964 return -1;
965 }
966
967#ifdef CONFIG_IEEE80211W
968 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800969 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700970 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
971 "that does not support management frame protection - "
972 "reject");
973 return -1;
974 }
975#endif /* CONFIG_IEEE80211W */
976
977 return 0;
978}
979
980
981/**
982 * wpa_supplicant_set_suites - Set authentication and encryption parameters
983 * @wpa_s: Pointer to wpa_supplicant data
984 * @bss: Scan results for the selected BSS, or %NULL if not available
985 * @ssid: Configuration data for the selected network
986 * @wpa_ie: Buffer for the WPA/RSN IE
987 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
988 * used buffer length in case the functions returns success.
989 * Returns: 0 on success or -1 on failure
990 *
991 * This function is used to configure authentication and encryption parameters
992 * based on the network configuration and scan result for the selected BSS (if
993 * available).
994 */
995int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
996 struct wpa_bss *bss, struct wpa_ssid *ssid,
997 u8 *wpa_ie, size_t *wpa_ie_len)
998{
999 struct wpa_ie_data ie;
1000 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001001 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002
1003 if (bss) {
1004 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1005 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001006 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001008 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009
1010 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1011 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1012 (ie.group_cipher & ssid->group_cipher) &&
1013 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1014 (ie.key_mgmt & ssid->key_mgmt)) {
1015 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1016 proto = WPA_PROTO_RSN;
1017 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001018 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019 (ie.group_cipher & ssid->group_cipher) &&
1020 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1021 (ie.key_mgmt & ssid->key_mgmt)) {
1022 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1023 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001024#ifdef CONFIG_HS20
1025 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1026 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1027 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001028 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001029 ie.group_cipher = WPA_CIPHER_CCMP;
1030 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1031 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1032 proto = WPA_PROTO_OSEN;
1033#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034 } else if (bss) {
1035 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001036 wpa_dbg(wpa_s, MSG_DEBUG,
1037 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1038 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1039 ssid->key_mgmt);
1040 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1041 MAC2STR(bss->bssid),
1042 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1043 bss_wpa ? " WPA" : "",
1044 bss_rsn ? " RSN" : "",
1045 bss_osen ? " OSEN" : "");
1046 if (bss_rsn) {
1047 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1048 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1049 wpa_dbg(wpa_s, MSG_DEBUG,
1050 "Could not parse RSN element");
1051 } else {
1052 wpa_dbg(wpa_s, MSG_DEBUG,
1053 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1054 ie.pairwise_cipher, ie.group_cipher,
1055 ie.key_mgmt);
1056 }
1057 }
1058 if (bss_wpa) {
1059 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1060 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1061 wpa_dbg(wpa_s, MSG_DEBUG,
1062 "Could not parse WPA element");
1063 } else {
1064 wpa_dbg(wpa_s, MSG_DEBUG,
1065 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1066 ie.pairwise_cipher, ie.group_cipher,
1067 ie.key_mgmt);
1068 }
1069 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070 return -1;
1071 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001072 if (ssid->proto & WPA_PROTO_OSEN)
1073 proto = WPA_PROTO_OSEN;
1074 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075 proto = WPA_PROTO_RSN;
1076 else
1077 proto = WPA_PROTO_WPA;
1078 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1079 os_memset(&ie, 0, sizeof(ie));
1080 ie.group_cipher = ssid->group_cipher;
1081 ie.pairwise_cipher = ssid->pairwise_cipher;
1082 ie.key_mgmt = ssid->key_mgmt;
1083#ifdef CONFIG_IEEE80211W
1084 ie.mgmt_group_cipher =
1085 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1086 WPA_CIPHER_AES_128_CMAC : 0;
1087#endif /* CONFIG_IEEE80211W */
1088 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1089 "based on configuration");
1090 } else
1091 proto = ie.proto;
1092 }
1093
1094 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1095 "pairwise %d key_mgmt %d proto %d",
1096 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1097#ifdef CONFIG_IEEE80211W
1098 if (ssid->ieee80211w) {
1099 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1100 ie.mgmt_group_cipher);
1101 }
1102#endif /* CONFIG_IEEE80211W */
1103
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001104 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1106 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001107 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108
1109 if (bss || !wpa_s->ap_ies_from_associnfo) {
1110 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1111 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1112 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1113 bss_rsn ? 2 + bss_rsn[1] : 0))
1114 return -1;
1115 }
1116
1117 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001118 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1119 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1121 "cipher");
1122 return -1;
1123 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001124 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1125 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001126
1127 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001128 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1129 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001130 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1131 "cipher");
1132 return -1;
1133 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001134 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1135 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001136
1137 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001138#ifdef CONFIG_SAE
1139 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1140 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1141#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001143#ifdef CONFIG_SUITEB192
1144 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1145 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1146 wpa_dbg(wpa_s, MSG_DEBUG,
1147 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1148#endif /* CONFIG_SUITEB192 */
1149#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001150 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1151 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1152 wpa_dbg(wpa_s, MSG_DEBUG,
1153 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001154#endif /* CONFIG_SUITEB */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001155#ifdef CONFIG_IEEE80211R
1156 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1157 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1158 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1159 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1160 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1161 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1162#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001163#ifdef CONFIG_SAE
1164 } else if (sel & WPA_KEY_MGMT_SAE) {
1165 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1166 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1167 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1168 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1169 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1170#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001171#ifdef CONFIG_IEEE80211W
1172 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1173 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1174 wpa_dbg(wpa_s, MSG_DEBUG,
1175 "WPA: using KEY_MGMT 802.1X with SHA256");
1176 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1177 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1178 wpa_dbg(wpa_s, MSG_DEBUG,
1179 "WPA: using KEY_MGMT PSK with SHA256");
1180#endif /* CONFIG_IEEE80211W */
1181 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1182 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1183 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1184 } else if (sel & WPA_KEY_MGMT_PSK) {
1185 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1186 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1187 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1188 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1189 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001190#ifdef CONFIG_HS20
1191 } else if (sel & WPA_KEY_MGMT_OSEN) {
1192 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1193 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1194#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001195 } else {
1196 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1197 "authenticated key management type");
1198 return -1;
1199 }
1200
1201 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1202 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1203 wpa_s->pairwise_cipher);
1204 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1205
1206#ifdef CONFIG_IEEE80211W
1207 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001208 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1210 sel = 0;
1211 if (sel & WPA_CIPHER_AES_128_CMAC) {
1212 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1213 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1214 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001215 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1216 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1217 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1218 "BIP-GMAC-128");
1219 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1220 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1221 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1222 "BIP-GMAC-256");
1223 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1224 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1225 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1226 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001227 } else {
1228 wpa_s->mgmt_group_cipher = 0;
1229 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1230 }
1231 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1232 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001233 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001234 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235#endif /* CONFIG_IEEE80211W */
1236
1237 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1238 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1239 return -1;
1240 }
1241
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001242 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001243 int psk_set = 0;
1244
1245 if (ssid->psk_set) {
1246 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
1247 psk_set = 1;
1248 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001249#ifndef CONFIG_NO_PBKDF2
1250 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1251 ssid->passphrase) {
1252 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001253 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1254 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001255 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1256 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001257 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001258 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001259 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001260 }
1261#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001262#ifdef CONFIG_EXT_PASSWORD
1263 if (ssid->ext_psk) {
1264 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1265 ssid->ext_psk);
1266 char pw_str[64 + 1];
1267 u8 psk[PMK_LEN];
1268
1269 if (pw == NULL) {
1270 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1271 "found from external storage");
1272 return -1;
1273 }
1274
1275 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1276 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1277 "PSK length %d in external storage",
1278 (int) wpabuf_len(pw));
1279 ext_password_free(pw);
1280 return -1;
1281 }
1282
1283 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1284 pw_str[wpabuf_len(pw)] = '\0';
1285
1286#ifndef CONFIG_NO_PBKDF2
1287 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1288 {
1289 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1290 4096, psk, PMK_LEN);
1291 os_memset(pw_str, 0, sizeof(pw_str));
1292 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1293 "external passphrase)",
1294 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001295 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001296 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001297 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001298 } else
1299#endif /* CONFIG_NO_PBKDF2 */
1300 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1301 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1302 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1303 "Invalid PSK hex string");
1304 os_memset(pw_str, 0, sizeof(pw_str));
1305 ext_password_free(pw);
1306 return -1;
1307 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001308 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001309 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001310 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001311 } else {
1312 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1313 "PSK available");
1314 os_memset(pw_str, 0, sizeof(pw_str));
1315 ext_password_free(pw);
1316 return -1;
1317 }
1318
1319 os_memset(pw_str, 0, sizeof(pw_str));
1320 ext_password_free(pw);
1321 }
1322#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001323
1324 if (!psk_set) {
1325 wpa_msg(wpa_s, MSG_INFO,
1326 "No PSK available for association");
1327 return -1;
1328 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001329 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1331
1332 return 0;
1333}
1334
1335
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001336static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1337{
1338 *pos = 0x00;
1339
1340 switch (idx) {
1341 case 0: /* Bits 0-7 */
1342 break;
1343 case 1: /* Bits 8-15 */
1344 break;
1345 case 2: /* Bits 16-23 */
1346#ifdef CONFIG_WNM
1347 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1348 *pos |= 0x08; /* Bit 19 - BSS Transition */
1349#endif /* CONFIG_WNM */
1350 break;
1351 case 3: /* Bits 24-31 */
1352#ifdef CONFIG_WNM
1353 *pos |= 0x02; /* Bit 25 - SSID List */
1354#endif /* CONFIG_WNM */
1355#ifdef CONFIG_INTERWORKING
1356 if (wpa_s->conf->interworking)
1357 *pos |= 0x80; /* Bit 31 - Interworking */
1358#endif /* CONFIG_INTERWORKING */
1359 break;
1360 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001361#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001362 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1363 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001364#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001365 break;
1366 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001367#ifdef CONFIG_HS20
1368 if (wpa_s->conf->hs20)
1369 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1370#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001371 break;
1372 case 6: /* Bits 48-55 */
1373 break;
1374 }
1375}
1376
1377
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001378int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001379{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001380 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001381 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001382
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001383 if (len < wpa_s->extended_capa_len)
1384 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001385 if (buflen < (size_t) len + 2) {
1386 wpa_printf(MSG_INFO,
1387 "Not enough room for building extended capabilities element");
1388 return -1;
1389 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001390
1391 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001392 *pos++ = len;
1393 for (i = 0; i < len; i++, pos++) {
1394 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001395
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001396 if (i < wpa_s->extended_capa_len) {
1397 *pos &= ~wpa_s->extended_capa_mask[i];
1398 *pos |= wpa_s->extended_capa[i];
1399 }
1400 }
1401
1402 while (len > 0 && buf[1 + len] == 0) {
1403 len--;
1404 buf[1] = len;
1405 }
1406 if (len == 0)
1407 return 0;
1408
1409 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001410}
1411
1412
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001413static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1414 struct wpa_bss *test_bss)
1415{
1416 struct wpa_bss *bss;
1417
1418 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1419 if (bss == test_bss)
1420 return 1;
1421 }
1422
1423 return 0;
1424}
1425
1426
1427static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1428 struct wpa_ssid *test_ssid)
1429{
1430 struct wpa_ssid *ssid;
1431
1432 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1433 if (ssid == test_ssid)
1434 return 1;
1435 }
1436
1437 return 0;
1438}
1439
1440
1441int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1442 struct wpa_ssid *test_ssid)
1443{
1444 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1445 return 0;
1446
1447 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1448}
1449
1450
1451void wpas_connect_work_free(struct wpa_connect_work *cwork)
1452{
1453 if (cwork == NULL)
1454 return;
1455 os_free(cwork);
1456}
1457
1458
1459void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1460{
1461 struct wpa_connect_work *cwork;
1462 struct wpa_radio_work *work = wpa_s->connect_work;
1463
1464 if (!work)
1465 return;
1466
1467 wpa_s->connect_work = NULL;
1468 cwork = work->ctx;
1469 work->ctx = NULL;
1470 wpas_connect_work_free(cwork);
1471 radio_work_done(work);
1472}
1473
1474
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001475int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1476{
1477 struct os_reltime now;
1478 u8 addr[ETH_ALEN];
1479
1480 os_get_reltime(&now);
1481 if (wpa_s->last_mac_addr_style == style &&
1482 wpa_s->last_mac_addr_change.sec != 0 &&
1483 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1484 wpa_s->conf->rand_addr_lifetime)) {
1485 wpa_msg(wpa_s, MSG_DEBUG,
1486 "Previously selected random MAC address has not yet expired");
1487 return 0;
1488 }
1489
1490 switch (style) {
1491 case 1:
1492 if (random_mac_addr(addr) < 0)
1493 return -1;
1494 break;
1495 case 2:
1496 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1497 if (random_mac_addr_keep_oui(addr) < 0)
1498 return -1;
1499 break;
1500 default:
1501 return -1;
1502 }
1503
1504 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1505 wpa_msg(wpa_s, MSG_INFO,
1506 "Failed to set random MAC address");
1507 return -1;
1508 }
1509
1510 os_get_reltime(&wpa_s->last_mac_addr_change);
1511 wpa_s->mac_addr_changed = 1;
1512 wpa_s->last_mac_addr_style = style;
1513
1514 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1515 wpa_msg(wpa_s, MSG_INFO,
1516 "Could not update MAC address information");
1517 return -1;
1518 }
1519
1520 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1521 MAC2STR(addr));
1522
1523 return 0;
1524}
1525
1526
1527int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1528{
1529 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1530 !wpa_s->conf->preassoc_mac_addr)
1531 return 0;
1532
1533 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1534}
1535
1536
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001537static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1538
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001539/**
1540 * wpa_supplicant_associate - Request association
1541 * @wpa_s: Pointer to wpa_supplicant data
1542 * @bss: Scan results for the selected BSS, or %NULL if not available
1543 * @ssid: Configuration data for the selected network
1544 *
1545 * This function is used to request %wpa_supplicant to associate with a BSS.
1546 */
1547void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1548 struct wpa_bss *bss, struct wpa_ssid *ssid)
1549{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001550 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001551 int rand_style;
1552
1553 if (ssid->mac_addr == -1)
1554 rand_style = wpa_s->conf->mac_addr;
1555 else
1556 rand_style = ssid->mac_addr;
1557
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001558 wmm_ac_clear_saved_tspecs(wpa_s);
1559 wpa_s->reassoc_same_bss = 0;
1560
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001561 if (wpa_s->last_ssid == ssid) {
1562 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001563 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1564 wmm_ac_save_tspecs(wpa_s);
1565 wpa_s->reassoc_same_bss = 1;
1566 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001567 } else if (rand_style > 0) {
1568 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1569 return;
1570 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1571 } else if (wpa_s->mac_addr_changed) {
1572 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1573 wpa_msg(wpa_s, MSG_INFO,
1574 "Could not restore permanent MAC address");
1575 return;
1576 }
1577 wpa_s->mac_addr_changed = 0;
1578 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1579 wpa_msg(wpa_s, MSG_INFO,
1580 "Could not update MAC address information");
1581 return;
1582 }
1583 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1584 }
1585 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001586
1587#ifdef CONFIG_IBSS_RSN
1588 ibss_rsn_deinit(wpa_s->ibss_rsn);
1589 wpa_s->ibss_rsn = NULL;
1590#endif /* CONFIG_IBSS_RSN */
1591
1592 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1593 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1594#ifdef CONFIG_AP
1595 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1596 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1597 "mode");
1598 return;
1599 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001600 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1601 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001602 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1603 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001604 return;
1605 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001606 wpa_s->current_bss = bss;
1607#else /* CONFIG_AP */
1608 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1609 "the build");
1610#endif /* CONFIG_AP */
1611 return;
1612 }
1613
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001614 if (ssid->mode == WPAS_MODE_MESH) {
1615#ifdef CONFIG_MESH
1616 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1617 wpa_msg(wpa_s, MSG_INFO,
1618 "Driver does not support mesh mode");
1619 return;
1620 }
1621 if (bss)
1622 ssid->frequency = bss->freq;
1623 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1624 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1625 return;
1626 }
1627 wpa_s->current_bss = bss;
1628 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
1629 "ssid=\"%s\" id=%d",
1630 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1631 ssid->id);
1632#else /* CONFIG_MESH */
1633 wpa_msg(wpa_s, MSG_ERROR,
1634 "mesh mode support not included in the build");
1635#endif /* CONFIG_MESH */
1636 return;
1637 }
1638
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001639#ifdef CONFIG_TDLS
1640 if (bss)
1641 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1642 bss->ie_len);
1643#endif /* CONFIG_TDLS */
1644
1645 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1646 ssid->mode == IEEE80211_MODE_INFRA) {
1647 sme_authenticate(wpa_s, bss, ssid);
1648 return;
1649 }
1650
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001651 if (wpa_s->connect_work) {
1652 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1653 return;
1654 }
1655
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001656 if (radio_work_pending(wpa_s, "connect")) {
1657 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1658 return;
1659 }
1660
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001661 cwork = os_zalloc(sizeof(*cwork));
1662 if (cwork == NULL)
1663 return;
1664
1665 cwork->bss = bss;
1666 cwork->ssid = ssid;
1667
1668 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1669 wpas_start_assoc_cb, cwork) < 0) {
1670 os_free(cwork);
1671 }
1672}
1673
1674
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001675static int bss_is_ibss(struct wpa_bss *bss)
1676{
1677 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1678 IEEE80211_CAP_IBSS;
1679}
1680
1681
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001682void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1683 const struct wpa_ssid *ssid,
1684 struct hostapd_freq_params *freq)
1685{
1686 enum hostapd_hw_mode hw_mode;
1687 struct hostapd_hw_modes *mode = NULL;
1688 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1689 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001690 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001691 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1692 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001693 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001694 unsigned int j;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001695 struct hostapd_freq_params vht_freq;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001696
1697 freq->freq = ssid->frequency;
1698
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001699 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1700 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1701
1702 if (ssid->mode != WPAS_MODE_IBSS)
1703 break;
1704
1705 /* Don't adjust control freq in case of fixed_freq */
1706 if (ssid->fixed_freq)
1707 break;
1708
1709 if (!bss_is_ibss(bss))
1710 continue;
1711
1712 if (ssid->ssid_len == bss->ssid_len &&
1713 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1714 wpa_printf(MSG_DEBUG,
1715 "IBSS already found in scan results, adjust control freq: %d",
1716 bss->freq);
1717 freq->freq = bss->freq;
1718 obss_scan = 0;
1719 break;
1720 }
1721 }
1722
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001723 /* For IBSS check HT_IBSS flag */
1724 if (ssid->mode == WPAS_MODE_IBSS &&
1725 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1726 return;
1727
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001728 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1729 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1730 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1731 wpa_printf(MSG_DEBUG,
1732 "IBSS: WEP/TKIP detected, do not try to enable HT");
1733 return;
1734 }
1735
1736 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001737 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1738 if (wpa_s->hw.modes[i].mode == hw_mode) {
1739 mode = &wpa_s->hw.modes[i];
1740 break;
1741 }
1742 }
1743
1744 if (!mode)
1745 return;
1746
1747 freq->ht_enabled = ht_supported(mode);
1748 if (!freq->ht_enabled)
1749 return;
1750
1751 /* Setup higher BW only for 5 GHz */
1752 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1753 return;
1754
1755 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1756 pri_chan = &mode->channels[chan_idx];
1757 if (pri_chan->chan == channel)
1758 break;
1759 pri_chan = NULL;
1760 }
1761 if (!pri_chan)
1762 return;
1763
1764 /* Check primary channel flags */
1765 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1766 return;
1767
1768 /* Check/setup HT40+/HT40- */
1769 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1770 if (ht40plus[j] == channel) {
1771 ht40 = 1;
1772 break;
1773 }
1774 }
1775
1776 /* Find secondary channel */
1777 for (i = 0; i < mode->num_channels; i++) {
1778 sec_chan = &mode->channels[i];
1779 if (sec_chan->chan == channel + ht40 * 4)
1780 break;
1781 sec_chan = NULL;
1782 }
1783 if (!sec_chan)
1784 return;
1785
1786 /* Check secondary channel flags */
1787 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1788 return;
1789
1790 freq->channel = pri_chan->chan;
1791
1792 switch (ht40) {
1793 case -1:
1794 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1795 return;
1796 freq->sec_channel_offset = -1;
1797 break;
1798 case 1:
1799 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1800 return;
1801 freq->sec_channel_offset = 1;
1802 break;
1803 default:
1804 break;
1805 }
1806
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001807 if (freq->sec_channel_offset && obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001808 struct wpa_scan_results *scan_res;
1809
1810 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1811 if (scan_res == NULL) {
1812 /* Back to HT20 */
1813 freq->sec_channel_offset = 0;
1814 return;
1815 }
1816
1817 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1818 sec_chan->chan);
1819 switch (res) {
1820 case 0:
1821 /* Back to HT20 */
1822 freq->sec_channel_offset = 0;
1823 break;
1824 case 1:
1825 /* Configuration allowed */
1826 break;
1827 case 2:
1828 /* Switch pri/sec channels */
1829 freq->freq = hw_get_freq(mode, sec_chan->chan);
1830 freq->sec_channel_offset = -freq->sec_channel_offset;
1831 freq->channel = sec_chan->chan;
1832 break;
1833 default:
1834 freq->sec_channel_offset = 0;
1835 break;
1836 }
1837
1838 wpa_scan_results_free(scan_res);
1839 }
1840
1841 wpa_printf(MSG_DEBUG,
1842 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
1843 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001844
1845 /* Not sure if mesh is ready for VHT */
1846 if (ssid->mode != WPAS_MODE_IBSS)
1847 return;
1848
1849 /* For IBSS check VHT_IBSS flag */
1850 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
1851 return;
1852
1853 vht_freq = *freq;
1854
1855 vht_freq.vht_enabled = vht_supported(mode);
1856 if (!vht_freq.vht_enabled)
1857 return;
1858
1859 /* setup center_freq1, bandwidth */
1860 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
1861 if (freq->channel >= vht80[j] &&
1862 freq->channel < vht80[j] + 16)
1863 break;
1864 }
1865
1866 if (j == ARRAY_SIZE(vht80))
1867 return;
1868
1869 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
1870 struct hostapd_channel_data *chan;
1871
1872 chan = hw_get_channel_chan(mode, i, NULL);
1873 if (!chan)
1874 return;
1875
1876 /* Back to HT configuration if channel not usable */
1877 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1878 return;
1879 }
1880
1881 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
1882 freq->channel, freq->ht_enabled,
1883 vht_freq.vht_enabled,
1884 freq->sec_channel_offset,
1885 VHT_CHANWIDTH_80MHZ,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08001886 vht80[j] + 6, 0, 0) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001887 return;
1888
1889 *freq = vht_freq;
1890
1891 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
1892 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001893}
1894
1895
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001896static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1897{
1898 struct wpa_connect_work *cwork = work->ctx;
1899 struct wpa_bss *bss = cwork->bss;
1900 struct wpa_ssid *ssid = cwork->ssid;
1901 struct wpa_supplicant *wpa_s = work->wpa_s;
1902 u8 wpa_ie[200];
1903 size_t wpa_ie_len;
1904 int use_crypt, ret, i, bssid_changed;
1905 int algs = WPA_AUTH_ALG_OPEN;
1906 unsigned int cipher_pairwise, cipher_group;
1907 struct wpa_driver_associate_params params;
1908 int wep_keys_set = 0;
1909 int assoc_failed = 0;
1910 struct wpa_ssid *old_ssid;
1911#ifdef CONFIG_HT_OVERRIDES
1912 struct ieee80211_ht_capabilities htcaps;
1913 struct ieee80211_ht_capabilities htcaps_mask;
1914#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001915#ifdef CONFIG_VHT_OVERRIDES
1916 struct ieee80211_vht_capabilities vhtcaps;
1917 struct ieee80211_vht_capabilities vhtcaps_mask;
1918#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001919
1920 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001921 if (work->started) {
1922 wpa_s->connect_work = NULL;
1923
1924 /* cancel possible auth. timeout */
1925 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1926 NULL);
1927 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001928 wpas_connect_work_free(cwork);
1929 return;
1930 }
1931
1932 wpa_s->connect_work = work;
1933
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001934 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001935 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1936 wpas_connect_work_done(wpa_s);
1937 return;
1938 }
1939
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001940 os_memset(&params, 0, sizeof(params));
1941 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001942 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001943 if (bss &&
1944 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001945#ifdef CONFIG_IEEE80211R
1946 const u8 *ie, *md = NULL;
1947#endif /* CONFIG_IEEE80211R */
1948 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1949 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1950 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1951 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1952 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1953 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1954 if (bssid_changed)
1955 wpas_notify_bssid_changed(wpa_s);
1956#ifdef CONFIG_IEEE80211R
1957 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1958 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1959 md = ie + 2;
1960 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1961 if (md) {
1962 /* Prepare for the next transition */
1963 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1964 }
1965#endif /* CONFIG_IEEE80211R */
1966#ifdef CONFIG_WPS
1967 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1968 wpa_s->conf->ap_scan == 2 &&
1969 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1970 /* Use ap_scan==1 style network selection to find the network
1971 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001972 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001973 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974 wpa_s->reassociate = 1;
1975 wpa_supplicant_req_scan(wpa_s, 0, 0);
1976 return;
1977#endif /* CONFIG_WPS */
1978 } else {
1979 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1980 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1981 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1982 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001983 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984 wpa_supplicant_cancel_scan(wpa_s);
1985
1986 /* Starting new association, so clear the possibly used WPA IE from the
1987 * previous association. */
1988 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1989
1990#ifdef IEEE8021X_EAPOL
1991 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1992 if (ssid->leap) {
1993 if (ssid->non_leap == 0)
1994 algs = WPA_AUTH_ALG_LEAP;
1995 else
1996 algs |= WPA_AUTH_ALG_LEAP;
1997 }
1998 }
1999#endif /* IEEE8021X_EAPOL */
2000 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2001 if (ssid->auth_alg) {
2002 algs = ssid->auth_alg;
2003 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2004 "0x%x", algs);
2005 }
2006
2007 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2008 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002009 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002011 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2012 wpa_s->conf->okc :
2013 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002014 (ssid->proto & WPA_PROTO_RSN);
2015 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002016 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002017 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002018 wpa_ie_len = sizeof(wpa_ie);
2019 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2020 wpa_ie, &wpa_ie_len)) {
2021 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2022 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002023 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002024 return;
2025 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002026 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2027 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2028 /*
2029 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2030 * use non-WPA since the scan results did not indicate that the
2031 * AP is using WPA or WPA2.
2032 */
2033 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2034 wpa_ie_len = 0;
2035 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002036 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002037 wpa_ie_len = sizeof(wpa_ie);
2038 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2039 wpa_ie, &wpa_ie_len)) {
2040 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2041 "key management and encryption suites (no "
2042 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002043 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002044 return;
2045 }
2046#ifdef CONFIG_WPS
2047 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2048 struct wpabuf *wps_ie;
2049 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2050 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2051 wpa_ie_len = wpabuf_len(wps_ie);
2052 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2053 } else
2054 wpa_ie_len = 0;
2055 wpabuf_free(wps_ie);
2056 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2057 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2058 params.wps = WPS_MODE_PRIVACY;
2059 else
2060 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002061 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002062#endif /* CONFIG_WPS */
2063 } else {
2064 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2065 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002066 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002067 }
2068
2069#ifdef CONFIG_P2P
2070 if (wpa_s->global->p2p) {
2071 u8 *pos;
2072 size_t len;
2073 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002074 pos = wpa_ie + wpa_ie_len;
2075 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002076 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2077 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002078 if (res >= 0)
2079 wpa_ie_len += res;
2080 }
2081
2082 wpa_s->cross_connect_disallowed = 0;
2083 if (bss) {
2084 struct wpabuf *p2p;
2085 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2086 if (p2p) {
2087 wpa_s->cross_connect_disallowed =
2088 p2p_get_cross_connect_disallowed(p2p);
2089 wpabuf_free(p2p);
2090 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2091 "connection",
2092 wpa_s->cross_connect_disallowed ?
2093 "disallows" : "allows");
2094 }
2095 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002096
2097 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002098#endif /* CONFIG_P2P */
2099
Dmitry Shmidt04949592012-07-19 12:16:46 -07002100#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002101 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002102 struct wpabuf *hs20;
2103 hs20 = wpabuf_alloc(20);
2104 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002105 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002106 size_t len;
2107
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002108 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002109 len = sizeof(wpa_ie) - wpa_ie_len;
2110 if (wpabuf_len(hs20) <= len) {
2111 os_memcpy(wpa_ie + wpa_ie_len,
2112 wpabuf_head(hs20), wpabuf_len(hs20));
2113 wpa_ie_len += wpabuf_len(hs20);
2114 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002115 wpabuf_free(hs20);
2116 }
2117 }
2118#endif /* CONFIG_HS20 */
2119
Dmitry Shmidt56052862013-10-04 10:23:25 -07002120 /*
2121 * Workaround: Add Extended Capabilities element only if the AP
2122 * included this element in Beacon/Probe Response frames. Some older
2123 * APs seem to have interoperability issues if this element is
2124 * included, so while the standard may require us to include the
2125 * element in all cases, it is justifiable to skip it to avoid
2126 * interoperability issues.
2127 */
2128 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002129 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002130 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002131 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2132 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002133 if (ext_capab_len > 0) {
2134 u8 *pos = wpa_ie;
2135 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2136 pos += 2 + pos[1];
2137 os_memmove(pos + ext_capab_len, pos,
2138 wpa_ie_len - (pos - wpa_ie));
2139 wpa_ie_len += ext_capab_len;
2140 os_memcpy(pos, ext_capab, ext_capab_len);
2141 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002142 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002143
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002144 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2145 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2146 size_t len;
2147
2148 len = sizeof(wpa_ie) - wpa_ie_len;
2149 if (wpabuf_len(buf) <= len) {
2150 os_memcpy(wpa_ie + wpa_ie_len,
2151 wpabuf_head(buf), wpabuf_len(buf));
2152 wpa_ie_len += wpabuf_len(buf);
2153 }
2154 }
2155
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002156 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2157 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002158 cipher_pairwise = wpa_s->pairwise_cipher;
2159 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002160 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2161 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2162 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2163 use_crypt = 0;
2164 if (wpa_set_wep_keys(wpa_s, ssid)) {
2165 use_crypt = 1;
2166 wep_keys_set = 1;
2167 }
2168 }
2169 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2170 use_crypt = 0;
2171
2172#ifdef IEEE8021X_EAPOL
2173 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2174 if ((ssid->eapol_flags &
2175 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2176 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2177 !wep_keys_set) {
2178 use_crypt = 0;
2179 } else {
2180 /* Assume that dynamic WEP-104 keys will be used and
2181 * set cipher suites in order for drivers to expect
2182 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002183 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002184 }
2185 }
2186#endif /* IEEE8021X_EAPOL */
2187
2188 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2189 /* Set the key before (and later after) association */
2190 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2191 }
2192
2193 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2194 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002195 params.ssid = bss->ssid;
2196 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002197 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
2198 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2199 MACSTR " freq=%u MHz based on scan results "
2200 "(bssid_set=%d)",
2201 MAC2STR(bss->bssid), bss->freq,
2202 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002203 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002204 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002205 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002206 params.bssid_hint = bss->bssid;
2207 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002208 } else {
2209 params.ssid = ssid->ssid;
2210 params.ssid_len = ssid->ssid_len;
2211 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002212
2213 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2214 wpa_s->conf->ap_scan == 2) {
2215 params.bssid = ssid->bssid;
2216 params.fixed_bssid = 1;
2217 }
2218
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002219 /* Initial frequency for IBSS/mesh */
2220 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002221 ssid->frequency > 0 && params.freq.freq == 0)
2222 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002223
2224 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002225 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002226 if (ssid->beacon_int)
2227 params.beacon_int = ssid->beacon_int;
2228 else
2229 params.beacon_int = wpa_s->conf->beacon_int;
2230 }
2231
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002232 params.wpa_ie = wpa_ie;
2233 params.wpa_ie_len = wpa_ie_len;
2234 params.pairwise_suite = cipher_pairwise;
2235 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002236 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002237 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002238 params.auth_alg = algs;
2239 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002240 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241 for (i = 0; i < NUM_WEP_KEYS; i++) {
2242 if (ssid->wep_key_len[i])
2243 params.wep_key[i] = ssid->wep_key[i];
2244 params.wep_key_len[i] = ssid->wep_key_len[i];
2245 }
2246 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2247
2248 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002249 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2250 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002251 params.passphrase = ssid->passphrase;
2252 if (ssid->psk_set)
2253 params.psk = ssid->psk;
2254 }
2255
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002256 if (wpa_s->conf->key_mgmt_offload) {
2257 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2258 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002259 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2260 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002261 params.req_key_mgmt_offload =
2262 ssid->proactive_key_caching < 0 ?
2263 wpa_s->conf->okc : ssid->proactive_key_caching;
2264 else
2265 params.req_key_mgmt_offload = 1;
2266
2267 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2268 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2269 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2270 ssid->psk_set)
2271 params.psk = ssid->psk;
2272 }
2273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002274 params.drop_unencrypted = use_crypt;
2275
2276#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002277 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002278 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002279 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2280 struct wpa_ie_data ie;
2281 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2282 ie.capabilities &
2283 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2284 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2285 "MFP: require MFP");
2286 params.mgmt_frame_protection =
2287 MGMT_FRAME_PROTECTION_REQUIRED;
2288 }
2289 }
2290#endif /* CONFIG_IEEE80211W */
2291
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002292 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002293
2294 if (wpa_s->parent->set_sta_uapsd)
2295 params.uapsd = wpa_s->parent->sta_uapsd;
2296 else
2297 params.uapsd = -1;
2298
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002299#ifdef CONFIG_HT_OVERRIDES
2300 os_memset(&htcaps, 0, sizeof(htcaps));
2301 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2302 params.htcaps = (u8 *) &htcaps;
2303 params.htcaps_mask = (u8 *) &htcaps_mask;
2304 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2305#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002306#ifdef CONFIG_VHT_OVERRIDES
2307 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2308 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2309 params.vhtcaps = &vhtcaps;
2310 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002311 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002312#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002313
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002314#ifdef CONFIG_P2P
2315 /*
2316 * If multi-channel concurrency is not supported, check for any
2317 * frequency conflict. In case of any frequency conflict, remove the
2318 * least prioritized connection.
2319 */
2320 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002321 int freq, num;
2322 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002323 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002324 wpa_printf(MSG_DEBUG,
2325 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002326 freq, params.freq.freq);
2327 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002328 wpa_s, params.freq.freq, ssid) < 0) {
2329 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002330 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002331 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002332 }
2333 }
2334#endif /* CONFIG_P2P */
2335
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002336 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002337 if (ret < 0) {
2338 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2339 "failed");
2340 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2341 /*
2342 * The driver is known to mean what is saying, so we
2343 * can stop right here; the association will not
2344 * succeed.
2345 */
2346 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002347 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2349 return;
2350 }
2351 /* try to continue anyway; new association will be tried again
2352 * after timeout */
2353 assoc_failed = 1;
2354 }
2355
2356 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2357 /* Set the key after the association just in case association
2358 * cleared the previously configured key. */
2359 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2360 /* No need to timeout authentication since there is no key
2361 * management. */
2362 wpa_supplicant_cancel_auth_timeout(wpa_s);
2363 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2364#ifdef CONFIG_IBSS_RSN
2365 } else if (ssid->mode == WPAS_MODE_IBSS &&
2366 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2367 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2368 /*
2369 * RSN IBSS authentication is per-STA and we can disable the
2370 * per-BSSID authentication.
2371 */
2372 wpa_supplicant_cancel_auth_timeout(wpa_s);
2373#endif /* CONFIG_IBSS_RSN */
2374 } else {
2375 /* Timeout for IEEE 802.11 authentication and association */
2376 int timeout = 60;
2377
2378 if (assoc_failed) {
2379 /* give IBSS a bit more time */
2380 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2381 } else if (wpa_s->conf->ap_scan == 1) {
2382 /* give IBSS a bit more time */
2383 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2384 }
2385 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2386 }
2387
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002388 if (wep_keys_set &&
2389 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002390 /* Set static WEP keys again */
2391 wpa_set_wep_keys(wpa_s, ssid);
2392 }
2393
2394 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2395 /*
2396 * Do not allow EAP session resumption between different
2397 * network configurations.
2398 */
2399 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2400 }
2401 old_ssid = wpa_s->current_ssid;
2402 wpa_s->current_ssid = ssid;
2403 wpa_s->current_bss = bss;
2404 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2405 wpa_supplicant_initiate_eapol(wpa_s);
2406 if (old_ssid != wpa_s->current_ssid)
2407 wpas_notify_network_changed(wpa_s);
2408}
2409
2410
2411static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2412 const u8 *addr)
2413{
2414 struct wpa_ssid *old_ssid;
2415
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002416 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002417 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002419 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002420 wpa_sm_set_config(wpa_s->wpa, NULL);
2421 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2422 if (old_ssid != wpa_s->current_ssid)
2423 wpas_notify_network_changed(wpa_s);
2424 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2425}
2426
2427
2428/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002429 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2430 * @wpa_s: Pointer to wpa_supplicant data
2431 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2432 *
2433 * This function is used to request %wpa_supplicant to deauthenticate from the
2434 * current AP.
2435 */
2436void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2437 int reason_code)
2438{
2439 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002440 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002441 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002443 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2444 " pending_bssid=" MACSTR " reason=%d state=%s",
2445 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2446 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2447
2448 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002449 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002450 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2451 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2452 wpa_s->wpa_state == WPA_ASSOCIATING))
2453 addr = wpa_s->pending_bssid;
2454 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2455 /*
2456 * When using driver-based BSS selection, we may not know the
2457 * BSSID with which we are currently trying to associate. We
2458 * need to notify the driver of this disconnection even in such
2459 * a case, so use the all zeros address here.
2460 */
2461 addr = wpa_s->bssid;
2462 zero_addr = 1;
2463 }
2464
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002465#ifdef CONFIG_TDLS
2466 wpa_tdls_teardown_peers(wpa_s->wpa);
2467#endif /* CONFIG_TDLS */
2468
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002469#ifdef CONFIG_MESH
2470 if (wpa_s->ifmsh) {
2471 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2472 wpa_s->ifname);
2473 wpa_supplicant_leave_mesh(wpa_s);
2474 }
2475#endif /* CONFIG_MESH */
2476
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002477 if (addr) {
2478 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002479 os_memset(&event, 0, sizeof(event));
2480 event.deauth_info.reason_code = (u16) reason_code;
2481 event.deauth_info.locally_generated = 1;
2482 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002483 if (zero_addr)
2484 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485 }
2486
2487 wpa_supplicant_clear_connection(wpa_s, addr);
2488}
2489
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002490static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2491 struct wpa_ssid *ssid)
2492{
2493 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2494 return;
2495
2496 ssid->disabled = 0;
2497 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2498 wpas_notify_network_enabled_changed(wpa_s, ssid);
2499
2500 /*
2501 * Try to reassociate since there is no current configuration and a new
2502 * network was made available.
2503 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002504 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002505 wpa_s->reassociate = 1;
2506}
2507
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508
2509/**
2510 * wpa_supplicant_enable_network - Mark a configured network as enabled
2511 * @wpa_s: wpa_supplicant structure for a network interface
2512 * @ssid: wpa_ssid structure for a configured network or %NULL
2513 *
2514 * Enables the specified network or all networks if no network specified.
2515 */
2516void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2517 struct wpa_ssid *ssid)
2518{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002519 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002520 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2521 wpa_supplicant_enable_one_network(wpa_s, ssid);
2522 } else
2523 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002525 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002526 if (wpa_s->sched_scanning) {
2527 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2528 "new network to scan filters");
2529 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530 }
2531
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002532 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2533 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002534 }
2535}
2536
2537
2538/**
2539 * wpa_supplicant_disable_network - Mark a configured network as disabled
2540 * @wpa_s: wpa_supplicant structure for a network interface
2541 * @ssid: wpa_ssid structure for a configured network or %NULL
2542 *
2543 * Disables the specified network or all networks if no network specified.
2544 */
2545void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2546 struct wpa_ssid *ssid)
2547{
2548 struct wpa_ssid *other_ssid;
2549 int was_disabled;
2550
2551 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002552 if (wpa_s->sched_scanning)
2553 wpa_supplicant_cancel_sched_scan(wpa_s);
2554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2556 other_ssid = other_ssid->next) {
2557 was_disabled = other_ssid->disabled;
2558 if (was_disabled == 2)
2559 continue; /* do not change persistent P2P group
2560 * data */
2561
2562 other_ssid->disabled = 1;
2563
2564 if (was_disabled != other_ssid->disabled)
2565 wpas_notify_network_enabled_changed(
2566 wpa_s, other_ssid);
2567 }
2568 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002569 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2571 } else if (ssid->disabled != 2) {
2572 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002573 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002574 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2575
2576 was_disabled = ssid->disabled;
2577
2578 ssid->disabled = 1;
2579
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002580 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002582 if (wpa_s->sched_scanning) {
2583 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2584 "to remove network from filters");
2585 wpa_supplicant_cancel_sched_scan(wpa_s);
2586 wpa_supplicant_req_scan(wpa_s, 0, 0);
2587 }
2588 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589 }
2590}
2591
2592
2593/**
2594 * wpa_supplicant_select_network - Attempt association with a network
2595 * @wpa_s: wpa_supplicant structure for a network interface
2596 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2597 */
2598void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2599 struct wpa_ssid *ssid)
2600{
2601
2602 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002603 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002605 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08002606 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002607 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002608 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002609 disconnected = 1;
2610 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002612 if (ssid)
2613 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2614
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002615 /*
2616 * Mark all other networks disabled or mark all networks enabled if no
2617 * network specified.
2618 */
2619 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2620 other_ssid = other_ssid->next) {
2621 int was_disabled = other_ssid->disabled;
2622 if (was_disabled == 2)
2623 continue; /* do not change persistent P2P group data */
2624
2625 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002626 if (was_disabled && !other_ssid->disabled)
2627 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628
2629 if (was_disabled != other_ssid->disabled)
2630 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2631 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002632
2633 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2634 /* We are already associated with the selected network */
2635 wpa_printf(MSG_DEBUG, "Already associated with the "
2636 "selected network - do nothing");
2637 return;
2638 }
2639
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002640 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002641 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002642 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002643 wpa_s->connect_without_scan =
2644 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002645
2646 /*
2647 * Don't optimize next scan freqs since a new ESS has been
2648 * selected.
2649 */
2650 os_free(wpa_s->next_scan_freqs);
2651 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002652 } else {
2653 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002654 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002655
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002656 wpa_s->disconnected = 0;
2657 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002658
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002659 if (wpa_s->connect_without_scan ||
2660 wpa_supplicant_fast_associate(wpa_s) != 1)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002661 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002662
2663 if (ssid)
2664 wpas_notify_network_selected(wpa_s, ssid);
2665}
2666
2667
2668/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002669 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2670 * @wpa_s: wpa_supplicant structure for a network interface
2671 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2672 * @pkcs11_module_path: PKCS #11 module path or NULL
2673 * Returns: 0 on success; -1 on failure
2674 *
2675 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2676 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2677 * module path fails the paths will be reset to the default value (NULL).
2678 */
2679int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2680 const char *pkcs11_engine_path,
2681 const char *pkcs11_module_path)
2682{
2683 char *pkcs11_engine_path_copy = NULL;
2684 char *pkcs11_module_path_copy = NULL;
2685
2686 if (pkcs11_engine_path != NULL) {
2687 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2688 if (pkcs11_engine_path_copy == NULL)
2689 return -1;
2690 }
2691 if (pkcs11_module_path != NULL) {
2692 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002693 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002694 os_free(pkcs11_engine_path_copy);
2695 return -1;
2696 }
2697 }
2698
2699 os_free(wpa_s->conf->pkcs11_engine_path);
2700 os_free(wpa_s->conf->pkcs11_module_path);
2701 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2702 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2703
2704 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2705 eapol_sm_deinit(wpa_s->eapol);
2706 wpa_s->eapol = NULL;
2707 if (wpa_supplicant_init_eapol(wpa_s)) {
2708 /* Error -> Reset paths to the default value (NULL) once. */
2709 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2710 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2711 NULL);
2712
2713 return -1;
2714 }
2715 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2716
2717 return 0;
2718}
2719
2720
2721/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2723 * @wpa_s: wpa_supplicant structure for a network interface
2724 * @ap_scan: AP scan mode
2725 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2726 *
2727 */
2728int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2729{
2730
2731 int old_ap_scan;
2732
2733 if (ap_scan < 0 || ap_scan > 2)
2734 return -1;
2735
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002736#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002737 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2738 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2739 wpa_s->wpa_state < WPA_COMPLETED) {
2740 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2741 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002742 return 0;
2743 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002744#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002745
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 old_ap_scan = wpa_s->conf->ap_scan;
2747 wpa_s->conf->ap_scan = ap_scan;
2748
2749 if (old_ap_scan != wpa_s->conf->ap_scan)
2750 wpas_notify_ap_scan_changed(wpa_s);
2751
2752 return 0;
2753}
2754
2755
2756/**
2757 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2758 * @wpa_s: wpa_supplicant structure for a network interface
2759 * @expire_age: Expiration age in seconds
2760 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2761 *
2762 */
2763int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2764 unsigned int bss_expire_age)
2765{
2766 if (bss_expire_age < 10) {
2767 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2768 bss_expire_age);
2769 return -1;
2770 }
2771 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2772 bss_expire_age);
2773 wpa_s->conf->bss_expiration_age = bss_expire_age;
2774
2775 return 0;
2776}
2777
2778
2779/**
2780 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2781 * @wpa_s: wpa_supplicant structure for a network interface
2782 * @expire_count: number of scans after which an unseen BSS is reclaimed
2783 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2784 *
2785 */
2786int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2787 unsigned int bss_expire_count)
2788{
2789 if (bss_expire_count < 1) {
2790 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2791 bss_expire_count);
2792 return -1;
2793 }
2794 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2795 bss_expire_count);
2796 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2797
2798 return 0;
2799}
2800
2801
2802/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002803 * wpa_supplicant_set_scan_interval - Set scan interval
2804 * @wpa_s: wpa_supplicant structure for a network interface
2805 * @scan_interval: scan interval in seconds
2806 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2807 *
2808 */
2809int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2810 int scan_interval)
2811{
2812 if (scan_interval < 0) {
2813 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2814 scan_interval);
2815 return -1;
2816 }
2817 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2818 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002819 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002820
2821 return 0;
2822}
2823
2824
2825/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002826 * wpa_supplicant_set_debug_params - Set global debug params
2827 * @global: wpa_global structure
2828 * @debug_level: debug level
2829 * @debug_timestamp: determines if show timestamp in debug data
2830 * @debug_show_keys: determines if show keys in debug data
2831 * Returns: 0 if succeed or -1 if debug_level has wrong value
2832 */
2833int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2834 int debug_timestamp, int debug_show_keys)
2835{
2836
2837 int old_level, old_timestamp, old_show_keys;
2838
2839 /* check for allowed debuglevels */
2840 if (debug_level != MSG_EXCESSIVE &&
2841 debug_level != MSG_MSGDUMP &&
2842 debug_level != MSG_DEBUG &&
2843 debug_level != MSG_INFO &&
2844 debug_level != MSG_WARNING &&
2845 debug_level != MSG_ERROR)
2846 return -1;
2847
2848 old_level = wpa_debug_level;
2849 old_timestamp = wpa_debug_timestamp;
2850 old_show_keys = wpa_debug_show_keys;
2851
2852 wpa_debug_level = debug_level;
2853 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2854 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2855
2856 if (wpa_debug_level != old_level)
2857 wpas_notify_debug_level_changed(global);
2858 if (wpa_debug_timestamp != old_timestamp)
2859 wpas_notify_debug_timestamp_changed(global);
2860 if (wpa_debug_show_keys != old_show_keys)
2861 wpas_notify_debug_show_keys_changed(global);
2862
2863 return 0;
2864}
2865
2866
2867/**
2868 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2869 * @wpa_s: Pointer to wpa_supplicant data
2870 * Returns: A pointer to the current network structure or %NULL on failure
2871 */
2872struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2873{
2874 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002875 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002876 int res;
2877 size_t ssid_len;
2878 u8 bssid[ETH_ALEN];
2879 int wired;
2880
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002881 res = wpa_drv_get_ssid(wpa_s, ssid);
2882 if (res < 0) {
2883 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2884 "driver");
2885 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002886 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002887 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002888
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002889 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002890 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2891 "driver");
2892 return NULL;
2893 }
2894
2895 wired = wpa_s->conf->ap_scan == 0 &&
2896 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2897
2898 entry = wpa_s->conf->ssid;
2899 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002900 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002901 ((ssid_len == entry->ssid_len &&
2902 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2903 (!entry->bssid_set ||
2904 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2905 return entry;
2906#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002907 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2909 (entry->ssid == NULL || entry->ssid_len == 0) &&
2910 (!entry->bssid_set ||
2911 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2912 return entry;
2913#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002914
Dmitry Shmidt04949592012-07-19 12:16:46 -07002915 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002916 entry->ssid_len == 0 &&
2917 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2918 return entry;
2919
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002920 entry = entry->next;
2921 }
2922
2923 return NULL;
2924}
2925
2926
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002927static int select_driver(struct wpa_supplicant *wpa_s, int i)
2928{
2929 struct wpa_global *global = wpa_s->global;
2930
2931 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2932 global->drv_priv[i] = wpa_drivers[i]->global_init();
2933 if (global->drv_priv[i] == NULL) {
2934 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2935 "'%s'", wpa_drivers[i]->name);
2936 return -1;
2937 }
2938 }
2939
2940 wpa_s->driver = wpa_drivers[i];
2941 wpa_s->global_drv_priv = global->drv_priv[i];
2942
2943 return 0;
2944}
2945
2946
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002947static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2948 const char *name)
2949{
2950 int i;
2951 size_t len;
2952 const char *pos, *driver = name;
2953
2954 if (wpa_s == NULL)
2955 return -1;
2956
2957 if (wpa_drivers[0] == NULL) {
2958 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2959 "wpa_supplicant");
2960 return -1;
2961 }
2962
2963 if (name == NULL) {
2964 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002965 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002966 }
2967
2968 do {
2969 pos = os_strchr(driver, ',');
2970 if (pos)
2971 len = pos - driver;
2972 else
2973 len = os_strlen(driver);
2974
2975 for (i = 0; wpa_drivers[i]; i++) {
2976 if (os_strlen(wpa_drivers[i]->name) == len &&
2977 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002978 0) {
2979 /* First driver that succeeds wins */
2980 if (select_driver(wpa_s, i) == 0)
2981 return 0;
2982 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002983 }
2984
2985 driver = pos + 1;
2986 } while (pos);
2987
2988 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2989 return -1;
2990}
2991
2992
2993/**
2994 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2995 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2996 * with struct wpa_driver_ops::init()
2997 * @src_addr: Source address of the EAPOL frame
2998 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2999 * @len: Length of the EAPOL data
3000 *
3001 * This function is called for each received EAPOL frame. Most driver
3002 * interfaces rely on more generic OS mechanism for receiving frames through
3003 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3004 * take care of received EAPOL frames and deliver them to the core supplicant
3005 * code by calling this function.
3006 */
3007void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3008 const u8 *buf, size_t len)
3009{
3010 struct wpa_supplicant *wpa_s = ctx;
3011
3012 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3013 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3014
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003015#ifdef CONFIG_PEERKEY
3016 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3017 wpa_s->current_ssid->peerkey &&
3018 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3019 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3020 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3021 return;
3022 }
3023#endif /* CONFIG_PEERKEY */
3024
Jouni Malinena05074c2012-12-21 21:35:35 +02003025 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3026 (wpa_s->last_eapol_matches_bssid &&
3027#ifdef CONFIG_AP
3028 !wpa_s->ap_iface &&
3029#endif /* CONFIG_AP */
3030 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003031 /*
3032 * There is possible race condition between receiving the
3033 * association event and the EAPOL frame since they are coming
3034 * through different paths from the driver. In order to avoid
3035 * issues in trying to process the EAPOL frame before receiving
3036 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003037 * the association event is received. This may also be needed in
3038 * driver-based roaming case, so also use src_addr != BSSID as a
3039 * trigger if we have previously confirmed that the
3040 * Authenticator uses BSSID as the src_addr (which is not the
3041 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003042 */
3043 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003044 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3045 wpa_supplicant_state_txt(wpa_s->wpa_state),
3046 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003047 wpabuf_free(wpa_s->pending_eapol_rx);
3048 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3049 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003050 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003051 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3052 ETH_ALEN);
3053 }
3054 return;
3055 }
3056
Jouni Malinena05074c2012-12-21 21:35:35 +02003057 wpa_s->last_eapol_matches_bssid =
3058 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3059
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003060#ifdef CONFIG_AP
3061 if (wpa_s->ap_iface) {
3062 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3063 return;
3064 }
3065#endif /* CONFIG_AP */
3066
3067 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3068 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3069 "no key management is configured");
3070 return;
3071 }
3072
3073 if (wpa_s->eapol_received == 0 &&
3074 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3075 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3076 wpa_s->wpa_state != WPA_COMPLETED) &&
3077 (wpa_s->current_ssid == NULL ||
3078 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3079 /* Timeout for completing IEEE 802.1X and WPA authentication */
3080 wpa_supplicant_req_auth_timeout(
3081 wpa_s,
3082 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3083 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3084 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
3085 70 : 10, 0);
3086 }
3087 wpa_s->eapol_received++;
3088
3089 if (wpa_s->countermeasures) {
3090 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3091 "EAPOL packet");
3092 return;
3093 }
3094
3095#ifdef CONFIG_IBSS_RSN
3096 if (wpa_s->current_ssid &&
3097 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3098 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3099 return;
3100 }
3101#endif /* CONFIG_IBSS_RSN */
3102
3103 /* Source address of the incoming EAPOL frame could be compared to the
3104 * current BSSID. However, it is possible that a centralized
3105 * Authenticator could be using another MAC address than the BSSID of
3106 * an AP, so just allow any address to be used for now. The replies are
3107 * still sent to the current BSSID (if available), though. */
3108
3109 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3110 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3111 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3112 return;
3113 wpa_drv_poll(wpa_s);
3114 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3115 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3116 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3117 /*
3118 * Set portValid = TRUE here since we are going to skip 4-way
3119 * handshake processing which would normally set portValid. We
3120 * need this to allow the EAPOL state machines to be completed
3121 * without going through EAPOL-Key handshake.
3122 */
3123 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3124 }
3125}
3126
3127
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003128int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003129{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003130 if ((!wpa_s->p2p_mgmt ||
3131 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3132 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003133 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003134 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3135 wpa_drv_get_mac_addr(wpa_s),
3136 ETH_P_EAPOL,
3137 wpa_supplicant_rx_eapol, wpa_s, 0);
3138 if (wpa_s->l2 == NULL)
3139 return -1;
3140 } else {
3141 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3142 if (addr)
3143 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3144 }
3145
3146 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3147 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3148 return -1;
3149 }
3150
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003151 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3152
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003153 return 0;
3154}
3155
3156
Dmitry Shmidt04949592012-07-19 12:16:46 -07003157static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3158 const u8 *buf, size_t len)
3159{
3160 struct wpa_supplicant *wpa_s = ctx;
3161 const struct l2_ethhdr *eth;
3162
3163 if (len < sizeof(*eth))
3164 return;
3165 eth = (const struct l2_ethhdr *) buf;
3166
3167 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3168 !(eth->h_dest[0] & 0x01)) {
3169 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3170 " (bridge - not for this interface - ignore)",
3171 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3172 return;
3173 }
3174
3175 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3176 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3177 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3178 len - sizeof(*eth));
3179}
3180
3181
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003182/**
3183 * wpa_supplicant_driver_init - Initialize driver interface parameters
3184 * @wpa_s: Pointer to wpa_supplicant data
3185 * Returns: 0 on success, -1 on failure
3186 *
3187 * This function is called to initialize driver interface parameters.
3188 * wpa_drv_init() must have been called before this function to initialize the
3189 * driver interface.
3190 */
3191int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3192{
3193 static int interface_count = 0;
3194
3195 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3196 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003197
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003198 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3199 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003200 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003201 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3202
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003203 if (wpa_s->bridge_ifname[0]) {
3204 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3205 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003206 wpa_s->l2_br = l2_packet_init_bridge(
3207 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3208 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003209 if (wpa_s->l2_br == NULL) {
3210 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3211 "connection for the bridge interface '%s'",
3212 wpa_s->bridge_ifname);
3213 return -1;
3214 }
3215 }
3216
3217 wpa_clear_keys(wpa_s, NULL);
3218
3219 /* Make sure that TKIP countermeasures are not left enabled (could
3220 * happen if wpa_supplicant is killed during countermeasures. */
3221 wpa_drv_set_countermeasures(wpa_s, 0);
3222
3223 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3224 wpa_drv_flush_pmkid(wpa_s);
3225
3226 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003227 wpa_s->prev_scan_wildcard = 0;
3228
Dmitry Shmidt04949592012-07-19 12:16:46 -07003229 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003230 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3231 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3232 interface_count = 0;
3233 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003234#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003235 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003236 wpa_supplicant_delayed_sched_scan(wpa_s,
3237 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003238 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003239 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003240 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003241#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003242 interface_count++;
3243 } else
3244 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3245
3246 return 0;
3247}
3248
3249
3250static int wpa_supplicant_daemon(const char *pid_file)
3251{
3252 wpa_printf(MSG_DEBUG, "Daemonize..");
3253 return os_daemonize(pid_file);
3254}
3255
3256
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003257static struct wpa_supplicant *
3258wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003259{
3260 struct wpa_supplicant *wpa_s;
3261
3262 wpa_s = os_zalloc(sizeof(*wpa_s));
3263 if (wpa_s == NULL)
3264 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003265 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003266 wpa_s->scan_interval = 5;
3267 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003268 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003269 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003270
3271 return wpa_s;
3272}
3273
3274
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003275#ifdef CONFIG_HT_OVERRIDES
3276
3277static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3278 struct ieee80211_ht_capabilities *htcaps,
3279 struct ieee80211_ht_capabilities *htcaps_mask,
3280 const char *ht_mcs)
3281{
3282 /* parse ht_mcs into hex array */
3283 int i;
3284 const char *tmp = ht_mcs;
3285 char *end = NULL;
3286
3287 /* If ht_mcs is null, do not set anything */
3288 if (!ht_mcs)
3289 return 0;
3290
3291 /* This is what we are setting in the kernel */
3292 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3293
3294 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3295
3296 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3297 errno = 0;
3298 long v = strtol(tmp, &end, 16);
3299 if (errno == 0) {
3300 wpa_msg(wpa_s, MSG_DEBUG,
3301 "htcap value[%i]: %ld end: %p tmp: %p",
3302 i, v, end, tmp);
3303 if (end == tmp)
3304 break;
3305
3306 htcaps->supported_mcs_set[i] = v;
3307 tmp = end;
3308 } else {
3309 wpa_msg(wpa_s, MSG_ERROR,
3310 "Failed to parse ht-mcs: %s, error: %s\n",
3311 ht_mcs, strerror(errno));
3312 return -1;
3313 }
3314 }
3315
3316 /*
3317 * If we were able to parse any values, then set mask for the MCS set.
3318 */
3319 if (i) {
3320 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3321 IEEE80211_HT_MCS_MASK_LEN - 1);
3322 /* skip the 3 reserved bits */
3323 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3324 0x1f;
3325 }
3326
3327 return 0;
3328}
3329
3330
3331static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3332 struct ieee80211_ht_capabilities *htcaps,
3333 struct ieee80211_ht_capabilities *htcaps_mask,
3334 int disabled)
3335{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003336 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003337
3338 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3339
3340 if (disabled == -1)
3341 return 0;
3342
3343 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3344 htcaps_mask->ht_capabilities_info |= msk;
3345 if (disabled)
3346 htcaps->ht_capabilities_info &= msk;
3347 else
3348 htcaps->ht_capabilities_info |= msk;
3349
3350 return 0;
3351}
3352
3353
3354static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3355 struct ieee80211_ht_capabilities *htcaps,
3356 struct ieee80211_ht_capabilities *htcaps_mask,
3357 int factor)
3358{
3359 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3360
3361 if (factor == -1)
3362 return 0;
3363
3364 if (factor < 0 || factor > 3) {
3365 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3366 "Must be 0-3 or -1", factor);
3367 return -EINVAL;
3368 }
3369
3370 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3371 htcaps->a_mpdu_params &= ~0x3;
3372 htcaps->a_mpdu_params |= factor & 0x3;
3373
3374 return 0;
3375}
3376
3377
3378static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3379 struct ieee80211_ht_capabilities *htcaps,
3380 struct ieee80211_ht_capabilities *htcaps_mask,
3381 int density)
3382{
3383 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3384
3385 if (density == -1)
3386 return 0;
3387
3388 if (density < 0 || density > 7) {
3389 wpa_msg(wpa_s, MSG_ERROR,
3390 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3391 density);
3392 return -EINVAL;
3393 }
3394
3395 htcaps_mask->a_mpdu_params |= 0x1C;
3396 htcaps->a_mpdu_params &= ~(0x1C);
3397 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3398
3399 return 0;
3400}
3401
3402
3403static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3404 struct ieee80211_ht_capabilities *htcaps,
3405 struct ieee80211_ht_capabilities *htcaps_mask,
3406 int disabled)
3407{
3408 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003409 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3410 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003411
3412 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3413
3414 if (disabled)
3415 htcaps->ht_capabilities_info &= ~msk;
3416 else
3417 htcaps->ht_capabilities_info |= msk;
3418
3419 htcaps_mask->ht_capabilities_info |= msk;
3420
3421 return 0;
3422}
3423
3424
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003425static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3426 struct ieee80211_ht_capabilities *htcaps,
3427 struct ieee80211_ht_capabilities *htcaps_mask,
3428 int disabled)
3429{
3430 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003431 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3432 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003433
3434 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3435
3436 if (disabled)
3437 htcaps->ht_capabilities_info &= ~msk;
3438 else
3439 htcaps->ht_capabilities_info |= msk;
3440
3441 htcaps_mask->ht_capabilities_info |= msk;
3442
3443 return 0;
3444}
3445
3446
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003447static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3448 struct ieee80211_ht_capabilities *htcaps,
3449 struct ieee80211_ht_capabilities *htcaps_mask,
3450 int disabled)
3451{
3452 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003453 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003454
3455 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3456
3457 if (disabled)
3458 htcaps->ht_capabilities_info &= ~msk;
3459 else
3460 htcaps->ht_capabilities_info |= msk;
3461
3462 htcaps_mask->ht_capabilities_info |= msk;
3463
3464 return 0;
3465}
3466
3467
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003468void wpa_supplicant_apply_ht_overrides(
3469 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3470 struct wpa_driver_associate_params *params)
3471{
3472 struct ieee80211_ht_capabilities *htcaps;
3473 struct ieee80211_ht_capabilities *htcaps_mask;
3474
3475 if (!ssid)
3476 return;
3477
3478 params->disable_ht = ssid->disable_ht;
3479 if (!params->htcaps || !params->htcaps_mask)
3480 return;
3481
3482 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3483 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3484 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3485 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3486 ssid->disable_max_amsdu);
3487 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3488 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3489 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003490 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003491 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003492
3493 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003494 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003495 htcaps->ht_capabilities_info |= bit;
3496 htcaps_mask->ht_capabilities_info |= bit;
3497 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003498}
3499
3500#endif /* CONFIG_HT_OVERRIDES */
3501
3502
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003503#ifdef CONFIG_VHT_OVERRIDES
3504void wpa_supplicant_apply_vht_overrides(
3505 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3506 struct wpa_driver_associate_params *params)
3507{
3508 struct ieee80211_vht_capabilities *vhtcaps;
3509 struct ieee80211_vht_capabilities *vhtcaps_mask;
3510
3511 if (!ssid)
3512 return;
3513
3514 params->disable_vht = ssid->disable_vht;
3515
3516 vhtcaps = (void *) params->vhtcaps;
3517 vhtcaps_mask = (void *) params->vhtcaps_mask;
3518
3519 if (!vhtcaps || !vhtcaps_mask)
3520 return;
3521
3522 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3523 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3524
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003525#ifdef CONFIG_HT_OVERRIDES
3526 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003527 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3528 int max_ampdu;
3529
3530 max_ampdu = (ssid->vht_capa &
3531 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3532 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003533
3534 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3535 wpa_set_ampdu_factor(wpa_s,
3536 (void *) params->htcaps,
3537 (void *) params->htcaps_mask,
3538 max_ampdu);
3539 }
3540#endif /* CONFIG_HT_OVERRIDES */
3541
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003542#define OVERRIDE_MCS(i) \
3543 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3544 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3545 3 << 2 * (i - 1); \
3546 vhtcaps->vht_supported_mcs_set.tx_map |= \
3547 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3548 } \
3549 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3550 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3551 3 << 2 * (i - 1); \
3552 vhtcaps->vht_supported_mcs_set.rx_map |= \
3553 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3554 }
3555
3556 OVERRIDE_MCS(1);
3557 OVERRIDE_MCS(2);
3558 OVERRIDE_MCS(3);
3559 OVERRIDE_MCS(4);
3560 OVERRIDE_MCS(5);
3561 OVERRIDE_MCS(6);
3562 OVERRIDE_MCS(7);
3563 OVERRIDE_MCS(8);
3564}
3565#endif /* CONFIG_VHT_OVERRIDES */
3566
3567
Dmitry Shmidt04949592012-07-19 12:16:46 -07003568static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3569{
3570#ifdef PCSC_FUNCS
3571 size_t len;
3572
3573 if (!wpa_s->conf->pcsc_reader)
3574 return 0;
3575
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003576 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003577 if (!wpa_s->scard)
3578 return 1;
3579
3580 if (wpa_s->conf->pcsc_pin &&
3581 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3582 scard_deinit(wpa_s->scard);
3583 wpa_s->scard = NULL;
3584 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3585 return -1;
3586 }
3587
3588 len = sizeof(wpa_s->imsi) - 1;
3589 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3590 scard_deinit(wpa_s->scard);
3591 wpa_s->scard = NULL;
3592 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3593 return -1;
3594 }
3595 wpa_s->imsi[len] = '\0';
3596
3597 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3598
3599 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3600 wpa_s->imsi, wpa_s->mnc_len);
3601
3602 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3603 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3604#endif /* PCSC_FUNCS */
3605
3606 return 0;
3607}
3608
3609
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003610int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3611{
3612 char *val, *pos;
3613
3614 ext_password_deinit(wpa_s->ext_pw);
3615 wpa_s->ext_pw = NULL;
3616 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3617
3618 if (!wpa_s->conf->ext_password_backend)
3619 return 0;
3620
3621 val = os_strdup(wpa_s->conf->ext_password_backend);
3622 if (val == NULL)
3623 return -1;
3624 pos = os_strchr(val, ':');
3625 if (pos)
3626 *pos++ = '\0';
3627
3628 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3629
3630 wpa_s->ext_pw = ext_password_init(val, pos);
3631 os_free(val);
3632 if (wpa_s->ext_pw == NULL) {
3633 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3634 return -1;
3635 }
3636 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3637
3638 return 0;
3639}
3640
3641
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003642static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003643 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003644{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003645 struct wowlan_triggers *triggers;
3646 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003647
3648 if (!wpa_s->conf->wowlan_triggers)
3649 return 0;
3650
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003651 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3652 if (triggers) {
3653 ret = wpa_drv_wowlan(wpa_s, triggers);
3654 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003655 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003656 return ret;
3657}
3658
3659
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003660static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3661 const char *rn)
3662{
3663 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3664 struct wpa_radio *radio;
3665
3666 while (rn && iface) {
3667 radio = iface->radio;
3668 if (radio && os_strcmp(rn, radio->name) == 0) {
3669 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3670 wpa_s->ifname, rn);
3671 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3672 return radio;
3673 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003674
3675 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003676 }
3677
3678 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3679 wpa_s->ifname, rn ? rn : "N/A");
3680 radio = os_zalloc(sizeof(*radio));
3681 if (radio == NULL)
3682 return NULL;
3683
3684 if (rn)
3685 os_strlcpy(radio->name, rn, sizeof(radio->name));
3686 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003687 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003688 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3689
3690 return radio;
3691}
3692
3693
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003694static void radio_work_free(struct wpa_radio_work *work)
3695{
3696 if (work->wpa_s->scan_work == work) {
3697 /* This should not really happen. */
3698 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3699 work->type, work, work->started);
3700 work->wpa_s->scan_work = NULL;
3701 }
3702
3703#ifdef CONFIG_P2P
3704 if (work->wpa_s->p2p_scan_work == work) {
3705 /* This should not really happen. */
3706 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3707 work->type, work, work->started);
3708 work->wpa_s->p2p_scan_work = NULL;
3709 }
3710#endif /* CONFIG_P2P */
3711
3712 dl_list_del(&work->list);
3713 os_free(work);
3714}
3715
3716
3717static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3718{
3719 struct wpa_radio *radio = eloop_ctx;
3720 struct wpa_radio_work *work;
3721 struct os_reltime now, diff;
3722 struct wpa_supplicant *wpa_s;
3723
3724 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3725 if (work == NULL)
3726 return;
3727
3728 if (work->started)
3729 return; /* already started and still in progress */
3730
3731 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3732 radio_list);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003733 if (wpa_s && wpa_s->radio->external_scan_running) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003734 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3735 return;
3736 }
3737
3738 os_get_reltime(&now);
3739 os_reltime_sub(&now, &work->time, &diff);
3740 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3741 work->type, work, diff.sec, diff.usec);
3742 work->started = 1;
3743 work->time = now;
3744 work->cb(work, 0);
3745}
3746
3747
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003748/*
3749 * This function removes both started and pending radio works running on
3750 * the provided interface's radio.
3751 * Prior to the removal of the radio work, its callback (cb) is called with
3752 * deinit set to be 1. Each work's callback is responsible for clearing its
3753 * internal data and restoring to a correct state.
3754 * @wpa_s: wpa_supplicant data
3755 * @type: type of works to be removed
3756 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3757 * this interface's works.
3758 */
3759void radio_remove_works(struct wpa_supplicant *wpa_s,
3760 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003761{
3762 struct wpa_radio_work *work, *tmp;
3763 struct wpa_radio *radio = wpa_s->radio;
3764
3765 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3766 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003767 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003768 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003769
3770 /* skip other ifaces' works */
3771 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003772 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003773
3774 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3775 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003776 work->cb(work, 1);
3777 radio_work_free(work);
3778 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003779
3780 /* in case we removed the started work */
3781 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003782}
3783
3784
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003785static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3786{
3787 struct wpa_radio *radio = wpa_s->radio;
3788
3789 if (!radio)
3790 return;
3791
3792 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3793 wpa_s->ifname, radio->name);
3794 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003795 radio_remove_works(wpa_s, NULL, 0);
3796 wpa_s->radio = NULL;
3797 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003798 return; /* Interfaces remain for this radio */
3799
3800 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003801 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003802 os_free(radio);
3803}
3804
3805
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003806void radio_work_check_next(struct wpa_supplicant *wpa_s)
3807{
3808 struct wpa_radio *radio = wpa_s->radio;
3809
3810 if (dl_list_empty(&radio->work))
3811 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003812 if (wpa_s->ext_work_in_progress) {
3813 wpa_printf(MSG_DEBUG,
3814 "External radio work in progress - delay start of pending item");
3815 return;
3816 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003817 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3818 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3819}
3820
3821
3822/**
3823 * radio_add_work - Add a radio work item
3824 * @wpa_s: Pointer to wpa_supplicant data
3825 * @freq: Frequency of the offchannel operation in MHz or 0
3826 * @type: Unique identifier for each type of work
3827 * @next: Force as the next work to be executed
3828 * @cb: Callback function for indicating when radio is available
3829 * @ctx: Context pointer for the work (work->ctx in cb())
3830 * Returns: 0 on success, -1 on failure
3831 *
3832 * This function is used to request time for an operation that requires
3833 * exclusive radio control. Once the radio is available, the registered callback
3834 * function will be called. radio_work_done() must be called once the exclusive
3835 * radio operation has been completed, so that the radio is freed for other
3836 * operations. The special case of deinit=1 is used to free the context data
3837 * during interface removal. That does not allow the callback function to start
3838 * the radio operation, i.e., it must free any resources allocated for the radio
3839 * work and return.
3840 *
3841 * The @freq parameter can be used to indicate a single channel on which the
3842 * offchannel operation will occur. This may allow multiple radio work
3843 * operations to be performed in parallel if they apply for the same channel.
3844 * Setting this to 0 indicates that the work item may use multiple channels or
3845 * requires exclusive control of the radio.
3846 */
3847int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3848 const char *type, int next,
3849 void (*cb)(struct wpa_radio_work *work, int deinit),
3850 void *ctx)
3851{
3852 struct wpa_radio_work *work;
3853 int was_empty;
3854
3855 work = os_zalloc(sizeof(*work));
3856 if (work == NULL)
3857 return -1;
3858 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3859 os_get_reltime(&work->time);
3860 work->freq = freq;
3861 work->type = type;
3862 work->wpa_s = wpa_s;
3863 work->cb = cb;
3864 work->ctx = ctx;
3865
3866 was_empty = dl_list_empty(&wpa_s->radio->work);
3867 if (next)
3868 dl_list_add(&wpa_s->radio->work, &work->list);
3869 else
3870 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3871 if (was_empty) {
3872 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3873 radio_work_check_next(wpa_s);
3874 }
3875
3876 return 0;
3877}
3878
3879
3880/**
3881 * radio_work_done - Indicate that a radio work item has been completed
3882 * @work: Completed work
3883 *
3884 * This function is called once the callback function registered with
3885 * radio_add_work() has completed its work.
3886 */
3887void radio_work_done(struct wpa_radio_work *work)
3888{
3889 struct wpa_supplicant *wpa_s = work->wpa_s;
3890 struct os_reltime now, diff;
3891 unsigned int started = work->started;
3892
3893 os_get_reltime(&now);
3894 os_reltime_sub(&now, &work->time, &diff);
3895 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3896 work->type, work, started ? "done" : "canceled",
3897 diff.sec, diff.usec);
3898 radio_work_free(work);
3899 if (started)
3900 radio_work_check_next(wpa_s);
3901}
3902
3903
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003904struct wpa_radio_work *
3905radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003906{
3907 struct wpa_radio_work *work;
3908 struct wpa_radio *radio = wpa_s->radio;
3909
3910 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3911 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003912 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003913 }
3914
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003915 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003916}
3917
3918
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003919static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3920 struct wpa_interface *iface)
3921{
3922 const char *ifname, *driver, *rn;
3923
3924 driver = iface->driver;
3925next_driver:
3926 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3927 return -1;
3928
3929 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3930 if (wpa_s->drv_priv == NULL) {
3931 const char *pos;
3932 pos = driver ? os_strchr(driver, ',') : NULL;
3933 if (pos) {
3934 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3935 "driver interface - try next driver wrapper");
3936 driver = pos + 1;
3937 goto next_driver;
3938 }
3939 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3940 "interface");
3941 return -1;
3942 }
3943 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3944 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3945 "driver_param '%s'", wpa_s->conf->driver_param);
3946 return -1;
3947 }
3948
3949 ifname = wpa_drv_get_ifname(wpa_s);
3950 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3951 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3952 "interface name with '%s'", ifname);
3953 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3954 }
3955
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003956 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003957 if (rn && rn[0] == '\0')
3958 rn = NULL;
3959
3960 wpa_s->radio = radio_add_interface(wpa_s, rn);
3961 if (wpa_s->radio == NULL)
3962 return -1;
3963
3964 return 0;
3965}
3966
3967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003968static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3969 struct wpa_interface *iface)
3970{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003971 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003972 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003973
3974 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3975 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3976 iface->confname ? iface->confname : "N/A",
3977 iface->driver ? iface->driver : "default",
3978 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3979 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3980
3981 if (iface->confname) {
3982#ifdef CONFIG_BACKEND_FILE
3983 wpa_s->confname = os_rel2abs_path(iface->confname);
3984 if (wpa_s->confname == NULL) {
3985 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3986 "for configuration file '%s'.",
3987 iface->confname);
3988 return -1;
3989 }
3990 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3991 iface->confname, wpa_s->confname);
3992#else /* CONFIG_BACKEND_FILE */
3993 wpa_s->confname = os_strdup(iface->confname);
3994#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003995 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003996 if (wpa_s->conf == NULL) {
3997 wpa_printf(MSG_ERROR, "Failed to read or parse "
3998 "configuration '%s'.", wpa_s->confname);
3999 return -1;
4000 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004001 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4002 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004003
4004 /*
4005 * Override ctrl_interface and driver_param if set on command
4006 * line.
4007 */
4008 if (iface->ctrl_interface) {
4009 os_free(wpa_s->conf->ctrl_interface);
4010 wpa_s->conf->ctrl_interface =
4011 os_strdup(iface->ctrl_interface);
4012 }
4013
4014 if (iface->driver_param) {
4015 os_free(wpa_s->conf->driver_param);
4016 wpa_s->conf->driver_param =
4017 os_strdup(iface->driver_param);
4018 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004019
4020 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4021 os_free(wpa_s->conf->ctrl_interface);
4022 wpa_s->conf->ctrl_interface = NULL;
4023 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004024 } else
4025 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4026 iface->driver_param);
4027
4028 if (wpa_s->conf == NULL) {
4029 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4030 return -1;
4031 }
4032
4033 if (iface->ifname == NULL) {
4034 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4035 return -1;
4036 }
4037 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4038 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4039 iface->ifname);
4040 return -1;
4041 }
4042 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4043
4044 if (iface->bridge_ifname) {
4045 if (os_strlen(iface->bridge_ifname) >=
4046 sizeof(wpa_s->bridge_ifname)) {
4047 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4048 "name '%s'.", iface->bridge_ifname);
4049 return -1;
4050 }
4051 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4052 sizeof(wpa_s->bridge_ifname));
4053 }
4054
4055 /* RSNA Supplicant Key Management - INITIALIZE */
4056 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4057 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4058
4059 /* Initialize driver interface and register driver event handler before
4060 * L2 receive handler so that association events are processed before
4061 * EAPOL-Key packets if both become available for the same select()
4062 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004063 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004064 return -1;
4065
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004066 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4067 return -1;
4068
4069 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4070 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4071 NULL);
4072 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4073
4074 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4075 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4076 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4077 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4078 "dot11RSNAConfigPMKLifetime");
4079 return -1;
4080 }
4081
4082 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4083 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4084 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4085 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4086 "dot11RSNAConfigPMKReauthThreshold");
4087 return -1;
4088 }
4089
4090 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4091 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4092 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4093 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4094 "dot11RSNAConfigSATimeout");
4095 return -1;
4096 }
4097
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004098 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4099 &wpa_s->hw.num_modes,
4100 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004101 if (wpa_s->hw.modes) {
4102 u16 i;
4103
4104 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4105 if (wpa_s->hw.modes[i].vht_capab) {
4106 wpa_s->hw_capab = CAPAB_VHT;
4107 break;
4108 }
4109
4110 if (wpa_s->hw.modes[i].ht_capab &
4111 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4112 wpa_s->hw_capab = CAPAB_HT40;
4113 else if (wpa_s->hw.modes[i].ht_capab &&
4114 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4115 wpa_s->hw_capab = CAPAB_HT;
4116 }
4117 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004118
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004119 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4120 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004121 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004122 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004123 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004124 wpa_s->drv_smps_modes = capa.smps_modes;
4125 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004126 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004127 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004128 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
4129 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4130 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004131 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4132 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004133 wpa_s->extended_capa = capa.extended_capa;
4134 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4135 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004136 wpa_s->num_multichan_concurrent =
4137 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004138 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4139
4140 if (capa.mac_addr_rand_scan_supported)
4141 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4142 if (wpa_s->sched_scan_supported &&
4143 capa.mac_addr_rand_sched_scan_supported)
4144 wpa_s->mac_addr_rand_supported |=
4145 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004146 }
4147 if (wpa_s->max_remain_on_chan == 0)
4148 wpa_s->max_remain_on_chan = 1000;
4149
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004150 /*
4151 * Only take p2p_mgmt parameters when P2P Device is supported.
4152 * Doing it here as it determines whether l2_packet_init() will be done
4153 * during wpa_supplicant_driver_init().
4154 */
4155 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4156 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4157 else
4158 iface->p2p_mgmt = 1;
4159
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004160 if (wpa_s->num_multichan_concurrent == 0)
4161 wpa_s->num_multichan_concurrent = 1;
4162
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004163 if (wpa_supplicant_driver_init(wpa_s) < 0)
4164 return -1;
4165
4166#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004167 if ((!iface->p2p_mgmt ||
4168 !(wpa_s->drv_flags &
4169 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4170 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004171 return -1;
4172#endif /* CONFIG_TDLS */
4173
4174 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4175 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4176 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4177 return -1;
4178 }
4179
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004180 if (wpas_wps_init(wpa_s))
4181 return -1;
4182
4183 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4184 return -1;
4185 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4186
4187 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4188 if (wpa_s->ctrl_iface == NULL) {
4189 wpa_printf(MSG_ERROR,
4190 "Failed to initialize control interface '%s'.\n"
4191 "You may have another wpa_supplicant process "
4192 "already running or the file was\n"
4193 "left by an unclean termination of wpa_supplicant "
4194 "in which case you will need\n"
4195 "to manually remove this file before starting "
4196 "wpa_supplicant again.\n",
4197 wpa_s->conf->ctrl_interface);
4198 return -1;
4199 }
4200
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004201 wpa_s->gas = gas_query_init(wpa_s);
4202 if (wpa_s->gas == NULL) {
4203 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4204 return -1;
4205 }
4206
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004207 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004208 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4209 return -1;
4210 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004211
4212 if (wpa_bss_init(wpa_s) < 0)
4213 return -1;
4214
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004215 /*
4216 * Set Wake-on-WLAN triggers, if configured.
4217 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4218 * have effect anyway when the interface is down).
4219 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004220 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004221 return -1;
4222
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004223#ifdef CONFIG_EAP_PROXY
4224{
4225 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004226 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4227 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004228 if (wpa_s->mnc_len > 0) {
4229 wpa_s->imsi[len] = '\0';
4230 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4231 wpa_s->imsi, wpa_s->mnc_len);
4232 } else {
4233 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4234 }
4235}
4236#endif /* CONFIG_EAP_PROXY */
4237
Dmitry Shmidt04949592012-07-19 12:16:46 -07004238 if (pcsc_reader_init(wpa_s) < 0)
4239 return -1;
4240
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004241 if (wpas_init_ext_pw(wpa_s) < 0)
4242 return -1;
4243
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004244 wpas_rrm_reset(wpa_s);
4245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004246 return 0;
4247}
4248
4249
4250static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004251 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004252{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004253 struct wpa_global *global = wpa_s->global;
4254 struct wpa_supplicant *iface, *prev;
4255
4256 if (wpa_s == wpa_s->parent)
4257 wpas_p2p_group_remove(wpa_s, "*");
4258
4259 iface = global->ifaces;
4260 while (iface) {
4261 if (iface == wpa_s || iface->parent != wpa_s) {
4262 iface = iface->next;
4263 continue;
4264 }
4265 wpa_printf(MSG_DEBUG,
4266 "Remove remaining child interface %s from parent %s",
4267 iface->ifname, wpa_s->ifname);
4268 prev = iface;
4269 iface = iface->next;
4270 wpa_supplicant_remove_iface(global, prev, terminate);
4271 }
4272
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004273 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004274 if (wpa_s->drv_priv) {
4275 wpa_supplicant_deauthenticate(wpa_s,
4276 WLAN_REASON_DEAUTH_LEAVING);
4277
4278 wpa_drv_set_countermeasures(wpa_s, 0);
4279 wpa_clear_keys(wpa_s, NULL);
4280 }
4281
4282 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004283 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004284
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004285 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004286 radio_remove_interface(wpa_s);
4287
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004288 if (wpa_s->drv_priv)
4289 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004290
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004291 if (notify)
4292 wpas_notify_iface_removed(wpa_s);
4293
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004294 if (terminate)
4295 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004296
4297 if (wpa_s->ctrl_iface) {
4298 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
4299 wpa_s->ctrl_iface = NULL;
4300 }
4301
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004302#ifdef CONFIG_MESH
4303 if (wpa_s->ifmsh) {
4304 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
4305 wpa_s->ifmsh = NULL;
4306 }
4307#endif /* CONFIG_MESH */
4308
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004309 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004310 wpa_config_free(wpa_s->conf);
4311 wpa_s->conf = NULL;
4312 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004313
4314 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004315}
4316
4317
4318/**
4319 * wpa_supplicant_add_iface - Add a new network interface
4320 * @global: Pointer to global data from wpa_supplicant_init()
4321 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004322 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004323 * Returns: Pointer to the created interface or %NULL on failure
4324 *
4325 * This function is used to add new network interfaces for %wpa_supplicant.
4326 * This can be called before wpa_supplicant_run() to add interfaces before the
4327 * main event loop has been started. In addition, new interfaces can be added
4328 * dynamically while %wpa_supplicant is already running. This could happen,
4329 * e.g., when a hotplug network adapter is inserted.
4330 */
4331struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004332 struct wpa_interface *iface,
4333 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004334{
4335 struct wpa_supplicant *wpa_s;
4336 struct wpa_interface t_iface;
4337 struct wpa_ssid *ssid;
4338
4339 if (global == NULL || iface == NULL)
4340 return NULL;
4341
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004342 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004343 if (wpa_s == NULL)
4344 return NULL;
4345
4346 wpa_s->global = global;
4347
4348 t_iface = *iface;
4349 if (global->params.override_driver) {
4350 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
4351 "('%s' -> '%s')",
4352 iface->driver, global->params.override_driver);
4353 t_iface.driver = global->params.override_driver;
4354 }
4355 if (global->params.override_ctrl_interface) {
4356 wpa_printf(MSG_DEBUG, "Override interface parameter: "
4357 "ctrl_interface ('%s' -> '%s')",
4358 iface->ctrl_interface,
4359 global->params.override_ctrl_interface);
4360 t_iface.ctrl_interface =
4361 global->params.override_ctrl_interface;
4362 }
4363 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
4364 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
4365 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004366 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004367 return NULL;
4368 }
4369
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004370 if (iface->p2p_mgmt == 0) {
4371 /* Notify the control interfaces about new iface */
4372 if (wpas_notify_iface_added(wpa_s)) {
4373 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
4374 return NULL;
4375 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004376
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004377 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4378 wpas_notify_network_added(wpa_s, ssid);
4379 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004380
4381 wpa_s->next = global->ifaces;
4382 global->ifaces = wpa_s;
4383
4384 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004385 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004386
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004387#ifdef CONFIG_P2P
4388 if (wpa_s->global->p2p == NULL &&
4389 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
4390 wpas_p2p_add_p2pdev_interface(wpa_s, iface->conf_p2p_dev) < 0) {
4391 wpa_printf(MSG_INFO,
4392 "P2P: Failed to enable P2P Device interface");
4393 /* Try to continue without. P2P will be disabled. */
4394 }
4395#endif /* CONFIG_P2P */
4396
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004397 return wpa_s;
4398}
4399
4400
4401/**
4402 * wpa_supplicant_remove_iface - Remove a network interface
4403 * @global: Pointer to global data from wpa_supplicant_init()
4404 * @wpa_s: Pointer to the network interface to be removed
4405 * Returns: 0 if interface was removed, -1 if interface was not found
4406 *
4407 * This function can be used to dynamically remove network interfaces from
4408 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
4409 * addition, this function is used to remove all remaining interfaces when
4410 * %wpa_supplicant is terminated.
4411 */
4412int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004413 struct wpa_supplicant *wpa_s,
4414 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004415{
4416 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004417#ifdef CONFIG_MESH
4418 unsigned int mesh_if_created = wpa_s->mesh_if_created;
4419 char *ifname = NULL;
4420#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004421
4422 /* Remove interface from the global list of interfaces */
4423 prev = global->ifaces;
4424 if (prev == wpa_s) {
4425 global->ifaces = wpa_s->next;
4426 } else {
4427 while (prev && prev->next != wpa_s)
4428 prev = prev->next;
4429 if (prev == NULL)
4430 return -1;
4431 prev->next = wpa_s->next;
4432 }
4433
4434 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
4435
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004436#ifdef CONFIG_MESH
4437 if (mesh_if_created) {
4438 ifname = os_strdup(wpa_s->ifname);
4439 if (ifname == NULL) {
4440 wpa_dbg(wpa_s, MSG_ERROR,
4441 "mesh: Failed to malloc ifname");
4442 return -1;
4443 }
4444 }
4445#endif /* CONFIG_MESH */
4446
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004447 if (global->p2p_group_formation == wpa_s)
4448 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004449 if (global->p2p_invite_group == wpa_s)
4450 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004451 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004452
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004453#ifdef CONFIG_MESH
4454 if (mesh_if_created) {
4455 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
4456 os_free(ifname);
4457 }
4458#endif /* CONFIG_MESH */
4459
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004460 return 0;
4461}
4462
4463
4464/**
4465 * wpa_supplicant_get_eap_mode - Get the current EAP mode
4466 * @wpa_s: Pointer to the network interface
4467 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
4468 */
4469const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
4470{
4471 const char *eapol_method;
4472
4473 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
4474 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4475 return "NO-EAP";
4476 }
4477
4478 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
4479 if (eapol_method == NULL)
4480 return "UNKNOWN-EAP";
4481
4482 return eapol_method;
4483}
4484
4485
4486/**
4487 * wpa_supplicant_get_iface - Get a new network interface
4488 * @global: Pointer to global data from wpa_supplicant_init()
4489 * @ifname: Interface name
4490 * Returns: Pointer to the interface or %NULL if not found
4491 */
4492struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4493 const char *ifname)
4494{
4495 struct wpa_supplicant *wpa_s;
4496
4497 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4498 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4499 return wpa_s;
4500 }
4501 return NULL;
4502}
4503
4504
4505#ifndef CONFIG_NO_WPA_MSG
4506static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4507{
4508 struct wpa_supplicant *wpa_s = ctx;
4509 if (wpa_s == NULL)
4510 return NULL;
4511 return wpa_s->ifname;
4512}
4513#endif /* CONFIG_NO_WPA_MSG */
4514
4515
4516/**
4517 * wpa_supplicant_init - Initialize %wpa_supplicant
4518 * @params: Parameters for %wpa_supplicant
4519 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4520 *
4521 * This function is used to initialize %wpa_supplicant. After successful
4522 * initialization, the returned data pointer can be used to add and remove
4523 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4524 */
4525struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4526{
4527 struct wpa_global *global;
4528 int ret, i;
4529
4530 if (params == NULL)
4531 return NULL;
4532
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004533#ifdef CONFIG_DRIVER_NDIS
4534 {
4535 void driver_ndis_init_ops(void);
4536 driver_ndis_init_ops();
4537 }
4538#endif /* CONFIG_DRIVER_NDIS */
4539
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004540#ifndef CONFIG_NO_WPA_MSG
4541 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4542#endif /* CONFIG_NO_WPA_MSG */
4543
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004544 if (params->wpa_debug_file_path)
4545 wpa_debug_open_file(params->wpa_debug_file_path);
4546 else
4547 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004548 if (params->wpa_debug_syslog)
4549 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004550 if (params->wpa_debug_tracing) {
4551 ret = wpa_debug_open_linux_tracing();
4552 if (ret) {
4553 wpa_printf(MSG_ERROR,
4554 "Failed to enable trace logging");
4555 return NULL;
4556 }
4557 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004558
4559 ret = eap_register_methods();
4560 if (ret) {
4561 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4562 if (ret == -2)
4563 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4564 "the same EAP type.");
4565 return NULL;
4566 }
4567
4568 global = os_zalloc(sizeof(*global));
4569 if (global == NULL)
4570 return NULL;
4571 dl_list_init(&global->p2p_srv_bonjour);
4572 dl_list_init(&global->p2p_srv_upnp);
4573 global->params.daemonize = params->daemonize;
4574 global->params.wait_for_monitor = params->wait_for_monitor;
4575 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4576 if (params->pid_file)
4577 global->params.pid_file = os_strdup(params->pid_file);
4578 if (params->ctrl_interface)
4579 global->params.ctrl_interface =
4580 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004581 if (params->ctrl_interface_group)
4582 global->params.ctrl_interface_group =
4583 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004584 if (params->override_driver)
4585 global->params.override_driver =
4586 os_strdup(params->override_driver);
4587 if (params->override_ctrl_interface)
4588 global->params.override_ctrl_interface =
4589 os_strdup(params->override_ctrl_interface);
4590 wpa_debug_level = global->params.wpa_debug_level =
4591 params->wpa_debug_level;
4592 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4593 params->wpa_debug_show_keys;
4594 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4595 params->wpa_debug_timestamp;
4596
4597 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4598
4599 if (eloop_init()) {
4600 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4601 wpa_supplicant_deinit(global);
4602 return NULL;
4603 }
4604
Jouni Malinen75ecf522011-06-27 15:19:46 -07004605 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004606
4607 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4608 if (global->ctrl_iface == NULL) {
4609 wpa_supplicant_deinit(global);
4610 return NULL;
4611 }
4612
4613 if (wpas_notify_supplicant_initialized(global)) {
4614 wpa_supplicant_deinit(global);
4615 return NULL;
4616 }
4617
4618 for (i = 0; wpa_drivers[i]; i++)
4619 global->drv_count++;
4620 if (global->drv_count == 0) {
4621 wpa_printf(MSG_ERROR, "No drivers enabled");
4622 wpa_supplicant_deinit(global);
4623 return NULL;
4624 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004625 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004626 if (global->drv_priv == NULL) {
4627 wpa_supplicant_deinit(global);
4628 return NULL;
4629 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004630
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004631#ifdef CONFIG_WIFI_DISPLAY
4632 if (wifi_display_init(global) < 0) {
4633 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4634 wpa_supplicant_deinit(global);
4635 return NULL;
4636 }
4637#endif /* CONFIG_WIFI_DISPLAY */
4638
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004639 return global;
4640}
4641
4642
4643/**
4644 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4645 * @global: Pointer to global data from wpa_supplicant_init()
4646 * Returns: 0 after successful event loop run, -1 on failure
4647 *
4648 * This function starts the main event loop and continues running as long as
4649 * there are any remaining events. In most cases, this function is running as
4650 * long as the %wpa_supplicant process in still in use.
4651 */
4652int wpa_supplicant_run(struct wpa_global *global)
4653{
4654 struct wpa_supplicant *wpa_s;
4655
4656 if (global->params.daemonize &&
4657 wpa_supplicant_daemon(global->params.pid_file))
4658 return -1;
4659
4660 if (global->params.wait_for_monitor) {
4661 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4662 if (wpa_s->ctrl_iface)
4663 wpa_supplicant_ctrl_iface_wait(
4664 wpa_s->ctrl_iface);
4665 }
4666
4667 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4668 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4669
4670 eloop_run();
4671
4672 return 0;
4673}
4674
4675
4676/**
4677 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4678 * @global: Pointer to global data from wpa_supplicant_init()
4679 *
4680 * This function is called to deinitialize %wpa_supplicant and to free all
4681 * allocated resources. Remaining network interfaces will also be removed.
4682 */
4683void wpa_supplicant_deinit(struct wpa_global *global)
4684{
4685 int i;
4686
4687 if (global == NULL)
4688 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004689
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004690#ifdef CONFIG_WIFI_DISPLAY
4691 wifi_display_deinit(global);
4692#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004693
4694 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004695 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004696
4697 if (global->ctrl_iface)
4698 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4699
4700 wpas_notify_supplicant_deinitialized(global);
4701
4702 eap_peer_unregister_methods();
4703#ifdef CONFIG_AP
4704 eap_server_unregister_methods();
4705#endif /* CONFIG_AP */
4706
4707 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4708 if (!global->drv_priv[i])
4709 continue;
4710 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4711 }
4712 os_free(global->drv_priv);
4713
4714 random_deinit();
4715
4716 eloop_destroy();
4717
4718 if (global->params.pid_file) {
4719 os_daemonize_terminate(global->params.pid_file);
4720 os_free(global->params.pid_file);
4721 }
4722 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004723 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004724 os_free(global->params.override_driver);
4725 os_free(global->params.override_ctrl_interface);
4726
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004727 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004728 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004729 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004730
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004731 os_free(global);
4732 wpa_debug_close_syslog();
4733 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004734 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004735}
4736
4737
4738void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4739{
4740 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4741 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4742 char country[3];
4743 country[0] = wpa_s->conf->country[0];
4744 country[1] = wpa_s->conf->country[1];
4745 country[2] = '\0';
4746 if (wpa_drv_set_country(wpa_s, country) < 0) {
4747 wpa_printf(MSG_ERROR, "Failed to set country code "
4748 "'%s'", country);
4749 }
4750 }
4751
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004752 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4753 wpas_init_ext_pw(wpa_s);
4754
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004755#ifdef CONFIG_WPS
4756 wpas_wps_update_config(wpa_s);
4757#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004758 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004759 wpa_s->conf->changed_parameters = 0;
4760}
4761
4762
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004763void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004764{
4765 int i;
4766
4767 for (i = 0; i < *num_freqs; i++) {
4768 if (freqs[i] == freq)
4769 return;
4770 }
4771
4772 freqs[*num_freqs] = freq;
4773 (*num_freqs)++;
4774}
4775
4776
4777static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4778{
4779 struct wpa_bss *bss, *cbss;
4780 const int max_freqs = 10;
4781 int *freqs;
4782 int num_freqs = 0;
4783
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004784 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004785 if (freqs == NULL)
4786 return NULL;
4787
4788 cbss = wpa_s->current_bss;
4789
4790 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4791 if (bss == cbss)
4792 continue;
4793 if (bss->ssid_len == cbss->ssid_len &&
4794 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4795 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4796 add_freq(freqs, &num_freqs, bss->freq);
4797 if (num_freqs == max_freqs)
4798 break;
4799 }
4800 }
4801
4802 if (num_freqs == 0) {
4803 os_free(freqs);
4804 freqs = NULL;
4805 }
4806
4807 return freqs;
4808}
4809
4810
4811void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4812{
4813 int timeout;
4814 int count;
4815 int *freqs = NULL;
4816
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004817 wpas_connect_work_done(wpa_s);
4818
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004819 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004820 * Remove possible authentication timeout since the connection failed.
4821 */
4822 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4823
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004824 /*
4825 * There is no point in blacklisting the AP if this event is
4826 * generated based on local request to disconnect.
4827 */
4828 if (wpa_s->own_disconnect_req) {
4829 wpa_s->own_disconnect_req = 0;
4830 wpa_dbg(wpa_s, MSG_DEBUG,
4831 "Ignore connection failure due to local request to disconnect");
4832 return;
4833 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004834 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004835 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4836 "indication since interface has been put into "
4837 "disconnected state");
4838 return;
4839 }
4840
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004841 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004842 * Add the failed BSSID into the blacklist and speed up next scan
4843 * attempt if there could be other APs that could accept association.
4844 * The current blacklist count indicates how many times we have tried
4845 * connecting to this AP and multiple attempts mean that other APs are
4846 * either not available or has already been tried, so that we can start
4847 * increasing the delay here to avoid constant scanning.
4848 */
4849 count = wpa_blacklist_add(wpa_s, bssid);
4850 if (count == 1 && wpa_s->current_bss) {
4851 /*
4852 * This BSS was not in the blacklist before. If there is
4853 * another BSS available for the same ESS, we should try that
4854 * next. Otherwise, we may as well try this one once more
4855 * before allowing other, likely worse, ESSes to be considered.
4856 */
4857 freqs = get_bss_freqs_in_ess(wpa_s);
4858 if (freqs) {
4859 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4860 "has been seen; try it next");
4861 wpa_blacklist_add(wpa_s, bssid);
4862 /*
4863 * On the next scan, go through only the known channels
4864 * used in this ESS based on previous scans to speed up
4865 * common load balancing use case.
4866 */
4867 os_free(wpa_s->next_scan_freqs);
4868 wpa_s->next_scan_freqs = freqs;
4869 }
4870 }
4871
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004872 /*
4873 * Add previous failure count in case the temporary blacklist was
4874 * cleared due to no other BSSes being available.
4875 */
4876 count += wpa_s->extra_blacklist_count;
4877
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004878 if (count > 3 && wpa_s->current_ssid) {
4879 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4880 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004881 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004882 }
4883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004884 switch (count) {
4885 case 1:
4886 timeout = 100;
4887 break;
4888 case 2:
4889 timeout = 500;
4890 break;
4891 case 3:
4892 timeout = 1000;
4893 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004894 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004895 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004896 break;
4897 default:
4898 timeout = 10000;
4899 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004900 }
4901
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004902 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4903 "ms", count, timeout);
4904
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004905 /*
4906 * TODO: if more than one possible AP is available in scan results,
4907 * could try the other ones before requesting a new scan.
4908 */
4909 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4910 1000 * (timeout % 1000));
4911}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004912
4913
4914int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4915{
4916 return wpa_s->conf->ap_scan == 2 ||
4917 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4918}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004919
Dmitry Shmidt04949592012-07-19 12:16:46 -07004920
4921#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4922int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4923 struct wpa_ssid *ssid,
4924 const char *field,
4925 const char *value)
4926{
4927#ifdef IEEE8021X_EAPOL
4928 struct eap_peer_config *eap = &ssid->eap;
4929
4930 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4931 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4932 (const u8 *) value, os_strlen(value));
4933
4934 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4935 case WPA_CTRL_REQ_EAP_IDENTITY:
4936 os_free(eap->identity);
4937 eap->identity = (u8 *) os_strdup(value);
4938 eap->identity_len = os_strlen(value);
4939 eap->pending_req_identity = 0;
4940 if (ssid == wpa_s->current_ssid)
4941 wpa_s->reassociate = 1;
4942 break;
4943 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004944 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004945 eap->password = (u8 *) os_strdup(value);
4946 eap->password_len = os_strlen(value);
4947 eap->pending_req_password = 0;
4948 if (ssid == wpa_s->current_ssid)
4949 wpa_s->reassociate = 1;
4950 break;
4951 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004952 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004953 eap->new_password = (u8 *) os_strdup(value);
4954 eap->new_password_len = os_strlen(value);
4955 eap->pending_req_new_password = 0;
4956 if (ssid == wpa_s->current_ssid)
4957 wpa_s->reassociate = 1;
4958 break;
4959 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004960 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004961 eap->pin = os_strdup(value);
4962 eap->pending_req_pin = 0;
4963 if (ssid == wpa_s->current_ssid)
4964 wpa_s->reassociate = 1;
4965 break;
4966 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004967 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004968 eap->otp = (u8 *) os_strdup(value);
4969 eap->otp_len = os_strlen(value);
4970 os_free(eap->pending_req_otp);
4971 eap->pending_req_otp = NULL;
4972 eap->pending_req_otp_len = 0;
4973 break;
4974 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004975 str_clear_free(eap->private_key_passwd);
4976 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004977 eap->pending_req_passphrase = 0;
4978 if (ssid == wpa_s->current_ssid)
4979 wpa_s->reassociate = 1;
4980 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004981 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004982 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004983 eap->external_sim_resp = os_strdup(value);
4984 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004985 case WPA_CTRL_REQ_PSK_PASSPHRASE:
4986 if (wpa_config_set(ssid, "psk", value, 0) < 0)
4987 return -1;
4988 ssid->mem_only_psk = 1;
4989 if (ssid->passphrase)
4990 wpa_config_update_psk(ssid);
4991 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
4992 wpa_supplicant_req_scan(wpa_s, 0, 0);
4993 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004994 default:
4995 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4996 return -1;
4997 }
4998
4999 return 0;
5000#else /* IEEE8021X_EAPOL */
5001 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5002 return -1;
5003#endif /* IEEE8021X_EAPOL */
5004}
5005#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
5006
5007
5008int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5009{
5010 int i;
5011 unsigned int drv_enc;
5012
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005013 if (wpa_s->p2p_mgmt)
5014 return 1; /* no normal network profiles on p2p_mgmt interface */
5015
Dmitry Shmidt04949592012-07-19 12:16:46 -07005016 if (ssid == NULL)
5017 return 1;
5018
5019 if (ssid->disabled)
5020 return 1;
5021
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005022 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005023 drv_enc = wpa_s->drv_enc;
5024 else
5025 drv_enc = (unsigned int) -1;
5026
5027 for (i = 0; i < NUM_WEP_KEYS; i++) {
5028 size_t len = ssid->wep_key_len[i];
5029 if (len == 0)
5030 continue;
5031 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5032 continue;
5033 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5034 continue;
5035 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5036 continue;
5037 return 1; /* invalid WEP key */
5038 }
5039
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005040 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005041 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5042 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005043 return 1;
5044
Dmitry Shmidt04949592012-07-19 12:16:46 -07005045 return 0;
5046}
5047
5048
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005049int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5050{
5051#ifdef CONFIG_IEEE80211W
5052 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
5053 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
5054 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
5055 /*
5056 * Driver does not support BIP -- ignore pmf=1 default
5057 * since the connection with PMF would fail and the
5058 * configuration does not require PMF to be enabled.
5059 */
5060 return NO_MGMT_FRAME_PROTECTION;
5061 }
5062
5063 return wpa_s->conf->pmf;
5064 }
5065
5066 return ssid->ieee80211w;
5067#else /* CONFIG_IEEE80211W */
5068 return NO_MGMT_FRAME_PROTECTION;
5069#endif /* CONFIG_IEEE80211W */
5070}
5071
5072
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005073int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005074{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005075 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005076 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005077 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005078 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005079 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005080}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005081
5082
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005083void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005084{
5085 struct wpa_ssid *ssid = wpa_s->current_ssid;
5086 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005087 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005088
5089 if (ssid == NULL) {
5090 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
5091 "SSID block");
5092 return;
5093 }
5094
5095 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
5096 return;
5097
5098 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005099
5100#ifdef CONFIG_P2P
5101 if (ssid->p2p_group &&
5102 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
5103 /*
5104 * Skip the wait time since there is a short timeout on the
5105 * connection to a P2P group.
5106 */
5107 return;
5108 }
5109#endif /* CONFIG_P2P */
5110
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005111 if (ssid->auth_failures > 50)
5112 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005113 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005114 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005115 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005116 dur = 90;
5117 else if (ssid->auth_failures > 3)
5118 dur = 60;
5119 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005120 dur = 30;
5121 else if (ssid->auth_failures > 1)
5122 dur = 20;
5123 else
5124 dur = 10;
5125
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005126 if (ssid->auth_failures > 1 &&
5127 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
5128 dur += os_random() % (ssid->auth_failures * 10);
5129
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005130 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005131 if (now.sec + dur <= ssid->disabled_until.sec)
5132 return;
5133
5134 ssid->disabled_until.sec = now.sec + dur;
5135
5136 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005137 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005138 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005139 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005140}
5141
5142
5143void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
5144 struct wpa_ssid *ssid, int clear_failures)
5145{
5146 if (ssid == NULL)
5147 return;
5148
5149 if (ssid->disabled_until.sec) {
5150 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
5151 "id=%d ssid=\"%s\"",
5152 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
5153 }
5154 ssid->disabled_until.sec = 0;
5155 ssid->disabled_until.usec = 0;
5156 if (clear_failures)
5157 ssid->auth_failures = 0;
5158}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005159
5160
5161int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
5162{
5163 size_t i;
5164
5165 if (wpa_s->disallow_aps_bssid == NULL)
5166 return 0;
5167
5168 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
5169 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
5170 bssid, ETH_ALEN) == 0)
5171 return 1;
5172 }
5173
5174 return 0;
5175}
5176
5177
5178int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
5179 size_t ssid_len)
5180{
5181 size_t i;
5182
5183 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
5184 return 0;
5185
5186 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
5187 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
5188 if (ssid_len == s->ssid_len &&
5189 os_memcmp(ssid, s->ssid, ssid_len) == 0)
5190 return 1;
5191 }
5192
5193 return 0;
5194}
5195
5196
5197/**
5198 * wpas_request_connection - Request a new connection
5199 * @wpa_s: Pointer to the network interface
5200 *
5201 * This function is used to request a new connection to be found. It will mark
5202 * the interface to allow reassociation and request a new scan to find a
5203 * suitable network to connect to.
5204 */
5205void wpas_request_connection(struct wpa_supplicant *wpa_s)
5206{
5207 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005208 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005209 wpa_supplicant_reinit_autoscan(wpa_s);
5210 wpa_s->extra_blacklist_count = 0;
5211 wpa_s->disconnected = 0;
5212 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005213
5214 if (wpa_supplicant_fast_associate(wpa_s) != 1)
5215 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005216 else
5217 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005218}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005219
5220
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005221void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
5222 struct wpa_used_freq_data *freqs_data,
5223 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005224{
5225 unsigned int i;
5226
5227 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
5228 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005229 for (i = 0; i < len; i++) {
5230 struct wpa_used_freq_data *cur = &freqs_data[i];
5231 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
5232 i, cur->freq, cur->flags);
5233 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005234}
5235
5236
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005237/*
5238 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005239 * are using the same radio as the current interface, and in addition, get
5240 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005241 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005242int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
5243 struct wpa_used_freq_data *freqs_data,
5244 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005245{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005246 struct wpa_supplicant *ifs;
5247 u8 bssid[ETH_ALEN];
5248 int freq;
5249 unsigned int idx = 0, i;
5250
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005251 wpa_dbg(wpa_s, MSG_DEBUG,
5252 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005253 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005254
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005255 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
5256 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005257 if (idx == len)
5258 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005259
5260 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
5261 continue;
5262
5263 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
5264 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
5265 freq = ifs->current_ssid->frequency;
5266 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
5267 freq = ifs->assoc_freq;
5268 else
5269 continue;
5270
5271 /* Hold only distinct freqs */
5272 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005273 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005274 break;
5275
5276 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005277 freqs_data[idx++].freq = freq;
5278
5279 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
5280 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
5281 WPA_FREQ_USED_BY_P2P_CLIENT :
5282 WPA_FREQ_USED_BY_INFRA_STATION;
5283 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005284 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005285
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005286 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005287 return idx;
5288}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005289
5290
5291/*
5292 * Find the operating frequencies of any of the virtual interfaces that
5293 * are using the same radio as the current interface.
5294 */
5295int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
5296 int *freq_array, unsigned int len)
5297{
5298 struct wpa_used_freq_data *freqs_data;
5299 int num, i;
5300
5301 os_memset(freq_array, 0, sizeof(int) * len);
5302
5303 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
5304 if (!freqs_data)
5305 return -1;
5306
5307 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
5308 for (i = 0; i < num; i++)
5309 freq_array[i] = freqs_data[i].freq;
5310
5311 os_free(freqs_data);
5312
5313 return num;
5314}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005315
5316
5317static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
5318{
5319 struct rrm_data *rrm = data;
5320
5321 if (!rrm->notify_neighbor_rep) {
5322 wpa_printf(MSG_ERROR,
5323 "RRM: Unexpected neighbor report timeout");
5324 return;
5325 }
5326
5327 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
5328 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
5329
5330 rrm->notify_neighbor_rep = NULL;
5331 rrm->neighbor_rep_cb_ctx = NULL;
5332}
5333
5334
5335/*
5336 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
5337 * @wpa_s: Pointer to wpa_supplicant
5338 */
5339void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
5340{
5341 wpa_s->rrm.rrm_used = 0;
5342
5343 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5344 NULL);
5345 if (wpa_s->rrm.notify_neighbor_rep)
5346 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
5347 wpa_s->rrm.next_neighbor_rep_token = 1;
5348}
5349
5350
5351/*
5352 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
5353 * @wpa_s: Pointer to wpa_supplicant
5354 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
5355 * @report_len: Length of neighbor report buffer
5356 */
5357void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
5358 const u8 *report, size_t report_len)
5359{
5360 struct wpabuf *neighbor_rep;
5361
5362 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
5363 if (report_len < 1)
5364 return;
5365
5366 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
5367 wpa_printf(MSG_DEBUG,
5368 "RRM: Discarding neighbor report with token %d (expected %d)",
5369 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
5370 return;
5371 }
5372
5373 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5374 NULL);
5375
5376 if (!wpa_s->rrm.notify_neighbor_rep) {
5377 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
5378 return;
5379 }
5380
5381 /* skipping the first byte, which is only an id (dialog token) */
5382 neighbor_rep = wpabuf_alloc(report_len - 1);
5383 if (neighbor_rep == NULL)
5384 return;
5385 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
5386 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
5387 report[0]);
5388 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
5389 neighbor_rep);
5390 wpa_s->rrm.notify_neighbor_rep = NULL;
5391 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
5392}
5393
5394
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005395#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
5396/* Workaround different, undefined for Windows, error codes used here */
5397#define ENOTCONN -1
5398#define EOPNOTSUPP -1
5399#define ECANCELED -1
5400#endif
5401
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005402/**
5403 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
5404 * @wpa_s: Pointer to wpa_supplicant
5405 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
5406 * is sent in the request.
5407 * @cb: Callback function to be called once the requested report arrives, or
5408 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
5409 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
5410 * the requester's responsibility to free it.
5411 * In the latter case NULL will be sent in 'neighbor_rep'.
5412 * @cb_ctx: Context value to send the callback function
5413 * Returns: 0 in case of success, negative error code otherwise
5414 *
5415 * In case there is a previous request which has not been answered yet, the
5416 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
5417 * Request must contain a callback function.
5418 */
5419int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
5420 const struct wpa_ssid *ssid,
5421 void (*cb)(void *ctx,
5422 struct wpabuf *neighbor_rep),
5423 void *cb_ctx)
5424{
5425 struct wpabuf *buf;
5426 const u8 *rrm_ie;
5427
5428 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
5429 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
5430 return -ENOTCONN;
5431 }
5432
5433 if (!wpa_s->rrm.rrm_used) {
5434 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
5435 return -EOPNOTSUPP;
5436 }
5437
5438 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
5439 WLAN_EID_RRM_ENABLED_CAPABILITIES);
5440 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
5441 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
5442 wpa_printf(MSG_DEBUG,
5443 "RRM: No network support for Neighbor Report.");
5444 return -EOPNOTSUPP;
5445 }
5446
5447 if (!cb) {
5448 wpa_printf(MSG_DEBUG,
5449 "RRM: Neighbor Report request must provide a callback.");
5450 return -EINVAL;
5451 }
5452
5453 /* Refuse if there's a live request */
5454 if (wpa_s->rrm.notify_neighbor_rep) {
5455 wpa_printf(MSG_DEBUG,
5456 "RRM: Currently handling previous Neighbor Report.");
5457 return -EBUSY;
5458 }
5459
5460 /* 3 = action category + action code + dialog token */
5461 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
5462 if (buf == NULL) {
5463 wpa_printf(MSG_DEBUG,
5464 "RRM: Failed to allocate Neighbor Report Request");
5465 return -ENOMEM;
5466 }
5467
5468 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
5469 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
5470 wpa_s->rrm.next_neighbor_rep_token);
5471
5472 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5473 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
5474 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
5475 if (ssid) {
5476 wpabuf_put_u8(buf, WLAN_EID_SSID);
5477 wpabuf_put_u8(buf, ssid->ssid_len);
5478 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
5479 }
5480
5481 wpa_s->rrm.next_neighbor_rep_token++;
5482
5483 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
5484 wpa_s->own_addr, wpa_s->bssid,
5485 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
5486 wpa_printf(MSG_DEBUG,
5487 "RRM: Failed to send Neighbor Report Request");
5488 wpabuf_free(buf);
5489 return -ECANCELED;
5490 }
5491
5492 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
5493 wpa_s->rrm.notify_neighbor_rep = cb;
5494 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
5495 wpas_rrm_neighbor_rep_timeout_handler,
5496 &wpa_s->rrm, NULL);
5497
5498 wpabuf_free(buf);
5499 return 0;
5500}
5501
5502
5503void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
5504 const u8 *src,
5505 const u8 *frame, size_t len,
5506 int rssi)
5507{
5508 struct wpabuf *buf;
5509 const struct rrm_link_measurement_request *req;
5510 struct rrm_link_measurement_report report;
5511
5512 if (wpa_s->wpa_state != WPA_COMPLETED) {
5513 wpa_printf(MSG_INFO,
5514 "RRM: Ignoring link measurement request. Not associated");
5515 return;
5516 }
5517
5518 if (!wpa_s->rrm.rrm_used) {
5519 wpa_printf(MSG_INFO,
5520 "RRM: Ignoring link measurement request. Not RRM network");
5521 return;
5522 }
5523
5524 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
5525 wpa_printf(MSG_INFO,
5526 "RRM: Measurement report failed. TX power insertion not supported");
5527 return;
5528 }
5529
5530 req = (const struct rrm_link_measurement_request *) frame;
5531 if (len < sizeof(*req)) {
5532 wpa_printf(MSG_INFO,
5533 "RRM: Link measurement report failed. Request too short");
5534 return;
5535 }
5536
5537 os_memset(&report, 0, sizeof(report));
5538 report.tpc.eid = WLAN_EID_TPC_REPORT;
5539 report.tpc.len = 2;
5540 report.rsni = 255; /* 255 indicates that RSNI is not available */
5541 report.dialog_token = req->dialog_token;
5542
5543 /*
5544 * It's possible to estimate RCPI based on RSSI in dBm. This
5545 * calculation will not reflect the correct value for high rates,
5546 * but it's good enough for Action frames which are transmitted
5547 * with up to 24 Mbps rates.
5548 */
5549 if (!rssi)
5550 report.rcpi = 255; /* not available */
5551 else if (rssi < -110)
5552 report.rcpi = 0;
5553 else if (rssi > 0)
5554 report.rcpi = 220;
5555 else
5556 report.rcpi = (rssi + 110) * 2;
5557
5558 /* action_category + action_code */
5559 buf = wpabuf_alloc(2 + sizeof(report));
5560 if (buf == NULL) {
5561 wpa_printf(MSG_ERROR,
5562 "RRM: Link measurement report failed. Buffer allocation failed");
5563 return;
5564 }
5565
5566 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5567 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
5568 wpabuf_put_data(buf, &report, sizeof(report));
5569 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
5570 wpabuf_head(buf), wpabuf_len(buf));
5571
5572 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
5573 wpa_s->own_addr, wpa_s->bssid,
5574 wpabuf_head(buf), wpabuf_len(buf), 0)) {
5575 wpa_printf(MSG_ERROR,
5576 "RRM: Link measurement report failed. Send action failed");
5577 }
5578 wpabuf_free(buf);
5579}