blob: f690b919058aa745f73931695becda044780abd5 [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 Shmidtd5e49232012-12-03 15:08:10 -0800734 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700735 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736 wpa_drv_set_operstate(wpa_s, 1);
737#ifndef IEEE8021X_EAPOL
738 wpa_drv_set_supp_port(wpa_s, 1);
739#endif /* IEEE8021X_EAPOL */
740 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700741 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700742 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700743
744 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700745 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
746 state == WPA_ASSOCIATED) {
747 wpa_s->new_connection = 1;
748 wpa_drv_set_operstate(wpa_s, 0);
749#ifndef IEEE8021X_EAPOL
750 wpa_drv_set_supp_port(wpa_s, 0);
751#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700752 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700753 }
754 wpa_s->wpa_state = state;
755
756#ifdef CONFIG_BGSCAN
757 if (state == WPA_COMPLETED)
758 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800759 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700760 wpa_supplicant_stop_bgscan(wpa_s);
761#endif /* CONFIG_BGSCAN */
762
Dmitry Shmidt04949592012-07-19 12:16:46 -0700763 if (state == WPA_AUTHENTICATING)
764 wpa_supplicant_stop_autoscan(wpa_s);
765
766 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
767 wpa_supplicant_start_autoscan(wpa_s);
768
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800769 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
770 wmm_ac_notify_disassoc(wpa_s);
771
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772 if (wpa_s->wpa_state != old_state) {
773 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
774
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700775 /*
776 * Notify the P2P Device interface about a state change in one
777 * of the interfaces.
778 */
779 wpas_p2p_indicate_state_change(wpa_s);
780
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781 if (wpa_s->wpa_state == WPA_COMPLETED ||
782 old_state == WPA_COMPLETED)
783 wpas_notify_auth_changed(wpa_s);
784 }
785}
786
787
788void wpa_supplicant_terminate_proc(struct wpa_global *global)
789{
790 int pending = 0;
791#ifdef CONFIG_WPS
792 struct wpa_supplicant *wpa_s = global->ifaces;
793 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800794 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700795 if (wpas_wps_terminate_pending(wpa_s) == 1)
796 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700797#ifdef CONFIG_P2P
798 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
799 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
800 wpas_p2p_disconnect(wpa_s);
801#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800802 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700803 }
804#endif /* CONFIG_WPS */
805 if (pending)
806 return;
807 eloop_terminate();
808}
809
810
811static void wpa_supplicant_terminate(int sig, void *signal_ctx)
812{
813 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700814 wpa_supplicant_terminate_proc(global);
815}
816
817
818void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
819{
820 enum wpa_states old_state = wpa_s->wpa_state;
821
822 wpa_s->pairwise_cipher = 0;
823 wpa_s->group_cipher = 0;
824 wpa_s->mgmt_group_cipher = 0;
825 wpa_s->key_mgmt = 0;
826 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700827 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700828
829 if (wpa_s->wpa_state != old_state)
830 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
831}
832
833
834/**
835 * wpa_supplicant_reload_configuration - Reload configuration data
836 * @wpa_s: Pointer to wpa_supplicant data
837 * Returns: 0 on success or -1 if configuration parsing failed
838 *
839 * This function can be used to request that the configuration data is reloaded
840 * (e.g., after configuration file change). This function is reloading
841 * configuration only for one interface, so this may need to be called multiple
842 * times if %wpa_supplicant is controlling multiple interfaces and all
843 * interfaces need reconfiguration.
844 */
845int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
846{
847 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700848 int reconf_ctrl;
849 int old_ap_scan;
850
851 if (wpa_s->confname == NULL)
852 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700853 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854 if (conf == NULL) {
855 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
856 "file '%s' - exiting", wpa_s->confname);
857 return -1;
858 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700859 wpa_config_read(wpa_s->confanother, conf);
860
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700861 conf->changed_parameters = (unsigned int) -1;
862
863 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
864 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
865 os_strcmp(conf->ctrl_interface,
866 wpa_s->conf->ctrl_interface) != 0);
867
868 if (reconf_ctrl && wpa_s->ctrl_iface) {
869 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
870 wpa_s->ctrl_iface = NULL;
871 }
872
873 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800874 if (wpa_s->current_ssid) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -0800875 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800876 wpa_supplicant_deauthenticate(wpa_s,
877 WLAN_REASON_DEAUTH_LEAVING);
878 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700879
880 /*
881 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800882 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700883 */
884 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
885 /*
886 * Clear forced success to clear EAP state for next
887 * authentication.
888 */
889 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
890 }
891 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
892 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800893 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700894 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
895 rsn_preauth_deinit(wpa_s->wpa);
896
897 old_ap_scan = wpa_s->conf->ap_scan;
898 wpa_config_free(wpa_s->conf);
899 wpa_s->conf = conf;
900 if (old_ap_scan != wpa_s->conf->ap_scan)
901 wpas_notify_ap_scan_changed(wpa_s);
902
903 if (reconf_ctrl)
904 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
905
906 wpa_supplicant_update_config(wpa_s);
907
908 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700909 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700910 wpa_s->reassociate = 1;
911 wpa_supplicant_req_scan(wpa_s, 0, 0);
912 }
913 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
914 return 0;
915}
916
917
918static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
919{
920 struct wpa_global *global = signal_ctx;
921 struct wpa_supplicant *wpa_s;
922 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
923 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
924 sig);
925 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
926 wpa_supplicant_terminate_proc(global);
927 }
928 }
929}
930
931
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700932static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
933 struct wpa_ssid *ssid,
934 struct wpa_ie_data *ie)
935{
936 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
937 if (ret) {
938 if (ret == -2) {
939 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
940 "from association info");
941 }
942 return -1;
943 }
944
945 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
946 "cipher suites");
947 if (!(ie->group_cipher & ssid->group_cipher)) {
948 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
949 "cipher 0x%x (mask 0x%x) - reject",
950 ie->group_cipher, ssid->group_cipher);
951 return -1;
952 }
953 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
954 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
955 "cipher 0x%x (mask 0x%x) - reject",
956 ie->pairwise_cipher, ssid->pairwise_cipher);
957 return -1;
958 }
959 if (!(ie->key_mgmt & ssid->key_mgmt)) {
960 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
961 "management 0x%x (mask 0x%x) - reject",
962 ie->key_mgmt, ssid->key_mgmt);
963 return -1;
964 }
965
966#ifdef CONFIG_IEEE80211W
967 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800968 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700969 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
970 "that does not support management frame protection - "
971 "reject");
972 return -1;
973 }
974#endif /* CONFIG_IEEE80211W */
975
976 return 0;
977}
978
979
980/**
981 * wpa_supplicant_set_suites - Set authentication and encryption parameters
982 * @wpa_s: Pointer to wpa_supplicant data
983 * @bss: Scan results for the selected BSS, or %NULL if not available
984 * @ssid: Configuration data for the selected network
985 * @wpa_ie: Buffer for the WPA/RSN IE
986 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
987 * used buffer length in case the functions returns success.
988 * Returns: 0 on success or -1 on failure
989 *
990 * This function is used to configure authentication and encryption parameters
991 * based on the network configuration and scan result for the selected BSS (if
992 * available).
993 */
994int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
995 struct wpa_bss *bss, struct wpa_ssid *ssid,
996 u8 *wpa_ie, size_t *wpa_ie_len)
997{
998 struct wpa_ie_data ie;
999 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001000 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001
1002 if (bss) {
1003 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1004 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001005 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001007 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008
1009 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1010 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1011 (ie.group_cipher & ssid->group_cipher) &&
1012 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1013 (ie.key_mgmt & ssid->key_mgmt)) {
1014 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1015 proto = WPA_PROTO_RSN;
1016 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001017 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001018 (ie.group_cipher & ssid->group_cipher) &&
1019 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1020 (ie.key_mgmt & ssid->key_mgmt)) {
1021 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1022 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001023#ifdef CONFIG_HS20
1024 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1025 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1026 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001027 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001028 ie.group_cipher = WPA_CIPHER_CCMP;
1029 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1030 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1031 proto = WPA_PROTO_OSEN;
1032#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001033 } else if (bss) {
1034 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001035 wpa_dbg(wpa_s, MSG_DEBUG,
1036 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1037 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1038 ssid->key_mgmt);
1039 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1040 MAC2STR(bss->bssid),
1041 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1042 bss_wpa ? " WPA" : "",
1043 bss_rsn ? " RSN" : "",
1044 bss_osen ? " OSEN" : "");
1045 if (bss_rsn) {
1046 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1047 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1048 wpa_dbg(wpa_s, MSG_DEBUG,
1049 "Could not parse RSN element");
1050 } else {
1051 wpa_dbg(wpa_s, MSG_DEBUG,
1052 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1053 ie.pairwise_cipher, ie.group_cipher,
1054 ie.key_mgmt);
1055 }
1056 }
1057 if (bss_wpa) {
1058 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1059 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1060 wpa_dbg(wpa_s, MSG_DEBUG,
1061 "Could not parse WPA element");
1062 } else {
1063 wpa_dbg(wpa_s, MSG_DEBUG,
1064 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1065 ie.pairwise_cipher, ie.group_cipher,
1066 ie.key_mgmt);
1067 }
1068 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069 return -1;
1070 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001071 if (ssid->proto & WPA_PROTO_OSEN)
1072 proto = WPA_PROTO_OSEN;
1073 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074 proto = WPA_PROTO_RSN;
1075 else
1076 proto = WPA_PROTO_WPA;
1077 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1078 os_memset(&ie, 0, sizeof(ie));
1079 ie.group_cipher = ssid->group_cipher;
1080 ie.pairwise_cipher = ssid->pairwise_cipher;
1081 ie.key_mgmt = ssid->key_mgmt;
1082#ifdef CONFIG_IEEE80211W
1083 ie.mgmt_group_cipher =
1084 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1085 WPA_CIPHER_AES_128_CMAC : 0;
1086#endif /* CONFIG_IEEE80211W */
1087 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1088 "based on configuration");
1089 } else
1090 proto = ie.proto;
1091 }
1092
1093 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1094 "pairwise %d key_mgmt %d proto %d",
1095 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1096#ifdef CONFIG_IEEE80211W
1097 if (ssid->ieee80211w) {
1098 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1099 ie.mgmt_group_cipher);
1100 }
1101#endif /* CONFIG_IEEE80211W */
1102
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001103 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1105 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001106 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001107
1108 if (bss || !wpa_s->ap_ies_from_associnfo) {
1109 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1110 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1111 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1112 bss_rsn ? 2 + bss_rsn[1] : 0))
1113 return -1;
1114 }
1115
1116 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001117 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1118 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1120 "cipher");
1121 return -1;
1122 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001123 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1124 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125
1126 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001127 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1128 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001129 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1130 "cipher");
1131 return -1;
1132 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001133 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1134 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001135
1136 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001137#ifdef CONFIG_SAE
1138 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1139 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1140#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001141 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001142#ifdef CONFIG_SUITEB192
1143 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1144 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1145 wpa_dbg(wpa_s, MSG_DEBUG,
1146 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1147#endif /* CONFIG_SUITEB192 */
1148#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001149 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1150 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1151 wpa_dbg(wpa_s, MSG_DEBUG,
1152 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001153#endif /* CONFIG_SUITEB */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001154#ifdef CONFIG_IEEE80211R
1155 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1156 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1157 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1158 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1159 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1160 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1161#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001162#ifdef CONFIG_SAE
1163 } else if (sel & WPA_KEY_MGMT_SAE) {
1164 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1165 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1166 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1167 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1168 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1169#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001170#ifdef CONFIG_IEEE80211W
1171 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1172 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1173 wpa_dbg(wpa_s, MSG_DEBUG,
1174 "WPA: using KEY_MGMT 802.1X with SHA256");
1175 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1176 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1177 wpa_dbg(wpa_s, MSG_DEBUG,
1178 "WPA: using KEY_MGMT PSK with SHA256");
1179#endif /* CONFIG_IEEE80211W */
1180 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1181 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1182 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1183 } else if (sel & WPA_KEY_MGMT_PSK) {
1184 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1185 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1186 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1187 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1188 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001189#ifdef CONFIG_HS20
1190 } else if (sel & WPA_KEY_MGMT_OSEN) {
1191 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1192 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1193#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194 } else {
1195 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1196 "authenticated key management type");
1197 return -1;
1198 }
1199
1200 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1201 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1202 wpa_s->pairwise_cipher);
1203 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1204
1205#ifdef CONFIG_IEEE80211W
1206 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001207 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001208 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1209 sel = 0;
1210 if (sel & WPA_CIPHER_AES_128_CMAC) {
1211 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1212 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1213 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001214 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1215 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1216 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1217 "BIP-GMAC-128");
1218 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1219 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1220 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1221 "BIP-GMAC-256");
1222 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1223 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1224 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1225 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001226 } else {
1227 wpa_s->mgmt_group_cipher = 0;
1228 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1229 }
1230 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1231 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001232 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001233 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001234#endif /* CONFIG_IEEE80211W */
1235
1236 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1237 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1238 return -1;
1239 }
1240
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001241 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001242 int psk_set = 0;
1243
1244 if (ssid->psk_set) {
1245 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
1246 psk_set = 1;
1247 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001248#ifndef CONFIG_NO_PBKDF2
1249 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1250 ssid->passphrase) {
1251 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001252 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1253 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001254 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1255 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001256 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001257 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001258 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001259 }
1260#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001261#ifdef CONFIG_EXT_PASSWORD
1262 if (ssid->ext_psk) {
1263 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1264 ssid->ext_psk);
1265 char pw_str[64 + 1];
1266 u8 psk[PMK_LEN];
1267
1268 if (pw == NULL) {
1269 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1270 "found from external storage");
1271 return -1;
1272 }
1273
1274 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1275 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1276 "PSK length %d in external storage",
1277 (int) wpabuf_len(pw));
1278 ext_password_free(pw);
1279 return -1;
1280 }
1281
1282 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1283 pw_str[wpabuf_len(pw)] = '\0';
1284
1285#ifndef CONFIG_NO_PBKDF2
1286 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1287 {
1288 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1289 4096, psk, PMK_LEN);
1290 os_memset(pw_str, 0, sizeof(pw_str));
1291 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1292 "external passphrase)",
1293 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001294 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001295 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001296 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001297 } else
1298#endif /* CONFIG_NO_PBKDF2 */
1299 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1300 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1301 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1302 "Invalid PSK hex string");
1303 os_memset(pw_str, 0, sizeof(pw_str));
1304 ext_password_free(pw);
1305 return -1;
1306 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001307 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001308 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001309 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001310 } else {
1311 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1312 "PSK available");
1313 os_memset(pw_str, 0, sizeof(pw_str));
1314 ext_password_free(pw);
1315 return -1;
1316 }
1317
1318 os_memset(pw_str, 0, sizeof(pw_str));
1319 ext_password_free(pw);
1320 }
1321#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001322
1323 if (!psk_set) {
1324 wpa_msg(wpa_s, MSG_INFO,
1325 "No PSK available for association");
1326 return -1;
1327 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001328 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001329 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1330
1331 return 0;
1332}
1333
1334
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001335static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1336{
1337 *pos = 0x00;
1338
1339 switch (idx) {
1340 case 0: /* Bits 0-7 */
1341 break;
1342 case 1: /* Bits 8-15 */
1343 break;
1344 case 2: /* Bits 16-23 */
1345#ifdef CONFIG_WNM
1346 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1347 *pos |= 0x08; /* Bit 19 - BSS Transition */
1348#endif /* CONFIG_WNM */
1349 break;
1350 case 3: /* Bits 24-31 */
1351#ifdef CONFIG_WNM
1352 *pos |= 0x02; /* Bit 25 - SSID List */
1353#endif /* CONFIG_WNM */
1354#ifdef CONFIG_INTERWORKING
1355 if (wpa_s->conf->interworking)
1356 *pos |= 0x80; /* Bit 31 - Interworking */
1357#endif /* CONFIG_INTERWORKING */
1358 break;
1359 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001360#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001361 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1362 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001363#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001364 break;
1365 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001366#ifdef CONFIG_HS20
1367 if (wpa_s->conf->hs20)
1368 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1369#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001370 break;
1371 case 6: /* Bits 48-55 */
1372 break;
1373 }
1374}
1375
1376
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001377int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001378{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001379 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001380 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001381
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001382 if (len < wpa_s->extended_capa_len)
1383 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001384 if (buflen < (size_t) len + 2) {
1385 wpa_printf(MSG_INFO,
1386 "Not enough room for building extended capabilities element");
1387 return -1;
1388 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001389
1390 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001391 *pos++ = len;
1392 for (i = 0; i < len; i++, pos++) {
1393 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001394
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001395 if (i < wpa_s->extended_capa_len) {
1396 *pos &= ~wpa_s->extended_capa_mask[i];
1397 *pos |= wpa_s->extended_capa[i];
1398 }
1399 }
1400
1401 while (len > 0 && buf[1 + len] == 0) {
1402 len--;
1403 buf[1] = len;
1404 }
1405 if (len == 0)
1406 return 0;
1407
1408 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001409}
1410
1411
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001412static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1413 struct wpa_bss *test_bss)
1414{
1415 struct wpa_bss *bss;
1416
1417 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1418 if (bss == test_bss)
1419 return 1;
1420 }
1421
1422 return 0;
1423}
1424
1425
1426static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1427 struct wpa_ssid *test_ssid)
1428{
1429 struct wpa_ssid *ssid;
1430
1431 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1432 if (ssid == test_ssid)
1433 return 1;
1434 }
1435
1436 return 0;
1437}
1438
1439
1440int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1441 struct wpa_ssid *test_ssid)
1442{
1443 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1444 return 0;
1445
1446 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1447}
1448
1449
1450void wpas_connect_work_free(struct wpa_connect_work *cwork)
1451{
1452 if (cwork == NULL)
1453 return;
1454 os_free(cwork);
1455}
1456
1457
1458void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1459{
1460 struct wpa_connect_work *cwork;
1461 struct wpa_radio_work *work = wpa_s->connect_work;
1462
1463 if (!work)
1464 return;
1465
1466 wpa_s->connect_work = NULL;
1467 cwork = work->ctx;
1468 work->ctx = NULL;
1469 wpas_connect_work_free(cwork);
1470 radio_work_done(work);
1471}
1472
1473
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001474int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1475{
1476 struct os_reltime now;
1477 u8 addr[ETH_ALEN];
1478
1479 os_get_reltime(&now);
1480 if (wpa_s->last_mac_addr_style == style &&
1481 wpa_s->last_mac_addr_change.sec != 0 &&
1482 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1483 wpa_s->conf->rand_addr_lifetime)) {
1484 wpa_msg(wpa_s, MSG_DEBUG,
1485 "Previously selected random MAC address has not yet expired");
1486 return 0;
1487 }
1488
1489 switch (style) {
1490 case 1:
1491 if (random_mac_addr(addr) < 0)
1492 return -1;
1493 break;
1494 case 2:
1495 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1496 if (random_mac_addr_keep_oui(addr) < 0)
1497 return -1;
1498 break;
1499 default:
1500 return -1;
1501 }
1502
1503 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1504 wpa_msg(wpa_s, MSG_INFO,
1505 "Failed to set random MAC address");
1506 return -1;
1507 }
1508
1509 os_get_reltime(&wpa_s->last_mac_addr_change);
1510 wpa_s->mac_addr_changed = 1;
1511 wpa_s->last_mac_addr_style = style;
1512
1513 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1514 wpa_msg(wpa_s, MSG_INFO,
1515 "Could not update MAC address information");
1516 return -1;
1517 }
1518
1519 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1520 MAC2STR(addr));
1521
1522 return 0;
1523}
1524
1525
1526int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1527{
1528 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1529 !wpa_s->conf->preassoc_mac_addr)
1530 return 0;
1531
1532 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1533}
1534
1535
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001536static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1537
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001538/**
1539 * wpa_supplicant_associate - Request association
1540 * @wpa_s: Pointer to wpa_supplicant data
1541 * @bss: Scan results for the selected BSS, or %NULL if not available
1542 * @ssid: Configuration data for the selected network
1543 *
1544 * This function is used to request %wpa_supplicant to associate with a BSS.
1545 */
1546void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1547 struct wpa_bss *bss, struct wpa_ssid *ssid)
1548{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001549 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001550 int rand_style;
1551
1552 if (ssid->mac_addr == -1)
1553 rand_style = wpa_s->conf->mac_addr;
1554 else
1555 rand_style = ssid->mac_addr;
1556
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001557 wmm_ac_clear_saved_tspecs(wpa_s);
1558 wpa_s->reassoc_same_bss = 0;
1559
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001560 if (wpa_s->last_ssid == ssid) {
1561 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001562 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1563 wmm_ac_save_tspecs(wpa_s);
1564 wpa_s->reassoc_same_bss = 1;
1565 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001566 } else if (rand_style > 0) {
1567 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1568 return;
1569 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1570 } else if (wpa_s->mac_addr_changed) {
1571 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1572 wpa_msg(wpa_s, MSG_INFO,
1573 "Could not restore permanent MAC address");
1574 return;
1575 }
1576 wpa_s->mac_addr_changed = 0;
1577 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1578 wpa_msg(wpa_s, MSG_INFO,
1579 "Could not update MAC address information");
1580 return;
1581 }
1582 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1583 }
1584 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001585
1586#ifdef CONFIG_IBSS_RSN
1587 ibss_rsn_deinit(wpa_s->ibss_rsn);
1588 wpa_s->ibss_rsn = NULL;
1589#endif /* CONFIG_IBSS_RSN */
1590
1591 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1592 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1593#ifdef CONFIG_AP
1594 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1595 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1596 "mode");
1597 return;
1598 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001599 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1600 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001601 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1602 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001603 return;
1604 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605 wpa_s->current_bss = bss;
1606#else /* CONFIG_AP */
1607 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1608 "the build");
1609#endif /* CONFIG_AP */
1610 return;
1611 }
1612
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001613 if (ssid->mode == WPAS_MODE_MESH) {
1614#ifdef CONFIG_MESH
1615 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1616 wpa_msg(wpa_s, MSG_INFO,
1617 "Driver does not support mesh mode");
1618 return;
1619 }
1620 if (bss)
1621 ssid->frequency = bss->freq;
1622 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1623 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1624 return;
1625 }
1626 wpa_s->current_bss = bss;
1627 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
1628 "ssid=\"%s\" id=%d",
1629 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1630 ssid->id);
1631#else /* CONFIG_MESH */
1632 wpa_msg(wpa_s, MSG_ERROR,
1633 "mesh mode support not included in the build");
1634#endif /* CONFIG_MESH */
1635 return;
1636 }
1637
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001638#ifdef CONFIG_TDLS
1639 if (bss)
1640 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1641 bss->ie_len);
1642#endif /* CONFIG_TDLS */
1643
1644 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1645 ssid->mode == IEEE80211_MODE_INFRA) {
1646 sme_authenticate(wpa_s, bss, ssid);
1647 return;
1648 }
1649
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001650 if (wpa_s->connect_work) {
1651 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1652 return;
1653 }
1654
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001655 if (radio_work_pending(wpa_s, "connect")) {
1656 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1657 return;
1658 }
1659
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001660 cwork = os_zalloc(sizeof(*cwork));
1661 if (cwork == NULL)
1662 return;
1663
1664 cwork->bss = bss;
1665 cwork->ssid = ssid;
1666
1667 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1668 wpas_start_assoc_cb, cwork) < 0) {
1669 os_free(cwork);
1670 }
1671}
1672
1673
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001674static int bss_is_ibss(struct wpa_bss *bss)
1675{
1676 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1677 IEEE80211_CAP_IBSS;
1678}
1679
1680
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001681void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1682 const struct wpa_ssid *ssid,
1683 struct hostapd_freq_params *freq)
1684{
1685 enum hostapd_hw_mode hw_mode;
1686 struct hostapd_hw_modes *mode = NULL;
1687 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1688 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001689 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001690 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1691 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001692 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001693 unsigned int j;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001694 struct hostapd_freq_params vht_freq;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001695
1696 freq->freq = ssid->frequency;
1697
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001698 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1699 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1700
1701 if (ssid->mode != WPAS_MODE_IBSS)
1702 break;
1703
1704 /* Don't adjust control freq in case of fixed_freq */
1705 if (ssid->fixed_freq)
1706 break;
1707
1708 if (!bss_is_ibss(bss))
1709 continue;
1710
1711 if (ssid->ssid_len == bss->ssid_len &&
1712 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1713 wpa_printf(MSG_DEBUG,
1714 "IBSS already found in scan results, adjust control freq: %d",
1715 bss->freq);
1716 freq->freq = bss->freq;
1717 obss_scan = 0;
1718 break;
1719 }
1720 }
1721
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001722 /* For IBSS check HT_IBSS flag */
1723 if (ssid->mode == WPAS_MODE_IBSS &&
1724 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1725 return;
1726
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001727 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1728 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1729 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1730 wpa_printf(MSG_DEBUG,
1731 "IBSS: WEP/TKIP detected, do not try to enable HT");
1732 return;
1733 }
1734
1735 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001736 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1737 if (wpa_s->hw.modes[i].mode == hw_mode) {
1738 mode = &wpa_s->hw.modes[i];
1739 break;
1740 }
1741 }
1742
1743 if (!mode)
1744 return;
1745
1746 freq->ht_enabled = ht_supported(mode);
1747 if (!freq->ht_enabled)
1748 return;
1749
1750 /* Setup higher BW only for 5 GHz */
1751 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1752 return;
1753
1754 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1755 pri_chan = &mode->channels[chan_idx];
1756 if (pri_chan->chan == channel)
1757 break;
1758 pri_chan = NULL;
1759 }
1760 if (!pri_chan)
1761 return;
1762
1763 /* Check primary channel flags */
1764 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1765 return;
1766
1767 /* Check/setup HT40+/HT40- */
1768 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1769 if (ht40plus[j] == channel) {
1770 ht40 = 1;
1771 break;
1772 }
1773 }
1774
1775 /* Find secondary channel */
1776 for (i = 0; i < mode->num_channels; i++) {
1777 sec_chan = &mode->channels[i];
1778 if (sec_chan->chan == channel + ht40 * 4)
1779 break;
1780 sec_chan = NULL;
1781 }
1782 if (!sec_chan)
1783 return;
1784
1785 /* Check secondary channel flags */
1786 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1787 return;
1788
1789 freq->channel = pri_chan->chan;
1790
1791 switch (ht40) {
1792 case -1:
1793 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1794 return;
1795 freq->sec_channel_offset = -1;
1796 break;
1797 case 1:
1798 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1799 return;
1800 freq->sec_channel_offset = 1;
1801 break;
1802 default:
1803 break;
1804 }
1805
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001806 if (freq->sec_channel_offset && obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001807 struct wpa_scan_results *scan_res;
1808
1809 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1810 if (scan_res == NULL) {
1811 /* Back to HT20 */
1812 freq->sec_channel_offset = 0;
1813 return;
1814 }
1815
1816 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1817 sec_chan->chan);
1818 switch (res) {
1819 case 0:
1820 /* Back to HT20 */
1821 freq->sec_channel_offset = 0;
1822 break;
1823 case 1:
1824 /* Configuration allowed */
1825 break;
1826 case 2:
1827 /* Switch pri/sec channels */
1828 freq->freq = hw_get_freq(mode, sec_chan->chan);
1829 freq->sec_channel_offset = -freq->sec_channel_offset;
1830 freq->channel = sec_chan->chan;
1831 break;
1832 default:
1833 freq->sec_channel_offset = 0;
1834 break;
1835 }
1836
1837 wpa_scan_results_free(scan_res);
1838 }
1839
1840 wpa_printf(MSG_DEBUG,
1841 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
1842 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001843
1844 /* Not sure if mesh is ready for VHT */
1845 if (ssid->mode != WPAS_MODE_IBSS)
1846 return;
1847
1848 /* For IBSS check VHT_IBSS flag */
1849 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
1850 return;
1851
1852 vht_freq = *freq;
1853
1854 vht_freq.vht_enabled = vht_supported(mode);
1855 if (!vht_freq.vht_enabled)
1856 return;
1857
1858 /* setup center_freq1, bandwidth */
1859 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
1860 if (freq->channel >= vht80[j] &&
1861 freq->channel < vht80[j] + 16)
1862 break;
1863 }
1864
1865 if (j == ARRAY_SIZE(vht80))
1866 return;
1867
1868 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
1869 struct hostapd_channel_data *chan;
1870
1871 chan = hw_get_channel_chan(mode, i, NULL);
1872 if (!chan)
1873 return;
1874
1875 /* Back to HT configuration if channel not usable */
1876 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1877 return;
1878 }
1879
1880 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
1881 freq->channel, freq->ht_enabled,
1882 vht_freq.vht_enabled,
1883 freq->sec_channel_offset,
1884 VHT_CHANWIDTH_80MHZ,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08001885 vht80[j] + 6, 0, 0) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001886 return;
1887
1888 *freq = vht_freq;
1889
1890 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
1891 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001892}
1893
1894
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001895static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1896{
1897 struct wpa_connect_work *cwork = work->ctx;
1898 struct wpa_bss *bss = cwork->bss;
1899 struct wpa_ssid *ssid = cwork->ssid;
1900 struct wpa_supplicant *wpa_s = work->wpa_s;
1901 u8 wpa_ie[200];
1902 size_t wpa_ie_len;
1903 int use_crypt, ret, i, bssid_changed;
1904 int algs = WPA_AUTH_ALG_OPEN;
1905 unsigned int cipher_pairwise, cipher_group;
1906 struct wpa_driver_associate_params params;
1907 int wep_keys_set = 0;
1908 int assoc_failed = 0;
1909 struct wpa_ssid *old_ssid;
1910#ifdef CONFIG_HT_OVERRIDES
1911 struct ieee80211_ht_capabilities htcaps;
1912 struct ieee80211_ht_capabilities htcaps_mask;
1913#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001914#ifdef CONFIG_VHT_OVERRIDES
1915 struct ieee80211_vht_capabilities vhtcaps;
1916 struct ieee80211_vht_capabilities vhtcaps_mask;
1917#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001918
1919 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001920 if (work->started) {
1921 wpa_s->connect_work = NULL;
1922
1923 /* cancel possible auth. timeout */
1924 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1925 NULL);
1926 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001927 wpas_connect_work_free(cwork);
1928 return;
1929 }
1930
1931 wpa_s->connect_work = work;
1932
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001933 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001934 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1935 wpas_connect_work_done(wpa_s);
1936 return;
1937 }
1938
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939 os_memset(&params, 0, sizeof(params));
1940 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001941 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001942 if (bss &&
1943 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001944#ifdef CONFIG_IEEE80211R
1945 const u8 *ie, *md = NULL;
1946#endif /* CONFIG_IEEE80211R */
1947 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1948 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1949 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1950 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1951 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1952 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1953 if (bssid_changed)
1954 wpas_notify_bssid_changed(wpa_s);
1955#ifdef CONFIG_IEEE80211R
1956 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1957 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1958 md = ie + 2;
1959 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1960 if (md) {
1961 /* Prepare for the next transition */
1962 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1963 }
1964#endif /* CONFIG_IEEE80211R */
1965#ifdef CONFIG_WPS
1966 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1967 wpa_s->conf->ap_scan == 2 &&
1968 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1969 /* Use ap_scan==1 style network selection to find the network
1970 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001971 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001972 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001973 wpa_s->reassociate = 1;
1974 wpa_supplicant_req_scan(wpa_s, 0, 0);
1975 return;
1976#endif /* CONFIG_WPS */
1977 } else {
1978 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1979 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1980 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1981 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001982 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001983 wpa_supplicant_cancel_scan(wpa_s);
1984
1985 /* Starting new association, so clear the possibly used WPA IE from the
1986 * previous association. */
1987 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1988
1989#ifdef IEEE8021X_EAPOL
1990 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1991 if (ssid->leap) {
1992 if (ssid->non_leap == 0)
1993 algs = WPA_AUTH_ALG_LEAP;
1994 else
1995 algs |= WPA_AUTH_ALG_LEAP;
1996 }
1997 }
1998#endif /* IEEE8021X_EAPOL */
1999 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2000 if (ssid->auth_alg) {
2001 algs = ssid->auth_alg;
2002 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2003 "0x%x", algs);
2004 }
2005
2006 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2007 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002008 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002010 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2011 wpa_s->conf->okc :
2012 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002013 (ssid->proto & WPA_PROTO_RSN);
2014 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002015 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002016 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002017 wpa_ie_len = sizeof(wpa_ie);
2018 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2019 wpa_ie, &wpa_ie_len)) {
2020 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2021 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002022 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002023 return;
2024 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002025 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2026 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2027 /*
2028 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2029 * use non-WPA since the scan results did not indicate that the
2030 * AP is using WPA or WPA2.
2031 */
2032 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2033 wpa_ie_len = 0;
2034 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002035 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002036 wpa_ie_len = sizeof(wpa_ie);
2037 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2038 wpa_ie, &wpa_ie_len)) {
2039 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2040 "key management and encryption suites (no "
2041 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002042 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002043 return;
2044 }
2045#ifdef CONFIG_WPS
2046 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2047 struct wpabuf *wps_ie;
2048 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2049 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2050 wpa_ie_len = wpabuf_len(wps_ie);
2051 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2052 } else
2053 wpa_ie_len = 0;
2054 wpabuf_free(wps_ie);
2055 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2056 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2057 params.wps = WPS_MODE_PRIVACY;
2058 else
2059 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002060 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061#endif /* CONFIG_WPS */
2062 } else {
2063 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2064 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002065 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002066 }
2067
2068#ifdef CONFIG_P2P
2069 if (wpa_s->global->p2p) {
2070 u8 *pos;
2071 size_t len;
2072 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002073 pos = wpa_ie + wpa_ie_len;
2074 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002075 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2076 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002077 if (res >= 0)
2078 wpa_ie_len += res;
2079 }
2080
2081 wpa_s->cross_connect_disallowed = 0;
2082 if (bss) {
2083 struct wpabuf *p2p;
2084 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2085 if (p2p) {
2086 wpa_s->cross_connect_disallowed =
2087 p2p_get_cross_connect_disallowed(p2p);
2088 wpabuf_free(p2p);
2089 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2090 "connection",
2091 wpa_s->cross_connect_disallowed ?
2092 "disallows" : "allows");
2093 }
2094 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002095
2096 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097#endif /* CONFIG_P2P */
2098
Dmitry Shmidt04949592012-07-19 12:16:46 -07002099#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002100 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002101 struct wpabuf *hs20;
2102 hs20 = wpabuf_alloc(20);
2103 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002104 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002105 size_t len;
2106
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002107 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002108 len = sizeof(wpa_ie) - wpa_ie_len;
2109 if (wpabuf_len(hs20) <= len) {
2110 os_memcpy(wpa_ie + wpa_ie_len,
2111 wpabuf_head(hs20), wpabuf_len(hs20));
2112 wpa_ie_len += wpabuf_len(hs20);
2113 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002114 wpabuf_free(hs20);
2115 }
2116 }
2117#endif /* CONFIG_HS20 */
2118
Dmitry Shmidt56052862013-10-04 10:23:25 -07002119 /*
2120 * Workaround: Add Extended Capabilities element only if the AP
2121 * included this element in Beacon/Probe Response frames. Some older
2122 * APs seem to have interoperability issues if this element is
2123 * included, so while the standard may require us to include the
2124 * element in all cases, it is justifiable to skip it to avoid
2125 * interoperability issues.
2126 */
2127 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002128 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002129 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002130 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2131 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002132 if (ext_capab_len > 0) {
2133 u8 *pos = wpa_ie;
2134 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2135 pos += 2 + pos[1];
2136 os_memmove(pos + ext_capab_len, pos,
2137 wpa_ie_len - (pos - wpa_ie));
2138 wpa_ie_len += ext_capab_len;
2139 os_memcpy(pos, ext_capab, ext_capab_len);
2140 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002141 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002142
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002143 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2144 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2145 size_t len;
2146
2147 len = sizeof(wpa_ie) - wpa_ie_len;
2148 if (wpabuf_len(buf) <= len) {
2149 os_memcpy(wpa_ie + wpa_ie_len,
2150 wpabuf_head(buf), wpabuf_len(buf));
2151 wpa_ie_len += wpabuf_len(buf);
2152 }
2153 }
2154
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002155 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2156 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002157 cipher_pairwise = wpa_s->pairwise_cipher;
2158 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002159 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2160 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2161 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2162 use_crypt = 0;
2163 if (wpa_set_wep_keys(wpa_s, ssid)) {
2164 use_crypt = 1;
2165 wep_keys_set = 1;
2166 }
2167 }
2168 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2169 use_crypt = 0;
2170
2171#ifdef IEEE8021X_EAPOL
2172 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2173 if ((ssid->eapol_flags &
2174 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2175 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2176 !wep_keys_set) {
2177 use_crypt = 0;
2178 } else {
2179 /* Assume that dynamic WEP-104 keys will be used and
2180 * set cipher suites in order for drivers to expect
2181 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002182 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002183 }
2184 }
2185#endif /* IEEE8021X_EAPOL */
2186
2187 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2188 /* Set the key before (and later after) association */
2189 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2190 }
2191
2192 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2193 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002194 params.ssid = bss->ssid;
2195 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002196 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
2197 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2198 MACSTR " freq=%u MHz based on scan results "
2199 "(bssid_set=%d)",
2200 MAC2STR(bss->bssid), bss->freq,
2201 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002202 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002203 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002204 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002205 params.bssid_hint = bss->bssid;
2206 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002207 } else {
2208 params.ssid = ssid->ssid;
2209 params.ssid_len = ssid->ssid_len;
2210 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002211
2212 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2213 wpa_s->conf->ap_scan == 2) {
2214 params.bssid = ssid->bssid;
2215 params.fixed_bssid = 1;
2216 }
2217
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002218 /* Initial frequency for IBSS/mesh */
2219 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002220 ssid->frequency > 0 && params.freq.freq == 0)
2221 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002222
2223 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002224 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002225 if (ssid->beacon_int)
2226 params.beacon_int = ssid->beacon_int;
2227 else
2228 params.beacon_int = wpa_s->conf->beacon_int;
2229 }
2230
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231 params.wpa_ie = wpa_ie;
2232 params.wpa_ie_len = wpa_ie_len;
2233 params.pairwise_suite = cipher_pairwise;
2234 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002235 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002236 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002237 params.auth_alg = algs;
2238 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002239 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002240 for (i = 0; i < NUM_WEP_KEYS; i++) {
2241 if (ssid->wep_key_len[i])
2242 params.wep_key[i] = ssid->wep_key[i];
2243 params.wep_key_len[i] = ssid->wep_key_len[i];
2244 }
2245 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2246
2247 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002248 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2249 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002250 params.passphrase = ssid->passphrase;
2251 if (ssid->psk_set)
2252 params.psk = ssid->psk;
2253 }
2254
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002255 if (wpa_s->conf->key_mgmt_offload) {
2256 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2257 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002258 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2259 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002260 params.req_key_mgmt_offload =
2261 ssid->proactive_key_caching < 0 ?
2262 wpa_s->conf->okc : ssid->proactive_key_caching;
2263 else
2264 params.req_key_mgmt_offload = 1;
2265
2266 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2267 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2268 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2269 ssid->psk_set)
2270 params.psk = ssid->psk;
2271 }
2272
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002273 params.drop_unencrypted = use_crypt;
2274
2275#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002276 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002277 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002278 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2279 struct wpa_ie_data ie;
2280 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2281 ie.capabilities &
2282 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2283 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2284 "MFP: require MFP");
2285 params.mgmt_frame_protection =
2286 MGMT_FRAME_PROTECTION_REQUIRED;
2287 }
2288 }
2289#endif /* CONFIG_IEEE80211W */
2290
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002291 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002292
2293 if (wpa_s->parent->set_sta_uapsd)
2294 params.uapsd = wpa_s->parent->sta_uapsd;
2295 else
2296 params.uapsd = -1;
2297
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002298#ifdef CONFIG_HT_OVERRIDES
2299 os_memset(&htcaps, 0, sizeof(htcaps));
2300 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2301 params.htcaps = (u8 *) &htcaps;
2302 params.htcaps_mask = (u8 *) &htcaps_mask;
2303 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2304#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002305#ifdef CONFIG_VHT_OVERRIDES
2306 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2307 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2308 params.vhtcaps = &vhtcaps;
2309 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002310 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002311#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002312
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002313#ifdef CONFIG_P2P
2314 /*
2315 * If multi-channel concurrency is not supported, check for any
2316 * frequency conflict. In case of any frequency conflict, remove the
2317 * least prioritized connection.
2318 */
2319 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002320 int freq, num;
2321 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002322 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002323 wpa_printf(MSG_DEBUG,
2324 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002325 freq, params.freq.freq);
2326 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002327 wpa_s, params.freq.freq, ssid) < 0) {
2328 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002329 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002330 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002331 }
2332 }
2333#endif /* CONFIG_P2P */
2334
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002335 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002336 if (ret < 0) {
2337 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2338 "failed");
2339 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2340 /*
2341 * The driver is known to mean what is saying, so we
2342 * can stop right here; the association will not
2343 * succeed.
2344 */
2345 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002346 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2348 return;
2349 }
2350 /* try to continue anyway; new association will be tried again
2351 * after timeout */
2352 assoc_failed = 1;
2353 }
2354
2355 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2356 /* Set the key after the association just in case association
2357 * cleared the previously configured key. */
2358 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2359 /* No need to timeout authentication since there is no key
2360 * management. */
2361 wpa_supplicant_cancel_auth_timeout(wpa_s);
2362 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2363#ifdef CONFIG_IBSS_RSN
2364 } else if (ssid->mode == WPAS_MODE_IBSS &&
2365 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2366 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2367 /*
2368 * RSN IBSS authentication is per-STA and we can disable the
2369 * per-BSSID authentication.
2370 */
2371 wpa_supplicant_cancel_auth_timeout(wpa_s);
2372#endif /* CONFIG_IBSS_RSN */
2373 } else {
2374 /* Timeout for IEEE 802.11 authentication and association */
2375 int timeout = 60;
2376
2377 if (assoc_failed) {
2378 /* give IBSS a bit more time */
2379 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2380 } else if (wpa_s->conf->ap_scan == 1) {
2381 /* give IBSS a bit more time */
2382 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2383 }
2384 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2385 }
2386
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002387 if (wep_keys_set &&
2388 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002389 /* Set static WEP keys again */
2390 wpa_set_wep_keys(wpa_s, ssid);
2391 }
2392
2393 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2394 /*
2395 * Do not allow EAP session resumption between different
2396 * network configurations.
2397 */
2398 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2399 }
2400 old_ssid = wpa_s->current_ssid;
2401 wpa_s->current_ssid = ssid;
2402 wpa_s->current_bss = bss;
2403 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2404 wpa_supplicant_initiate_eapol(wpa_s);
2405 if (old_ssid != wpa_s->current_ssid)
2406 wpas_notify_network_changed(wpa_s);
2407}
2408
2409
2410static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2411 const u8 *addr)
2412{
2413 struct wpa_ssid *old_ssid;
2414
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002415 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002416 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002417 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002418 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002419 wpa_sm_set_config(wpa_s->wpa, NULL);
2420 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2421 if (old_ssid != wpa_s->current_ssid)
2422 wpas_notify_network_changed(wpa_s);
2423 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2424}
2425
2426
2427/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002428 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2429 * @wpa_s: Pointer to wpa_supplicant data
2430 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2431 *
2432 * This function is used to request %wpa_supplicant to deauthenticate from the
2433 * current AP.
2434 */
2435void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2436 int reason_code)
2437{
2438 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002439 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002440 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002442 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2443 " pending_bssid=" MACSTR " reason=%d state=%s",
2444 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2445 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2446
2447 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002448 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002449 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2450 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2451 wpa_s->wpa_state == WPA_ASSOCIATING))
2452 addr = wpa_s->pending_bssid;
2453 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2454 /*
2455 * When using driver-based BSS selection, we may not know the
2456 * BSSID with which we are currently trying to associate. We
2457 * need to notify the driver of this disconnection even in such
2458 * a case, so use the all zeros address here.
2459 */
2460 addr = wpa_s->bssid;
2461 zero_addr = 1;
2462 }
2463
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002464#ifdef CONFIG_TDLS
2465 wpa_tdls_teardown_peers(wpa_s->wpa);
2466#endif /* CONFIG_TDLS */
2467
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002468#ifdef CONFIG_MESH
2469 if (wpa_s->ifmsh) {
2470 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2471 wpa_s->ifname);
2472 wpa_supplicant_leave_mesh(wpa_s);
2473 }
2474#endif /* CONFIG_MESH */
2475
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002476 if (addr) {
2477 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002478 os_memset(&event, 0, sizeof(event));
2479 event.deauth_info.reason_code = (u16) reason_code;
2480 event.deauth_info.locally_generated = 1;
2481 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002482 if (zero_addr)
2483 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484 }
2485
2486 wpa_supplicant_clear_connection(wpa_s, addr);
2487}
2488
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002489static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2490 struct wpa_ssid *ssid)
2491{
2492 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2493 return;
2494
2495 ssid->disabled = 0;
2496 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2497 wpas_notify_network_enabled_changed(wpa_s, ssid);
2498
2499 /*
2500 * Try to reassociate since there is no current configuration and a new
2501 * network was made available.
2502 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002503 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002504 wpa_s->reassociate = 1;
2505}
2506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507
2508/**
2509 * wpa_supplicant_enable_network - Mark a configured network as enabled
2510 * @wpa_s: wpa_supplicant structure for a network interface
2511 * @ssid: wpa_ssid structure for a configured network or %NULL
2512 *
2513 * Enables the specified network or all networks if no network specified.
2514 */
2515void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2516 struct wpa_ssid *ssid)
2517{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002519 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2520 wpa_supplicant_enable_one_network(wpa_s, ssid);
2521 } else
2522 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002524 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002525 if (wpa_s->sched_scanning) {
2526 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2527 "new network to scan filters");
2528 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 }
2530
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002531 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2532 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533 }
2534}
2535
2536
2537/**
2538 * wpa_supplicant_disable_network - Mark a configured network as disabled
2539 * @wpa_s: wpa_supplicant structure for a network interface
2540 * @ssid: wpa_ssid structure for a configured network or %NULL
2541 *
2542 * Disables the specified network or all networks if no network specified.
2543 */
2544void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2545 struct wpa_ssid *ssid)
2546{
2547 struct wpa_ssid *other_ssid;
2548 int was_disabled;
2549
2550 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002551 if (wpa_s->sched_scanning)
2552 wpa_supplicant_cancel_sched_scan(wpa_s);
2553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2555 other_ssid = other_ssid->next) {
2556 was_disabled = other_ssid->disabled;
2557 if (was_disabled == 2)
2558 continue; /* do not change persistent P2P group
2559 * data */
2560
2561 other_ssid->disabled = 1;
2562
2563 if (was_disabled != other_ssid->disabled)
2564 wpas_notify_network_enabled_changed(
2565 wpa_s, other_ssid);
2566 }
2567 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002568 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2570 } else if (ssid->disabled != 2) {
2571 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002572 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2574
2575 was_disabled = ssid->disabled;
2576
2577 ssid->disabled = 1;
2578
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002579 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002580 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002581 if (wpa_s->sched_scanning) {
2582 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2583 "to remove network from filters");
2584 wpa_supplicant_cancel_sched_scan(wpa_s);
2585 wpa_supplicant_req_scan(wpa_s, 0, 0);
2586 }
2587 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002588 }
2589}
2590
2591
2592/**
2593 * wpa_supplicant_select_network - Attempt association with a network
2594 * @wpa_s: wpa_supplicant structure for a network interface
2595 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2596 */
2597void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2598 struct wpa_ssid *ssid)
2599{
2600
2601 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002602 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002604 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08002605 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002606 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002608 disconnected = 1;
2609 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002610
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002611 if (ssid)
2612 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2613
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002614 /*
2615 * Mark all other networks disabled or mark all networks enabled if no
2616 * network specified.
2617 */
2618 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2619 other_ssid = other_ssid->next) {
2620 int was_disabled = other_ssid->disabled;
2621 if (was_disabled == 2)
2622 continue; /* do not change persistent P2P group data */
2623
2624 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002625 if (was_disabled && !other_ssid->disabled)
2626 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002627
2628 if (was_disabled != other_ssid->disabled)
2629 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2630 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002631
2632 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2633 /* We are already associated with the selected network */
2634 wpa_printf(MSG_DEBUG, "Already associated with the "
2635 "selected network - do nothing");
2636 return;
2637 }
2638
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002639 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002640 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002641 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002642 wpa_s->connect_without_scan =
2643 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002644
2645 /*
2646 * Don't optimize next scan freqs since a new ESS has been
2647 * selected.
2648 */
2649 os_free(wpa_s->next_scan_freqs);
2650 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002651 } else {
2652 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002653 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002654
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002655 wpa_s->disconnected = 0;
2656 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002657
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002658 if (wpa_s->connect_without_scan ||
2659 wpa_supplicant_fast_associate(wpa_s) != 1)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002660 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661
2662 if (ssid)
2663 wpas_notify_network_selected(wpa_s, ssid);
2664}
2665
2666
2667/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002668 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2669 * @wpa_s: wpa_supplicant structure for a network interface
2670 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2671 * @pkcs11_module_path: PKCS #11 module path or NULL
2672 * Returns: 0 on success; -1 on failure
2673 *
2674 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2675 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2676 * module path fails the paths will be reset to the default value (NULL).
2677 */
2678int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2679 const char *pkcs11_engine_path,
2680 const char *pkcs11_module_path)
2681{
2682 char *pkcs11_engine_path_copy = NULL;
2683 char *pkcs11_module_path_copy = NULL;
2684
2685 if (pkcs11_engine_path != NULL) {
2686 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2687 if (pkcs11_engine_path_copy == NULL)
2688 return -1;
2689 }
2690 if (pkcs11_module_path != NULL) {
2691 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002692 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002693 os_free(pkcs11_engine_path_copy);
2694 return -1;
2695 }
2696 }
2697
2698 os_free(wpa_s->conf->pkcs11_engine_path);
2699 os_free(wpa_s->conf->pkcs11_module_path);
2700 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2701 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2702
2703 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2704 eapol_sm_deinit(wpa_s->eapol);
2705 wpa_s->eapol = NULL;
2706 if (wpa_supplicant_init_eapol(wpa_s)) {
2707 /* Error -> Reset paths to the default value (NULL) once. */
2708 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2709 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2710 NULL);
2711
2712 return -1;
2713 }
2714 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2715
2716 return 0;
2717}
2718
2719
2720/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002721 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2722 * @wpa_s: wpa_supplicant structure for a network interface
2723 * @ap_scan: AP scan mode
2724 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2725 *
2726 */
2727int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2728{
2729
2730 int old_ap_scan;
2731
2732 if (ap_scan < 0 || ap_scan > 2)
2733 return -1;
2734
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002735#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002736 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2737 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2738 wpa_s->wpa_state < WPA_COMPLETED) {
2739 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2740 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002741 return 0;
2742 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002743#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002745 old_ap_scan = wpa_s->conf->ap_scan;
2746 wpa_s->conf->ap_scan = ap_scan;
2747
2748 if (old_ap_scan != wpa_s->conf->ap_scan)
2749 wpas_notify_ap_scan_changed(wpa_s);
2750
2751 return 0;
2752}
2753
2754
2755/**
2756 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2757 * @wpa_s: wpa_supplicant structure for a network interface
2758 * @expire_age: Expiration age in seconds
2759 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2760 *
2761 */
2762int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2763 unsigned int bss_expire_age)
2764{
2765 if (bss_expire_age < 10) {
2766 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2767 bss_expire_age);
2768 return -1;
2769 }
2770 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2771 bss_expire_age);
2772 wpa_s->conf->bss_expiration_age = bss_expire_age;
2773
2774 return 0;
2775}
2776
2777
2778/**
2779 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2780 * @wpa_s: wpa_supplicant structure for a network interface
2781 * @expire_count: number of scans after which an unseen BSS is reclaimed
2782 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2783 *
2784 */
2785int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2786 unsigned int bss_expire_count)
2787{
2788 if (bss_expire_count < 1) {
2789 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2790 bss_expire_count);
2791 return -1;
2792 }
2793 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2794 bss_expire_count);
2795 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2796
2797 return 0;
2798}
2799
2800
2801/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002802 * wpa_supplicant_set_scan_interval - Set scan interval
2803 * @wpa_s: wpa_supplicant structure for a network interface
2804 * @scan_interval: scan interval in seconds
2805 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2806 *
2807 */
2808int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2809 int scan_interval)
2810{
2811 if (scan_interval < 0) {
2812 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2813 scan_interval);
2814 return -1;
2815 }
2816 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2817 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002818 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002819
2820 return 0;
2821}
2822
2823
2824/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002825 * wpa_supplicant_set_debug_params - Set global debug params
2826 * @global: wpa_global structure
2827 * @debug_level: debug level
2828 * @debug_timestamp: determines if show timestamp in debug data
2829 * @debug_show_keys: determines if show keys in debug data
2830 * Returns: 0 if succeed or -1 if debug_level has wrong value
2831 */
2832int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2833 int debug_timestamp, int debug_show_keys)
2834{
2835
2836 int old_level, old_timestamp, old_show_keys;
2837
2838 /* check for allowed debuglevels */
2839 if (debug_level != MSG_EXCESSIVE &&
2840 debug_level != MSG_MSGDUMP &&
2841 debug_level != MSG_DEBUG &&
2842 debug_level != MSG_INFO &&
2843 debug_level != MSG_WARNING &&
2844 debug_level != MSG_ERROR)
2845 return -1;
2846
2847 old_level = wpa_debug_level;
2848 old_timestamp = wpa_debug_timestamp;
2849 old_show_keys = wpa_debug_show_keys;
2850
2851 wpa_debug_level = debug_level;
2852 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2853 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2854
2855 if (wpa_debug_level != old_level)
2856 wpas_notify_debug_level_changed(global);
2857 if (wpa_debug_timestamp != old_timestamp)
2858 wpas_notify_debug_timestamp_changed(global);
2859 if (wpa_debug_show_keys != old_show_keys)
2860 wpas_notify_debug_show_keys_changed(global);
2861
2862 return 0;
2863}
2864
2865
2866/**
2867 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2868 * @wpa_s: Pointer to wpa_supplicant data
2869 * Returns: A pointer to the current network structure or %NULL on failure
2870 */
2871struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2872{
2873 struct wpa_ssid *entry;
2874 u8 ssid[MAX_SSID_LEN];
2875 int res;
2876 size_t ssid_len;
2877 u8 bssid[ETH_ALEN];
2878 int wired;
2879
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002880 res = wpa_drv_get_ssid(wpa_s, ssid);
2881 if (res < 0) {
2882 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2883 "driver");
2884 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002886 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002887
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002888 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002889 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2890 "driver");
2891 return NULL;
2892 }
2893
2894 wired = wpa_s->conf->ap_scan == 0 &&
2895 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2896
2897 entry = wpa_s->conf->ssid;
2898 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002899 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002900 ((ssid_len == entry->ssid_len &&
2901 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2902 (!entry->bssid_set ||
2903 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2904 return entry;
2905#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002906 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002907 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2908 (entry->ssid == NULL || entry->ssid_len == 0) &&
2909 (!entry->bssid_set ||
2910 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2911 return entry;
2912#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002913
Dmitry Shmidt04949592012-07-19 12:16:46 -07002914 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002915 entry->ssid_len == 0 &&
2916 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2917 return entry;
2918
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919 entry = entry->next;
2920 }
2921
2922 return NULL;
2923}
2924
2925
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002926static int select_driver(struct wpa_supplicant *wpa_s, int i)
2927{
2928 struct wpa_global *global = wpa_s->global;
2929
2930 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2931 global->drv_priv[i] = wpa_drivers[i]->global_init();
2932 if (global->drv_priv[i] == NULL) {
2933 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2934 "'%s'", wpa_drivers[i]->name);
2935 return -1;
2936 }
2937 }
2938
2939 wpa_s->driver = wpa_drivers[i];
2940 wpa_s->global_drv_priv = global->drv_priv[i];
2941
2942 return 0;
2943}
2944
2945
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002946static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2947 const char *name)
2948{
2949 int i;
2950 size_t len;
2951 const char *pos, *driver = name;
2952
2953 if (wpa_s == NULL)
2954 return -1;
2955
2956 if (wpa_drivers[0] == NULL) {
2957 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2958 "wpa_supplicant");
2959 return -1;
2960 }
2961
2962 if (name == NULL) {
2963 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002964 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002965 }
2966
2967 do {
2968 pos = os_strchr(driver, ',');
2969 if (pos)
2970 len = pos - driver;
2971 else
2972 len = os_strlen(driver);
2973
2974 for (i = 0; wpa_drivers[i]; i++) {
2975 if (os_strlen(wpa_drivers[i]->name) == len &&
2976 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002977 0) {
2978 /* First driver that succeeds wins */
2979 if (select_driver(wpa_s, i) == 0)
2980 return 0;
2981 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002982 }
2983
2984 driver = pos + 1;
2985 } while (pos);
2986
2987 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2988 return -1;
2989}
2990
2991
2992/**
2993 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2994 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2995 * with struct wpa_driver_ops::init()
2996 * @src_addr: Source address of the EAPOL frame
2997 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2998 * @len: Length of the EAPOL data
2999 *
3000 * This function is called for each received EAPOL frame. Most driver
3001 * interfaces rely on more generic OS mechanism for receiving frames through
3002 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3003 * take care of received EAPOL frames and deliver them to the core supplicant
3004 * code by calling this function.
3005 */
3006void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3007 const u8 *buf, size_t len)
3008{
3009 struct wpa_supplicant *wpa_s = ctx;
3010
3011 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3012 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3013
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003014#ifdef CONFIG_PEERKEY
3015 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3016 wpa_s->current_ssid->peerkey &&
3017 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3018 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3019 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3020 return;
3021 }
3022#endif /* CONFIG_PEERKEY */
3023
Jouni Malinena05074c2012-12-21 21:35:35 +02003024 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3025 (wpa_s->last_eapol_matches_bssid &&
3026#ifdef CONFIG_AP
3027 !wpa_s->ap_iface &&
3028#endif /* CONFIG_AP */
3029 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003030 /*
3031 * There is possible race condition between receiving the
3032 * association event and the EAPOL frame since they are coming
3033 * through different paths from the driver. In order to avoid
3034 * issues in trying to process the EAPOL frame before receiving
3035 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003036 * the association event is received. This may also be needed in
3037 * driver-based roaming case, so also use src_addr != BSSID as a
3038 * trigger if we have previously confirmed that the
3039 * Authenticator uses BSSID as the src_addr (which is not the
3040 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003041 */
3042 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003043 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3044 wpa_supplicant_state_txt(wpa_s->wpa_state),
3045 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003046 wpabuf_free(wpa_s->pending_eapol_rx);
3047 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3048 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003049 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003050 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3051 ETH_ALEN);
3052 }
3053 return;
3054 }
3055
Jouni Malinena05074c2012-12-21 21:35:35 +02003056 wpa_s->last_eapol_matches_bssid =
3057 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3058
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003059#ifdef CONFIG_AP
3060 if (wpa_s->ap_iface) {
3061 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3062 return;
3063 }
3064#endif /* CONFIG_AP */
3065
3066 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3067 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3068 "no key management is configured");
3069 return;
3070 }
3071
3072 if (wpa_s->eapol_received == 0 &&
3073 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3074 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3075 wpa_s->wpa_state != WPA_COMPLETED) &&
3076 (wpa_s->current_ssid == NULL ||
3077 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3078 /* Timeout for completing IEEE 802.1X and WPA authentication */
3079 wpa_supplicant_req_auth_timeout(
3080 wpa_s,
3081 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3082 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3083 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
3084 70 : 10, 0);
3085 }
3086 wpa_s->eapol_received++;
3087
3088 if (wpa_s->countermeasures) {
3089 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3090 "EAPOL packet");
3091 return;
3092 }
3093
3094#ifdef CONFIG_IBSS_RSN
3095 if (wpa_s->current_ssid &&
3096 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3097 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3098 return;
3099 }
3100#endif /* CONFIG_IBSS_RSN */
3101
3102 /* Source address of the incoming EAPOL frame could be compared to the
3103 * current BSSID. However, it is possible that a centralized
3104 * Authenticator could be using another MAC address than the BSSID of
3105 * an AP, so just allow any address to be used for now. The replies are
3106 * still sent to the current BSSID (if available), though. */
3107
3108 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3109 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3110 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3111 return;
3112 wpa_drv_poll(wpa_s);
3113 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3114 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3115 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3116 /*
3117 * Set portValid = TRUE here since we are going to skip 4-way
3118 * handshake processing which would normally set portValid. We
3119 * need this to allow the EAPOL state machines to be completed
3120 * without going through EAPOL-Key handshake.
3121 */
3122 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3123 }
3124}
3125
3126
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003127int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003128{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003129 if ((!wpa_s->p2p_mgmt ||
3130 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3131 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003132 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003133 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3134 wpa_drv_get_mac_addr(wpa_s),
3135 ETH_P_EAPOL,
3136 wpa_supplicant_rx_eapol, wpa_s, 0);
3137 if (wpa_s->l2 == NULL)
3138 return -1;
3139 } else {
3140 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3141 if (addr)
3142 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3143 }
3144
3145 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3146 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3147 return -1;
3148 }
3149
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003150 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3151
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003152 return 0;
3153}
3154
3155
Dmitry Shmidt04949592012-07-19 12:16:46 -07003156static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3157 const u8 *buf, size_t len)
3158{
3159 struct wpa_supplicant *wpa_s = ctx;
3160 const struct l2_ethhdr *eth;
3161
3162 if (len < sizeof(*eth))
3163 return;
3164 eth = (const struct l2_ethhdr *) buf;
3165
3166 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3167 !(eth->h_dest[0] & 0x01)) {
3168 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3169 " (bridge - not for this interface - ignore)",
3170 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3171 return;
3172 }
3173
3174 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3175 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3176 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3177 len - sizeof(*eth));
3178}
3179
3180
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003181/**
3182 * wpa_supplicant_driver_init - Initialize driver interface parameters
3183 * @wpa_s: Pointer to wpa_supplicant data
3184 * Returns: 0 on success, -1 on failure
3185 *
3186 * This function is called to initialize driver interface parameters.
3187 * wpa_drv_init() must have been called before this function to initialize the
3188 * driver interface.
3189 */
3190int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3191{
3192 static int interface_count = 0;
3193
3194 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3195 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003196
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003197 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3198 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003199 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003200 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3201
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003202 if (wpa_s->bridge_ifname[0]) {
3203 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3204 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003205 wpa_s->l2_br = l2_packet_init_bridge(
3206 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3207 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003208 if (wpa_s->l2_br == NULL) {
3209 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3210 "connection for the bridge interface '%s'",
3211 wpa_s->bridge_ifname);
3212 return -1;
3213 }
3214 }
3215
3216 wpa_clear_keys(wpa_s, NULL);
3217
3218 /* Make sure that TKIP countermeasures are not left enabled (could
3219 * happen if wpa_supplicant is killed during countermeasures. */
3220 wpa_drv_set_countermeasures(wpa_s, 0);
3221
3222 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3223 wpa_drv_flush_pmkid(wpa_s);
3224
3225 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003226 wpa_s->prev_scan_wildcard = 0;
3227
Dmitry Shmidt04949592012-07-19 12:16:46 -07003228 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003229 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3230 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3231 interface_count = 0;
3232 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003233#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003234 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003235 wpa_supplicant_delayed_sched_scan(wpa_s,
3236 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003237 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003238 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003239 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003240#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003241 interface_count++;
3242 } else
3243 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3244
3245 return 0;
3246}
3247
3248
3249static int wpa_supplicant_daemon(const char *pid_file)
3250{
3251 wpa_printf(MSG_DEBUG, "Daemonize..");
3252 return os_daemonize(pid_file);
3253}
3254
3255
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003256static struct wpa_supplicant *
3257wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003258{
3259 struct wpa_supplicant *wpa_s;
3260
3261 wpa_s = os_zalloc(sizeof(*wpa_s));
3262 if (wpa_s == NULL)
3263 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003264 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003265 wpa_s->scan_interval = 5;
3266 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003267 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003268 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003269
3270 return wpa_s;
3271}
3272
3273
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003274#ifdef CONFIG_HT_OVERRIDES
3275
3276static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3277 struct ieee80211_ht_capabilities *htcaps,
3278 struct ieee80211_ht_capabilities *htcaps_mask,
3279 const char *ht_mcs)
3280{
3281 /* parse ht_mcs into hex array */
3282 int i;
3283 const char *tmp = ht_mcs;
3284 char *end = NULL;
3285
3286 /* If ht_mcs is null, do not set anything */
3287 if (!ht_mcs)
3288 return 0;
3289
3290 /* This is what we are setting in the kernel */
3291 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3292
3293 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3294
3295 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3296 errno = 0;
3297 long v = strtol(tmp, &end, 16);
3298 if (errno == 0) {
3299 wpa_msg(wpa_s, MSG_DEBUG,
3300 "htcap value[%i]: %ld end: %p tmp: %p",
3301 i, v, end, tmp);
3302 if (end == tmp)
3303 break;
3304
3305 htcaps->supported_mcs_set[i] = v;
3306 tmp = end;
3307 } else {
3308 wpa_msg(wpa_s, MSG_ERROR,
3309 "Failed to parse ht-mcs: %s, error: %s\n",
3310 ht_mcs, strerror(errno));
3311 return -1;
3312 }
3313 }
3314
3315 /*
3316 * If we were able to parse any values, then set mask for the MCS set.
3317 */
3318 if (i) {
3319 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3320 IEEE80211_HT_MCS_MASK_LEN - 1);
3321 /* skip the 3 reserved bits */
3322 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3323 0x1f;
3324 }
3325
3326 return 0;
3327}
3328
3329
3330static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3331 struct ieee80211_ht_capabilities *htcaps,
3332 struct ieee80211_ht_capabilities *htcaps_mask,
3333 int disabled)
3334{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003335 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003336
3337 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3338
3339 if (disabled == -1)
3340 return 0;
3341
3342 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3343 htcaps_mask->ht_capabilities_info |= msk;
3344 if (disabled)
3345 htcaps->ht_capabilities_info &= msk;
3346 else
3347 htcaps->ht_capabilities_info |= msk;
3348
3349 return 0;
3350}
3351
3352
3353static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3354 struct ieee80211_ht_capabilities *htcaps,
3355 struct ieee80211_ht_capabilities *htcaps_mask,
3356 int factor)
3357{
3358 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3359
3360 if (factor == -1)
3361 return 0;
3362
3363 if (factor < 0 || factor > 3) {
3364 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3365 "Must be 0-3 or -1", factor);
3366 return -EINVAL;
3367 }
3368
3369 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3370 htcaps->a_mpdu_params &= ~0x3;
3371 htcaps->a_mpdu_params |= factor & 0x3;
3372
3373 return 0;
3374}
3375
3376
3377static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3378 struct ieee80211_ht_capabilities *htcaps,
3379 struct ieee80211_ht_capabilities *htcaps_mask,
3380 int density)
3381{
3382 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3383
3384 if (density == -1)
3385 return 0;
3386
3387 if (density < 0 || density > 7) {
3388 wpa_msg(wpa_s, MSG_ERROR,
3389 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3390 density);
3391 return -EINVAL;
3392 }
3393
3394 htcaps_mask->a_mpdu_params |= 0x1C;
3395 htcaps->a_mpdu_params &= ~(0x1C);
3396 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3397
3398 return 0;
3399}
3400
3401
3402static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3403 struct ieee80211_ht_capabilities *htcaps,
3404 struct ieee80211_ht_capabilities *htcaps_mask,
3405 int disabled)
3406{
3407 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003408 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3409 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003410
3411 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3412
3413 if (disabled)
3414 htcaps->ht_capabilities_info &= ~msk;
3415 else
3416 htcaps->ht_capabilities_info |= msk;
3417
3418 htcaps_mask->ht_capabilities_info |= msk;
3419
3420 return 0;
3421}
3422
3423
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003424static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3425 struct ieee80211_ht_capabilities *htcaps,
3426 struct ieee80211_ht_capabilities *htcaps_mask,
3427 int disabled)
3428{
3429 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003430 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3431 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003432
3433 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3434
3435 if (disabled)
3436 htcaps->ht_capabilities_info &= ~msk;
3437 else
3438 htcaps->ht_capabilities_info |= msk;
3439
3440 htcaps_mask->ht_capabilities_info |= msk;
3441
3442 return 0;
3443}
3444
3445
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003446static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3447 struct ieee80211_ht_capabilities *htcaps,
3448 struct ieee80211_ht_capabilities *htcaps_mask,
3449 int disabled)
3450{
3451 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003452 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003453
3454 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3455
3456 if (disabled)
3457 htcaps->ht_capabilities_info &= ~msk;
3458 else
3459 htcaps->ht_capabilities_info |= msk;
3460
3461 htcaps_mask->ht_capabilities_info |= msk;
3462
3463 return 0;
3464}
3465
3466
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003467void wpa_supplicant_apply_ht_overrides(
3468 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3469 struct wpa_driver_associate_params *params)
3470{
3471 struct ieee80211_ht_capabilities *htcaps;
3472 struct ieee80211_ht_capabilities *htcaps_mask;
3473
3474 if (!ssid)
3475 return;
3476
3477 params->disable_ht = ssid->disable_ht;
3478 if (!params->htcaps || !params->htcaps_mask)
3479 return;
3480
3481 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3482 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3483 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3484 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3485 ssid->disable_max_amsdu);
3486 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3487 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3488 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003489 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003490 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003491
3492 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003493 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003494 htcaps->ht_capabilities_info |= bit;
3495 htcaps_mask->ht_capabilities_info |= bit;
3496 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003497}
3498
3499#endif /* CONFIG_HT_OVERRIDES */
3500
3501
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003502#ifdef CONFIG_VHT_OVERRIDES
3503void wpa_supplicant_apply_vht_overrides(
3504 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3505 struct wpa_driver_associate_params *params)
3506{
3507 struct ieee80211_vht_capabilities *vhtcaps;
3508 struct ieee80211_vht_capabilities *vhtcaps_mask;
3509
3510 if (!ssid)
3511 return;
3512
3513 params->disable_vht = ssid->disable_vht;
3514
3515 vhtcaps = (void *) params->vhtcaps;
3516 vhtcaps_mask = (void *) params->vhtcaps_mask;
3517
3518 if (!vhtcaps || !vhtcaps_mask)
3519 return;
3520
3521 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3522 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3523
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003524#ifdef CONFIG_HT_OVERRIDES
3525 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003526 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3527 int max_ampdu;
3528
3529 max_ampdu = (ssid->vht_capa &
3530 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3531 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003532
3533 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3534 wpa_set_ampdu_factor(wpa_s,
3535 (void *) params->htcaps,
3536 (void *) params->htcaps_mask,
3537 max_ampdu);
3538 }
3539#endif /* CONFIG_HT_OVERRIDES */
3540
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003541#define OVERRIDE_MCS(i) \
3542 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3543 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3544 3 << 2 * (i - 1); \
3545 vhtcaps->vht_supported_mcs_set.tx_map |= \
3546 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3547 } \
3548 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3549 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3550 3 << 2 * (i - 1); \
3551 vhtcaps->vht_supported_mcs_set.rx_map |= \
3552 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3553 }
3554
3555 OVERRIDE_MCS(1);
3556 OVERRIDE_MCS(2);
3557 OVERRIDE_MCS(3);
3558 OVERRIDE_MCS(4);
3559 OVERRIDE_MCS(5);
3560 OVERRIDE_MCS(6);
3561 OVERRIDE_MCS(7);
3562 OVERRIDE_MCS(8);
3563}
3564#endif /* CONFIG_VHT_OVERRIDES */
3565
3566
Dmitry Shmidt04949592012-07-19 12:16:46 -07003567static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3568{
3569#ifdef PCSC_FUNCS
3570 size_t len;
3571
3572 if (!wpa_s->conf->pcsc_reader)
3573 return 0;
3574
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003575 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003576 if (!wpa_s->scard)
3577 return 1;
3578
3579 if (wpa_s->conf->pcsc_pin &&
3580 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3581 scard_deinit(wpa_s->scard);
3582 wpa_s->scard = NULL;
3583 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3584 return -1;
3585 }
3586
3587 len = sizeof(wpa_s->imsi) - 1;
3588 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3589 scard_deinit(wpa_s->scard);
3590 wpa_s->scard = NULL;
3591 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3592 return -1;
3593 }
3594 wpa_s->imsi[len] = '\0';
3595
3596 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3597
3598 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3599 wpa_s->imsi, wpa_s->mnc_len);
3600
3601 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3602 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3603#endif /* PCSC_FUNCS */
3604
3605 return 0;
3606}
3607
3608
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003609int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3610{
3611 char *val, *pos;
3612
3613 ext_password_deinit(wpa_s->ext_pw);
3614 wpa_s->ext_pw = NULL;
3615 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3616
3617 if (!wpa_s->conf->ext_password_backend)
3618 return 0;
3619
3620 val = os_strdup(wpa_s->conf->ext_password_backend);
3621 if (val == NULL)
3622 return -1;
3623 pos = os_strchr(val, ':');
3624 if (pos)
3625 *pos++ = '\0';
3626
3627 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3628
3629 wpa_s->ext_pw = ext_password_init(val, pos);
3630 os_free(val);
3631 if (wpa_s->ext_pw == NULL) {
3632 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3633 return -1;
3634 }
3635 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3636
3637 return 0;
3638}
3639
3640
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003641static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003642 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003643{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003644 struct wowlan_triggers *triggers;
3645 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003646
3647 if (!wpa_s->conf->wowlan_triggers)
3648 return 0;
3649
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003650 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3651 if (triggers) {
3652 ret = wpa_drv_wowlan(wpa_s, triggers);
3653 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003654 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003655 return ret;
3656}
3657
3658
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003659static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3660 const char *rn)
3661{
3662 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3663 struct wpa_radio *radio;
3664
3665 while (rn && iface) {
3666 radio = iface->radio;
3667 if (radio && os_strcmp(rn, radio->name) == 0) {
3668 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3669 wpa_s->ifname, rn);
3670 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3671 return radio;
3672 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003673
3674 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003675 }
3676
3677 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3678 wpa_s->ifname, rn ? rn : "N/A");
3679 radio = os_zalloc(sizeof(*radio));
3680 if (radio == NULL)
3681 return NULL;
3682
3683 if (rn)
3684 os_strlcpy(radio->name, rn, sizeof(radio->name));
3685 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003686 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003687 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3688
3689 return radio;
3690}
3691
3692
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003693static void radio_work_free(struct wpa_radio_work *work)
3694{
3695 if (work->wpa_s->scan_work == work) {
3696 /* This should not really happen. */
3697 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3698 work->type, work, work->started);
3699 work->wpa_s->scan_work = NULL;
3700 }
3701
3702#ifdef CONFIG_P2P
3703 if (work->wpa_s->p2p_scan_work == work) {
3704 /* This should not really happen. */
3705 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3706 work->type, work, work->started);
3707 work->wpa_s->p2p_scan_work = NULL;
3708 }
3709#endif /* CONFIG_P2P */
3710
3711 dl_list_del(&work->list);
3712 os_free(work);
3713}
3714
3715
3716static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3717{
3718 struct wpa_radio *radio = eloop_ctx;
3719 struct wpa_radio_work *work;
3720 struct os_reltime now, diff;
3721 struct wpa_supplicant *wpa_s;
3722
3723 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3724 if (work == NULL)
3725 return;
3726
3727 if (work->started)
3728 return; /* already started and still in progress */
3729
3730 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3731 radio_list);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003732 if (wpa_s && wpa_s->radio->external_scan_running) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003733 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3734 return;
3735 }
3736
3737 os_get_reltime(&now);
3738 os_reltime_sub(&now, &work->time, &diff);
3739 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3740 work->type, work, diff.sec, diff.usec);
3741 work->started = 1;
3742 work->time = now;
3743 work->cb(work, 0);
3744}
3745
3746
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003747/*
3748 * This function removes both started and pending radio works running on
3749 * the provided interface's radio.
3750 * Prior to the removal of the radio work, its callback (cb) is called with
3751 * deinit set to be 1. Each work's callback is responsible for clearing its
3752 * internal data and restoring to a correct state.
3753 * @wpa_s: wpa_supplicant data
3754 * @type: type of works to be removed
3755 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3756 * this interface's works.
3757 */
3758void radio_remove_works(struct wpa_supplicant *wpa_s,
3759 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003760{
3761 struct wpa_radio_work *work, *tmp;
3762 struct wpa_radio *radio = wpa_s->radio;
3763
3764 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3765 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003766 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003767 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003768
3769 /* skip other ifaces' works */
3770 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003771 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003772
3773 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3774 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003775 work->cb(work, 1);
3776 radio_work_free(work);
3777 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003778
3779 /* in case we removed the started work */
3780 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003781}
3782
3783
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003784static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3785{
3786 struct wpa_radio *radio = wpa_s->radio;
3787
3788 if (!radio)
3789 return;
3790
3791 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3792 wpa_s->ifname, radio->name);
3793 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003794 radio_remove_works(wpa_s, NULL, 0);
3795 wpa_s->radio = NULL;
3796 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003797 return; /* Interfaces remain for this radio */
3798
3799 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003800 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003801 os_free(radio);
3802}
3803
3804
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003805void radio_work_check_next(struct wpa_supplicant *wpa_s)
3806{
3807 struct wpa_radio *radio = wpa_s->radio;
3808
3809 if (dl_list_empty(&radio->work))
3810 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003811 if (wpa_s->ext_work_in_progress) {
3812 wpa_printf(MSG_DEBUG,
3813 "External radio work in progress - delay start of pending item");
3814 return;
3815 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003816 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3817 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3818}
3819
3820
3821/**
3822 * radio_add_work - Add a radio work item
3823 * @wpa_s: Pointer to wpa_supplicant data
3824 * @freq: Frequency of the offchannel operation in MHz or 0
3825 * @type: Unique identifier for each type of work
3826 * @next: Force as the next work to be executed
3827 * @cb: Callback function for indicating when radio is available
3828 * @ctx: Context pointer for the work (work->ctx in cb())
3829 * Returns: 0 on success, -1 on failure
3830 *
3831 * This function is used to request time for an operation that requires
3832 * exclusive radio control. Once the radio is available, the registered callback
3833 * function will be called. radio_work_done() must be called once the exclusive
3834 * radio operation has been completed, so that the radio is freed for other
3835 * operations. The special case of deinit=1 is used to free the context data
3836 * during interface removal. That does not allow the callback function to start
3837 * the radio operation, i.e., it must free any resources allocated for the radio
3838 * work and return.
3839 *
3840 * The @freq parameter can be used to indicate a single channel on which the
3841 * offchannel operation will occur. This may allow multiple radio work
3842 * operations to be performed in parallel if they apply for the same channel.
3843 * Setting this to 0 indicates that the work item may use multiple channels or
3844 * requires exclusive control of the radio.
3845 */
3846int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3847 const char *type, int next,
3848 void (*cb)(struct wpa_radio_work *work, int deinit),
3849 void *ctx)
3850{
3851 struct wpa_radio_work *work;
3852 int was_empty;
3853
3854 work = os_zalloc(sizeof(*work));
3855 if (work == NULL)
3856 return -1;
3857 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3858 os_get_reltime(&work->time);
3859 work->freq = freq;
3860 work->type = type;
3861 work->wpa_s = wpa_s;
3862 work->cb = cb;
3863 work->ctx = ctx;
3864
3865 was_empty = dl_list_empty(&wpa_s->radio->work);
3866 if (next)
3867 dl_list_add(&wpa_s->radio->work, &work->list);
3868 else
3869 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3870 if (was_empty) {
3871 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3872 radio_work_check_next(wpa_s);
3873 }
3874
3875 return 0;
3876}
3877
3878
3879/**
3880 * radio_work_done - Indicate that a radio work item has been completed
3881 * @work: Completed work
3882 *
3883 * This function is called once the callback function registered with
3884 * radio_add_work() has completed its work.
3885 */
3886void radio_work_done(struct wpa_radio_work *work)
3887{
3888 struct wpa_supplicant *wpa_s = work->wpa_s;
3889 struct os_reltime now, diff;
3890 unsigned int started = work->started;
3891
3892 os_get_reltime(&now);
3893 os_reltime_sub(&now, &work->time, &diff);
3894 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3895 work->type, work, started ? "done" : "canceled",
3896 diff.sec, diff.usec);
3897 radio_work_free(work);
3898 if (started)
3899 radio_work_check_next(wpa_s);
3900}
3901
3902
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003903struct wpa_radio_work *
3904radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003905{
3906 struct wpa_radio_work *work;
3907 struct wpa_radio *radio = wpa_s->radio;
3908
3909 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3910 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003911 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003912 }
3913
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003914 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003915}
3916
3917
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003918static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3919 struct wpa_interface *iface)
3920{
3921 const char *ifname, *driver, *rn;
3922
3923 driver = iface->driver;
3924next_driver:
3925 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3926 return -1;
3927
3928 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3929 if (wpa_s->drv_priv == NULL) {
3930 const char *pos;
3931 pos = driver ? os_strchr(driver, ',') : NULL;
3932 if (pos) {
3933 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3934 "driver interface - try next driver wrapper");
3935 driver = pos + 1;
3936 goto next_driver;
3937 }
3938 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3939 "interface");
3940 return -1;
3941 }
3942 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3943 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3944 "driver_param '%s'", wpa_s->conf->driver_param);
3945 return -1;
3946 }
3947
3948 ifname = wpa_drv_get_ifname(wpa_s);
3949 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3950 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3951 "interface name with '%s'", ifname);
3952 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3953 }
3954
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003955 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003956 if (rn && rn[0] == '\0')
3957 rn = NULL;
3958
3959 wpa_s->radio = radio_add_interface(wpa_s, rn);
3960 if (wpa_s->radio == NULL)
3961 return -1;
3962
3963 return 0;
3964}
3965
3966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003967static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3968 struct wpa_interface *iface)
3969{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003970 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003971 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003972
3973 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3974 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3975 iface->confname ? iface->confname : "N/A",
3976 iface->driver ? iface->driver : "default",
3977 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3978 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3979
3980 if (iface->confname) {
3981#ifdef CONFIG_BACKEND_FILE
3982 wpa_s->confname = os_rel2abs_path(iface->confname);
3983 if (wpa_s->confname == NULL) {
3984 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3985 "for configuration file '%s'.",
3986 iface->confname);
3987 return -1;
3988 }
3989 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3990 iface->confname, wpa_s->confname);
3991#else /* CONFIG_BACKEND_FILE */
3992 wpa_s->confname = os_strdup(iface->confname);
3993#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003994 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003995 if (wpa_s->conf == NULL) {
3996 wpa_printf(MSG_ERROR, "Failed to read or parse "
3997 "configuration '%s'.", wpa_s->confname);
3998 return -1;
3999 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004000 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4001 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004002
4003 /*
4004 * Override ctrl_interface and driver_param if set on command
4005 * line.
4006 */
4007 if (iface->ctrl_interface) {
4008 os_free(wpa_s->conf->ctrl_interface);
4009 wpa_s->conf->ctrl_interface =
4010 os_strdup(iface->ctrl_interface);
4011 }
4012
4013 if (iface->driver_param) {
4014 os_free(wpa_s->conf->driver_param);
4015 wpa_s->conf->driver_param =
4016 os_strdup(iface->driver_param);
4017 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004018
4019 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4020 os_free(wpa_s->conf->ctrl_interface);
4021 wpa_s->conf->ctrl_interface = NULL;
4022 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004023 } else
4024 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4025 iface->driver_param);
4026
4027 if (wpa_s->conf == NULL) {
4028 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4029 return -1;
4030 }
4031
4032 if (iface->ifname == NULL) {
4033 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4034 return -1;
4035 }
4036 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4037 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4038 iface->ifname);
4039 return -1;
4040 }
4041 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4042
4043 if (iface->bridge_ifname) {
4044 if (os_strlen(iface->bridge_ifname) >=
4045 sizeof(wpa_s->bridge_ifname)) {
4046 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4047 "name '%s'.", iface->bridge_ifname);
4048 return -1;
4049 }
4050 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4051 sizeof(wpa_s->bridge_ifname));
4052 }
4053
4054 /* RSNA Supplicant Key Management - INITIALIZE */
4055 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4056 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4057
4058 /* Initialize driver interface and register driver event handler before
4059 * L2 receive handler so that association events are processed before
4060 * EAPOL-Key packets if both become available for the same select()
4061 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004062 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004063 return -1;
4064
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004065 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4066 return -1;
4067
4068 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4069 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4070 NULL);
4071 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4072
4073 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4074 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4075 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4076 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4077 "dot11RSNAConfigPMKLifetime");
4078 return -1;
4079 }
4080
4081 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4082 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4083 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4084 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4085 "dot11RSNAConfigPMKReauthThreshold");
4086 return -1;
4087 }
4088
4089 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4090 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4091 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4092 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4093 "dot11RSNAConfigSATimeout");
4094 return -1;
4095 }
4096
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004097 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4098 &wpa_s->hw.num_modes,
4099 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004100 if (wpa_s->hw.modes) {
4101 u16 i;
4102
4103 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4104 if (wpa_s->hw.modes[i].vht_capab) {
4105 wpa_s->hw_capab = CAPAB_VHT;
4106 break;
4107 }
4108
4109 if (wpa_s->hw.modes[i].ht_capab &
4110 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4111 wpa_s->hw_capab = CAPAB_HT40;
4112 else if (wpa_s->hw.modes[i].ht_capab &&
4113 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4114 wpa_s->hw_capab = CAPAB_HT;
4115 }
4116 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004117
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004118 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4119 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004120 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004121 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004122 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004123 wpa_s->drv_smps_modes = capa.smps_modes;
4124 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004125 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004127 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
4128 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4129 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004130 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4131 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004132 wpa_s->extended_capa = capa.extended_capa;
4133 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4134 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004135 wpa_s->num_multichan_concurrent =
4136 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004137 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4138
4139 if (capa.mac_addr_rand_scan_supported)
4140 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4141 if (wpa_s->sched_scan_supported &&
4142 capa.mac_addr_rand_sched_scan_supported)
4143 wpa_s->mac_addr_rand_supported |=
4144 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004145 }
4146 if (wpa_s->max_remain_on_chan == 0)
4147 wpa_s->max_remain_on_chan = 1000;
4148
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004149 /*
4150 * Only take p2p_mgmt parameters when P2P Device is supported.
4151 * Doing it here as it determines whether l2_packet_init() will be done
4152 * during wpa_supplicant_driver_init().
4153 */
4154 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4155 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4156 else
4157 iface->p2p_mgmt = 1;
4158
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004159 if (wpa_s->num_multichan_concurrent == 0)
4160 wpa_s->num_multichan_concurrent = 1;
4161
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004162 if (wpa_supplicant_driver_init(wpa_s) < 0)
4163 return -1;
4164
4165#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004166 if ((!iface->p2p_mgmt ||
4167 !(wpa_s->drv_flags &
4168 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4169 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004170 return -1;
4171#endif /* CONFIG_TDLS */
4172
4173 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4174 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4175 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4176 return -1;
4177 }
4178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004179 if (wpas_wps_init(wpa_s))
4180 return -1;
4181
4182 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4183 return -1;
4184 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4185
4186 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4187 if (wpa_s->ctrl_iface == NULL) {
4188 wpa_printf(MSG_ERROR,
4189 "Failed to initialize control interface '%s'.\n"
4190 "You may have another wpa_supplicant process "
4191 "already running or the file was\n"
4192 "left by an unclean termination of wpa_supplicant "
4193 "in which case you will need\n"
4194 "to manually remove this file before starting "
4195 "wpa_supplicant again.\n",
4196 wpa_s->conf->ctrl_interface);
4197 return -1;
4198 }
4199
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004200 wpa_s->gas = gas_query_init(wpa_s);
4201 if (wpa_s->gas == NULL) {
4202 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4203 return -1;
4204 }
4205
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004206 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004207 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4208 return -1;
4209 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004210
4211 if (wpa_bss_init(wpa_s) < 0)
4212 return -1;
4213
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004214 /*
4215 * Set Wake-on-WLAN triggers, if configured.
4216 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4217 * have effect anyway when the interface is down).
4218 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004219 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004220 return -1;
4221
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004222#ifdef CONFIG_EAP_PROXY
4223{
4224 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004225 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4226 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004227 if (wpa_s->mnc_len > 0) {
4228 wpa_s->imsi[len] = '\0';
4229 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4230 wpa_s->imsi, wpa_s->mnc_len);
4231 } else {
4232 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4233 }
4234}
4235#endif /* CONFIG_EAP_PROXY */
4236
Dmitry Shmidt04949592012-07-19 12:16:46 -07004237 if (pcsc_reader_init(wpa_s) < 0)
4238 return -1;
4239
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004240 if (wpas_init_ext_pw(wpa_s) < 0)
4241 return -1;
4242
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004243 wpas_rrm_reset(wpa_s);
4244
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004245 return 0;
4246}
4247
4248
4249static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004250 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004251{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004252 struct wpa_global *global = wpa_s->global;
4253 struct wpa_supplicant *iface, *prev;
4254
4255 if (wpa_s == wpa_s->parent)
4256 wpas_p2p_group_remove(wpa_s, "*");
4257
4258 iface = global->ifaces;
4259 while (iface) {
4260 if (iface == wpa_s || iface->parent != wpa_s) {
4261 iface = iface->next;
4262 continue;
4263 }
4264 wpa_printf(MSG_DEBUG,
4265 "Remove remaining child interface %s from parent %s",
4266 iface->ifname, wpa_s->ifname);
4267 prev = iface;
4268 iface = iface->next;
4269 wpa_supplicant_remove_iface(global, prev, terminate);
4270 }
4271
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004272 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004273 if (wpa_s->drv_priv) {
4274 wpa_supplicant_deauthenticate(wpa_s,
4275 WLAN_REASON_DEAUTH_LEAVING);
4276
4277 wpa_drv_set_countermeasures(wpa_s, 0);
4278 wpa_clear_keys(wpa_s, NULL);
4279 }
4280
4281 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004282 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004283
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004284 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004285 radio_remove_interface(wpa_s);
4286
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004287 if (wpa_s->drv_priv)
4288 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004289
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004290 if (notify)
4291 wpas_notify_iface_removed(wpa_s);
4292
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004293 if (terminate)
4294 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004295
4296 if (wpa_s->ctrl_iface) {
4297 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
4298 wpa_s->ctrl_iface = NULL;
4299 }
4300
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004301#ifdef CONFIG_MESH
4302 if (wpa_s->ifmsh) {
4303 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
4304 wpa_s->ifmsh = NULL;
4305 }
4306#endif /* CONFIG_MESH */
4307
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004308 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004309 wpa_config_free(wpa_s->conf);
4310 wpa_s->conf = NULL;
4311 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004312
4313 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004314}
4315
4316
4317/**
4318 * wpa_supplicant_add_iface - Add a new network interface
4319 * @global: Pointer to global data from wpa_supplicant_init()
4320 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004321 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004322 * Returns: Pointer to the created interface or %NULL on failure
4323 *
4324 * This function is used to add new network interfaces for %wpa_supplicant.
4325 * This can be called before wpa_supplicant_run() to add interfaces before the
4326 * main event loop has been started. In addition, new interfaces can be added
4327 * dynamically while %wpa_supplicant is already running. This could happen,
4328 * e.g., when a hotplug network adapter is inserted.
4329 */
4330struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004331 struct wpa_interface *iface,
4332 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004333{
4334 struct wpa_supplicant *wpa_s;
4335 struct wpa_interface t_iface;
4336 struct wpa_ssid *ssid;
4337
4338 if (global == NULL || iface == NULL)
4339 return NULL;
4340
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004341 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004342 if (wpa_s == NULL)
4343 return NULL;
4344
4345 wpa_s->global = global;
4346
4347 t_iface = *iface;
4348 if (global->params.override_driver) {
4349 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
4350 "('%s' -> '%s')",
4351 iface->driver, global->params.override_driver);
4352 t_iface.driver = global->params.override_driver;
4353 }
4354 if (global->params.override_ctrl_interface) {
4355 wpa_printf(MSG_DEBUG, "Override interface parameter: "
4356 "ctrl_interface ('%s' -> '%s')",
4357 iface->ctrl_interface,
4358 global->params.override_ctrl_interface);
4359 t_iface.ctrl_interface =
4360 global->params.override_ctrl_interface;
4361 }
4362 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
4363 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
4364 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004365 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004366 return NULL;
4367 }
4368
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004369 if (iface->p2p_mgmt == 0) {
4370 /* Notify the control interfaces about new iface */
4371 if (wpas_notify_iface_added(wpa_s)) {
4372 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
4373 return NULL;
4374 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004375
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004376 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4377 wpas_notify_network_added(wpa_s, ssid);
4378 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004379
4380 wpa_s->next = global->ifaces;
4381 global->ifaces = wpa_s;
4382
4383 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004384 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004385
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004386#ifdef CONFIG_P2P
4387 if (wpa_s->global->p2p == NULL &&
4388 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
4389 wpas_p2p_add_p2pdev_interface(wpa_s, iface->conf_p2p_dev) < 0) {
4390 wpa_printf(MSG_INFO,
4391 "P2P: Failed to enable P2P Device interface");
4392 /* Try to continue without. P2P will be disabled. */
4393 }
4394#endif /* CONFIG_P2P */
4395
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004396 return wpa_s;
4397}
4398
4399
4400/**
4401 * wpa_supplicant_remove_iface - Remove a network interface
4402 * @global: Pointer to global data from wpa_supplicant_init()
4403 * @wpa_s: Pointer to the network interface to be removed
4404 * Returns: 0 if interface was removed, -1 if interface was not found
4405 *
4406 * This function can be used to dynamically remove network interfaces from
4407 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
4408 * addition, this function is used to remove all remaining interfaces when
4409 * %wpa_supplicant is terminated.
4410 */
4411int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004412 struct wpa_supplicant *wpa_s,
4413 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004414{
4415 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004416#ifdef CONFIG_MESH
4417 unsigned int mesh_if_created = wpa_s->mesh_if_created;
4418 char *ifname = NULL;
4419#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004420
4421 /* Remove interface from the global list of interfaces */
4422 prev = global->ifaces;
4423 if (prev == wpa_s) {
4424 global->ifaces = wpa_s->next;
4425 } else {
4426 while (prev && prev->next != wpa_s)
4427 prev = prev->next;
4428 if (prev == NULL)
4429 return -1;
4430 prev->next = wpa_s->next;
4431 }
4432
4433 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
4434
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004435#ifdef CONFIG_MESH
4436 if (mesh_if_created) {
4437 ifname = os_strdup(wpa_s->ifname);
4438 if (ifname == NULL) {
4439 wpa_dbg(wpa_s, MSG_ERROR,
4440 "mesh: Failed to malloc ifname");
4441 return -1;
4442 }
4443 }
4444#endif /* CONFIG_MESH */
4445
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004446 if (global->p2p_group_formation == wpa_s)
4447 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004448 if (global->p2p_invite_group == wpa_s)
4449 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004450 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004451
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004452#ifdef CONFIG_MESH
4453 if (mesh_if_created) {
4454 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
4455 os_free(ifname);
4456 }
4457#endif /* CONFIG_MESH */
4458
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004459 return 0;
4460}
4461
4462
4463/**
4464 * wpa_supplicant_get_eap_mode - Get the current EAP mode
4465 * @wpa_s: Pointer to the network interface
4466 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
4467 */
4468const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
4469{
4470 const char *eapol_method;
4471
4472 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
4473 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4474 return "NO-EAP";
4475 }
4476
4477 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
4478 if (eapol_method == NULL)
4479 return "UNKNOWN-EAP";
4480
4481 return eapol_method;
4482}
4483
4484
4485/**
4486 * wpa_supplicant_get_iface - Get a new network interface
4487 * @global: Pointer to global data from wpa_supplicant_init()
4488 * @ifname: Interface name
4489 * Returns: Pointer to the interface or %NULL if not found
4490 */
4491struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4492 const char *ifname)
4493{
4494 struct wpa_supplicant *wpa_s;
4495
4496 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4497 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4498 return wpa_s;
4499 }
4500 return NULL;
4501}
4502
4503
4504#ifndef CONFIG_NO_WPA_MSG
4505static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4506{
4507 struct wpa_supplicant *wpa_s = ctx;
4508 if (wpa_s == NULL)
4509 return NULL;
4510 return wpa_s->ifname;
4511}
4512#endif /* CONFIG_NO_WPA_MSG */
4513
4514
4515/**
4516 * wpa_supplicant_init - Initialize %wpa_supplicant
4517 * @params: Parameters for %wpa_supplicant
4518 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4519 *
4520 * This function is used to initialize %wpa_supplicant. After successful
4521 * initialization, the returned data pointer can be used to add and remove
4522 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4523 */
4524struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4525{
4526 struct wpa_global *global;
4527 int ret, i;
4528
4529 if (params == NULL)
4530 return NULL;
4531
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004532#ifdef CONFIG_DRIVER_NDIS
4533 {
4534 void driver_ndis_init_ops(void);
4535 driver_ndis_init_ops();
4536 }
4537#endif /* CONFIG_DRIVER_NDIS */
4538
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004539#ifndef CONFIG_NO_WPA_MSG
4540 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4541#endif /* CONFIG_NO_WPA_MSG */
4542
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004543 if (params->wpa_debug_file_path)
4544 wpa_debug_open_file(params->wpa_debug_file_path);
4545 else
4546 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004547 if (params->wpa_debug_syslog)
4548 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004549 if (params->wpa_debug_tracing) {
4550 ret = wpa_debug_open_linux_tracing();
4551 if (ret) {
4552 wpa_printf(MSG_ERROR,
4553 "Failed to enable trace logging");
4554 return NULL;
4555 }
4556 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557
4558 ret = eap_register_methods();
4559 if (ret) {
4560 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4561 if (ret == -2)
4562 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4563 "the same EAP type.");
4564 return NULL;
4565 }
4566
4567 global = os_zalloc(sizeof(*global));
4568 if (global == NULL)
4569 return NULL;
4570 dl_list_init(&global->p2p_srv_bonjour);
4571 dl_list_init(&global->p2p_srv_upnp);
4572 global->params.daemonize = params->daemonize;
4573 global->params.wait_for_monitor = params->wait_for_monitor;
4574 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4575 if (params->pid_file)
4576 global->params.pid_file = os_strdup(params->pid_file);
4577 if (params->ctrl_interface)
4578 global->params.ctrl_interface =
4579 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004580 if (params->ctrl_interface_group)
4581 global->params.ctrl_interface_group =
4582 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004583 if (params->override_driver)
4584 global->params.override_driver =
4585 os_strdup(params->override_driver);
4586 if (params->override_ctrl_interface)
4587 global->params.override_ctrl_interface =
4588 os_strdup(params->override_ctrl_interface);
4589 wpa_debug_level = global->params.wpa_debug_level =
4590 params->wpa_debug_level;
4591 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4592 params->wpa_debug_show_keys;
4593 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4594 params->wpa_debug_timestamp;
4595
4596 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4597
4598 if (eloop_init()) {
4599 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4600 wpa_supplicant_deinit(global);
4601 return NULL;
4602 }
4603
Jouni Malinen75ecf522011-06-27 15:19:46 -07004604 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004605
4606 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4607 if (global->ctrl_iface == NULL) {
4608 wpa_supplicant_deinit(global);
4609 return NULL;
4610 }
4611
4612 if (wpas_notify_supplicant_initialized(global)) {
4613 wpa_supplicant_deinit(global);
4614 return NULL;
4615 }
4616
4617 for (i = 0; wpa_drivers[i]; i++)
4618 global->drv_count++;
4619 if (global->drv_count == 0) {
4620 wpa_printf(MSG_ERROR, "No drivers enabled");
4621 wpa_supplicant_deinit(global);
4622 return NULL;
4623 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004624 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004625 if (global->drv_priv == NULL) {
4626 wpa_supplicant_deinit(global);
4627 return NULL;
4628 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004629
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004630#ifdef CONFIG_WIFI_DISPLAY
4631 if (wifi_display_init(global) < 0) {
4632 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4633 wpa_supplicant_deinit(global);
4634 return NULL;
4635 }
4636#endif /* CONFIG_WIFI_DISPLAY */
4637
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004638 return global;
4639}
4640
4641
4642/**
4643 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4644 * @global: Pointer to global data from wpa_supplicant_init()
4645 * Returns: 0 after successful event loop run, -1 on failure
4646 *
4647 * This function starts the main event loop and continues running as long as
4648 * there are any remaining events. In most cases, this function is running as
4649 * long as the %wpa_supplicant process in still in use.
4650 */
4651int wpa_supplicant_run(struct wpa_global *global)
4652{
4653 struct wpa_supplicant *wpa_s;
4654
4655 if (global->params.daemonize &&
4656 wpa_supplicant_daemon(global->params.pid_file))
4657 return -1;
4658
4659 if (global->params.wait_for_monitor) {
4660 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4661 if (wpa_s->ctrl_iface)
4662 wpa_supplicant_ctrl_iface_wait(
4663 wpa_s->ctrl_iface);
4664 }
4665
4666 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4667 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4668
4669 eloop_run();
4670
4671 return 0;
4672}
4673
4674
4675/**
4676 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4677 * @global: Pointer to global data from wpa_supplicant_init()
4678 *
4679 * This function is called to deinitialize %wpa_supplicant and to free all
4680 * allocated resources. Remaining network interfaces will also be removed.
4681 */
4682void wpa_supplicant_deinit(struct wpa_global *global)
4683{
4684 int i;
4685
4686 if (global == NULL)
4687 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004688
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004689#ifdef CONFIG_WIFI_DISPLAY
4690 wifi_display_deinit(global);
4691#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004692
4693 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004694 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004695
4696 if (global->ctrl_iface)
4697 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4698
4699 wpas_notify_supplicant_deinitialized(global);
4700
4701 eap_peer_unregister_methods();
4702#ifdef CONFIG_AP
4703 eap_server_unregister_methods();
4704#endif /* CONFIG_AP */
4705
4706 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4707 if (!global->drv_priv[i])
4708 continue;
4709 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4710 }
4711 os_free(global->drv_priv);
4712
4713 random_deinit();
4714
4715 eloop_destroy();
4716
4717 if (global->params.pid_file) {
4718 os_daemonize_terminate(global->params.pid_file);
4719 os_free(global->params.pid_file);
4720 }
4721 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004722 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004723 os_free(global->params.override_driver);
4724 os_free(global->params.override_ctrl_interface);
4725
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004726 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004727 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004728 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004729
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004730 os_free(global);
4731 wpa_debug_close_syslog();
4732 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004733 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004734}
4735
4736
4737void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4738{
4739 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4740 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4741 char country[3];
4742 country[0] = wpa_s->conf->country[0];
4743 country[1] = wpa_s->conf->country[1];
4744 country[2] = '\0';
4745 if (wpa_drv_set_country(wpa_s, country) < 0) {
4746 wpa_printf(MSG_ERROR, "Failed to set country code "
4747 "'%s'", country);
4748 }
4749 }
4750
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004751 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4752 wpas_init_ext_pw(wpa_s);
4753
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004754#ifdef CONFIG_WPS
4755 wpas_wps_update_config(wpa_s);
4756#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004757 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004758 wpa_s->conf->changed_parameters = 0;
4759}
4760
4761
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004762void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004763{
4764 int i;
4765
4766 for (i = 0; i < *num_freqs; i++) {
4767 if (freqs[i] == freq)
4768 return;
4769 }
4770
4771 freqs[*num_freqs] = freq;
4772 (*num_freqs)++;
4773}
4774
4775
4776static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4777{
4778 struct wpa_bss *bss, *cbss;
4779 const int max_freqs = 10;
4780 int *freqs;
4781 int num_freqs = 0;
4782
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004783 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004784 if (freqs == NULL)
4785 return NULL;
4786
4787 cbss = wpa_s->current_bss;
4788
4789 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4790 if (bss == cbss)
4791 continue;
4792 if (bss->ssid_len == cbss->ssid_len &&
4793 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4794 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4795 add_freq(freqs, &num_freqs, bss->freq);
4796 if (num_freqs == max_freqs)
4797 break;
4798 }
4799 }
4800
4801 if (num_freqs == 0) {
4802 os_free(freqs);
4803 freqs = NULL;
4804 }
4805
4806 return freqs;
4807}
4808
4809
4810void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4811{
4812 int timeout;
4813 int count;
4814 int *freqs = NULL;
4815
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004816 wpas_connect_work_done(wpa_s);
4817
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004818 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004819 * Remove possible authentication timeout since the connection failed.
4820 */
4821 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4822
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004823 /*
4824 * There is no point in blacklisting the AP if this event is
4825 * generated based on local request to disconnect.
4826 */
4827 if (wpa_s->own_disconnect_req) {
4828 wpa_s->own_disconnect_req = 0;
4829 wpa_dbg(wpa_s, MSG_DEBUG,
4830 "Ignore connection failure due to local request to disconnect");
4831 return;
4832 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004833 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004834 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4835 "indication since interface has been put into "
4836 "disconnected state");
4837 return;
4838 }
4839
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004840 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004841 * Add the failed BSSID into the blacklist and speed up next scan
4842 * attempt if there could be other APs that could accept association.
4843 * The current blacklist count indicates how many times we have tried
4844 * connecting to this AP and multiple attempts mean that other APs are
4845 * either not available or has already been tried, so that we can start
4846 * increasing the delay here to avoid constant scanning.
4847 */
4848 count = wpa_blacklist_add(wpa_s, bssid);
4849 if (count == 1 && wpa_s->current_bss) {
4850 /*
4851 * This BSS was not in the blacklist before. If there is
4852 * another BSS available for the same ESS, we should try that
4853 * next. Otherwise, we may as well try this one once more
4854 * before allowing other, likely worse, ESSes to be considered.
4855 */
4856 freqs = get_bss_freqs_in_ess(wpa_s);
4857 if (freqs) {
4858 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4859 "has been seen; try it next");
4860 wpa_blacklist_add(wpa_s, bssid);
4861 /*
4862 * On the next scan, go through only the known channels
4863 * used in this ESS based on previous scans to speed up
4864 * common load balancing use case.
4865 */
4866 os_free(wpa_s->next_scan_freqs);
4867 wpa_s->next_scan_freqs = freqs;
4868 }
4869 }
4870
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004871 /*
4872 * Add previous failure count in case the temporary blacklist was
4873 * cleared due to no other BSSes being available.
4874 */
4875 count += wpa_s->extra_blacklist_count;
4876
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004877 if (count > 3 && wpa_s->current_ssid) {
4878 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4879 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004880 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004881 }
4882
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004883 switch (count) {
4884 case 1:
4885 timeout = 100;
4886 break;
4887 case 2:
4888 timeout = 500;
4889 break;
4890 case 3:
4891 timeout = 1000;
4892 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004893 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004894 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004895 break;
4896 default:
4897 timeout = 10000;
4898 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004899 }
4900
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004901 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4902 "ms", count, timeout);
4903
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004904 /*
4905 * TODO: if more than one possible AP is available in scan results,
4906 * could try the other ones before requesting a new scan.
4907 */
4908 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4909 1000 * (timeout % 1000));
4910}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004911
4912
4913int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4914{
4915 return wpa_s->conf->ap_scan == 2 ||
4916 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4917}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004918
Dmitry Shmidt04949592012-07-19 12:16:46 -07004919
4920#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4921int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4922 struct wpa_ssid *ssid,
4923 const char *field,
4924 const char *value)
4925{
4926#ifdef IEEE8021X_EAPOL
4927 struct eap_peer_config *eap = &ssid->eap;
4928
4929 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4930 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4931 (const u8 *) value, os_strlen(value));
4932
4933 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4934 case WPA_CTRL_REQ_EAP_IDENTITY:
4935 os_free(eap->identity);
4936 eap->identity = (u8 *) os_strdup(value);
4937 eap->identity_len = os_strlen(value);
4938 eap->pending_req_identity = 0;
4939 if (ssid == wpa_s->current_ssid)
4940 wpa_s->reassociate = 1;
4941 break;
4942 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004943 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004944 eap->password = (u8 *) os_strdup(value);
4945 eap->password_len = os_strlen(value);
4946 eap->pending_req_password = 0;
4947 if (ssid == wpa_s->current_ssid)
4948 wpa_s->reassociate = 1;
4949 break;
4950 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004951 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004952 eap->new_password = (u8 *) os_strdup(value);
4953 eap->new_password_len = os_strlen(value);
4954 eap->pending_req_new_password = 0;
4955 if (ssid == wpa_s->current_ssid)
4956 wpa_s->reassociate = 1;
4957 break;
4958 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004959 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004960 eap->pin = os_strdup(value);
4961 eap->pending_req_pin = 0;
4962 if (ssid == wpa_s->current_ssid)
4963 wpa_s->reassociate = 1;
4964 break;
4965 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004966 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004967 eap->otp = (u8 *) os_strdup(value);
4968 eap->otp_len = os_strlen(value);
4969 os_free(eap->pending_req_otp);
4970 eap->pending_req_otp = NULL;
4971 eap->pending_req_otp_len = 0;
4972 break;
4973 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004974 str_clear_free(eap->private_key_passwd);
4975 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004976 eap->pending_req_passphrase = 0;
4977 if (ssid == wpa_s->current_ssid)
4978 wpa_s->reassociate = 1;
4979 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004980 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004981 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004982 eap->external_sim_resp = os_strdup(value);
4983 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07004984 case WPA_CTRL_REQ_PSK_PASSPHRASE:
4985 if (wpa_config_set(ssid, "psk", value, 0) < 0)
4986 return -1;
4987 ssid->mem_only_psk = 1;
4988 if (ssid->passphrase)
4989 wpa_config_update_psk(ssid);
4990 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
4991 wpa_supplicant_req_scan(wpa_s, 0, 0);
4992 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004993 default:
4994 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4995 return -1;
4996 }
4997
4998 return 0;
4999#else /* IEEE8021X_EAPOL */
5000 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5001 return -1;
5002#endif /* IEEE8021X_EAPOL */
5003}
5004#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
5005
5006
5007int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5008{
5009 int i;
5010 unsigned int drv_enc;
5011
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005012 if (wpa_s->p2p_mgmt)
5013 return 1; /* no normal network profiles on p2p_mgmt interface */
5014
Dmitry Shmidt04949592012-07-19 12:16:46 -07005015 if (ssid == NULL)
5016 return 1;
5017
5018 if (ssid->disabled)
5019 return 1;
5020
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005021 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005022 drv_enc = wpa_s->drv_enc;
5023 else
5024 drv_enc = (unsigned int) -1;
5025
5026 for (i = 0; i < NUM_WEP_KEYS; i++) {
5027 size_t len = ssid->wep_key_len[i];
5028 if (len == 0)
5029 continue;
5030 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5031 continue;
5032 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5033 continue;
5034 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5035 continue;
5036 return 1; /* invalid WEP key */
5037 }
5038
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005039 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005040 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5041 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005042 return 1;
5043
Dmitry Shmidt04949592012-07-19 12:16:46 -07005044 return 0;
5045}
5046
5047
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005048int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5049{
5050#ifdef CONFIG_IEEE80211W
5051 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
5052 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
5053 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
5054 /*
5055 * Driver does not support BIP -- ignore pmf=1 default
5056 * since the connection with PMF would fail and the
5057 * configuration does not require PMF to be enabled.
5058 */
5059 return NO_MGMT_FRAME_PROTECTION;
5060 }
5061
5062 return wpa_s->conf->pmf;
5063 }
5064
5065 return ssid->ieee80211w;
5066#else /* CONFIG_IEEE80211W */
5067 return NO_MGMT_FRAME_PROTECTION;
5068#endif /* CONFIG_IEEE80211W */
5069}
5070
5071
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005072int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005073{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005074 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005075 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005076 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005077 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005078 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005079}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005080
5081
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005082void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005083{
5084 struct wpa_ssid *ssid = wpa_s->current_ssid;
5085 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005086 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005087
5088 if (ssid == NULL) {
5089 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
5090 "SSID block");
5091 return;
5092 }
5093
5094 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
5095 return;
5096
5097 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005098
5099#ifdef CONFIG_P2P
5100 if (ssid->p2p_group &&
5101 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
5102 /*
5103 * Skip the wait time since there is a short timeout on the
5104 * connection to a P2P group.
5105 */
5106 return;
5107 }
5108#endif /* CONFIG_P2P */
5109
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005110 if (ssid->auth_failures > 50)
5111 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005112 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005113 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005114 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005115 dur = 90;
5116 else if (ssid->auth_failures > 3)
5117 dur = 60;
5118 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005119 dur = 30;
5120 else if (ssid->auth_failures > 1)
5121 dur = 20;
5122 else
5123 dur = 10;
5124
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005125 if (ssid->auth_failures > 1 &&
5126 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
5127 dur += os_random() % (ssid->auth_failures * 10);
5128
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005129 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005130 if (now.sec + dur <= ssid->disabled_until.sec)
5131 return;
5132
5133 ssid->disabled_until.sec = now.sec + dur;
5134
5135 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005136 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005137 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005138 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005139}
5140
5141
5142void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
5143 struct wpa_ssid *ssid, int clear_failures)
5144{
5145 if (ssid == NULL)
5146 return;
5147
5148 if (ssid->disabled_until.sec) {
5149 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
5150 "id=%d ssid=\"%s\"",
5151 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
5152 }
5153 ssid->disabled_until.sec = 0;
5154 ssid->disabled_until.usec = 0;
5155 if (clear_failures)
5156 ssid->auth_failures = 0;
5157}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005158
5159
5160int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
5161{
5162 size_t i;
5163
5164 if (wpa_s->disallow_aps_bssid == NULL)
5165 return 0;
5166
5167 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
5168 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
5169 bssid, ETH_ALEN) == 0)
5170 return 1;
5171 }
5172
5173 return 0;
5174}
5175
5176
5177int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
5178 size_t ssid_len)
5179{
5180 size_t i;
5181
5182 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
5183 return 0;
5184
5185 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
5186 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
5187 if (ssid_len == s->ssid_len &&
5188 os_memcmp(ssid, s->ssid, ssid_len) == 0)
5189 return 1;
5190 }
5191
5192 return 0;
5193}
5194
5195
5196/**
5197 * wpas_request_connection - Request a new connection
5198 * @wpa_s: Pointer to the network interface
5199 *
5200 * This function is used to request a new connection to be found. It will mark
5201 * the interface to allow reassociation and request a new scan to find a
5202 * suitable network to connect to.
5203 */
5204void wpas_request_connection(struct wpa_supplicant *wpa_s)
5205{
5206 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005207 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005208 wpa_supplicant_reinit_autoscan(wpa_s);
5209 wpa_s->extra_blacklist_count = 0;
5210 wpa_s->disconnected = 0;
5211 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005212
5213 if (wpa_supplicant_fast_associate(wpa_s) != 1)
5214 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005215 else
5216 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005217}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005218
5219
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005220void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
5221 struct wpa_used_freq_data *freqs_data,
5222 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005223{
5224 unsigned int i;
5225
5226 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
5227 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005228 for (i = 0; i < len; i++) {
5229 struct wpa_used_freq_data *cur = &freqs_data[i];
5230 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
5231 i, cur->freq, cur->flags);
5232 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005233}
5234
5235
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005236/*
5237 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005238 * are using the same radio as the current interface, and in addition, get
5239 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005240 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005241int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
5242 struct wpa_used_freq_data *freqs_data,
5243 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005244{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005245 struct wpa_supplicant *ifs;
5246 u8 bssid[ETH_ALEN];
5247 int freq;
5248 unsigned int idx = 0, i;
5249
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005250 wpa_dbg(wpa_s, MSG_DEBUG,
5251 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005252 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005253
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005254 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
5255 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005256 if (idx == len)
5257 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005258
5259 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
5260 continue;
5261
5262 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
5263 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
5264 freq = ifs->current_ssid->frequency;
5265 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
5266 freq = ifs->assoc_freq;
5267 else
5268 continue;
5269
5270 /* Hold only distinct freqs */
5271 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005272 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005273 break;
5274
5275 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005276 freqs_data[idx++].freq = freq;
5277
5278 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
5279 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
5280 WPA_FREQ_USED_BY_P2P_CLIENT :
5281 WPA_FREQ_USED_BY_INFRA_STATION;
5282 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005283 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005284
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005285 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005286 return idx;
5287}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005288
5289
5290/*
5291 * Find the operating frequencies of any of the virtual interfaces that
5292 * are using the same radio as the current interface.
5293 */
5294int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
5295 int *freq_array, unsigned int len)
5296{
5297 struct wpa_used_freq_data *freqs_data;
5298 int num, i;
5299
5300 os_memset(freq_array, 0, sizeof(int) * len);
5301
5302 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
5303 if (!freqs_data)
5304 return -1;
5305
5306 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
5307 for (i = 0; i < num; i++)
5308 freq_array[i] = freqs_data[i].freq;
5309
5310 os_free(freqs_data);
5311
5312 return num;
5313}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005314
5315
5316static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
5317{
5318 struct rrm_data *rrm = data;
5319
5320 if (!rrm->notify_neighbor_rep) {
5321 wpa_printf(MSG_ERROR,
5322 "RRM: Unexpected neighbor report timeout");
5323 return;
5324 }
5325
5326 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
5327 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
5328
5329 rrm->notify_neighbor_rep = NULL;
5330 rrm->neighbor_rep_cb_ctx = NULL;
5331}
5332
5333
5334/*
5335 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
5336 * @wpa_s: Pointer to wpa_supplicant
5337 */
5338void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
5339{
5340 wpa_s->rrm.rrm_used = 0;
5341
5342 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5343 NULL);
5344 if (wpa_s->rrm.notify_neighbor_rep)
5345 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
5346 wpa_s->rrm.next_neighbor_rep_token = 1;
5347}
5348
5349
5350/*
5351 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
5352 * @wpa_s: Pointer to wpa_supplicant
5353 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
5354 * @report_len: Length of neighbor report buffer
5355 */
5356void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
5357 const u8 *report, size_t report_len)
5358{
5359 struct wpabuf *neighbor_rep;
5360
5361 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
5362 if (report_len < 1)
5363 return;
5364
5365 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
5366 wpa_printf(MSG_DEBUG,
5367 "RRM: Discarding neighbor report with token %d (expected %d)",
5368 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
5369 return;
5370 }
5371
5372 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5373 NULL);
5374
5375 if (!wpa_s->rrm.notify_neighbor_rep) {
5376 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
5377 return;
5378 }
5379
5380 /* skipping the first byte, which is only an id (dialog token) */
5381 neighbor_rep = wpabuf_alloc(report_len - 1);
5382 if (neighbor_rep == NULL)
5383 return;
5384 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
5385 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
5386 report[0]);
5387 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
5388 neighbor_rep);
5389 wpa_s->rrm.notify_neighbor_rep = NULL;
5390 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
5391}
5392
5393
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005394#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
5395/* Workaround different, undefined for Windows, error codes used here */
5396#define ENOTCONN -1
5397#define EOPNOTSUPP -1
5398#define ECANCELED -1
5399#endif
5400
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005401/**
5402 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
5403 * @wpa_s: Pointer to wpa_supplicant
5404 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
5405 * is sent in the request.
5406 * @cb: Callback function to be called once the requested report arrives, or
5407 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
5408 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
5409 * the requester's responsibility to free it.
5410 * In the latter case NULL will be sent in 'neighbor_rep'.
5411 * @cb_ctx: Context value to send the callback function
5412 * Returns: 0 in case of success, negative error code otherwise
5413 *
5414 * In case there is a previous request which has not been answered yet, the
5415 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
5416 * Request must contain a callback function.
5417 */
5418int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
5419 const struct wpa_ssid *ssid,
5420 void (*cb)(void *ctx,
5421 struct wpabuf *neighbor_rep),
5422 void *cb_ctx)
5423{
5424 struct wpabuf *buf;
5425 const u8 *rrm_ie;
5426
5427 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
5428 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
5429 return -ENOTCONN;
5430 }
5431
5432 if (!wpa_s->rrm.rrm_used) {
5433 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
5434 return -EOPNOTSUPP;
5435 }
5436
5437 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
5438 WLAN_EID_RRM_ENABLED_CAPABILITIES);
5439 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
5440 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
5441 wpa_printf(MSG_DEBUG,
5442 "RRM: No network support for Neighbor Report.");
5443 return -EOPNOTSUPP;
5444 }
5445
5446 if (!cb) {
5447 wpa_printf(MSG_DEBUG,
5448 "RRM: Neighbor Report request must provide a callback.");
5449 return -EINVAL;
5450 }
5451
5452 /* Refuse if there's a live request */
5453 if (wpa_s->rrm.notify_neighbor_rep) {
5454 wpa_printf(MSG_DEBUG,
5455 "RRM: Currently handling previous Neighbor Report.");
5456 return -EBUSY;
5457 }
5458
5459 /* 3 = action category + action code + dialog token */
5460 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
5461 if (buf == NULL) {
5462 wpa_printf(MSG_DEBUG,
5463 "RRM: Failed to allocate Neighbor Report Request");
5464 return -ENOMEM;
5465 }
5466
5467 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
5468 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
5469 wpa_s->rrm.next_neighbor_rep_token);
5470
5471 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5472 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
5473 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
5474 if (ssid) {
5475 wpabuf_put_u8(buf, WLAN_EID_SSID);
5476 wpabuf_put_u8(buf, ssid->ssid_len);
5477 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
5478 }
5479
5480 wpa_s->rrm.next_neighbor_rep_token++;
5481
5482 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
5483 wpa_s->own_addr, wpa_s->bssid,
5484 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
5485 wpa_printf(MSG_DEBUG,
5486 "RRM: Failed to send Neighbor Report Request");
5487 wpabuf_free(buf);
5488 return -ECANCELED;
5489 }
5490
5491 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
5492 wpa_s->rrm.notify_neighbor_rep = cb;
5493 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
5494 wpas_rrm_neighbor_rep_timeout_handler,
5495 &wpa_s->rrm, NULL);
5496
5497 wpabuf_free(buf);
5498 return 0;
5499}
5500
5501
5502void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
5503 const u8 *src,
5504 const u8 *frame, size_t len,
5505 int rssi)
5506{
5507 struct wpabuf *buf;
5508 const struct rrm_link_measurement_request *req;
5509 struct rrm_link_measurement_report report;
5510
5511 if (wpa_s->wpa_state != WPA_COMPLETED) {
5512 wpa_printf(MSG_INFO,
5513 "RRM: Ignoring link measurement request. Not associated");
5514 return;
5515 }
5516
5517 if (!wpa_s->rrm.rrm_used) {
5518 wpa_printf(MSG_INFO,
5519 "RRM: Ignoring link measurement request. Not RRM network");
5520 return;
5521 }
5522
5523 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
5524 wpa_printf(MSG_INFO,
5525 "RRM: Measurement report failed. TX power insertion not supported");
5526 return;
5527 }
5528
5529 req = (const struct rrm_link_measurement_request *) frame;
5530 if (len < sizeof(*req)) {
5531 wpa_printf(MSG_INFO,
5532 "RRM: Link measurement report failed. Request too short");
5533 return;
5534 }
5535
5536 os_memset(&report, 0, sizeof(report));
5537 report.tpc.eid = WLAN_EID_TPC_REPORT;
5538 report.tpc.len = 2;
5539 report.rsni = 255; /* 255 indicates that RSNI is not available */
5540 report.dialog_token = req->dialog_token;
5541
5542 /*
5543 * It's possible to estimate RCPI based on RSSI in dBm. This
5544 * calculation will not reflect the correct value for high rates,
5545 * but it's good enough for Action frames which are transmitted
5546 * with up to 24 Mbps rates.
5547 */
5548 if (!rssi)
5549 report.rcpi = 255; /* not available */
5550 else if (rssi < -110)
5551 report.rcpi = 0;
5552 else if (rssi > 0)
5553 report.rcpi = 220;
5554 else
5555 report.rcpi = (rssi + 110) * 2;
5556
5557 /* action_category + action_code */
5558 buf = wpabuf_alloc(2 + sizeof(report));
5559 if (buf == NULL) {
5560 wpa_printf(MSG_ERROR,
5561 "RRM: Link measurement report failed. Buffer allocation failed");
5562 return;
5563 }
5564
5565 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5566 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
5567 wpabuf_put_data(buf, &report, sizeof(report));
5568 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
5569 wpabuf_head(buf), wpabuf_len(buf));
5570
5571 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
5572 wpa_s->own_addr, wpa_s->bssid,
5573 wpabuf_head(buf), wpabuf_len(buf), 0)) {
5574 wpa_printf(MSG_ERROR,
5575 "RRM: Link measurement report failed. Send action failed");
5576 }
5577 wpabuf_free(buf);
5578}