blob: 19fb8900bd756620321adeb398bc6db1e2403bef [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
459 wpas_wps_deinit(wpa_s);
460
461 wpabuf_free(wpa_s->pending_eapol_rx);
462 wpa_s->pending_eapol_rx = NULL;
463
464#ifdef CONFIG_IBSS_RSN
465 ibss_rsn_deinit(wpa_s->ibss_rsn);
466 wpa_s->ibss_rsn = NULL;
467#endif /* CONFIG_IBSS_RSN */
468
469 sme_deinit(wpa_s);
470
471#ifdef CONFIG_AP
472 wpa_supplicant_ap_deinit(wpa_s);
473#endif /* CONFIG_AP */
474
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700475 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700476
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800477#ifdef CONFIG_OFFCHANNEL
478 offchannel_deinit(wpa_s);
479#endif /* CONFIG_OFFCHANNEL */
480
481 wpa_supplicant_cancel_sched_scan(wpa_s);
482
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700483 os_free(wpa_s->next_scan_freqs);
484 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800485
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800486 os_free(wpa_s->manual_scan_freqs);
487 wpa_s->manual_scan_freqs = NULL;
488
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700489 os_free(wpa_s->manual_sched_scan_freqs);
490 wpa_s->manual_sched_scan_freqs = NULL;
491
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800492 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
493
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800494 gas_query_deinit(wpa_s->gas);
495 wpa_s->gas = NULL;
496
497 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700498
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700499 ieee802_1x_dealloc_kay_sm(wpa_s);
500
Dmitry Shmidt04949592012-07-19 12:16:46 -0700501 os_free(wpa_s->bssid_filter);
502 wpa_s->bssid_filter = NULL;
503
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800504 os_free(wpa_s->disallow_aps_bssid);
505 wpa_s->disallow_aps_bssid = NULL;
506 os_free(wpa_s->disallow_aps_ssid);
507 wpa_s->disallow_aps_ssid = NULL;
508
Dmitry Shmidt04949592012-07-19 12:16:46 -0700509 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700510#ifdef CONFIG_WNM
511 wnm_deallocate_memory(wpa_s);
512#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700513
514 ext_password_deinit(wpa_s->ext_pw);
515 wpa_s->ext_pw = NULL;
516
517 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800518 wpa_s->last_gas_resp = NULL;
519 wpabuf_free(wpa_s->prev_gas_resp);
520 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700521
522 os_free(wpa_s->last_scan_res);
523 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800524
525#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700526 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800527#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700528
529 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
530 wpabuf_free(wpa_s->vendor_elem[i]);
531 wpa_s->vendor_elem[i] = NULL;
532 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800533
534 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700535}
536
537
538/**
539 * wpa_clear_keys - Clear keys configured for the driver
540 * @wpa_s: Pointer to wpa_supplicant data
541 * @addr: Previously used BSSID or %NULL if not available
542 *
543 * This function clears the encryption keys that has been previously configured
544 * for the driver.
545 */
546void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
547{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800548 int i, max;
549
550#ifdef CONFIG_IEEE80211W
551 max = 6;
552#else /* CONFIG_IEEE80211W */
553 max = 4;
554#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700555
556 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800557 for (i = 0; i < max; i++) {
558 if (wpa_s->keys_cleared & BIT(i))
559 continue;
560 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
561 NULL, 0);
562 }
563 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
564 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700565 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
566 0);
567 /* MLME-SETPROTECTION.request(None) */
568 wpa_drv_mlme_setprotection(
569 wpa_s, addr,
570 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
571 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
572 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800573 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700574}
575
576
577/**
578 * wpa_supplicant_state_txt - Get the connection state name as a text string
579 * @state: State (wpa_state; WPA_*)
580 * Returns: The state name as a printable text string
581 */
582const char * wpa_supplicant_state_txt(enum wpa_states state)
583{
584 switch (state) {
585 case WPA_DISCONNECTED:
586 return "DISCONNECTED";
587 case WPA_INACTIVE:
588 return "INACTIVE";
589 case WPA_INTERFACE_DISABLED:
590 return "INTERFACE_DISABLED";
591 case WPA_SCANNING:
592 return "SCANNING";
593 case WPA_AUTHENTICATING:
594 return "AUTHENTICATING";
595 case WPA_ASSOCIATING:
596 return "ASSOCIATING";
597 case WPA_ASSOCIATED:
598 return "ASSOCIATED";
599 case WPA_4WAY_HANDSHAKE:
600 return "4WAY_HANDSHAKE";
601 case WPA_GROUP_HANDSHAKE:
602 return "GROUP_HANDSHAKE";
603 case WPA_COMPLETED:
604 return "COMPLETED";
605 default:
606 return "UNKNOWN";
607 }
608}
609
610
611#ifdef CONFIG_BGSCAN
612
613static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
614{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800615 const char *name;
616
617 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
618 name = wpa_s->current_ssid->bgscan;
619 else
620 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800621 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800622 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800623 if (wpas_driver_bss_selection(wpa_s))
624 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700625 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
626 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800627#ifdef CONFIG_P2P
628 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
629 return;
630#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700631
632 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800633 if (wpa_s->current_ssid) {
634 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700635 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
636 "bgscan");
637 /*
638 * Live without bgscan; it is only used as a roaming
639 * optimization, so the initial connection is not
640 * affected.
641 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700642 } else {
643 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700644 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700645 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
646 0);
647 if (scan_res) {
648 bgscan_notify_scan(wpa_s, scan_res);
649 wpa_scan_results_free(scan_res);
650 }
651 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700652 } else
653 wpa_s->bgscan_ssid = NULL;
654}
655
656
657static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
658{
659 if (wpa_s->bgscan_ssid != NULL) {
660 bgscan_deinit(wpa_s);
661 wpa_s->bgscan_ssid = NULL;
662 }
663}
664
665#endif /* CONFIG_BGSCAN */
666
667
Dmitry Shmidt04949592012-07-19 12:16:46 -0700668static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
669{
670 if (autoscan_init(wpa_s, 0))
671 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
672}
673
674
675static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
676{
677 autoscan_deinit(wpa_s);
678}
679
680
681void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
682{
683 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
684 wpa_s->wpa_state == WPA_SCANNING) {
685 autoscan_deinit(wpa_s);
686 wpa_supplicant_start_autoscan(wpa_s);
687 }
688}
689
690
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691/**
692 * wpa_supplicant_set_state - Set current connection state
693 * @wpa_s: Pointer to wpa_supplicant data
694 * @state: The new connection state
695 *
696 * This function is called whenever the connection state changes, e.g.,
697 * association is completed for WPA/WPA2 4-Way Handshake is started.
698 */
699void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
700 enum wpa_states state)
701{
702 enum wpa_states old_state = wpa_s->wpa_state;
703
704 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
705 wpa_supplicant_state_txt(wpa_s->wpa_state),
706 wpa_supplicant_state_txt(state));
707
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800708 if (state == WPA_INTERFACE_DISABLED) {
709 /* Assure normal scan when interface is restored */
710 wpa_s->normal_scans = 0;
711 }
712
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700713 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800714 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700715 /* Reinitialize normal_scan counter */
716 wpa_s->normal_scans = 0;
717 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800718
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700719 if (state != WPA_SCANNING)
720 wpa_supplicant_notify_scanning(wpa_s, 0);
721
722 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700723 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700724#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700725 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800726 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800727 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700728 ssid ? ssid->id : -1,
729 ssid && ssid->id_str ? ssid->id_str : "");
730#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700731 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800732 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700733 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734 wpa_drv_set_operstate(wpa_s, 1);
735#ifndef IEEE8021X_EAPOL
736 wpa_drv_set_supp_port(wpa_s, 1);
737#endif /* IEEE8021X_EAPOL */
738 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700739 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700741
742 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
744 state == WPA_ASSOCIATED) {
745 wpa_s->new_connection = 1;
746 wpa_drv_set_operstate(wpa_s, 0);
747#ifndef IEEE8021X_EAPOL
748 wpa_drv_set_supp_port(wpa_s, 0);
749#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700750 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700751 }
752 wpa_s->wpa_state = state;
753
754#ifdef CONFIG_BGSCAN
755 if (state == WPA_COMPLETED)
756 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800757 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700758 wpa_supplicant_stop_bgscan(wpa_s);
759#endif /* CONFIG_BGSCAN */
760
Dmitry Shmidt04949592012-07-19 12:16:46 -0700761 if (state == WPA_AUTHENTICATING)
762 wpa_supplicant_stop_autoscan(wpa_s);
763
764 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
765 wpa_supplicant_start_autoscan(wpa_s);
766
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800767 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
768 wmm_ac_notify_disassoc(wpa_s);
769
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700770 if (wpa_s->wpa_state != old_state) {
771 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
772
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700773 /*
774 * Notify the P2P Device interface about a state change in one
775 * of the interfaces.
776 */
777 wpas_p2p_indicate_state_change(wpa_s);
778
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779 if (wpa_s->wpa_state == WPA_COMPLETED ||
780 old_state == WPA_COMPLETED)
781 wpas_notify_auth_changed(wpa_s);
782 }
783}
784
785
786void wpa_supplicant_terminate_proc(struct wpa_global *global)
787{
788 int pending = 0;
789#ifdef CONFIG_WPS
790 struct wpa_supplicant *wpa_s = global->ifaces;
791 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800792 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700793 if (wpas_wps_terminate_pending(wpa_s) == 1)
794 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700795#ifdef CONFIG_P2P
796 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
797 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
798 wpas_p2p_disconnect(wpa_s);
799#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800800 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700801 }
802#endif /* CONFIG_WPS */
803 if (pending)
804 return;
805 eloop_terminate();
806}
807
808
809static void wpa_supplicant_terminate(int sig, void *signal_ctx)
810{
811 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700812 wpa_supplicant_terminate_proc(global);
813}
814
815
816void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
817{
818 enum wpa_states old_state = wpa_s->wpa_state;
819
820 wpa_s->pairwise_cipher = 0;
821 wpa_s->group_cipher = 0;
822 wpa_s->mgmt_group_cipher = 0;
823 wpa_s->key_mgmt = 0;
824 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700825 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700826
827 if (wpa_s->wpa_state != old_state)
828 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
829}
830
831
832/**
833 * wpa_supplicant_reload_configuration - Reload configuration data
834 * @wpa_s: Pointer to wpa_supplicant data
835 * Returns: 0 on success or -1 if configuration parsing failed
836 *
837 * This function can be used to request that the configuration data is reloaded
838 * (e.g., after configuration file change). This function is reloading
839 * configuration only for one interface, so this may need to be called multiple
840 * times if %wpa_supplicant is controlling multiple interfaces and all
841 * interfaces need reconfiguration.
842 */
843int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
844{
845 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700846 int reconf_ctrl;
847 int old_ap_scan;
848
849 if (wpa_s->confname == NULL)
850 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700851 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700852 if (conf == NULL) {
853 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
854 "file '%s' - exiting", wpa_s->confname);
855 return -1;
856 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700857 wpa_config_read(wpa_s->confanother, conf);
858
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700859 conf->changed_parameters = (unsigned int) -1;
860
861 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
862 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
863 os_strcmp(conf->ctrl_interface,
864 wpa_s->conf->ctrl_interface) != 0);
865
866 if (reconf_ctrl && wpa_s->ctrl_iface) {
867 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
868 wpa_s->ctrl_iface = NULL;
869 }
870
871 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800872 if (wpa_s->current_ssid) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -0800873 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800874 wpa_supplicant_deauthenticate(wpa_s,
875 WLAN_REASON_DEAUTH_LEAVING);
876 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700877
878 /*
879 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800880 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700881 */
882 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
883 /*
884 * Clear forced success to clear EAP state for next
885 * authentication.
886 */
887 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
888 }
889 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
890 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800891 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
893 rsn_preauth_deinit(wpa_s->wpa);
894
895 old_ap_scan = wpa_s->conf->ap_scan;
896 wpa_config_free(wpa_s->conf);
897 wpa_s->conf = conf;
898 if (old_ap_scan != wpa_s->conf->ap_scan)
899 wpas_notify_ap_scan_changed(wpa_s);
900
901 if (reconf_ctrl)
902 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
903
904 wpa_supplicant_update_config(wpa_s);
905
906 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700907 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700908 wpa_s->reassociate = 1;
909 wpa_supplicant_req_scan(wpa_s, 0, 0);
910 }
911 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
912 return 0;
913}
914
915
916static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
917{
918 struct wpa_global *global = signal_ctx;
919 struct wpa_supplicant *wpa_s;
920 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
921 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
922 sig);
923 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
924 wpa_supplicant_terminate_proc(global);
925 }
926 }
927}
928
929
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
931 struct wpa_ssid *ssid,
932 struct wpa_ie_data *ie)
933{
934 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
935 if (ret) {
936 if (ret == -2) {
937 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
938 "from association info");
939 }
940 return -1;
941 }
942
943 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
944 "cipher suites");
945 if (!(ie->group_cipher & ssid->group_cipher)) {
946 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
947 "cipher 0x%x (mask 0x%x) - reject",
948 ie->group_cipher, ssid->group_cipher);
949 return -1;
950 }
951 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
952 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
953 "cipher 0x%x (mask 0x%x) - reject",
954 ie->pairwise_cipher, ssid->pairwise_cipher);
955 return -1;
956 }
957 if (!(ie->key_mgmt & ssid->key_mgmt)) {
958 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
959 "management 0x%x (mask 0x%x) - reject",
960 ie->key_mgmt, ssid->key_mgmt);
961 return -1;
962 }
963
964#ifdef CONFIG_IEEE80211W
965 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800966 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700967 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
968 "that does not support management frame protection - "
969 "reject");
970 return -1;
971 }
972#endif /* CONFIG_IEEE80211W */
973
974 return 0;
975}
976
977
978/**
979 * wpa_supplicant_set_suites - Set authentication and encryption parameters
980 * @wpa_s: Pointer to wpa_supplicant data
981 * @bss: Scan results for the selected BSS, or %NULL if not available
982 * @ssid: Configuration data for the selected network
983 * @wpa_ie: Buffer for the WPA/RSN IE
984 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
985 * used buffer length in case the functions returns success.
986 * Returns: 0 on success or -1 on failure
987 *
988 * This function is used to configure authentication and encryption parameters
989 * based on the network configuration and scan result for the selected BSS (if
990 * available).
991 */
992int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
993 struct wpa_bss *bss, struct wpa_ssid *ssid,
994 u8 *wpa_ie, size_t *wpa_ie_len)
995{
996 struct wpa_ie_data ie;
997 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800998 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999
1000 if (bss) {
1001 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1002 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001003 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001004 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001005 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006
1007 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1008 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1009 (ie.group_cipher & ssid->group_cipher) &&
1010 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1011 (ie.key_mgmt & ssid->key_mgmt)) {
1012 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1013 proto = WPA_PROTO_RSN;
1014 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001015 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 (ie.group_cipher & ssid->group_cipher) &&
1017 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1018 (ie.key_mgmt & ssid->key_mgmt)) {
1019 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1020 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001021#ifdef CONFIG_HS20
1022 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1023 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1024 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001025 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001026 ie.group_cipher = WPA_CIPHER_CCMP;
1027 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1028 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1029 proto = WPA_PROTO_OSEN;
1030#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001031 } else if (bss) {
1032 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001033 wpa_dbg(wpa_s, MSG_DEBUG,
1034 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1035 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1036 ssid->key_mgmt);
1037 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1038 MAC2STR(bss->bssid),
1039 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1040 bss_wpa ? " WPA" : "",
1041 bss_rsn ? " RSN" : "",
1042 bss_osen ? " OSEN" : "");
1043 if (bss_rsn) {
1044 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1045 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1046 wpa_dbg(wpa_s, MSG_DEBUG,
1047 "Could not parse RSN element");
1048 } else {
1049 wpa_dbg(wpa_s, MSG_DEBUG,
1050 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1051 ie.pairwise_cipher, ie.group_cipher,
1052 ie.key_mgmt);
1053 }
1054 }
1055 if (bss_wpa) {
1056 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1057 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1058 wpa_dbg(wpa_s, MSG_DEBUG,
1059 "Could not parse WPA element");
1060 } else {
1061 wpa_dbg(wpa_s, MSG_DEBUG,
1062 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1063 ie.pairwise_cipher, ie.group_cipher,
1064 ie.key_mgmt);
1065 }
1066 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001067 return -1;
1068 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001069 if (ssid->proto & WPA_PROTO_OSEN)
1070 proto = WPA_PROTO_OSEN;
1071 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001072 proto = WPA_PROTO_RSN;
1073 else
1074 proto = WPA_PROTO_WPA;
1075 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1076 os_memset(&ie, 0, sizeof(ie));
1077 ie.group_cipher = ssid->group_cipher;
1078 ie.pairwise_cipher = ssid->pairwise_cipher;
1079 ie.key_mgmt = ssid->key_mgmt;
1080#ifdef CONFIG_IEEE80211W
1081 ie.mgmt_group_cipher =
1082 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1083 WPA_CIPHER_AES_128_CMAC : 0;
1084#endif /* CONFIG_IEEE80211W */
1085 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1086 "based on configuration");
1087 } else
1088 proto = ie.proto;
1089 }
1090
1091 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1092 "pairwise %d key_mgmt %d proto %d",
1093 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1094#ifdef CONFIG_IEEE80211W
1095 if (ssid->ieee80211w) {
1096 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1097 ie.mgmt_group_cipher);
1098 }
1099#endif /* CONFIG_IEEE80211W */
1100
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001101 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001102 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1103 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001104 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105
1106 if (bss || !wpa_s->ap_ies_from_associnfo) {
1107 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1108 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1109 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1110 bss_rsn ? 2 + bss_rsn[1] : 0))
1111 return -1;
1112 }
1113
1114 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001115 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1116 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1118 "cipher");
1119 return -1;
1120 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001121 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1122 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001123
1124 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001125 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1126 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001127 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1128 "cipher");
1129 return -1;
1130 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001131 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1132 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001133
1134 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001135#ifdef CONFIG_SAE
1136 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1137 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1138#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001140#ifdef CONFIG_SUITEB192
1141 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1142 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1143 wpa_dbg(wpa_s, MSG_DEBUG,
1144 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1145#endif /* CONFIG_SUITEB192 */
1146#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001147 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1148 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1149 wpa_dbg(wpa_s, MSG_DEBUG,
1150 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001151#endif /* CONFIG_SUITEB */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152#ifdef CONFIG_IEEE80211R
1153 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1154 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1155 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1156 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1157 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1158 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1159#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001160#ifdef CONFIG_SAE
1161 } else if (sel & WPA_KEY_MGMT_SAE) {
1162 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1163 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1164 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1165 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1166 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1167#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001168#ifdef CONFIG_IEEE80211W
1169 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1170 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1171 wpa_dbg(wpa_s, MSG_DEBUG,
1172 "WPA: using KEY_MGMT 802.1X with SHA256");
1173 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1174 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1175 wpa_dbg(wpa_s, MSG_DEBUG,
1176 "WPA: using KEY_MGMT PSK with SHA256");
1177#endif /* CONFIG_IEEE80211W */
1178 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1179 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1180 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1181 } else if (sel & WPA_KEY_MGMT_PSK) {
1182 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1183 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1184 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1185 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1186 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001187#ifdef CONFIG_HS20
1188 } else if (sel & WPA_KEY_MGMT_OSEN) {
1189 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1190 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1191#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001192 } else {
1193 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1194 "authenticated key management type");
1195 return -1;
1196 }
1197
1198 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1199 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1200 wpa_s->pairwise_cipher);
1201 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1202
1203#ifdef CONFIG_IEEE80211W
1204 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001205 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001206 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1207 sel = 0;
1208 if (sel & WPA_CIPHER_AES_128_CMAC) {
1209 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1210 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1211 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001212 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1213 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1214 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1215 "BIP-GMAC-128");
1216 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1217 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1218 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1219 "BIP-GMAC-256");
1220 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1221 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1222 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1223 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001224 } else {
1225 wpa_s->mgmt_group_cipher = 0;
1226 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1227 }
1228 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1229 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001230 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001231 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001232#endif /* CONFIG_IEEE80211W */
1233
1234 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1235 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1236 return -1;
1237 }
1238
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001239 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001240 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001241#ifndef CONFIG_NO_PBKDF2
1242 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1243 ssid->passphrase) {
1244 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001245 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1246 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001247 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1248 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001249 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
1250 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001251 }
1252#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001253#ifdef CONFIG_EXT_PASSWORD
1254 if (ssid->ext_psk) {
1255 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1256 ssid->ext_psk);
1257 char pw_str[64 + 1];
1258 u8 psk[PMK_LEN];
1259
1260 if (pw == NULL) {
1261 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1262 "found from external storage");
1263 return -1;
1264 }
1265
1266 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1267 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1268 "PSK length %d in external storage",
1269 (int) wpabuf_len(pw));
1270 ext_password_free(pw);
1271 return -1;
1272 }
1273
1274 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1275 pw_str[wpabuf_len(pw)] = '\0';
1276
1277#ifndef CONFIG_NO_PBKDF2
1278 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1279 {
1280 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1281 4096, psk, PMK_LEN);
1282 os_memset(pw_str, 0, sizeof(pw_str));
1283 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1284 "external passphrase)",
1285 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001286 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
1287 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001288 } else
1289#endif /* CONFIG_NO_PBKDF2 */
1290 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1291 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1292 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1293 "Invalid PSK hex string");
1294 os_memset(pw_str, 0, sizeof(pw_str));
1295 ext_password_free(pw);
1296 return -1;
1297 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001298 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
1299 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001300 } else {
1301 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1302 "PSK available");
1303 os_memset(pw_str, 0, sizeof(pw_str));
1304 ext_password_free(pw);
1305 return -1;
1306 }
1307
1308 os_memset(pw_str, 0, sizeof(pw_str));
1309 ext_password_free(pw);
1310 }
1311#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001312 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001313 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1314
1315 return 0;
1316}
1317
1318
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001319static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1320{
1321 *pos = 0x00;
1322
1323 switch (idx) {
1324 case 0: /* Bits 0-7 */
1325 break;
1326 case 1: /* Bits 8-15 */
1327 break;
1328 case 2: /* Bits 16-23 */
1329#ifdef CONFIG_WNM
1330 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1331 *pos |= 0x08; /* Bit 19 - BSS Transition */
1332#endif /* CONFIG_WNM */
1333 break;
1334 case 3: /* Bits 24-31 */
1335#ifdef CONFIG_WNM
1336 *pos |= 0x02; /* Bit 25 - SSID List */
1337#endif /* CONFIG_WNM */
1338#ifdef CONFIG_INTERWORKING
1339 if (wpa_s->conf->interworking)
1340 *pos |= 0x80; /* Bit 31 - Interworking */
1341#endif /* CONFIG_INTERWORKING */
1342 break;
1343 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001344#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001345 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1346 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001347#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001348 break;
1349 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001350#ifdef CONFIG_HS20
1351 if (wpa_s->conf->hs20)
1352 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1353#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001354 break;
1355 case 6: /* Bits 48-55 */
1356 break;
1357 }
1358}
1359
1360
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001361int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001362{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001363 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001364 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001365
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001366 if (len < wpa_s->extended_capa_len)
1367 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001368 if (buflen < (size_t) len + 2) {
1369 wpa_printf(MSG_INFO,
1370 "Not enough room for building extended capabilities element");
1371 return -1;
1372 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001373
1374 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001375 *pos++ = len;
1376 for (i = 0; i < len; i++, pos++) {
1377 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001378
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001379 if (i < wpa_s->extended_capa_len) {
1380 *pos &= ~wpa_s->extended_capa_mask[i];
1381 *pos |= wpa_s->extended_capa[i];
1382 }
1383 }
1384
1385 while (len > 0 && buf[1 + len] == 0) {
1386 len--;
1387 buf[1] = len;
1388 }
1389 if (len == 0)
1390 return 0;
1391
1392 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001393}
1394
1395
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001396static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1397 struct wpa_bss *test_bss)
1398{
1399 struct wpa_bss *bss;
1400
1401 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1402 if (bss == test_bss)
1403 return 1;
1404 }
1405
1406 return 0;
1407}
1408
1409
1410static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1411 struct wpa_ssid *test_ssid)
1412{
1413 struct wpa_ssid *ssid;
1414
1415 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1416 if (ssid == test_ssid)
1417 return 1;
1418 }
1419
1420 return 0;
1421}
1422
1423
1424int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1425 struct wpa_ssid *test_ssid)
1426{
1427 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1428 return 0;
1429
1430 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1431}
1432
1433
1434void wpas_connect_work_free(struct wpa_connect_work *cwork)
1435{
1436 if (cwork == NULL)
1437 return;
1438 os_free(cwork);
1439}
1440
1441
1442void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1443{
1444 struct wpa_connect_work *cwork;
1445 struct wpa_radio_work *work = wpa_s->connect_work;
1446
1447 if (!work)
1448 return;
1449
1450 wpa_s->connect_work = NULL;
1451 cwork = work->ctx;
1452 work->ctx = NULL;
1453 wpas_connect_work_free(cwork);
1454 radio_work_done(work);
1455}
1456
1457
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001458int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1459{
1460 struct os_reltime now;
1461 u8 addr[ETH_ALEN];
1462
1463 os_get_reltime(&now);
1464 if (wpa_s->last_mac_addr_style == style &&
1465 wpa_s->last_mac_addr_change.sec != 0 &&
1466 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1467 wpa_s->conf->rand_addr_lifetime)) {
1468 wpa_msg(wpa_s, MSG_DEBUG,
1469 "Previously selected random MAC address has not yet expired");
1470 return 0;
1471 }
1472
1473 switch (style) {
1474 case 1:
1475 if (random_mac_addr(addr) < 0)
1476 return -1;
1477 break;
1478 case 2:
1479 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1480 if (random_mac_addr_keep_oui(addr) < 0)
1481 return -1;
1482 break;
1483 default:
1484 return -1;
1485 }
1486
1487 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1488 wpa_msg(wpa_s, MSG_INFO,
1489 "Failed to set random MAC address");
1490 return -1;
1491 }
1492
1493 os_get_reltime(&wpa_s->last_mac_addr_change);
1494 wpa_s->mac_addr_changed = 1;
1495 wpa_s->last_mac_addr_style = style;
1496
1497 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1498 wpa_msg(wpa_s, MSG_INFO,
1499 "Could not update MAC address information");
1500 return -1;
1501 }
1502
1503 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1504 MAC2STR(addr));
1505
1506 return 0;
1507}
1508
1509
1510int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1511{
1512 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1513 !wpa_s->conf->preassoc_mac_addr)
1514 return 0;
1515
1516 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1517}
1518
1519
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001520static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001522/**
1523 * wpa_supplicant_associate - Request association
1524 * @wpa_s: Pointer to wpa_supplicant data
1525 * @bss: Scan results for the selected BSS, or %NULL if not available
1526 * @ssid: Configuration data for the selected network
1527 *
1528 * This function is used to request %wpa_supplicant to associate with a BSS.
1529 */
1530void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1531 struct wpa_bss *bss, struct wpa_ssid *ssid)
1532{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001533 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001534 int rand_style;
1535
1536 if (ssid->mac_addr == -1)
1537 rand_style = wpa_s->conf->mac_addr;
1538 else
1539 rand_style = ssid->mac_addr;
1540
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001541 wmm_ac_clear_saved_tspecs(wpa_s);
1542 wpa_s->reassoc_same_bss = 0;
1543
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001544 if (wpa_s->last_ssid == ssid) {
1545 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001546 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1547 wmm_ac_save_tspecs(wpa_s);
1548 wpa_s->reassoc_same_bss = 1;
1549 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001550 } else if (rand_style > 0) {
1551 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1552 return;
1553 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1554 } else if (wpa_s->mac_addr_changed) {
1555 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1556 wpa_msg(wpa_s, MSG_INFO,
1557 "Could not restore permanent MAC address");
1558 return;
1559 }
1560 wpa_s->mac_addr_changed = 0;
1561 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1562 wpa_msg(wpa_s, MSG_INFO,
1563 "Could not update MAC address information");
1564 return;
1565 }
1566 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1567 }
1568 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001569
1570#ifdef CONFIG_IBSS_RSN
1571 ibss_rsn_deinit(wpa_s->ibss_rsn);
1572 wpa_s->ibss_rsn = NULL;
1573#endif /* CONFIG_IBSS_RSN */
1574
1575 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1576 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1577#ifdef CONFIG_AP
1578 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1579 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1580 "mode");
1581 return;
1582 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001583 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1584 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001585 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1586 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001587 return;
1588 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001589 wpa_s->current_bss = bss;
1590#else /* CONFIG_AP */
1591 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1592 "the build");
1593#endif /* CONFIG_AP */
1594 return;
1595 }
1596
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001597 if (ssid->mode == WPAS_MODE_MESH) {
1598#ifdef CONFIG_MESH
1599 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1600 wpa_msg(wpa_s, MSG_INFO,
1601 "Driver does not support mesh mode");
1602 return;
1603 }
1604 if (bss)
1605 ssid->frequency = bss->freq;
1606 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1607 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1608 return;
1609 }
1610 wpa_s->current_bss = bss;
1611 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
1612 "ssid=\"%s\" id=%d",
1613 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1614 ssid->id);
1615#else /* CONFIG_MESH */
1616 wpa_msg(wpa_s, MSG_ERROR,
1617 "mesh mode support not included in the build");
1618#endif /* CONFIG_MESH */
1619 return;
1620 }
1621
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622#ifdef CONFIG_TDLS
1623 if (bss)
1624 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1625 bss->ie_len);
1626#endif /* CONFIG_TDLS */
1627
1628 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1629 ssid->mode == IEEE80211_MODE_INFRA) {
1630 sme_authenticate(wpa_s, bss, ssid);
1631 return;
1632 }
1633
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001634 if (wpa_s->connect_work) {
1635 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1636 return;
1637 }
1638
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001639 if (radio_work_pending(wpa_s, "connect")) {
1640 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1641 return;
1642 }
1643
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001644 cwork = os_zalloc(sizeof(*cwork));
1645 if (cwork == NULL)
1646 return;
1647
1648 cwork->bss = bss;
1649 cwork->ssid = ssid;
1650
1651 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1652 wpas_start_assoc_cb, cwork) < 0) {
1653 os_free(cwork);
1654 }
1655}
1656
1657
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001658static int bss_is_ibss(struct wpa_bss *bss)
1659{
1660 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1661 IEEE80211_CAP_IBSS;
1662}
1663
1664
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001665void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1666 const struct wpa_ssid *ssid,
1667 struct hostapd_freq_params *freq)
1668{
1669 enum hostapd_hw_mode hw_mode;
1670 struct hostapd_hw_modes *mode = NULL;
1671 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1672 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001673 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001674 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1675 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001676 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001677 unsigned int j;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001678 struct hostapd_freq_params vht_freq;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001679
1680 freq->freq = ssid->frequency;
1681
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001682 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1683 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1684
1685 if (ssid->mode != WPAS_MODE_IBSS)
1686 break;
1687
1688 /* Don't adjust control freq in case of fixed_freq */
1689 if (ssid->fixed_freq)
1690 break;
1691
1692 if (!bss_is_ibss(bss))
1693 continue;
1694
1695 if (ssid->ssid_len == bss->ssid_len &&
1696 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1697 wpa_printf(MSG_DEBUG,
1698 "IBSS already found in scan results, adjust control freq: %d",
1699 bss->freq);
1700 freq->freq = bss->freq;
1701 obss_scan = 0;
1702 break;
1703 }
1704 }
1705
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001706 /* For IBSS check HT_IBSS flag */
1707 if (ssid->mode == WPAS_MODE_IBSS &&
1708 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1709 return;
1710
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001711 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1712 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1713 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1714 wpa_printf(MSG_DEBUG,
1715 "IBSS: WEP/TKIP detected, do not try to enable HT");
1716 return;
1717 }
1718
1719 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001720 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1721 if (wpa_s->hw.modes[i].mode == hw_mode) {
1722 mode = &wpa_s->hw.modes[i];
1723 break;
1724 }
1725 }
1726
1727 if (!mode)
1728 return;
1729
1730 freq->ht_enabled = ht_supported(mode);
1731 if (!freq->ht_enabled)
1732 return;
1733
1734 /* Setup higher BW only for 5 GHz */
1735 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1736 return;
1737
1738 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1739 pri_chan = &mode->channels[chan_idx];
1740 if (pri_chan->chan == channel)
1741 break;
1742 pri_chan = NULL;
1743 }
1744 if (!pri_chan)
1745 return;
1746
1747 /* Check primary channel flags */
1748 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1749 return;
1750
1751 /* Check/setup HT40+/HT40- */
1752 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1753 if (ht40plus[j] == channel) {
1754 ht40 = 1;
1755 break;
1756 }
1757 }
1758
1759 /* Find secondary channel */
1760 for (i = 0; i < mode->num_channels; i++) {
1761 sec_chan = &mode->channels[i];
1762 if (sec_chan->chan == channel + ht40 * 4)
1763 break;
1764 sec_chan = NULL;
1765 }
1766 if (!sec_chan)
1767 return;
1768
1769 /* Check secondary channel flags */
1770 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1771 return;
1772
1773 freq->channel = pri_chan->chan;
1774
1775 switch (ht40) {
1776 case -1:
1777 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1778 return;
1779 freq->sec_channel_offset = -1;
1780 break;
1781 case 1:
1782 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1783 return;
1784 freq->sec_channel_offset = 1;
1785 break;
1786 default:
1787 break;
1788 }
1789
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001790 if (freq->sec_channel_offset && obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001791 struct wpa_scan_results *scan_res;
1792
1793 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1794 if (scan_res == NULL) {
1795 /* Back to HT20 */
1796 freq->sec_channel_offset = 0;
1797 return;
1798 }
1799
1800 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1801 sec_chan->chan);
1802 switch (res) {
1803 case 0:
1804 /* Back to HT20 */
1805 freq->sec_channel_offset = 0;
1806 break;
1807 case 1:
1808 /* Configuration allowed */
1809 break;
1810 case 2:
1811 /* Switch pri/sec channels */
1812 freq->freq = hw_get_freq(mode, sec_chan->chan);
1813 freq->sec_channel_offset = -freq->sec_channel_offset;
1814 freq->channel = sec_chan->chan;
1815 break;
1816 default:
1817 freq->sec_channel_offset = 0;
1818 break;
1819 }
1820
1821 wpa_scan_results_free(scan_res);
1822 }
1823
1824 wpa_printf(MSG_DEBUG,
1825 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
1826 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001827
1828 /* Not sure if mesh is ready for VHT */
1829 if (ssid->mode != WPAS_MODE_IBSS)
1830 return;
1831
1832 /* For IBSS check VHT_IBSS flag */
1833 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
1834 return;
1835
1836 vht_freq = *freq;
1837
1838 vht_freq.vht_enabled = vht_supported(mode);
1839 if (!vht_freq.vht_enabled)
1840 return;
1841
1842 /* setup center_freq1, bandwidth */
1843 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
1844 if (freq->channel >= vht80[j] &&
1845 freq->channel < vht80[j] + 16)
1846 break;
1847 }
1848
1849 if (j == ARRAY_SIZE(vht80))
1850 return;
1851
1852 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
1853 struct hostapd_channel_data *chan;
1854
1855 chan = hw_get_channel_chan(mode, i, NULL);
1856 if (!chan)
1857 return;
1858
1859 /* Back to HT configuration if channel not usable */
1860 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1861 return;
1862 }
1863
1864 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
1865 freq->channel, freq->ht_enabled,
1866 vht_freq.vht_enabled,
1867 freq->sec_channel_offset,
1868 VHT_CHANWIDTH_80MHZ,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08001869 vht80[j] + 6, 0, 0) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001870 return;
1871
1872 *freq = vht_freq;
1873
1874 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
1875 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001876}
1877
1878
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001879static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1880{
1881 struct wpa_connect_work *cwork = work->ctx;
1882 struct wpa_bss *bss = cwork->bss;
1883 struct wpa_ssid *ssid = cwork->ssid;
1884 struct wpa_supplicant *wpa_s = work->wpa_s;
1885 u8 wpa_ie[200];
1886 size_t wpa_ie_len;
1887 int use_crypt, ret, i, bssid_changed;
1888 int algs = WPA_AUTH_ALG_OPEN;
1889 unsigned int cipher_pairwise, cipher_group;
1890 struct wpa_driver_associate_params params;
1891 int wep_keys_set = 0;
1892 int assoc_failed = 0;
1893 struct wpa_ssid *old_ssid;
1894#ifdef CONFIG_HT_OVERRIDES
1895 struct ieee80211_ht_capabilities htcaps;
1896 struct ieee80211_ht_capabilities htcaps_mask;
1897#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001898#ifdef CONFIG_VHT_OVERRIDES
1899 struct ieee80211_vht_capabilities vhtcaps;
1900 struct ieee80211_vht_capabilities vhtcaps_mask;
1901#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001902
1903 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001904 if (work->started) {
1905 wpa_s->connect_work = NULL;
1906
1907 /* cancel possible auth. timeout */
1908 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1909 NULL);
1910 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001911 wpas_connect_work_free(cwork);
1912 return;
1913 }
1914
1915 wpa_s->connect_work = work;
1916
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001917 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001918 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1919 wpas_connect_work_done(wpa_s);
1920 return;
1921 }
1922
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923 os_memset(&params, 0, sizeof(params));
1924 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001925 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001926 if (bss &&
1927 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001928#ifdef CONFIG_IEEE80211R
1929 const u8 *ie, *md = NULL;
1930#endif /* CONFIG_IEEE80211R */
1931 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1932 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1933 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1934 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1935 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1936 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1937 if (bssid_changed)
1938 wpas_notify_bssid_changed(wpa_s);
1939#ifdef CONFIG_IEEE80211R
1940 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1941 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1942 md = ie + 2;
1943 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1944 if (md) {
1945 /* Prepare for the next transition */
1946 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1947 }
1948#endif /* CONFIG_IEEE80211R */
1949#ifdef CONFIG_WPS
1950 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1951 wpa_s->conf->ap_scan == 2 &&
1952 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1953 /* Use ap_scan==1 style network selection to find the network
1954 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001955 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001956 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001957 wpa_s->reassociate = 1;
1958 wpa_supplicant_req_scan(wpa_s, 0, 0);
1959 return;
1960#endif /* CONFIG_WPS */
1961 } else {
1962 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1963 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1964 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1965 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001966 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001967 wpa_supplicant_cancel_scan(wpa_s);
1968
1969 /* Starting new association, so clear the possibly used WPA IE from the
1970 * previous association. */
1971 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1972
1973#ifdef IEEE8021X_EAPOL
1974 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1975 if (ssid->leap) {
1976 if (ssid->non_leap == 0)
1977 algs = WPA_AUTH_ALG_LEAP;
1978 else
1979 algs |= WPA_AUTH_ALG_LEAP;
1980 }
1981 }
1982#endif /* IEEE8021X_EAPOL */
1983 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1984 if (ssid->auth_alg) {
1985 algs = ssid->auth_alg;
1986 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1987 "0x%x", algs);
1988 }
1989
1990 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1991 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001992 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001994 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1995 wpa_s->conf->okc :
1996 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001997 (ssid->proto & WPA_PROTO_RSN);
1998 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001999 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002000 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002001 wpa_ie_len = sizeof(wpa_ie);
2002 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2003 wpa_ie, &wpa_ie_len)) {
2004 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2005 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002006 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002007 return;
2008 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002009 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2010 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2011 /*
2012 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2013 * use non-WPA since the scan results did not indicate that the
2014 * AP is using WPA or WPA2.
2015 */
2016 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2017 wpa_ie_len = 0;
2018 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002019 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002020 wpa_ie_len = sizeof(wpa_ie);
2021 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2022 wpa_ie, &wpa_ie_len)) {
2023 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2024 "key management and encryption suites (no "
2025 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002026 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002027 return;
2028 }
2029#ifdef CONFIG_WPS
2030 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2031 struct wpabuf *wps_ie;
2032 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2033 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2034 wpa_ie_len = wpabuf_len(wps_ie);
2035 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2036 } else
2037 wpa_ie_len = 0;
2038 wpabuf_free(wps_ie);
2039 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2040 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2041 params.wps = WPS_MODE_PRIVACY;
2042 else
2043 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002044 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002045#endif /* CONFIG_WPS */
2046 } else {
2047 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2048 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002049 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050 }
2051
2052#ifdef CONFIG_P2P
2053 if (wpa_s->global->p2p) {
2054 u8 *pos;
2055 size_t len;
2056 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057 pos = wpa_ie + wpa_ie_len;
2058 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002059 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2060 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061 if (res >= 0)
2062 wpa_ie_len += res;
2063 }
2064
2065 wpa_s->cross_connect_disallowed = 0;
2066 if (bss) {
2067 struct wpabuf *p2p;
2068 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2069 if (p2p) {
2070 wpa_s->cross_connect_disallowed =
2071 p2p_get_cross_connect_disallowed(p2p);
2072 wpabuf_free(p2p);
2073 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2074 "connection",
2075 wpa_s->cross_connect_disallowed ?
2076 "disallows" : "allows");
2077 }
2078 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002079
2080 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002081#endif /* CONFIG_P2P */
2082
Dmitry Shmidt04949592012-07-19 12:16:46 -07002083#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002084 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002085 struct wpabuf *hs20;
2086 hs20 = wpabuf_alloc(20);
2087 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002088 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002089 size_t len;
2090
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002091 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002092 len = sizeof(wpa_ie) - wpa_ie_len;
2093 if (wpabuf_len(hs20) <= len) {
2094 os_memcpy(wpa_ie + wpa_ie_len,
2095 wpabuf_head(hs20), wpabuf_len(hs20));
2096 wpa_ie_len += wpabuf_len(hs20);
2097 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002098 wpabuf_free(hs20);
2099 }
2100 }
2101#endif /* CONFIG_HS20 */
2102
Dmitry Shmidt56052862013-10-04 10:23:25 -07002103 /*
2104 * Workaround: Add Extended Capabilities element only if the AP
2105 * included this element in Beacon/Probe Response frames. Some older
2106 * APs seem to have interoperability issues if this element is
2107 * included, so while the standard may require us to include the
2108 * element in all cases, it is justifiable to skip it to avoid
2109 * interoperability issues.
2110 */
2111 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002112 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002113 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002114 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2115 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002116 if (ext_capab_len > 0) {
2117 u8 *pos = wpa_ie;
2118 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2119 pos += 2 + pos[1];
2120 os_memmove(pos + ext_capab_len, pos,
2121 wpa_ie_len - (pos - wpa_ie));
2122 wpa_ie_len += ext_capab_len;
2123 os_memcpy(pos, ext_capab, ext_capab_len);
2124 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002125 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002126
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002127 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2128 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2129 size_t len;
2130
2131 len = sizeof(wpa_ie) - wpa_ie_len;
2132 if (wpabuf_len(buf) <= len) {
2133 os_memcpy(wpa_ie + wpa_ie_len,
2134 wpabuf_head(buf), wpabuf_len(buf));
2135 wpa_ie_len += wpabuf_len(buf);
2136 }
2137 }
2138
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002139 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2140 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002141 cipher_pairwise = wpa_s->pairwise_cipher;
2142 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002143 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2144 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2145 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2146 use_crypt = 0;
2147 if (wpa_set_wep_keys(wpa_s, ssid)) {
2148 use_crypt = 1;
2149 wep_keys_set = 1;
2150 }
2151 }
2152 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2153 use_crypt = 0;
2154
2155#ifdef IEEE8021X_EAPOL
2156 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2157 if ((ssid->eapol_flags &
2158 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2159 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2160 !wep_keys_set) {
2161 use_crypt = 0;
2162 } else {
2163 /* Assume that dynamic WEP-104 keys will be used and
2164 * set cipher suites in order for drivers to expect
2165 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002166 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002167 }
2168 }
2169#endif /* IEEE8021X_EAPOL */
2170
2171 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2172 /* Set the key before (and later after) association */
2173 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2174 }
2175
2176 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2177 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002178 params.ssid = bss->ssid;
2179 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002180 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
2181 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2182 MACSTR " freq=%u MHz based on scan results "
2183 "(bssid_set=%d)",
2184 MAC2STR(bss->bssid), bss->freq,
2185 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002186 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002187 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002188 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002189 params.bssid_hint = bss->bssid;
2190 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002191 } else {
2192 params.ssid = ssid->ssid;
2193 params.ssid_len = ssid->ssid_len;
2194 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002195
2196 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2197 wpa_s->conf->ap_scan == 2) {
2198 params.bssid = ssid->bssid;
2199 params.fixed_bssid = 1;
2200 }
2201
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002202 /* Initial frequency for IBSS/mesh */
2203 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002204 ssid->frequency > 0 && params.freq.freq == 0)
2205 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002206
2207 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002208 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002209 if (ssid->beacon_int)
2210 params.beacon_int = ssid->beacon_int;
2211 else
2212 params.beacon_int = wpa_s->conf->beacon_int;
2213 }
2214
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002215 params.wpa_ie = wpa_ie;
2216 params.wpa_ie_len = wpa_ie_len;
2217 params.pairwise_suite = cipher_pairwise;
2218 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002219 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002220 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221 params.auth_alg = algs;
2222 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002223 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002224 for (i = 0; i < NUM_WEP_KEYS; i++) {
2225 if (ssid->wep_key_len[i])
2226 params.wep_key[i] = ssid->wep_key[i];
2227 params.wep_key_len[i] = ssid->wep_key_len[i];
2228 }
2229 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2230
2231 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002232 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2233 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234 params.passphrase = ssid->passphrase;
2235 if (ssid->psk_set)
2236 params.psk = ssid->psk;
2237 }
2238
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002239 if (wpa_s->conf->key_mgmt_offload) {
2240 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2241 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002242 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2243 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002244 params.req_key_mgmt_offload =
2245 ssid->proactive_key_caching < 0 ?
2246 wpa_s->conf->okc : ssid->proactive_key_caching;
2247 else
2248 params.req_key_mgmt_offload = 1;
2249
2250 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2251 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2252 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2253 ssid->psk_set)
2254 params.psk = ssid->psk;
2255 }
2256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002257 params.drop_unencrypted = use_crypt;
2258
2259#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002260 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002261 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002262 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2263 struct wpa_ie_data ie;
2264 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2265 ie.capabilities &
2266 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2267 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2268 "MFP: require MFP");
2269 params.mgmt_frame_protection =
2270 MGMT_FRAME_PROTECTION_REQUIRED;
2271 }
2272 }
2273#endif /* CONFIG_IEEE80211W */
2274
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002275 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276
2277 if (wpa_s->parent->set_sta_uapsd)
2278 params.uapsd = wpa_s->parent->sta_uapsd;
2279 else
2280 params.uapsd = -1;
2281
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002282#ifdef CONFIG_HT_OVERRIDES
2283 os_memset(&htcaps, 0, sizeof(htcaps));
2284 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2285 params.htcaps = (u8 *) &htcaps;
2286 params.htcaps_mask = (u8 *) &htcaps_mask;
2287 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2288#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002289#ifdef CONFIG_VHT_OVERRIDES
2290 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2291 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2292 params.vhtcaps = &vhtcaps;
2293 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002294 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002295#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002296
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002297#ifdef CONFIG_P2P
2298 /*
2299 * If multi-channel concurrency is not supported, check for any
2300 * frequency conflict. In case of any frequency conflict, remove the
2301 * least prioritized connection.
2302 */
2303 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002304 int freq, num;
2305 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002306 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002307 wpa_printf(MSG_DEBUG,
2308 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002309 freq, params.freq.freq);
2310 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002311 wpa_s, params.freq.freq, ssid) < 0) {
2312 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002313 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002314 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002315 }
2316 }
2317#endif /* CONFIG_P2P */
2318
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002319 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002320 if (ret < 0) {
2321 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2322 "failed");
2323 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2324 /*
2325 * The driver is known to mean what is saying, so we
2326 * can stop right here; the association will not
2327 * succeed.
2328 */
2329 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002330 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002331 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2332 return;
2333 }
2334 /* try to continue anyway; new association will be tried again
2335 * after timeout */
2336 assoc_failed = 1;
2337 }
2338
2339 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2340 /* Set the key after the association just in case association
2341 * cleared the previously configured key. */
2342 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2343 /* No need to timeout authentication since there is no key
2344 * management. */
2345 wpa_supplicant_cancel_auth_timeout(wpa_s);
2346 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2347#ifdef CONFIG_IBSS_RSN
2348 } else if (ssid->mode == WPAS_MODE_IBSS &&
2349 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2350 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2351 /*
2352 * RSN IBSS authentication is per-STA and we can disable the
2353 * per-BSSID authentication.
2354 */
2355 wpa_supplicant_cancel_auth_timeout(wpa_s);
2356#endif /* CONFIG_IBSS_RSN */
2357 } else {
2358 /* Timeout for IEEE 802.11 authentication and association */
2359 int timeout = 60;
2360
2361 if (assoc_failed) {
2362 /* give IBSS a bit more time */
2363 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2364 } else if (wpa_s->conf->ap_scan == 1) {
2365 /* give IBSS a bit more time */
2366 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2367 }
2368 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2369 }
2370
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002371 if (wep_keys_set &&
2372 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373 /* Set static WEP keys again */
2374 wpa_set_wep_keys(wpa_s, ssid);
2375 }
2376
2377 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2378 /*
2379 * Do not allow EAP session resumption between different
2380 * network configurations.
2381 */
2382 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2383 }
2384 old_ssid = wpa_s->current_ssid;
2385 wpa_s->current_ssid = ssid;
2386 wpa_s->current_bss = bss;
2387 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2388 wpa_supplicant_initiate_eapol(wpa_s);
2389 if (old_ssid != wpa_s->current_ssid)
2390 wpas_notify_network_changed(wpa_s);
2391}
2392
2393
2394static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2395 const u8 *addr)
2396{
2397 struct wpa_ssid *old_ssid;
2398
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002399 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002401 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002402 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002403 wpa_sm_set_config(wpa_s->wpa, NULL);
2404 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2405 if (old_ssid != wpa_s->current_ssid)
2406 wpas_notify_network_changed(wpa_s);
2407 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2408}
2409
2410
2411/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002412 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2413 * @wpa_s: Pointer to wpa_supplicant data
2414 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2415 *
2416 * This function is used to request %wpa_supplicant to deauthenticate from the
2417 * current AP.
2418 */
2419void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2420 int reason_code)
2421{
2422 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002423 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002424 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002425
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002426 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2427 " pending_bssid=" MACSTR " reason=%d state=%s",
2428 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2429 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2430
2431 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002433 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2434 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2435 wpa_s->wpa_state == WPA_ASSOCIATING))
2436 addr = wpa_s->pending_bssid;
2437 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2438 /*
2439 * When using driver-based BSS selection, we may not know the
2440 * BSSID with which we are currently trying to associate. We
2441 * need to notify the driver of this disconnection even in such
2442 * a case, so use the all zeros address here.
2443 */
2444 addr = wpa_s->bssid;
2445 zero_addr = 1;
2446 }
2447
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002448#ifdef CONFIG_TDLS
2449 wpa_tdls_teardown_peers(wpa_s->wpa);
2450#endif /* CONFIG_TDLS */
2451
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002452#ifdef CONFIG_MESH
2453 if (wpa_s->ifmsh) {
2454 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2455 wpa_s->ifname);
2456 wpa_supplicant_leave_mesh(wpa_s);
2457 }
2458#endif /* CONFIG_MESH */
2459
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002460 if (addr) {
2461 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002462 os_memset(&event, 0, sizeof(event));
2463 event.deauth_info.reason_code = (u16) reason_code;
2464 event.deauth_info.locally_generated = 1;
2465 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002466 if (zero_addr)
2467 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 }
2469
2470 wpa_supplicant_clear_connection(wpa_s, addr);
2471}
2472
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002473static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2474 struct wpa_ssid *ssid)
2475{
2476 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2477 return;
2478
2479 ssid->disabled = 0;
2480 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2481 wpas_notify_network_enabled_changed(wpa_s, ssid);
2482
2483 /*
2484 * Try to reassociate since there is no current configuration and a new
2485 * network was made available.
2486 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002487 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002488 wpa_s->reassociate = 1;
2489}
2490
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002491
2492/**
2493 * wpa_supplicant_enable_network - Mark a configured network as enabled
2494 * @wpa_s: wpa_supplicant structure for a network interface
2495 * @ssid: wpa_ssid structure for a configured network or %NULL
2496 *
2497 * Enables the specified network or all networks if no network specified.
2498 */
2499void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2500 struct wpa_ssid *ssid)
2501{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002503 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2504 wpa_supplicant_enable_one_network(wpa_s, ssid);
2505 } else
2506 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002508 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002509 if (wpa_s->sched_scanning) {
2510 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2511 "new network to scan filters");
2512 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 }
2514
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002515 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2516 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 }
2518}
2519
2520
2521/**
2522 * wpa_supplicant_disable_network - Mark a configured network as disabled
2523 * @wpa_s: wpa_supplicant structure for a network interface
2524 * @ssid: wpa_ssid structure for a configured network or %NULL
2525 *
2526 * Disables the specified network or all networks if no network specified.
2527 */
2528void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2529 struct wpa_ssid *ssid)
2530{
2531 struct wpa_ssid *other_ssid;
2532 int was_disabled;
2533
2534 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002535 if (wpa_s->sched_scanning)
2536 wpa_supplicant_cancel_sched_scan(wpa_s);
2537
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2539 other_ssid = other_ssid->next) {
2540 was_disabled = other_ssid->disabled;
2541 if (was_disabled == 2)
2542 continue; /* do not change persistent P2P group
2543 * data */
2544
2545 other_ssid->disabled = 1;
2546
2547 if (was_disabled != other_ssid->disabled)
2548 wpas_notify_network_enabled_changed(
2549 wpa_s, other_ssid);
2550 }
2551 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002552 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002553 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2554 } else if (ssid->disabled != 2) {
2555 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002556 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2558
2559 was_disabled = ssid->disabled;
2560
2561 ssid->disabled = 1;
2562
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002563 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002565 if (wpa_s->sched_scanning) {
2566 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2567 "to remove network from filters");
2568 wpa_supplicant_cancel_sched_scan(wpa_s);
2569 wpa_supplicant_req_scan(wpa_s, 0, 0);
2570 }
2571 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002572 }
2573}
2574
2575
2576/**
2577 * wpa_supplicant_select_network - Attempt association with a network
2578 * @wpa_s: wpa_supplicant structure for a network interface
2579 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2580 */
2581void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2582 struct wpa_ssid *ssid)
2583{
2584
2585 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002586 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002588 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08002589 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002590 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002592 disconnected = 1;
2593 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002594
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002595 if (ssid)
2596 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2597
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598 /*
2599 * Mark all other networks disabled or mark all networks enabled if no
2600 * network specified.
2601 */
2602 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2603 other_ssid = other_ssid->next) {
2604 int was_disabled = other_ssid->disabled;
2605 if (was_disabled == 2)
2606 continue; /* do not change persistent P2P group data */
2607
2608 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002609 if (was_disabled && !other_ssid->disabled)
2610 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611
2612 if (was_disabled != other_ssid->disabled)
2613 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2614 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002615
2616 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2617 /* We are already associated with the selected network */
2618 wpa_printf(MSG_DEBUG, "Already associated with the "
2619 "selected network - do nothing");
2620 return;
2621 }
2622
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002623 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002624 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002625 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002626 wpa_s->connect_without_scan =
2627 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
2628 } else {
2629 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002630 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002631
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002632 wpa_s->disconnected = 0;
2633 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002634
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002635 if (wpa_s->connect_without_scan ||
2636 wpa_supplicant_fast_associate(wpa_s) != 1)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002637 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638
2639 if (ssid)
2640 wpas_notify_network_selected(wpa_s, ssid);
2641}
2642
2643
2644/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002645 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2646 * @wpa_s: wpa_supplicant structure for a network interface
2647 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2648 * @pkcs11_module_path: PKCS #11 module path or NULL
2649 * Returns: 0 on success; -1 on failure
2650 *
2651 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2652 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2653 * module path fails the paths will be reset to the default value (NULL).
2654 */
2655int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2656 const char *pkcs11_engine_path,
2657 const char *pkcs11_module_path)
2658{
2659 char *pkcs11_engine_path_copy = NULL;
2660 char *pkcs11_module_path_copy = NULL;
2661
2662 if (pkcs11_engine_path != NULL) {
2663 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2664 if (pkcs11_engine_path_copy == NULL)
2665 return -1;
2666 }
2667 if (pkcs11_module_path != NULL) {
2668 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002669 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002670 os_free(pkcs11_engine_path_copy);
2671 return -1;
2672 }
2673 }
2674
2675 os_free(wpa_s->conf->pkcs11_engine_path);
2676 os_free(wpa_s->conf->pkcs11_module_path);
2677 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2678 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2679
2680 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2681 eapol_sm_deinit(wpa_s->eapol);
2682 wpa_s->eapol = NULL;
2683 if (wpa_supplicant_init_eapol(wpa_s)) {
2684 /* Error -> Reset paths to the default value (NULL) once. */
2685 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2686 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2687 NULL);
2688
2689 return -1;
2690 }
2691 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2692
2693 return 0;
2694}
2695
2696
2697/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2699 * @wpa_s: wpa_supplicant structure for a network interface
2700 * @ap_scan: AP scan mode
2701 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2702 *
2703 */
2704int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2705{
2706
2707 int old_ap_scan;
2708
2709 if (ap_scan < 0 || ap_scan > 2)
2710 return -1;
2711
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002712#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002713 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2714 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2715 wpa_s->wpa_state < WPA_COMPLETED) {
2716 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2717 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002718 return 0;
2719 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002720#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002721
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 old_ap_scan = wpa_s->conf->ap_scan;
2723 wpa_s->conf->ap_scan = ap_scan;
2724
2725 if (old_ap_scan != wpa_s->conf->ap_scan)
2726 wpas_notify_ap_scan_changed(wpa_s);
2727
2728 return 0;
2729}
2730
2731
2732/**
2733 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2734 * @wpa_s: wpa_supplicant structure for a network interface
2735 * @expire_age: Expiration age in seconds
2736 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2737 *
2738 */
2739int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2740 unsigned int bss_expire_age)
2741{
2742 if (bss_expire_age < 10) {
2743 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2744 bss_expire_age);
2745 return -1;
2746 }
2747 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2748 bss_expire_age);
2749 wpa_s->conf->bss_expiration_age = bss_expire_age;
2750
2751 return 0;
2752}
2753
2754
2755/**
2756 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2757 * @wpa_s: wpa_supplicant structure for a network interface
2758 * @expire_count: number of scans after which an unseen BSS is reclaimed
2759 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2760 *
2761 */
2762int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2763 unsigned int bss_expire_count)
2764{
2765 if (bss_expire_count < 1) {
2766 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2767 bss_expire_count);
2768 return -1;
2769 }
2770 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2771 bss_expire_count);
2772 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2773
2774 return 0;
2775}
2776
2777
2778/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002779 * wpa_supplicant_set_scan_interval - Set scan interval
2780 * @wpa_s: wpa_supplicant structure for a network interface
2781 * @scan_interval: scan interval in seconds
2782 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2783 *
2784 */
2785int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2786 int scan_interval)
2787{
2788 if (scan_interval < 0) {
2789 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2790 scan_interval);
2791 return -1;
2792 }
2793 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2794 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002795 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002796
2797 return 0;
2798}
2799
2800
2801/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002802 * wpa_supplicant_set_debug_params - Set global debug params
2803 * @global: wpa_global structure
2804 * @debug_level: debug level
2805 * @debug_timestamp: determines if show timestamp in debug data
2806 * @debug_show_keys: determines if show keys in debug data
2807 * Returns: 0 if succeed or -1 if debug_level has wrong value
2808 */
2809int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2810 int debug_timestamp, int debug_show_keys)
2811{
2812
2813 int old_level, old_timestamp, old_show_keys;
2814
2815 /* check for allowed debuglevels */
2816 if (debug_level != MSG_EXCESSIVE &&
2817 debug_level != MSG_MSGDUMP &&
2818 debug_level != MSG_DEBUG &&
2819 debug_level != MSG_INFO &&
2820 debug_level != MSG_WARNING &&
2821 debug_level != MSG_ERROR)
2822 return -1;
2823
2824 old_level = wpa_debug_level;
2825 old_timestamp = wpa_debug_timestamp;
2826 old_show_keys = wpa_debug_show_keys;
2827
2828 wpa_debug_level = debug_level;
2829 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2830 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2831
2832 if (wpa_debug_level != old_level)
2833 wpas_notify_debug_level_changed(global);
2834 if (wpa_debug_timestamp != old_timestamp)
2835 wpas_notify_debug_timestamp_changed(global);
2836 if (wpa_debug_show_keys != old_show_keys)
2837 wpas_notify_debug_show_keys_changed(global);
2838
2839 return 0;
2840}
2841
2842
2843/**
2844 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2845 * @wpa_s: Pointer to wpa_supplicant data
2846 * Returns: A pointer to the current network structure or %NULL on failure
2847 */
2848struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2849{
2850 struct wpa_ssid *entry;
2851 u8 ssid[MAX_SSID_LEN];
2852 int res;
2853 size_t ssid_len;
2854 u8 bssid[ETH_ALEN];
2855 int wired;
2856
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002857 res = wpa_drv_get_ssid(wpa_s, ssid);
2858 if (res < 0) {
2859 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2860 "driver");
2861 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002862 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002863 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002864
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002865 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002866 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2867 "driver");
2868 return NULL;
2869 }
2870
2871 wired = wpa_s->conf->ap_scan == 0 &&
2872 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2873
2874 entry = wpa_s->conf->ssid;
2875 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002876 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002877 ((ssid_len == entry->ssid_len &&
2878 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2879 (!entry->bssid_set ||
2880 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2881 return entry;
2882#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002883 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002884 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2885 (entry->ssid == NULL || entry->ssid_len == 0) &&
2886 (!entry->bssid_set ||
2887 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2888 return entry;
2889#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002890
Dmitry Shmidt04949592012-07-19 12:16:46 -07002891 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002892 entry->ssid_len == 0 &&
2893 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2894 return entry;
2895
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002896 entry = entry->next;
2897 }
2898
2899 return NULL;
2900}
2901
2902
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002903static int select_driver(struct wpa_supplicant *wpa_s, int i)
2904{
2905 struct wpa_global *global = wpa_s->global;
2906
2907 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2908 global->drv_priv[i] = wpa_drivers[i]->global_init();
2909 if (global->drv_priv[i] == NULL) {
2910 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2911 "'%s'", wpa_drivers[i]->name);
2912 return -1;
2913 }
2914 }
2915
2916 wpa_s->driver = wpa_drivers[i];
2917 wpa_s->global_drv_priv = global->drv_priv[i];
2918
2919 return 0;
2920}
2921
2922
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002923static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2924 const char *name)
2925{
2926 int i;
2927 size_t len;
2928 const char *pos, *driver = name;
2929
2930 if (wpa_s == NULL)
2931 return -1;
2932
2933 if (wpa_drivers[0] == NULL) {
2934 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2935 "wpa_supplicant");
2936 return -1;
2937 }
2938
2939 if (name == NULL) {
2940 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002941 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002942 }
2943
2944 do {
2945 pos = os_strchr(driver, ',');
2946 if (pos)
2947 len = pos - driver;
2948 else
2949 len = os_strlen(driver);
2950
2951 for (i = 0; wpa_drivers[i]; i++) {
2952 if (os_strlen(wpa_drivers[i]->name) == len &&
2953 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002954 0) {
2955 /* First driver that succeeds wins */
2956 if (select_driver(wpa_s, i) == 0)
2957 return 0;
2958 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959 }
2960
2961 driver = pos + 1;
2962 } while (pos);
2963
2964 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2965 return -1;
2966}
2967
2968
2969/**
2970 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2971 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2972 * with struct wpa_driver_ops::init()
2973 * @src_addr: Source address of the EAPOL frame
2974 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2975 * @len: Length of the EAPOL data
2976 *
2977 * This function is called for each received EAPOL frame. Most driver
2978 * interfaces rely on more generic OS mechanism for receiving frames through
2979 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2980 * take care of received EAPOL frames and deliver them to the core supplicant
2981 * code by calling this function.
2982 */
2983void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2984 const u8 *buf, size_t len)
2985{
2986 struct wpa_supplicant *wpa_s = ctx;
2987
2988 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2989 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2990
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002991#ifdef CONFIG_PEERKEY
2992 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2993 wpa_s->current_ssid->peerkey &&
2994 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2995 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2996 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2997 return;
2998 }
2999#endif /* CONFIG_PEERKEY */
3000
Jouni Malinena05074c2012-12-21 21:35:35 +02003001 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3002 (wpa_s->last_eapol_matches_bssid &&
3003#ifdef CONFIG_AP
3004 !wpa_s->ap_iface &&
3005#endif /* CONFIG_AP */
3006 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007 /*
3008 * There is possible race condition between receiving the
3009 * association event and the EAPOL frame since they are coming
3010 * through different paths from the driver. In order to avoid
3011 * issues in trying to process the EAPOL frame before receiving
3012 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003013 * the association event is received. This may also be needed in
3014 * driver-based roaming case, so also use src_addr != BSSID as a
3015 * trigger if we have previously confirmed that the
3016 * Authenticator uses BSSID as the src_addr (which is not the
3017 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003018 */
3019 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003020 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3021 wpa_supplicant_state_txt(wpa_s->wpa_state),
3022 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003023 wpabuf_free(wpa_s->pending_eapol_rx);
3024 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3025 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003026 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003027 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3028 ETH_ALEN);
3029 }
3030 return;
3031 }
3032
Jouni Malinena05074c2012-12-21 21:35:35 +02003033 wpa_s->last_eapol_matches_bssid =
3034 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3035
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003036#ifdef CONFIG_AP
3037 if (wpa_s->ap_iface) {
3038 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3039 return;
3040 }
3041#endif /* CONFIG_AP */
3042
3043 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3044 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3045 "no key management is configured");
3046 return;
3047 }
3048
3049 if (wpa_s->eapol_received == 0 &&
3050 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3051 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3052 wpa_s->wpa_state != WPA_COMPLETED) &&
3053 (wpa_s->current_ssid == NULL ||
3054 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3055 /* Timeout for completing IEEE 802.1X and WPA authentication */
3056 wpa_supplicant_req_auth_timeout(
3057 wpa_s,
3058 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3059 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3060 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
3061 70 : 10, 0);
3062 }
3063 wpa_s->eapol_received++;
3064
3065 if (wpa_s->countermeasures) {
3066 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3067 "EAPOL packet");
3068 return;
3069 }
3070
3071#ifdef CONFIG_IBSS_RSN
3072 if (wpa_s->current_ssid &&
3073 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3074 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3075 return;
3076 }
3077#endif /* CONFIG_IBSS_RSN */
3078
3079 /* Source address of the incoming EAPOL frame could be compared to the
3080 * current BSSID. However, it is possible that a centralized
3081 * Authenticator could be using another MAC address than the BSSID of
3082 * an AP, so just allow any address to be used for now. The replies are
3083 * still sent to the current BSSID (if available), though. */
3084
3085 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3086 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3087 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3088 return;
3089 wpa_drv_poll(wpa_s);
3090 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3091 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3092 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3093 /*
3094 * Set portValid = TRUE here since we are going to skip 4-way
3095 * handshake processing which would normally set portValid. We
3096 * need this to allow the EAPOL state machines to be completed
3097 * without going through EAPOL-Key handshake.
3098 */
3099 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3100 }
3101}
3102
3103
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003104int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003105{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003106 if ((!wpa_s->p2p_mgmt ||
3107 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3108 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003109 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003110 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3111 wpa_drv_get_mac_addr(wpa_s),
3112 ETH_P_EAPOL,
3113 wpa_supplicant_rx_eapol, wpa_s, 0);
3114 if (wpa_s->l2 == NULL)
3115 return -1;
3116 } else {
3117 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3118 if (addr)
3119 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3120 }
3121
3122 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3123 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3124 return -1;
3125 }
3126
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003127 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3128
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003129 return 0;
3130}
3131
3132
Dmitry Shmidt04949592012-07-19 12:16:46 -07003133static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3134 const u8 *buf, size_t len)
3135{
3136 struct wpa_supplicant *wpa_s = ctx;
3137 const struct l2_ethhdr *eth;
3138
3139 if (len < sizeof(*eth))
3140 return;
3141 eth = (const struct l2_ethhdr *) buf;
3142
3143 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3144 !(eth->h_dest[0] & 0x01)) {
3145 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3146 " (bridge - not for this interface - ignore)",
3147 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3148 return;
3149 }
3150
3151 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3152 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3153 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3154 len - sizeof(*eth));
3155}
3156
3157
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003158/**
3159 * wpa_supplicant_driver_init - Initialize driver interface parameters
3160 * @wpa_s: Pointer to wpa_supplicant data
3161 * Returns: 0 on success, -1 on failure
3162 *
3163 * This function is called to initialize driver interface parameters.
3164 * wpa_drv_init() must have been called before this function to initialize the
3165 * driver interface.
3166 */
3167int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3168{
3169 static int interface_count = 0;
3170
3171 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3172 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003173
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003174 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3175 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003176 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003177 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003179 if (wpa_s->bridge_ifname[0]) {
3180 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3181 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003182 wpa_s->l2_br = l2_packet_init_bridge(
3183 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3184 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003185 if (wpa_s->l2_br == NULL) {
3186 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3187 "connection for the bridge interface '%s'",
3188 wpa_s->bridge_ifname);
3189 return -1;
3190 }
3191 }
3192
3193 wpa_clear_keys(wpa_s, NULL);
3194
3195 /* Make sure that TKIP countermeasures are not left enabled (could
3196 * happen if wpa_supplicant is killed during countermeasures. */
3197 wpa_drv_set_countermeasures(wpa_s, 0);
3198
3199 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3200 wpa_drv_flush_pmkid(wpa_s);
3201
3202 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003203 wpa_s->prev_scan_wildcard = 0;
3204
Dmitry Shmidt04949592012-07-19 12:16:46 -07003205 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003206 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3207 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3208 interface_count = 0;
3209 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003210#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003211 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003212 wpa_supplicant_delayed_sched_scan(wpa_s,
3213 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003214 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003215 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003216 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003217#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003218 interface_count++;
3219 } else
3220 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3221
3222 return 0;
3223}
3224
3225
3226static int wpa_supplicant_daemon(const char *pid_file)
3227{
3228 wpa_printf(MSG_DEBUG, "Daemonize..");
3229 return os_daemonize(pid_file);
3230}
3231
3232
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003233static struct wpa_supplicant *
3234wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003235{
3236 struct wpa_supplicant *wpa_s;
3237
3238 wpa_s = os_zalloc(sizeof(*wpa_s));
3239 if (wpa_s == NULL)
3240 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003241 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003242 wpa_s->scan_interval = 5;
3243 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003244 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003245 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003246
3247 return wpa_s;
3248}
3249
3250
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003251#ifdef CONFIG_HT_OVERRIDES
3252
3253static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3254 struct ieee80211_ht_capabilities *htcaps,
3255 struct ieee80211_ht_capabilities *htcaps_mask,
3256 const char *ht_mcs)
3257{
3258 /* parse ht_mcs into hex array */
3259 int i;
3260 const char *tmp = ht_mcs;
3261 char *end = NULL;
3262
3263 /* If ht_mcs is null, do not set anything */
3264 if (!ht_mcs)
3265 return 0;
3266
3267 /* This is what we are setting in the kernel */
3268 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3269
3270 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3271
3272 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3273 errno = 0;
3274 long v = strtol(tmp, &end, 16);
3275 if (errno == 0) {
3276 wpa_msg(wpa_s, MSG_DEBUG,
3277 "htcap value[%i]: %ld end: %p tmp: %p",
3278 i, v, end, tmp);
3279 if (end == tmp)
3280 break;
3281
3282 htcaps->supported_mcs_set[i] = v;
3283 tmp = end;
3284 } else {
3285 wpa_msg(wpa_s, MSG_ERROR,
3286 "Failed to parse ht-mcs: %s, error: %s\n",
3287 ht_mcs, strerror(errno));
3288 return -1;
3289 }
3290 }
3291
3292 /*
3293 * If we were able to parse any values, then set mask for the MCS set.
3294 */
3295 if (i) {
3296 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3297 IEEE80211_HT_MCS_MASK_LEN - 1);
3298 /* skip the 3 reserved bits */
3299 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3300 0x1f;
3301 }
3302
3303 return 0;
3304}
3305
3306
3307static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3308 struct ieee80211_ht_capabilities *htcaps,
3309 struct ieee80211_ht_capabilities *htcaps_mask,
3310 int disabled)
3311{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003312 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003313
3314 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3315
3316 if (disabled == -1)
3317 return 0;
3318
3319 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3320 htcaps_mask->ht_capabilities_info |= msk;
3321 if (disabled)
3322 htcaps->ht_capabilities_info &= msk;
3323 else
3324 htcaps->ht_capabilities_info |= msk;
3325
3326 return 0;
3327}
3328
3329
3330static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3331 struct ieee80211_ht_capabilities *htcaps,
3332 struct ieee80211_ht_capabilities *htcaps_mask,
3333 int factor)
3334{
3335 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3336
3337 if (factor == -1)
3338 return 0;
3339
3340 if (factor < 0 || factor > 3) {
3341 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3342 "Must be 0-3 or -1", factor);
3343 return -EINVAL;
3344 }
3345
3346 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3347 htcaps->a_mpdu_params &= ~0x3;
3348 htcaps->a_mpdu_params |= factor & 0x3;
3349
3350 return 0;
3351}
3352
3353
3354static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3355 struct ieee80211_ht_capabilities *htcaps,
3356 struct ieee80211_ht_capabilities *htcaps_mask,
3357 int density)
3358{
3359 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3360
3361 if (density == -1)
3362 return 0;
3363
3364 if (density < 0 || density > 7) {
3365 wpa_msg(wpa_s, MSG_ERROR,
3366 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3367 density);
3368 return -EINVAL;
3369 }
3370
3371 htcaps_mask->a_mpdu_params |= 0x1C;
3372 htcaps->a_mpdu_params &= ~(0x1C);
3373 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3374
3375 return 0;
3376}
3377
3378
3379static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3380 struct ieee80211_ht_capabilities *htcaps,
3381 struct ieee80211_ht_capabilities *htcaps_mask,
3382 int disabled)
3383{
3384 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003385 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3386 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003387
3388 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3389
3390 if (disabled)
3391 htcaps->ht_capabilities_info &= ~msk;
3392 else
3393 htcaps->ht_capabilities_info |= msk;
3394
3395 htcaps_mask->ht_capabilities_info |= msk;
3396
3397 return 0;
3398}
3399
3400
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003401static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3402 struct ieee80211_ht_capabilities *htcaps,
3403 struct ieee80211_ht_capabilities *htcaps_mask,
3404 int disabled)
3405{
3406 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003407 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3408 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003409
3410 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3411
3412 if (disabled)
3413 htcaps->ht_capabilities_info &= ~msk;
3414 else
3415 htcaps->ht_capabilities_info |= msk;
3416
3417 htcaps_mask->ht_capabilities_info |= msk;
3418
3419 return 0;
3420}
3421
3422
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003423static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3424 struct ieee80211_ht_capabilities *htcaps,
3425 struct ieee80211_ht_capabilities *htcaps_mask,
3426 int disabled)
3427{
3428 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003429 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003430
3431 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3432
3433 if (disabled)
3434 htcaps->ht_capabilities_info &= ~msk;
3435 else
3436 htcaps->ht_capabilities_info |= msk;
3437
3438 htcaps_mask->ht_capabilities_info |= msk;
3439
3440 return 0;
3441}
3442
3443
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003444void wpa_supplicant_apply_ht_overrides(
3445 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3446 struct wpa_driver_associate_params *params)
3447{
3448 struct ieee80211_ht_capabilities *htcaps;
3449 struct ieee80211_ht_capabilities *htcaps_mask;
3450
3451 if (!ssid)
3452 return;
3453
3454 params->disable_ht = ssid->disable_ht;
3455 if (!params->htcaps || !params->htcaps_mask)
3456 return;
3457
3458 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3459 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3460 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3461 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3462 ssid->disable_max_amsdu);
3463 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3464 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3465 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003466 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003467 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003468
3469 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003470 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003471 htcaps->ht_capabilities_info |= bit;
3472 htcaps_mask->ht_capabilities_info |= bit;
3473 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003474}
3475
3476#endif /* CONFIG_HT_OVERRIDES */
3477
3478
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003479#ifdef CONFIG_VHT_OVERRIDES
3480void wpa_supplicant_apply_vht_overrides(
3481 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3482 struct wpa_driver_associate_params *params)
3483{
3484 struct ieee80211_vht_capabilities *vhtcaps;
3485 struct ieee80211_vht_capabilities *vhtcaps_mask;
3486
3487 if (!ssid)
3488 return;
3489
3490 params->disable_vht = ssid->disable_vht;
3491
3492 vhtcaps = (void *) params->vhtcaps;
3493 vhtcaps_mask = (void *) params->vhtcaps_mask;
3494
3495 if (!vhtcaps || !vhtcaps_mask)
3496 return;
3497
3498 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3499 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3500
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003501#ifdef CONFIG_HT_OVERRIDES
3502 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003503 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3504 int max_ampdu;
3505
3506 max_ampdu = (ssid->vht_capa &
3507 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3508 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003509
3510 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3511 wpa_set_ampdu_factor(wpa_s,
3512 (void *) params->htcaps,
3513 (void *) params->htcaps_mask,
3514 max_ampdu);
3515 }
3516#endif /* CONFIG_HT_OVERRIDES */
3517
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003518#define OVERRIDE_MCS(i) \
3519 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3520 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3521 3 << 2 * (i - 1); \
3522 vhtcaps->vht_supported_mcs_set.tx_map |= \
3523 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3524 } \
3525 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3526 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3527 3 << 2 * (i - 1); \
3528 vhtcaps->vht_supported_mcs_set.rx_map |= \
3529 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3530 }
3531
3532 OVERRIDE_MCS(1);
3533 OVERRIDE_MCS(2);
3534 OVERRIDE_MCS(3);
3535 OVERRIDE_MCS(4);
3536 OVERRIDE_MCS(5);
3537 OVERRIDE_MCS(6);
3538 OVERRIDE_MCS(7);
3539 OVERRIDE_MCS(8);
3540}
3541#endif /* CONFIG_VHT_OVERRIDES */
3542
3543
Dmitry Shmidt04949592012-07-19 12:16:46 -07003544static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3545{
3546#ifdef PCSC_FUNCS
3547 size_t len;
3548
3549 if (!wpa_s->conf->pcsc_reader)
3550 return 0;
3551
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003552 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003553 if (!wpa_s->scard)
3554 return 1;
3555
3556 if (wpa_s->conf->pcsc_pin &&
3557 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3558 scard_deinit(wpa_s->scard);
3559 wpa_s->scard = NULL;
3560 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3561 return -1;
3562 }
3563
3564 len = sizeof(wpa_s->imsi) - 1;
3565 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3566 scard_deinit(wpa_s->scard);
3567 wpa_s->scard = NULL;
3568 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3569 return -1;
3570 }
3571 wpa_s->imsi[len] = '\0';
3572
3573 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3574
3575 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3576 wpa_s->imsi, wpa_s->mnc_len);
3577
3578 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3579 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3580#endif /* PCSC_FUNCS */
3581
3582 return 0;
3583}
3584
3585
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003586int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3587{
3588 char *val, *pos;
3589
3590 ext_password_deinit(wpa_s->ext_pw);
3591 wpa_s->ext_pw = NULL;
3592 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3593
3594 if (!wpa_s->conf->ext_password_backend)
3595 return 0;
3596
3597 val = os_strdup(wpa_s->conf->ext_password_backend);
3598 if (val == NULL)
3599 return -1;
3600 pos = os_strchr(val, ':');
3601 if (pos)
3602 *pos++ = '\0';
3603
3604 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3605
3606 wpa_s->ext_pw = ext_password_init(val, pos);
3607 os_free(val);
3608 if (wpa_s->ext_pw == NULL) {
3609 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3610 return -1;
3611 }
3612 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3613
3614 return 0;
3615}
3616
3617
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003618static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003619 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003620{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003621 struct wowlan_triggers *triggers;
3622 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003623
3624 if (!wpa_s->conf->wowlan_triggers)
3625 return 0;
3626
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003627 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3628 if (triggers) {
3629 ret = wpa_drv_wowlan(wpa_s, triggers);
3630 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003631 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003632 return ret;
3633}
3634
3635
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003636static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3637 const char *rn)
3638{
3639 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3640 struct wpa_radio *radio;
3641
3642 while (rn && iface) {
3643 radio = iface->radio;
3644 if (radio && os_strcmp(rn, radio->name) == 0) {
3645 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3646 wpa_s->ifname, rn);
3647 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3648 return radio;
3649 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003650
3651 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003652 }
3653
3654 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3655 wpa_s->ifname, rn ? rn : "N/A");
3656 radio = os_zalloc(sizeof(*radio));
3657 if (radio == NULL)
3658 return NULL;
3659
3660 if (rn)
3661 os_strlcpy(radio->name, rn, sizeof(radio->name));
3662 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003663 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003664 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3665
3666 return radio;
3667}
3668
3669
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003670static void radio_work_free(struct wpa_radio_work *work)
3671{
3672 if (work->wpa_s->scan_work == work) {
3673 /* This should not really happen. */
3674 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3675 work->type, work, work->started);
3676 work->wpa_s->scan_work = NULL;
3677 }
3678
3679#ifdef CONFIG_P2P
3680 if (work->wpa_s->p2p_scan_work == work) {
3681 /* This should not really happen. */
3682 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3683 work->type, work, work->started);
3684 work->wpa_s->p2p_scan_work = NULL;
3685 }
3686#endif /* CONFIG_P2P */
3687
3688 dl_list_del(&work->list);
3689 os_free(work);
3690}
3691
3692
3693static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3694{
3695 struct wpa_radio *radio = eloop_ctx;
3696 struct wpa_radio_work *work;
3697 struct os_reltime now, diff;
3698 struct wpa_supplicant *wpa_s;
3699
3700 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3701 if (work == NULL)
3702 return;
3703
3704 if (work->started)
3705 return; /* already started and still in progress */
3706
3707 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3708 radio_list);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003709 if (wpa_s && wpa_s->radio->external_scan_running) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003710 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3711 return;
3712 }
3713
3714 os_get_reltime(&now);
3715 os_reltime_sub(&now, &work->time, &diff);
3716 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3717 work->type, work, diff.sec, diff.usec);
3718 work->started = 1;
3719 work->time = now;
3720 work->cb(work, 0);
3721}
3722
3723
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003724/*
3725 * This function removes both started and pending radio works running on
3726 * the provided interface's radio.
3727 * Prior to the removal of the radio work, its callback (cb) is called with
3728 * deinit set to be 1. Each work's callback is responsible for clearing its
3729 * internal data and restoring to a correct state.
3730 * @wpa_s: wpa_supplicant data
3731 * @type: type of works to be removed
3732 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3733 * this interface's works.
3734 */
3735void radio_remove_works(struct wpa_supplicant *wpa_s,
3736 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003737{
3738 struct wpa_radio_work *work, *tmp;
3739 struct wpa_radio *radio = wpa_s->radio;
3740
3741 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3742 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003743 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003744 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003745
3746 /* skip other ifaces' works */
3747 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003748 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003749
3750 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3751 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003752 work->cb(work, 1);
3753 radio_work_free(work);
3754 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003755
3756 /* in case we removed the started work */
3757 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003758}
3759
3760
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003761static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3762{
3763 struct wpa_radio *radio = wpa_s->radio;
3764
3765 if (!radio)
3766 return;
3767
3768 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3769 wpa_s->ifname, radio->name);
3770 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003771 radio_remove_works(wpa_s, NULL, 0);
3772 wpa_s->radio = NULL;
3773 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003774 return; /* Interfaces remain for this radio */
3775
3776 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003777 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003778 os_free(radio);
3779}
3780
3781
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003782void radio_work_check_next(struct wpa_supplicant *wpa_s)
3783{
3784 struct wpa_radio *radio = wpa_s->radio;
3785
3786 if (dl_list_empty(&radio->work))
3787 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003788 if (wpa_s->ext_work_in_progress) {
3789 wpa_printf(MSG_DEBUG,
3790 "External radio work in progress - delay start of pending item");
3791 return;
3792 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003793 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3794 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3795}
3796
3797
3798/**
3799 * radio_add_work - Add a radio work item
3800 * @wpa_s: Pointer to wpa_supplicant data
3801 * @freq: Frequency of the offchannel operation in MHz or 0
3802 * @type: Unique identifier for each type of work
3803 * @next: Force as the next work to be executed
3804 * @cb: Callback function for indicating when radio is available
3805 * @ctx: Context pointer for the work (work->ctx in cb())
3806 * Returns: 0 on success, -1 on failure
3807 *
3808 * This function is used to request time for an operation that requires
3809 * exclusive radio control. Once the radio is available, the registered callback
3810 * function will be called. radio_work_done() must be called once the exclusive
3811 * radio operation has been completed, so that the radio is freed for other
3812 * operations. The special case of deinit=1 is used to free the context data
3813 * during interface removal. That does not allow the callback function to start
3814 * the radio operation, i.e., it must free any resources allocated for the radio
3815 * work and return.
3816 *
3817 * The @freq parameter can be used to indicate a single channel on which the
3818 * offchannel operation will occur. This may allow multiple radio work
3819 * operations to be performed in parallel if they apply for the same channel.
3820 * Setting this to 0 indicates that the work item may use multiple channels or
3821 * requires exclusive control of the radio.
3822 */
3823int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3824 const char *type, int next,
3825 void (*cb)(struct wpa_radio_work *work, int deinit),
3826 void *ctx)
3827{
3828 struct wpa_radio_work *work;
3829 int was_empty;
3830
3831 work = os_zalloc(sizeof(*work));
3832 if (work == NULL)
3833 return -1;
3834 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3835 os_get_reltime(&work->time);
3836 work->freq = freq;
3837 work->type = type;
3838 work->wpa_s = wpa_s;
3839 work->cb = cb;
3840 work->ctx = ctx;
3841
3842 was_empty = dl_list_empty(&wpa_s->radio->work);
3843 if (next)
3844 dl_list_add(&wpa_s->radio->work, &work->list);
3845 else
3846 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3847 if (was_empty) {
3848 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3849 radio_work_check_next(wpa_s);
3850 }
3851
3852 return 0;
3853}
3854
3855
3856/**
3857 * radio_work_done - Indicate that a radio work item has been completed
3858 * @work: Completed work
3859 *
3860 * This function is called once the callback function registered with
3861 * radio_add_work() has completed its work.
3862 */
3863void radio_work_done(struct wpa_radio_work *work)
3864{
3865 struct wpa_supplicant *wpa_s = work->wpa_s;
3866 struct os_reltime now, diff;
3867 unsigned int started = work->started;
3868
3869 os_get_reltime(&now);
3870 os_reltime_sub(&now, &work->time, &diff);
3871 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3872 work->type, work, started ? "done" : "canceled",
3873 diff.sec, diff.usec);
3874 radio_work_free(work);
3875 if (started)
3876 radio_work_check_next(wpa_s);
3877}
3878
3879
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003880struct wpa_radio_work *
3881radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003882{
3883 struct wpa_radio_work *work;
3884 struct wpa_radio *radio = wpa_s->radio;
3885
3886 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3887 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003888 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003889 }
3890
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003891 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003892}
3893
3894
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003895static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3896 struct wpa_interface *iface)
3897{
3898 const char *ifname, *driver, *rn;
3899
3900 driver = iface->driver;
3901next_driver:
3902 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3903 return -1;
3904
3905 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3906 if (wpa_s->drv_priv == NULL) {
3907 const char *pos;
3908 pos = driver ? os_strchr(driver, ',') : NULL;
3909 if (pos) {
3910 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3911 "driver interface - try next driver wrapper");
3912 driver = pos + 1;
3913 goto next_driver;
3914 }
3915 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3916 "interface");
3917 return -1;
3918 }
3919 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3920 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3921 "driver_param '%s'", wpa_s->conf->driver_param);
3922 return -1;
3923 }
3924
3925 ifname = wpa_drv_get_ifname(wpa_s);
3926 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3927 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3928 "interface name with '%s'", ifname);
3929 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3930 }
3931
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003932 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003933 if (rn && rn[0] == '\0')
3934 rn = NULL;
3935
3936 wpa_s->radio = radio_add_interface(wpa_s, rn);
3937 if (wpa_s->radio == NULL)
3938 return -1;
3939
3940 return 0;
3941}
3942
3943
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003944static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3945 struct wpa_interface *iface)
3946{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003947 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003948 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003949
3950 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3951 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3952 iface->confname ? iface->confname : "N/A",
3953 iface->driver ? iface->driver : "default",
3954 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3955 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3956
3957 if (iface->confname) {
3958#ifdef CONFIG_BACKEND_FILE
3959 wpa_s->confname = os_rel2abs_path(iface->confname);
3960 if (wpa_s->confname == NULL) {
3961 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3962 "for configuration file '%s'.",
3963 iface->confname);
3964 return -1;
3965 }
3966 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3967 iface->confname, wpa_s->confname);
3968#else /* CONFIG_BACKEND_FILE */
3969 wpa_s->confname = os_strdup(iface->confname);
3970#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003971 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003972 if (wpa_s->conf == NULL) {
3973 wpa_printf(MSG_ERROR, "Failed to read or parse "
3974 "configuration '%s'.", wpa_s->confname);
3975 return -1;
3976 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003977 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3978 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003979
3980 /*
3981 * Override ctrl_interface and driver_param if set on command
3982 * line.
3983 */
3984 if (iface->ctrl_interface) {
3985 os_free(wpa_s->conf->ctrl_interface);
3986 wpa_s->conf->ctrl_interface =
3987 os_strdup(iface->ctrl_interface);
3988 }
3989
3990 if (iface->driver_param) {
3991 os_free(wpa_s->conf->driver_param);
3992 wpa_s->conf->driver_param =
3993 os_strdup(iface->driver_param);
3994 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003995
3996 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3997 os_free(wpa_s->conf->ctrl_interface);
3998 wpa_s->conf->ctrl_interface = NULL;
3999 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004000 } else
4001 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4002 iface->driver_param);
4003
4004 if (wpa_s->conf == NULL) {
4005 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4006 return -1;
4007 }
4008
4009 if (iface->ifname == NULL) {
4010 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4011 return -1;
4012 }
4013 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4014 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4015 iface->ifname);
4016 return -1;
4017 }
4018 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4019
4020 if (iface->bridge_ifname) {
4021 if (os_strlen(iface->bridge_ifname) >=
4022 sizeof(wpa_s->bridge_ifname)) {
4023 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4024 "name '%s'.", iface->bridge_ifname);
4025 return -1;
4026 }
4027 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4028 sizeof(wpa_s->bridge_ifname));
4029 }
4030
4031 /* RSNA Supplicant Key Management - INITIALIZE */
4032 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4033 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4034
4035 /* Initialize driver interface and register driver event handler before
4036 * L2 receive handler so that association events are processed before
4037 * EAPOL-Key packets if both become available for the same select()
4038 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004039 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004040 return -1;
4041
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004042 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4043 return -1;
4044
4045 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4046 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4047 NULL);
4048 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4049
4050 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4051 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4052 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4053 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4054 "dot11RSNAConfigPMKLifetime");
4055 return -1;
4056 }
4057
4058 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4059 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4060 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4061 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4062 "dot11RSNAConfigPMKReauthThreshold");
4063 return -1;
4064 }
4065
4066 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4067 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4068 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4069 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4070 "dot11RSNAConfigSATimeout");
4071 return -1;
4072 }
4073
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004074 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4075 &wpa_s->hw.num_modes,
4076 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004077 if (wpa_s->hw.modes) {
4078 u16 i;
4079
4080 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4081 if (wpa_s->hw.modes[i].vht_capab) {
4082 wpa_s->hw_capab = CAPAB_VHT;
4083 break;
4084 }
4085
4086 if (wpa_s->hw.modes[i].ht_capab &
4087 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4088 wpa_s->hw_capab = CAPAB_HT40;
4089 else if (wpa_s->hw.modes[i].ht_capab &&
4090 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4091 wpa_s->hw_capab = CAPAB_HT;
4092 }
4093 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004094
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004095 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4096 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004097 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004098 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004099 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004100 wpa_s->drv_smps_modes = capa.smps_modes;
4101 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004102 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004103 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004104 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
4105 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4106 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004107 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4108 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004109 wpa_s->extended_capa = capa.extended_capa;
4110 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4111 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004112 wpa_s->num_multichan_concurrent =
4113 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004114 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4115
4116 if (capa.mac_addr_rand_scan_supported)
4117 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4118 if (wpa_s->sched_scan_supported &&
4119 capa.mac_addr_rand_sched_scan_supported)
4120 wpa_s->mac_addr_rand_supported |=
4121 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004122 }
4123 if (wpa_s->max_remain_on_chan == 0)
4124 wpa_s->max_remain_on_chan = 1000;
4125
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004126 /*
4127 * Only take p2p_mgmt parameters when P2P Device is supported.
4128 * Doing it here as it determines whether l2_packet_init() will be done
4129 * during wpa_supplicant_driver_init().
4130 */
4131 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4132 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4133 else
4134 iface->p2p_mgmt = 1;
4135
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004136 if (wpa_s->num_multichan_concurrent == 0)
4137 wpa_s->num_multichan_concurrent = 1;
4138
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004139 if (wpa_supplicant_driver_init(wpa_s) < 0)
4140 return -1;
4141
4142#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004143 if ((!iface->p2p_mgmt ||
4144 !(wpa_s->drv_flags &
4145 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4146 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004147 return -1;
4148#endif /* CONFIG_TDLS */
4149
4150 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4151 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4152 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4153 return -1;
4154 }
4155
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004156 if (wpas_wps_init(wpa_s))
4157 return -1;
4158
4159 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4160 return -1;
4161 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4162
4163 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4164 if (wpa_s->ctrl_iface == NULL) {
4165 wpa_printf(MSG_ERROR,
4166 "Failed to initialize control interface '%s'.\n"
4167 "You may have another wpa_supplicant process "
4168 "already running or the file was\n"
4169 "left by an unclean termination of wpa_supplicant "
4170 "in which case you will need\n"
4171 "to manually remove this file before starting "
4172 "wpa_supplicant again.\n",
4173 wpa_s->conf->ctrl_interface);
4174 return -1;
4175 }
4176
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004177 wpa_s->gas = gas_query_init(wpa_s);
4178 if (wpa_s->gas == NULL) {
4179 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4180 return -1;
4181 }
4182
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004183 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004184 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4185 return -1;
4186 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004187
4188 if (wpa_bss_init(wpa_s) < 0)
4189 return -1;
4190
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004191 /*
4192 * Set Wake-on-WLAN triggers, if configured.
4193 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4194 * have effect anyway when the interface is down).
4195 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004196 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004197 return -1;
4198
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004199#ifdef CONFIG_EAP_PROXY
4200{
4201 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004202 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4203 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004204 if (wpa_s->mnc_len > 0) {
4205 wpa_s->imsi[len] = '\0';
4206 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4207 wpa_s->imsi, wpa_s->mnc_len);
4208 } else {
4209 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4210 }
4211}
4212#endif /* CONFIG_EAP_PROXY */
4213
Dmitry Shmidt04949592012-07-19 12:16:46 -07004214 if (pcsc_reader_init(wpa_s) < 0)
4215 return -1;
4216
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004217 if (wpas_init_ext_pw(wpa_s) < 0)
4218 return -1;
4219
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004220 wpas_rrm_reset(wpa_s);
4221
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004222 return 0;
4223}
4224
4225
4226static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004227 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004228{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004229 struct wpa_global *global = wpa_s->global;
4230 struct wpa_supplicant *iface, *prev;
4231
4232 if (wpa_s == wpa_s->parent)
4233 wpas_p2p_group_remove(wpa_s, "*");
4234
4235 iface = global->ifaces;
4236 while (iface) {
4237 if (iface == wpa_s || iface->parent != wpa_s) {
4238 iface = iface->next;
4239 continue;
4240 }
4241 wpa_printf(MSG_DEBUG,
4242 "Remove remaining child interface %s from parent %s",
4243 iface->ifname, wpa_s->ifname);
4244 prev = iface;
4245 iface = iface->next;
4246 wpa_supplicant_remove_iface(global, prev, terminate);
4247 }
4248
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004249 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004250 if (wpa_s->drv_priv) {
4251 wpa_supplicant_deauthenticate(wpa_s,
4252 WLAN_REASON_DEAUTH_LEAVING);
4253
4254 wpa_drv_set_countermeasures(wpa_s, 0);
4255 wpa_clear_keys(wpa_s, NULL);
4256 }
4257
4258 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004259 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004260
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004261 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004262 radio_remove_interface(wpa_s);
4263
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004264 if (wpa_s->drv_priv)
4265 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004266
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004267 if (notify)
4268 wpas_notify_iface_removed(wpa_s);
4269
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004270 if (terminate)
4271 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004272
4273 if (wpa_s->ctrl_iface) {
4274 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
4275 wpa_s->ctrl_iface = NULL;
4276 }
4277
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004278#ifdef CONFIG_MESH
4279 if (wpa_s->ifmsh) {
4280 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
4281 wpa_s->ifmsh = NULL;
4282 }
4283#endif /* CONFIG_MESH */
4284
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004285 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004286 wpa_config_free(wpa_s->conf);
4287 wpa_s->conf = NULL;
4288 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004289
4290 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004291}
4292
4293
4294/**
4295 * wpa_supplicant_add_iface - Add a new network interface
4296 * @global: Pointer to global data from wpa_supplicant_init()
4297 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004298 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004299 * Returns: Pointer to the created interface or %NULL on failure
4300 *
4301 * This function is used to add new network interfaces for %wpa_supplicant.
4302 * This can be called before wpa_supplicant_run() to add interfaces before the
4303 * main event loop has been started. In addition, new interfaces can be added
4304 * dynamically while %wpa_supplicant is already running. This could happen,
4305 * e.g., when a hotplug network adapter is inserted.
4306 */
4307struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004308 struct wpa_interface *iface,
4309 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004310{
4311 struct wpa_supplicant *wpa_s;
4312 struct wpa_interface t_iface;
4313 struct wpa_ssid *ssid;
4314
4315 if (global == NULL || iface == NULL)
4316 return NULL;
4317
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004318 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004319 if (wpa_s == NULL)
4320 return NULL;
4321
4322 wpa_s->global = global;
4323
4324 t_iface = *iface;
4325 if (global->params.override_driver) {
4326 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
4327 "('%s' -> '%s')",
4328 iface->driver, global->params.override_driver);
4329 t_iface.driver = global->params.override_driver;
4330 }
4331 if (global->params.override_ctrl_interface) {
4332 wpa_printf(MSG_DEBUG, "Override interface parameter: "
4333 "ctrl_interface ('%s' -> '%s')",
4334 iface->ctrl_interface,
4335 global->params.override_ctrl_interface);
4336 t_iface.ctrl_interface =
4337 global->params.override_ctrl_interface;
4338 }
4339 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
4340 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
4341 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004342 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004343 return NULL;
4344 }
4345
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004346 if (iface->p2p_mgmt == 0) {
4347 /* Notify the control interfaces about new iface */
4348 if (wpas_notify_iface_added(wpa_s)) {
4349 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
4350 return NULL;
4351 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004352
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004353 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4354 wpas_notify_network_added(wpa_s, ssid);
4355 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004356
4357 wpa_s->next = global->ifaces;
4358 global->ifaces = wpa_s;
4359
4360 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004361 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004362
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004363#ifdef CONFIG_P2P
4364 if (wpa_s->global->p2p == NULL &&
4365 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
4366 wpas_p2p_add_p2pdev_interface(wpa_s, iface->conf_p2p_dev) < 0) {
4367 wpa_printf(MSG_INFO,
4368 "P2P: Failed to enable P2P Device interface");
4369 /* Try to continue without. P2P will be disabled. */
4370 }
4371#endif /* CONFIG_P2P */
4372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004373 return wpa_s;
4374}
4375
4376
4377/**
4378 * wpa_supplicant_remove_iface - Remove a network interface
4379 * @global: Pointer to global data from wpa_supplicant_init()
4380 * @wpa_s: Pointer to the network interface to be removed
4381 * Returns: 0 if interface was removed, -1 if interface was not found
4382 *
4383 * This function can be used to dynamically remove network interfaces from
4384 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
4385 * addition, this function is used to remove all remaining interfaces when
4386 * %wpa_supplicant is terminated.
4387 */
4388int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004389 struct wpa_supplicant *wpa_s,
4390 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004391{
4392 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004393#ifdef CONFIG_MESH
4394 unsigned int mesh_if_created = wpa_s->mesh_if_created;
4395 char *ifname = NULL;
4396#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004397
4398 /* Remove interface from the global list of interfaces */
4399 prev = global->ifaces;
4400 if (prev == wpa_s) {
4401 global->ifaces = wpa_s->next;
4402 } else {
4403 while (prev && prev->next != wpa_s)
4404 prev = prev->next;
4405 if (prev == NULL)
4406 return -1;
4407 prev->next = wpa_s->next;
4408 }
4409
4410 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
4411
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004412#ifdef CONFIG_MESH
4413 if (mesh_if_created) {
4414 ifname = os_strdup(wpa_s->ifname);
4415 if (ifname == NULL) {
4416 wpa_dbg(wpa_s, MSG_ERROR,
4417 "mesh: Failed to malloc ifname");
4418 return -1;
4419 }
4420 }
4421#endif /* CONFIG_MESH */
4422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004423 if (global->p2p_group_formation == wpa_s)
4424 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004425 if (global->p2p_invite_group == wpa_s)
4426 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004427 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004428
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004429#ifdef CONFIG_MESH
4430 if (mesh_if_created) {
4431 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
4432 os_free(ifname);
4433 }
4434#endif /* CONFIG_MESH */
4435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004436 return 0;
4437}
4438
4439
4440/**
4441 * wpa_supplicant_get_eap_mode - Get the current EAP mode
4442 * @wpa_s: Pointer to the network interface
4443 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
4444 */
4445const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
4446{
4447 const char *eapol_method;
4448
4449 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
4450 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4451 return "NO-EAP";
4452 }
4453
4454 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
4455 if (eapol_method == NULL)
4456 return "UNKNOWN-EAP";
4457
4458 return eapol_method;
4459}
4460
4461
4462/**
4463 * wpa_supplicant_get_iface - Get a new network interface
4464 * @global: Pointer to global data from wpa_supplicant_init()
4465 * @ifname: Interface name
4466 * Returns: Pointer to the interface or %NULL if not found
4467 */
4468struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4469 const char *ifname)
4470{
4471 struct wpa_supplicant *wpa_s;
4472
4473 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4474 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4475 return wpa_s;
4476 }
4477 return NULL;
4478}
4479
4480
4481#ifndef CONFIG_NO_WPA_MSG
4482static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4483{
4484 struct wpa_supplicant *wpa_s = ctx;
4485 if (wpa_s == NULL)
4486 return NULL;
4487 return wpa_s->ifname;
4488}
4489#endif /* CONFIG_NO_WPA_MSG */
4490
4491
4492/**
4493 * wpa_supplicant_init - Initialize %wpa_supplicant
4494 * @params: Parameters for %wpa_supplicant
4495 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4496 *
4497 * This function is used to initialize %wpa_supplicant. After successful
4498 * initialization, the returned data pointer can be used to add and remove
4499 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4500 */
4501struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4502{
4503 struct wpa_global *global;
4504 int ret, i;
4505
4506 if (params == NULL)
4507 return NULL;
4508
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004509#ifdef CONFIG_DRIVER_NDIS
4510 {
4511 void driver_ndis_init_ops(void);
4512 driver_ndis_init_ops();
4513 }
4514#endif /* CONFIG_DRIVER_NDIS */
4515
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004516#ifndef CONFIG_NO_WPA_MSG
4517 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4518#endif /* CONFIG_NO_WPA_MSG */
4519
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004520 if (params->wpa_debug_file_path)
4521 wpa_debug_open_file(params->wpa_debug_file_path);
4522 else
4523 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004524 if (params->wpa_debug_syslog)
4525 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004526 if (params->wpa_debug_tracing) {
4527 ret = wpa_debug_open_linux_tracing();
4528 if (ret) {
4529 wpa_printf(MSG_ERROR,
4530 "Failed to enable trace logging");
4531 return NULL;
4532 }
4533 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004534
4535 ret = eap_register_methods();
4536 if (ret) {
4537 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4538 if (ret == -2)
4539 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4540 "the same EAP type.");
4541 return NULL;
4542 }
4543
4544 global = os_zalloc(sizeof(*global));
4545 if (global == NULL)
4546 return NULL;
4547 dl_list_init(&global->p2p_srv_bonjour);
4548 dl_list_init(&global->p2p_srv_upnp);
4549 global->params.daemonize = params->daemonize;
4550 global->params.wait_for_monitor = params->wait_for_monitor;
4551 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4552 if (params->pid_file)
4553 global->params.pid_file = os_strdup(params->pid_file);
4554 if (params->ctrl_interface)
4555 global->params.ctrl_interface =
4556 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004557 if (params->ctrl_interface_group)
4558 global->params.ctrl_interface_group =
4559 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004560 if (params->override_driver)
4561 global->params.override_driver =
4562 os_strdup(params->override_driver);
4563 if (params->override_ctrl_interface)
4564 global->params.override_ctrl_interface =
4565 os_strdup(params->override_ctrl_interface);
4566 wpa_debug_level = global->params.wpa_debug_level =
4567 params->wpa_debug_level;
4568 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4569 params->wpa_debug_show_keys;
4570 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4571 params->wpa_debug_timestamp;
4572
4573 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4574
4575 if (eloop_init()) {
4576 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4577 wpa_supplicant_deinit(global);
4578 return NULL;
4579 }
4580
Jouni Malinen75ecf522011-06-27 15:19:46 -07004581 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004582
4583 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4584 if (global->ctrl_iface == NULL) {
4585 wpa_supplicant_deinit(global);
4586 return NULL;
4587 }
4588
4589 if (wpas_notify_supplicant_initialized(global)) {
4590 wpa_supplicant_deinit(global);
4591 return NULL;
4592 }
4593
4594 for (i = 0; wpa_drivers[i]; i++)
4595 global->drv_count++;
4596 if (global->drv_count == 0) {
4597 wpa_printf(MSG_ERROR, "No drivers enabled");
4598 wpa_supplicant_deinit(global);
4599 return NULL;
4600 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004601 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004602 if (global->drv_priv == NULL) {
4603 wpa_supplicant_deinit(global);
4604 return NULL;
4605 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004606
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004607#ifdef CONFIG_WIFI_DISPLAY
4608 if (wifi_display_init(global) < 0) {
4609 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4610 wpa_supplicant_deinit(global);
4611 return NULL;
4612 }
4613#endif /* CONFIG_WIFI_DISPLAY */
4614
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004615 return global;
4616}
4617
4618
4619/**
4620 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4621 * @global: Pointer to global data from wpa_supplicant_init()
4622 * Returns: 0 after successful event loop run, -1 on failure
4623 *
4624 * This function starts the main event loop and continues running as long as
4625 * there are any remaining events. In most cases, this function is running as
4626 * long as the %wpa_supplicant process in still in use.
4627 */
4628int wpa_supplicant_run(struct wpa_global *global)
4629{
4630 struct wpa_supplicant *wpa_s;
4631
4632 if (global->params.daemonize &&
4633 wpa_supplicant_daemon(global->params.pid_file))
4634 return -1;
4635
4636 if (global->params.wait_for_monitor) {
4637 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4638 if (wpa_s->ctrl_iface)
4639 wpa_supplicant_ctrl_iface_wait(
4640 wpa_s->ctrl_iface);
4641 }
4642
4643 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4644 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4645
4646 eloop_run();
4647
4648 return 0;
4649}
4650
4651
4652/**
4653 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4654 * @global: Pointer to global data from wpa_supplicant_init()
4655 *
4656 * This function is called to deinitialize %wpa_supplicant and to free all
4657 * allocated resources. Remaining network interfaces will also be removed.
4658 */
4659void wpa_supplicant_deinit(struct wpa_global *global)
4660{
4661 int i;
4662
4663 if (global == NULL)
4664 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004665
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004666#ifdef CONFIG_WIFI_DISPLAY
4667 wifi_display_deinit(global);
4668#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004669
4670 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004671 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004672
4673 if (global->ctrl_iface)
4674 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4675
4676 wpas_notify_supplicant_deinitialized(global);
4677
4678 eap_peer_unregister_methods();
4679#ifdef CONFIG_AP
4680 eap_server_unregister_methods();
4681#endif /* CONFIG_AP */
4682
4683 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4684 if (!global->drv_priv[i])
4685 continue;
4686 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4687 }
4688 os_free(global->drv_priv);
4689
4690 random_deinit();
4691
4692 eloop_destroy();
4693
4694 if (global->params.pid_file) {
4695 os_daemonize_terminate(global->params.pid_file);
4696 os_free(global->params.pid_file);
4697 }
4698 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004699 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004700 os_free(global->params.override_driver);
4701 os_free(global->params.override_ctrl_interface);
4702
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004703 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004704 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004705 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004706
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004707 os_free(global);
4708 wpa_debug_close_syslog();
4709 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004710 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004711}
4712
4713
4714void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4715{
4716 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4717 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4718 char country[3];
4719 country[0] = wpa_s->conf->country[0];
4720 country[1] = wpa_s->conf->country[1];
4721 country[2] = '\0';
4722 if (wpa_drv_set_country(wpa_s, country) < 0) {
4723 wpa_printf(MSG_ERROR, "Failed to set country code "
4724 "'%s'", country);
4725 }
4726 }
4727
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004728 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4729 wpas_init_ext_pw(wpa_s);
4730
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004731#ifdef CONFIG_WPS
4732 wpas_wps_update_config(wpa_s);
4733#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004734 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004735 wpa_s->conf->changed_parameters = 0;
4736}
4737
4738
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004739void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004740{
4741 int i;
4742
4743 for (i = 0; i < *num_freqs; i++) {
4744 if (freqs[i] == freq)
4745 return;
4746 }
4747
4748 freqs[*num_freqs] = freq;
4749 (*num_freqs)++;
4750}
4751
4752
4753static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4754{
4755 struct wpa_bss *bss, *cbss;
4756 const int max_freqs = 10;
4757 int *freqs;
4758 int num_freqs = 0;
4759
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004760 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004761 if (freqs == NULL)
4762 return NULL;
4763
4764 cbss = wpa_s->current_bss;
4765
4766 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4767 if (bss == cbss)
4768 continue;
4769 if (bss->ssid_len == cbss->ssid_len &&
4770 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4771 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4772 add_freq(freqs, &num_freqs, bss->freq);
4773 if (num_freqs == max_freqs)
4774 break;
4775 }
4776 }
4777
4778 if (num_freqs == 0) {
4779 os_free(freqs);
4780 freqs = NULL;
4781 }
4782
4783 return freqs;
4784}
4785
4786
4787void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4788{
4789 int timeout;
4790 int count;
4791 int *freqs = NULL;
4792
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004793 wpas_connect_work_done(wpa_s);
4794
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004795 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004796 * Remove possible authentication timeout since the connection failed.
4797 */
4798 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4799
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004800 /*
4801 * There is no point in blacklisting the AP if this event is
4802 * generated based on local request to disconnect.
4803 */
4804 if (wpa_s->own_disconnect_req) {
4805 wpa_s->own_disconnect_req = 0;
4806 wpa_dbg(wpa_s, MSG_DEBUG,
4807 "Ignore connection failure due to local request to disconnect");
4808 return;
4809 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004810 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004811 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4812 "indication since interface has been put into "
4813 "disconnected state");
4814 return;
4815 }
4816
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004817 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004818 * Add the failed BSSID into the blacklist and speed up next scan
4819 * attempt if there could be other APs that could accept association.
4820 * The current blacklist count indicates how many times we have tried
4821 * connecting to this AP and multiple attempts mean that other APs are
4822 * either not available or has already been tried, so that we can start
4823 * increasing the delay here to avoid constant scanning.
4824 */
4825 count = wpa_blacklist_add(wpa_s, bssid);
4826 if (count == 1 && wpa_s->current_bss) {
4827 /*
4828 * This BSS was not in the blacklist before. If there is
4829 * another BSS available for the same ESS, we should try that
4830 * next. Otherwise, we may as well try this one once more
4831 * before allowing other, likely worse, ESSes to be considered.
4832 */
4833 freqs = get_bss_freqs_in_ess(wpa_s);
4834 if (freqs) {
4835 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4836 "has been seen; try it next");
4837 wpa_blacklist_add(wpa_s, bssid);
4838 /*
4839 * On the next scan, go through only the known channels
4840 * used in this ESS based on previous scans to speed up
4841 * common load balancing use case.
4842 */
4843 os_free(wpa_s->next_scan_freqs);
4844 wpa_s->next_scan_freqs = freqs;
4845 }
4846 }
4847
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004848 /*
4849 * Add previous failure count in case the temporary blacklist was
4850 * cleared due to no other BSSes being available.
4851 */
4852 count += wpa_s->extra_blacklist_count;
4853
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004854 if (count > 3 && wpa_s->current_ssid) {
4855 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4856 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004857 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004858 }
4859
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004860 switch (count) {
4861 case 1:
4862 timeout = 100;
4863 break;
4864 case 2:
4865 timeout = 500;
4866 break;
4867 case 3:
4868 timeout = 1000;
4869 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004870 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004871 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004872 break;
4873 default:
4874 timeout = 10000;
4875 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004876 }
4877
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004878 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4879 "ms", count, timeout);
4880
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004881 /*
4882 * TODO: if more than one possible AP is available in scan results,
4883 * could try the other ones before requesting a new scan.
4884 */
4885 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4886 1000 * (timeout % 1000));
4887}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004888
4889
4890int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4891{
4892 return wpa_s->conf->ap_scan == 2 ||
4893 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4894}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004895
Dmitry Shmidt04949592012-07-19 12:16:46 -07004896
4897#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4898int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4899 struct wpa_ssid *ssid,
4900 const char *field,
4901 const char *value)
4902{
4903#ifdef IEEE8021X_EAPOL
4904 struct eap_peer_config *eap = &ssid->eap;
4905
4906 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4907 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4908 (const u8 *) value, os_strlen(value));
4909
4910 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4911 case WPA_CTRL_REQ_EAP_IDENTITY:
4912 os_free(eap->identity);
4913 eap->identity = (u8 *) os_strdup(value);
4914 eap->identity_len = os_strlen(value);
4915 eap->pending_req_identity = 0;
4916 if (ssid == wpa_s->current_ssid)
4917 wpa_s->reassociate = 1;
4918 break;
4919 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004920 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004921 eap->password = (u8 *) os_strdup(value);
4922 eap->password_len = os_strlen(value);
4923 eap->pending_req_password = 0;
4924 if (ssid == wpa_s->current_ssid)
4925 wpa_s->reassociate = 1;
4926 break;
4927 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004928 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004929 eap->new_password = (u8 *) os_strdup(value);
4930 eap->new_password_len = os_strlen(value);
4931 eap->pending_req_new_password = 0;
4932 if (ssid == wpa_s->current_ssid)
4933 wpa_s->reassociate = 1;
4934 break;
4935 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004936 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004937 eap->pin = os_strdup(value);
4938 eap->pending_req_pin = 0;
4939 if (ssid == wpa_s->current_ssid)
4940 wpa_s->reassociate = 1;
4941 break;
4942 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004943 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004944 eap->otp = (u8 *) os_strdup(value);
4945 eap->otp_len = os_strlen(value);
4946 os_free(eap->pending_req_otp);
4947 eap->pending_req_otp = NULL;
4948 eap->pending_req_otp_len = 0;
4949 break;
4950 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004951 str_clear_free(eap->private_key_passwd);
4952 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004953 eap->pending_req_passphrase = 0;
4954 if (ssid == wpa_s->current_ssid)
4955 wpa_s->reassociate = 1;
4956 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004957 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004958 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004959 eap->external_sim_resp = os_strdup(value);
4960 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004961 default:
4962 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4963 return -1;
4964 }
4965
4966 return 0;
4967#else /* IEEE8021X_EAPOL */
4968 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4969 return -1;
4970#endif /* IEEE8021X_EAPOL */
4971}
4972#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4973
4974
4975int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4976{
4977 int i;
4978 unsigned int drv_enc;
4979
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004980 if (wpa_s->p2p_mgmt)
4981 return 1; /* no normal network profiles on p2p_mgmt interface */
4982
Dmitry Shmidt04949592012-07-19 12:16:46 -07004983 if (ssid == NULL)
4984 return 1;
4985
4986 if (ssid->disabled)
4987 return 1;
4988
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004989 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07004990 drv_enc = wpa_s->drv_enc;
4991 else
4992 drv_enc = (unsigned int) -1;
4993
4994 for (i = 0; i < NUM_WEP_KEYS; i++) {
4995 size_t len = ssid->wep_key_len[i];
4996 if (len == 0)
4997 continue;
4998 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4999 continue;
5000 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5001 continue;
5002 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5003 continue;
5004 return 1; /* invalid WEP key */
5005 }
5006
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005007 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07005008 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005009 return 1;
5010
Dmitry Shmidt04949592012-07-19 12:16:46 -07005011 return 0;
5012}
5013
5014
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005015int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5016{
5017#ifdef CONFIG_IEEE80211W
5018 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
5019 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
5020 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
5021 /*
5022 * Driver does not support BIP -- ignore pmf=1 default
5023 * since the connection with PMF would fail and the
5024 * configuration does not require PMF to be enabled.
5025 */
5026 return NO_MGMT_FRAME_PROTECTION;
5027 }
5028
5029 return wpa_s->conf->pmf;
5030 }
5031
5032 return ssid->ieee80211w;
5033#else /* CONFIG_IEEE80211W */
5034 return NO_MGMT_FRAME_PROTECTION;
5035#endif /* CONFIG_IEEE80211W */
5036}
5037
5038
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005039int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005040{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005041 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005042 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005043 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005044 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005045 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005046}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005047
5048
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005049void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005050{
5051 struct wpa_ssid *ssid = wpa_s->current_ssid;
5052 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005053 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005054
5055 if (ssid == NULL) {
5056 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
5057 "SSID block");
5058 return;
5059 }
5060
5061 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
5062 return;
5063
5064 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005065
5066#ifdef CONFIG_P2P
5067 if (ssid->p2p_group &&
5068 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
5069 /*
5070 * Skip the wait time since there is a short timeout on the
5071 * connection to a P2P group.
5072 */
5073 return;
5074 }
5075#endif /* CONFIG_P2P */
5076
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005077 if (ssid->auth_failures > 50)
5078 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005079 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005080 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005081 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005082 dur = 90;
5083 else if (ssid->auth_failures > 3)
5084 dur = 60;
5085 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005086 dur = 30;
5087 else if (ssid->auth_failures > 1)
5088 dur = 20;
5089 else
5090 dur = 10;
5091
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005092 if (ssid->auth_failures > 1 &&
5093 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
5094 dur += os_random() % (ssid->auth_failures * 10);
5095
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005096 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005097 if (now.sec + dur <= ssid->disabled_until.sec)
5098 return;
5099
5100 ssid->disabled_until.sec = now.sec + dur;
5101
5102 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005103 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005104 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005105 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005106}
5107
5108
5109void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
5110 struct wpa_ssid *ssid, int clear_failures)
5111{
5112 if (ssid == NULL)
5113 return;
5114
5115 if (ssid->disabled_until.sec) {
5116 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
5117 "id=%d ssid=\"%s\"",
5118 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
5119 }
5120 ssid->disabled_until.sec = 0;
5121 ssid->disabled_until.usec = 0;
5122 if (clear_failures)
5123 ssid->auth_failures = 0;
5124}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005125
5126
5127int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
5128{
5129 size_t i;
5130
5131 if (wpa_s->disallow_aps_bssid == NULL)
5132 return 0;
5133
5134 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
5135 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
5136 bssid, ETH_ALEN) == 0)
5137 return 1;
5138 }
5139
5140 return 0;
5141}
5142
5143
5144int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
5145 size_t ssid_len)
5146{
5147 size_t i;
5148
5149 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
5150 return 0;
5151
5152 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
5153 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
5154 if (ssid_len == s->ssid_len &&
5155 os_memcmp(ssid, s->ssid, ssid_len) == 0)
5156 return 1;
5157 }
5158
5159 return 0;
5160}
5161
5162
5163/**
5164 * wpas_request_connection - Request a new connection
5165 * @wpa_s: Pointer to the network interface
5166 *
5167 * This function is used to request a new connection to be found. It will mark
5168 * the interface to allow reassociation and request a new scan to find a
5169 * suitable network to connect to.
5170 */
5171void wpas_request_connection(struct wpa_supplicant *wpa_s)
5172{
5173 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005174 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005175 wpa_supplicant_reinit_autoscan(wpa_s);
5176 wpa_s->extra_blacklist_count = 0;
5177 wpa_s->disconnected = 0;
5178 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005179
5180 if (wpa_supplicant_fast_associate(wpa_s) != 1)
5181 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005182 else
5183 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005184}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005185
5186
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005187void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
5188 struct wpa_used_freq_data *freqs_data,
5189 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005190{
5191 unsigned int i;
5192
5193 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
5194 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005195 for (i = 0; i < len; i++) {
5196 struct wpa_used_freq_data *cur = &freqs_data[i];
5197 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
5198 i, cur->freq, cur->flags);
5199 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005200}
5201
5202
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005203/*
5204 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005205 * are using the same radio as the current interface, and in addition, get
5206 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005207 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005208int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
5209 struct wpa_used_freq_data *freqs_data,
5210 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005211{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005212 struct wpa_supplicant *ifs;
5213 u8 bssid[ETH_ALEN];
5214 int freq;
5215 unsigned int idx = 0, i;
5216
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005217 wpa_dbg(wpa_s, MSG_DEBUG,
5218 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005219 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005220
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005221 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
5222 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005223 if (idx == len)
5224 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005225
5226 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
5227 continue;
5228
5229 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
5230 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
5231 freq = ifs->current_ssid->frequency;
5232 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
5233 freq = ifs->assoc_freq;
5234 else
5235 continue;
5236
5237 /* Hold only distinct freqs */
5238 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005239 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005240 break;
5241
5242 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005243 freqs_data[idx++].freq = freq;
5244
5245 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
5246 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
5247 WPA_FREQ_USED_BY_P2P_CLIENT :
5248 WPA_FREQ_USED_BY_INFRA_STATION;
5249 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005250 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005251
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005252 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005253 return idx;
5254}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005255
5256
5257/*
5258 * Find the operating frequencies of any of the virtual interfaces that
5259 * are using the same radio as the current interface.
5260 */
5261int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
5262 int *freq_array, unsigned int len)
5263{
5264 struct wpa_used_freq_data *freqs_data;
5265 int num, i;
5266
5267 os_memset(freq_array, 0, sizeof(int) * len);
5268
5269 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
5270 if (!freqs_data)
5271 return -1;
5272
5273 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
5274 for (i = 0; i < num; i++)
5275 freq_array[i] = freqs_data[i].freq;
5276
5277 os_free(freqs_data);
5278
5279 return num;
5280}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005281
5282
5283static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
5284{
5285 struct rrm_data *rrm = data;
5286
5287 if (!rrm->notify_neighbor_rep) {
5288 wpa_printf(MSG_ERROR,
5289 "RRM: Unexpected neighbor report timeout");
5290 return;
5291 }
5292
5293 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
5294 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
5295
5296 rrm->notify_neighbor_rep = NULL;
5297 rrm->neighbor_rep_cb_ctx = NULL;
5298}
5299
5300
5301/*
5302 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
5303 * @wpa_s: Pointer to wpa_supplicant
5304 */
5305void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
5306{
5307 wpa_s->rrm.rrm_used = 0;
5308
5309 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5310 NULL);
5311 if (wpa_s->rrm.notify_neighbor_rep)
5312 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
5313 wpa_s->rrm.next_neighbor_rep_token = 1;
5314}
5315
5316
5317/*
5318 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
5319 * @wpa_s: Pointer to wpa_supplicant
5320 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
5321 * @report_len: Length of neighbor report buffer
5322 */
5323void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
5324 const u8 *report, size_t report_len)
5325{
5326 struct wpabuf *neighbor_rep;
5327
5328 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
5329 if (report_len < 1)
5330 return;
5331
5332 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
5333 wpa_printf(MSG_DEBUG,
5334 "RRM: Discarding neighbor report with token %d (expected %d)",
5335 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
5336 return;
5337 }
5338
5339 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5340 NULL);
5341
5342 if (!wpa_s->rrm.notify_neighbor_rep) {
5343 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
5344 return;
5345 }
5346
5347 /* skipping the first byte, which is only an id (dialog token) */
5348 neighbor_rep = wpabuf_alloc(report_len - 1);
5349 if (neighbor_rep == NULL)
5350 return;
5351 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
5352 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
5353 report[0]);
5354 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
5355 neighbor_rep);
5356 wpa_s->rrm.notify_neighbor_rep = NULL;
5357 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
5358}
5359
5360
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005361#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
5362/* Workaround different, undefined for Windows, error codes used here */
5363#define ENOTCONN -1
5364#define EOPNOTSUPP -1
5365#define ECANCELED -1
5366#endif
5367
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005368/**
5369 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
5370 * @wpa_s: Pointer to wpa_supplicant
5371 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
5372 * is sent in the request.
5373 * @cb: Callback function to be called once the requested report arrives, or
5374 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
5375 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
5376 * the requester's responsibility to free it.
5377 * In the latter case NULL will be sent in 'neighbor_rep'.
5378 * @cb_ctx: Context value to send the callback function
5379 * Returns: 0 in case of success, negative error code otherwise
5380 *
5381 * In case there is a previous request which has not been answered yet, the
5382 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
5383 * Request must contain a callback function.
5384 */
5385int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
5386 const struct wpa_ssid *ssid,
5387 void (*cb)(void *ctx,
5388 struct wpabuf *neighbor_rep),
5389 void *cb_ctx)
5390{
5391 struct wpabuf *buf;
5392 const u8 *rrm_ie;
5393
5394 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
5395 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
5396 return -ENOTCONN;
5397 }
5398
5399 if (!wpa_s->rrm.rrm_used) {
5400 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
5401 return -EOPNOTSUPP;
5402 }
5403
5404 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
5405 WLAN_EID_RRM_ENABLED_CAPABILITIES);
5406 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
5407 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
5408 wpa_printf(MSG_DEBUG,
5409 "RRM: No network support for Neighbor Report.");
5410 return -EOPNOTSUPP;
5411 }
5412
5413 if (!cb) {
5414 wpa_printf(MSG_DEBUG,
5415 "RRM: Neighbor Report request must provide a callback.");
5416 return -EINVAL;
5417 }
5418
5419 /* Refuse if there's a live request */
5420 if (wpa_s->rrm.notify_neighbor_rep) {
5421 wpa_printf(MSG_DEBUG,
5422 "RRM: Currently handling previous Neighbor Report.");
5423 return -EBUSY;
5424 }
5425
5426 /* 3 = action category + action code + dialog token */
5427 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
5428 if (buf == NULL) {
5429 wpa_printf(MSG_DEBUG,
5430 "RRM: Failed to allocate Neighbor Report Request");
5431 return -ENOMEM;
5432 }
5433
5434 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
5435 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
5436 wpa_s->rrm.next_neighbor_rep_token);
5437
5438 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5439 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
5440 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
5441 if (ssid) {
5442 wpabuf_put_u8(buf, WLAN_EID_SSID);
5443 wpabuf_put_u8(buf, ssid->ssid_len);
5444 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
5445 }
5446
5447 wpa_s->rrm.next_neighbor_rep_token++;
5448
5449 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
5450 wpa_s->own_addr, wpa_s->bssid,
5451 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
5452 wpa_printf(MSG_DEBUG,
5453 "RRM: Failed to send Neighbor Report Request");
5454 wpabuf_free(buf);
5455 return -ECANCELED;
5456 }
5457
5458 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
5459 wpa_s->rrm.notify_neighbor_rep = cb;
5460 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
5461 wpas_rrm_neighbor_rep_timeout_handler,
5462 &wpa_s->rrm, NULL);
5463
5464 wpabuf_free(buf);
5465 return 0;
5466}
5467
5468
5469void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
5470 const u8 *src,
5471 const u8 *frame, size_t len,
5472 int rssi)
5473{
5474 struct wpabuf *buf;
5475 const struct rrm_link_measurement_request *req;
5476 struct rrm_link_measurement_report report;
5477
5478 if (wpa_s->wpa_state != WPA_COMPLETED) {
5479 wpa_printf(MSG_INFO,
5480 "RRM: Ignoring link measurement request. Not associated");
5481 return;
5482 }
5483
5484 if (!wpa_s->rrm.rrm_used) {
5485 wpa_printf(MSG_INFO,
5486 "RRM: Ignoring link measurement request. Not RRM network");
5487 return;
5488 }
5489
5490 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
5491 wpa_printf(MSG_INFO,
5492 "RRM: Measurement report failed. TX power insertion not supported");
5493 return;
5494 }
5495
5496 req = (const struct rrm_link_measurement_request *) frame;
5497 if (len < sizeof(*req)) {
5498 wpa_printf(MSG_INFO,
5499 "RRM: Link measurement report failed. Request too short");
5500 return;
5501 }
5502
5503 os_memset(&report, 0, sizeof(report));
5504 report.tpc.eid = WLAN_EID_TPC_REPORT;
5505 report.tpc.len = 2;
5506 report.rsni = 255; /* 255 indicates that RSNI is not available */
5507 report.dialog_token = req->dialog_token;
5508
5509 /*
5510 * It's possible to estimate RCPI based on RSSI in dBm. This
5511 * calculation will not reflect the correct value for high rates,
5512 * but it's good enough for Action frames which are transmitted
5513 * with up to 24 Mbps rates.
5514 */
5515 if (!rssi)
5516 report.rcpi = 255; /* not available */
5517 else if (rssi < -110)
5518 report.rcpi = 0;
5519 else if (rssi > 0)
5520 report.rcpi = 220;
5521 else
5522 report.rcpi = (rssi + 110) * 2;
5523
5524 /* action_category + action_code */
5525 buf = wpabuf_alloc(2 + sizeof(report));
5526 if (buf == NULL) {
5527 wpa_printf(MSG_ERROR,
5528 "RRM: Link measurement report failed. Buffer allocation failed");
5529 return;
5530 }
5531
5532 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5533 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
5534 wpabuf_put_data(buf, &report, sizeof(report));
5535 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
5536 wpabuf_head(buf), wpabuf_len(buf));
5537
5538 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
5539 wpa_s->own_addr, wpa_s->bssid,
5540 wpabuf_head(buf), wpabuf_len(buf), 0)) {
5541 wpa_printf(MSG_ERROR,
5542 "RRM: Link measurement report failed. Send action failed");
5543 }
5544 wpabuf_free(buf);
5545}