blob: 722294da2b2e123fec8448e582b62a8eea1eb5fe [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
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070058const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070059"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
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070062const char *const 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. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070073const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080074"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070075const char *const 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";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070082const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070083"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";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070090const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070091"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";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070099const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700100"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
101"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
102"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
103"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
104"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
105"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
106"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
107"\n";
108#endif /* CONFIG_NO_STDOUT_DEBUG */
109
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700110/* Configure default/group WEP keys for static WEP */
111int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
112{
113 int i, set = 0;
114
115 for (i = 0; i < NUM_WEP_KEYS; i++) {
116 if (ssid->wep_key_len[i] == 0)
117 continue;
118
119 set = 1;
120 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
121 i, i == ssid->wep_tx_keyidx, NULL, 0,
122 ssid->wep_key[i], ssid->wep_key_len[i]);
123 }
124
125 return set;
126}
127
128
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700129int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
130 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700131{
132 u8 key[32];
133 size_t keylen;
134 enum wpa_alg alg;
135 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800136 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700137
138 /* IBSS/WPA-None uses only one key (Group) for both receiving and
139 * sending unicast and multicast packets. */
140
141 if (ssid->mode != WPAS_MODE_IBSS) {
142 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
143 "IBSS/ad-hoc) for WPA-None", ssid->mode);
144 return -1;
145 }
146
147 if (!ssid->psk_set) {
148 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
149 "WPA-None");
150 return -1;
151 }
152
153 switch (wpa_s->group_cipher) {
154 case WPA_CIPHER_CCMP:
155 os_memcpy(key, ssid->psk, 16);
156 keylen = 16;
157 alg = WPA_ALG_CCMP;
158 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700159 case WPA_CIPHER_GCMP:
160 os_memcpy(key, ssid->psk, 16);
161 keylen = 16;
162 alg = WPA_ALG_GCMP;
163 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700164 case WPA_CIPHER_TKIP:
165 /* WPA-None uses the same Michael MIC key for both TX and RX */
166 os_memcpy(key, ssid->psk, 16 + 8);
167 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
168 keylen = 32;
169 alg = WPA_ALG_TKIP;
170 break;
171 default:
172 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
173 "WPA-None", wpa_s->group_cipher);
174 return -1;
175 }
176
177 /* TODO: should actually remember the previously used seq#, both for TX
178 * and RX from each STA.. */
179
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800180 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
181 os_memset(key, 0, sizeof(key));
182 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700183}
184
185
186static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
187{
188 struct wpa_supplicant *wpa_s = eloop_ctx;
189 const u8 *bssid = wpa_s->bssid;
190 if (is_zero_ether_addr(bssid))
191 bssid = wpa_s->pending_bssid;
192 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
193 MAC2STR(bssid));
194 wpa_blacklist_add(wpa_s, bssid);
195 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800196 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700197 wpa_s->reassociate = 1;
198
199 /*
200 * If we timed out, the AP or the local radio may be busy.
201 * So, wait a second until scanning again.
202 */
203 wpa_supplicant_req_scan(wpa_s, 1, 0);
204}
205
206
207/**
208 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
209 * @wpa_s: Pointer to wpa_supplicant data
210 * @sec: Number of seconds after which to time out authentication
211 * @usec: Number of microseconds after which to time out authentication
212 *
213 * This function is used to schedule a timeout for the current authentication
214 * attempt.
215 */
216void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
217 int sec, int usec)
218{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700219 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700220 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
221 return;
222
223 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
224 "%d usec", sec, usec);
225 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
226 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
227}
228
229
230/**
231 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
232 * @wpa_s: Pointer to wpa_supplicant data
233 *
234 * This function is used to cancel authentication timeout scheduled with
235 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
236 * been completed.
237 */
238void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
239{
240 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
241 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
242 wpa_blacklist_del(wpa_s, wpa_s->bssid);
243}
244
245
246/**
247 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
248 * @wpa_s: Pointer to wpa_supplicant data
249 *
250 * This function is used to configure EAPOL state machine based on the selected
251 * authentication mode.
252 */
253void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
254{
255#ifdef IEEE8021X_EAPOL
256 struct eapol_config eapol_conf;
257 struct wpa_ssid *ssid = wpa_s->current_ssid;
258
259#ifdef CONFIG_IBSS_RSN
260 if (ssid->mode == WPAS_MODE_IBSS &&
261 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
262 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
263 /*
264 * RSN IBSS authentication is per-STA and we can disable the
265 * per-BSSID EAPOL authentication.
266 */
267 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
268 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
269 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
270 return;
271 }
272#endif /* CONFIG_IBSS_RSN */
273
274 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
275 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
276
277 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
278 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
279 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
280 else
281 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
282
283 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
284 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
285 eapol_conf.accept_802_1x_keys = 1;
286 eapol_conf.required_keys = 0;
287 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
288 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
289 }
290 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
291 eapol_conf.required_keys |=
292 EAPOL_REQUIRE_KEY_BROADCAST;
293 }
294
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700295 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700296 eapol_conf.required_keys = 0;
297 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700298 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299 eapol_conf.workaround = ssid->eap_workaround;
300 eapol_conf.eap_disabled =
301 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
302 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
303 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700304 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800305
306#ifdef CONFIG_WPS
307 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
308 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
309 if (wpa_s->current_bss) {
310 struct wpabuf *ie;
311 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
312 WPS_IE_VENDOR_TYPE);
313 if (ie) {
314 if (wps_is_20(ie))
315 eapol_conf.wps |=
316 EAPOL_PEER_IS_WPS20_AP;
317 wpabuf_free(ie);
318 }
319 }
320 }
321#endif /* CONFIG_WPS */
322
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700323 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700324
325 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800326#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700327}
328
329
330/**
331 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
332 * @wpa_s: Pointer to wpa_supplicant data
333 * @ssid: Configuration data for the network
334 *
335 * This function is used to configure WPA state machine and related parameters
336 * to a mode where WPA is not enabled. This is called as part of the
337 * authentication configuration when the selected network does not use WPA.
338 */
339void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
340 struct wpa_ssid *ssid)
341{
342 int i;
343
344 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
345 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
346 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
347 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
348 else
349 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
350 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
351 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
352 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
353 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
354 wpa_s->group_cipher = WPA_CIPHER_NONE;
355 wpa_s->mgmt_group_cipher = 0;
356
357 for (i = 0; i < NUM_WEP_KEYS; i++) {
358 if (ssid->wep_key_len[i] > 5) {
359 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
360 wpa_s->group_cipher = WPA_CIPHER_WEP104;
361 break;
362 } else if (ssid->wep_key_len[i] > 0) {
363 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
364 wpa_s->group_cipher = WPA_CIPHER_WEP40;
365 break;
366 }
367 }
368
369 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
370 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
371 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
372 wpa_s->pairwise_cipher);
373 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
374#ifdef CONFIG_IEEE80211W
375 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
376 wpa_s->mgmt_group_cipher);
377#endif /* CONFIG_IEEE80211W */
378
379 pmksa_cache_clear_current(wpa_s->wpa);
380}
381
382
Dmitry Shmidt04949592012-07-19 12:16:46 -0700383void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800384{
385 int i;
386 if (wpa_s->hw.modes == NULL)
387 return;
388
389 for (i = 0; i < wpa_s->hw.num_modes; i++) {
390 os_free(wpa_s->hw.modes[i].channels);
391 os_free(wpa_s->hw.modes[i].rates);
392 }
393
394 os_free(wpa_s->hw.modes);
395 wpa_s->hw.modes = NULL;
396}
397
398
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700399static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
400{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700401 int i;
402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700403 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700404 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700405 scard_deinit(wpa_s->scard);
406 wpa_s->scard = NULL;
407 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
408 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
409 l2_packet_deinit(wpa_s->l2);
410 wpa_s->l2 = NULL;
411 if (wpa_s->l2_br) {
412 l2_packet_deinit(wpa_s->l2_br);
413 wpa_s->l2_br = NULL;
414 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800415#ifdef CONFIG_TESTING_OPTIONS
416 l2_packet_deinit(wpa_s->l2_test);
417 wpa_s->l2_test = NULL;
418#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700420 if (wpa_s->conf != NULL) {
421 struct wpa_ssid *ssid;
422 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
423 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 }
425
426 os_free(wpa_s->confname);
427 wpa_s->confname = NULL;
428
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700429 os_free(wpa_s->confanother);
430 wpa_s->confanother = NULL;
431
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432 wpa_sm_set_eapol(wpa_s->wpa, NULL);
433 eapol_sm_deinit(wpa_s->eapol);
434 wpa_s->eapol = NULL;
435
436 rsn_preauth_deinit(wpa_s->wpa);
437
438#ifdef CONFIG_TDLS
439 wpa_tdls_deinit(wpa_s->wpa);
440#endif /* CONFIG_TDLS */
441
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800442 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 pmksa_candidate_free(wpa_s->wpa);
444 wpa_sm_deinit(wpa_s->wpa);
445 wpa_s->wpa = NULL;
446 wpa_blacklist_clear(wpa_s);
447
448 wpa_bss_deinit(wpa_s);
449
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700450 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451 wpa_supplicant_cancel_scan(wpa_s);
452 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800453 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
454#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
455 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
456 wpa_s, NULL);
457#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700458
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700459 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
460
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700461 wpas_wps_deinit(wpa_s);
462
463 wpabuf_free(wpa_s->pending_eapol_rx);
464 wpa_s->pending_eapol_rx = NULL;
465
466#ifdef CONFIG_IBSS_RSN
467 ibss_rsn_deinit(wpa_s->ibss_rsn);
468 wpa_s->ibss_rsn = NULL;
469#endif /* CONFIG_IBSS_RSN */
470
471 sme_deinit(wpa_s);
472
473#ifdef CONFIG_AP
474 wpa_supplicant_ap_deinit(wpa_s);
475#endif /* CONFIG_AP */
476
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700477 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800479#ifdef CONFIG_OFFCHANNEL
480 offchannel_deinit(wpa_s);
481#endif /* CONFIG_OFFCHANNEL */
482
483 wpa_supplicant_cancel_sched_scan(wpa_s);
484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700485 os_free(wpa_s->next_scan_freqs);
486 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800487
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800488 os_free(wpa_s->manual_scan_freqs);
489 wpa_s->manual_scan_freqs = NULL;
490
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700491 os_free(wpa_s->manual_sched_scan_freqs);
492 wpa_s->manual_sched_scan_freqs = NULL;
493
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800494 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
495
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700496 /*
497 * Need to remove any pending gas-query radio work before the
498 * gas_query_deinit() call because gas_query::work has not yet been set
499 * for works that have not been started. gas_query_free() will be unable
500 * to cancel such pending radio works and once the pending gas-query
501 * radio work eventually gets removed, the deinit notification call to
502 * gas_query_start_cb() would result in dereferencing freed memory.
503 */
504 if (wpa_s->radio)
505 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800506 gas_query_deinit(wpa_s->gas);
507 wpa_s->gas = NULL;
508
509 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700510
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700511 ieee802_1x_dealloc_kay_sm(wpa_s);
512
Dmitry Shmidt04949592012-07-19 12:16:46 -0700513 os_free(wpa_s->bssid_filter);
514 wpa_s->bssid_filter = NULL;
515
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800516 os_free(wpa_s->disallow_aps_bssid);
517 wpa_s->disallow_aps_bssid = NULL;
518 os_free(wpa_s->disallow_aps_ssid);
519 wpa_s->disallow_aps_ssid = NULL;
520
Dmitry Shmidt04949592012-07-19 12:16:46 -0700521 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700522#ifdef CONFIG_WNM
523 wnm_deallocate_memory(wpa_s);
524#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700525
526 ext_password_deinit(wpa_s->ext_pw);
527 wpa_s->ext_pw = NULL;
528
529 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800530 wpa_s->last_gas_resp = NULL;
531 wpabuf_free(wpa_s->prev_gas_resp);
532 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700533
534 os_free(wpa_s->last_scan_res);
535 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800536
537#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700538 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800539#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700540
541 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
542 wpabuf_free(wpa_s->vendor_elem[i]);
543 wpa_s->vendor_elem[i] = NULL;
544 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800545
546 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700547}
548
549
550/**
551 * wpa_clear_keys - Clear keys configured for the driver
552 * @wpa_s: Pointer to wpa_supplicant data
553 * @addr: Previously used BSSID or %NULL if not available
554 *
555 * This function clears the encryption keys that has been previously configured
556 * for the driver.
557 */
558void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
559{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800560 int i, max;
561
562#ifdef CONFIG_IEEE80211W
563 max = 6;
564#else /* CONFIG_IEEE80211W */
565 max = 4;
566#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700567
568 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800569 for (i = 0; i < max; i++) {
570 if (wpa_s->keys_cleared & BIT(i))
571 continue;
572 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
573 NULL, 0);
574 }
575 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
576 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
578 0);
579 /* MLME-SETPROTECTION.request(None) */
580 wpa_drv_mlme_setprotection(
581 wpa_s, addr,
582 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
583 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
584 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800585 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700586}
587
588
589/**
590 * wpa_supplicant_state_txt - Get the connection state name as a text string
591 * @state: State (wpa_state; WPA_*)
592 * Returns: The state name as a printable text string
593 */
594const char * wpa_supplicant_state_txt(enum wpa_states state)
595{
596 switch (state) {
597 case WPA_DISCONNECTED:
598 return "DISCONNECTED";
599 case WPA_INACTIVE:
600 return "INACTIVE";
601 case WPA_INTERFACE_DISABLED:
602 return "INTERFACE_DISABLED";
603 case WPA_SCANNING:
604 return "SCANNING";
605 case WPA_AUTHENTICATING:
606 return "AUTHENTICATING";
607 case WPA_ASSOCIATING:
608 return "ASSOCIATING";
609 case WPA_ASSOCIATED:
610 return "ASSOCIATED";
611 case WPA_4WAY_HANDSHAKE:
612 return "4WAY_HANDSHAKE";
613 case WPA_GROUP_HANDSHAKE:
614 return "GROUP_HANDSHAKE";
615 case WPA_COMPLETED:
616 return "COMPLETED";
617 default:
618 return "UNKNOWN";
619 }
620}
621
622
623#ifdef CONFIG_BGSCAN
624
625static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
626{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800627 const char *name;
628
629 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
630 name = wpa_s->current_ssid->bgscan;
631 else
632 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800633 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800634 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800635 if (wpas_driver_bss_selection(wpa_s))
636 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
638 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800639#ifdef CONFIG_P2P
640 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
641 return;
642#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700643
644 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800645 if (wpa_s->current_ssid) {
646 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700647 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
648 "bgscan");
649 /*
650 * Live without bgscan; it is only used as a roaming
651 * optimization, so the initial connection is not
652 * affected.
653 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700654 } else {
655 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700656 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700657 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
658 0);
659 if (scan_res) {
660 bgscan_notify_scan(wpa_s, scan_res);
661 wpa_scan_results_free(scan_res);
662 }
663 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700664 } else
665 wpa_s->bgscan_ssid = NULL;
666}
667
668
669static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
670{
671 if (wpa_s->bgscan_ssid != NULL) {
672 bgscan_deinit(wpa_s);
673 wpa_s->bgscan_ssid = NULL;
674 }
675}
676
677#endif /* CONFIG_BGSCAN */
678
679
Dmitry Shmidt04949592012-07-19 12:16:46 -0700680static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
681{
682 if (autoscan_init(wpa_s, 0))
683 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
684}
685
686
687static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
688{
689 autoscan_deinit(wpa_s);
690}
691
692
693void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
694{
695 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
696 wpa_s->wpa_state == WPA_SCANNING) {
697 autoscan_deinit(wpa_s);
698 wpa_supplicant_start_autoscan(wpa_s);
699 }
700}
701
702
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700703/**
704 * wpa_supplicant_set_state - Set current connection state
705 * @wpa_s: Pointer to wpa_supplicant data
706 * @state: The new connection state
707 *
708 * This function is called whenever the connection state changes, e.g.,
709 * association is completed for WPA/WPA2 4-Way Handshake is started.
710 */
711void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
712 enum wpa_states state)
713{
714 enum wpa_states old_state = wpa_s->wpa_state;
715
716 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
717 wpa_supplicant_state_txt(wpa_s->wpa_state),
718 wpa_supplicant_state_txt(state));
719
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800720 if (state == WPA_INTERFACE_DISABLED) {
721 /* Assure normal scan when interface is restored */
722 wpa_s->normal_scans = 0;
723 }
724
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700725 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800726 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700727 /* Reinitialize normal_scan counter */
728 wpa_s->normal_scans = 0;
729 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800730
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700731#ifdef CONFIG_P2P
732 /*
733 * P2PS client has to reply to Probe Request frames received on the
734 * group operating channel. Enable Probe Request frame reporting for
735 * P2P connected client in case p2p_cli_probe configuration property is
736 * set to 1.
737 */
738 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
739 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
740 wpa_s->current_ssid->p2p_group) {
741 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
742 wpa_dbg(wpa_s, MSG_DEBUG,
743 "P2P: Enable CLI Probe Request RX reporting");
744 wpa_s->p2p_cli_probe =
745 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
746 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
747 wpa_dbg(wpa_s, MSG_DEBUG,
748 "P2P: Disable CLI Probe Request RX reporting");
749 wpa_s->p2p_cli_probe = 0;
750 wpa_drv_probe_req_report(wpa_s, 0);
751 }
752 }
753#endif /* CONFIG_P2P */
754
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755 if (state != WPA_SCANNING)
756 wpa_supplicant_notify_scanning(wpa_s, 0);
757
758 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700759 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700760#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700761 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800762 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800763 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700764 ssid ? ssid->id : -1,
765 ssid && ssid->id_str ? ssid->id_str : "");
766#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700767 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700768 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800769 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700770 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700771 wpa_drv_set_operstate(wpa_s, 1);
772#ifndef IEEE8021X_EAPOL
773 wpa_drv_set_supp_port(wpa_s, 1);
774#endif /* IEEE8021X_EAPOL */
775 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700776 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700777 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700778
779 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700780 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
781 state == WPA_ASSOCIATED) {
782 wpa_s->new_connection = 1;
783 wpa_drv_set_operstate(wpa_s, 0);
784#ifndef IEEE8021X_EAPOL
785 wpa_drv_set_supp_port(wpa_s, 0);
786#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700787 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700788 }
789 wpa_s->wpa_state = state;
790
791#ifdef CONFIG_BGSCAN
792 if (state == WPA_COMPLETED)
793 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800794 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700795 wpa_supplicant_stop_bgscan(wpa_s);
796#endif /* CONFIG_BGSCAN */
797
Dmitry Shmidt04949592012-07-19 12:16:46 -0700798 if (state == WPA_AUTHENTICATING)
799 wpa_supplicant_stop_autoscan(wpa_s);
800
801 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
802 wpa_supplicant_start_autoscan(wpa_s);
803
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800804 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
805 wmm_ac_notify_disassoc(wpa_s);
806
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807 if (wpa_s->wpa_state != old_state) {
808 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
809
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700810 /*
811 * Notify the P2P Device interface about a state change in one
812 * of the interfaces.
813 */
814 wpas_p2p_indicate_state_change(wpa_s);
815
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700816 if (wpa_s->wpa_state == WPA_COMPLETED ||
817 old_state == WPA_COMPLETED)
818 wpas_notify_auth_changed(wpa_s);
819 }
820}
821
822
823void wpa_supplicant_terminate_proc(struct wpa_global *global)
824{
825 int pending = 0;
826#ifdef CONFIG_WPS
827 struct wpa_supplicant *wpa_s = global->ifaces;
828 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800829 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700830 if (wpas_wps_terminate_pending(wpa_s) == 1)
831 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700832#ifdef CONFIG_P2P
833 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
834 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
835 wpas_p2p_disconnect(wpa_s);
836#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800837 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700838 }
839#endif /* CONFIG_WPS */
840 if (pending)
841 return;
842 eloop_terminate();
843}
844
845
846static void wpa_supplicant_terminate(int sig, void *signal_ctx)
847{
848 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849 wpa_supplicant_terminate_proc(global);
850}
851
852
853void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
854{
855 enum wpa_states old_state = wpa_s->wpa_state;
856
857 wpa_s->pairwise_cipher = 0;
858 wpa_s->group_cipher = 0;
859 wpa_s->mgmt_group_cipher = 0;
860 wpa_s->key_mgmt = 0;
861 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700862 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700863
864 if (wpa_s->wpa_state != old_state)
865 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
866}
867
868
869/**
870 * wpa_supplicant_reload_configuration - Reload configuration data
871 * @wpa_s: Pointer to wpa_supplicant data
872 * Returns: 0 on success or -1 if configuration parsing failed
873 *
874 * This function can be used to request that the configuration data is reloaded
875 * (e.g., after configuration file change). This function is reloading
876 * configuration only for one interface, so this may need to be called multiple
877 * times if %wpa_supplicant is controlling multiple interfaces and all
878 * interfaces need reconfiguration.
879 */
880int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
881{
882 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700883 int reconf_ctrl;
884 int old_ap_scan;
885
886 if (wpa_s->confname == NULL)
887 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700888 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700889 if (conf == NULL) {
890 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
891 "file '%s' - exiting", wpa_s->confname);
892 return -1;
893 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700894 wpa_config_read(wpa_s->confanother, conf);
895
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700896 conf->changed_parameters = (unsigned int) -1;
897
898 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
899 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
900 os_strcmp(conf->ctrl_interface,
901 wpa_s->conf->ctrl_interface) != 0);
902
903 if (reconf_ctrl && wpa_s->ctrl_iface) {
904 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
905 wpa_s->ctrl_iface = NULL;
906 }
907
908 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800909 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700910 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
911 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800912 wpa_supplicant_deauthenticate(wpa_s,
913 WLAN_REASON_DEAUTH_LEAVING);
914 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700915
916 /*
917 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800918 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700919 */
920 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
921 /*
922 * Clear forced success to clear EAP state for next
923 * authentication.
924 */
925 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
926 }
927 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
928 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800929 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
931 rsn_preauth_deinit(wpa_s->wpa);
932
933 old_ap_scan = wpa_s->conf->ap_scan;
934 wpa_config_free(wpa_s->conf);
935 wpa_s->conf = conf;
936 if (old_ap_scan != wpa_s->conf->ap_scan)
937 wpas_notify_ap_scan_changed(wpa_s);
938
939 if (reconf_ctrl)
940 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
941
942 wpa_supplicant_update_config(wpa_s);
943
944 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700945 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700946 wpa_s->reassociate = 1;
947 wpa_supplicant_req_scan(wpa_s, 0, 0);
948 }
949 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
950 return 0;
951}
952
953
954static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
955{
956 struct wpa_global *global = signal_ctx;
957 struct wpa_supplicant *wpa_s;
958 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
959 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
960 sig);
961 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
962 wpa_supplicant_terminate_proc(global);
963 }
964 }
965}
966
967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700968static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
969 struct wpa_ssid *ssid,
970 struct wpa_ie_data *ie)
971{
972 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
973 if (ret) {
974 if (ret == -2) {
975 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
976 "from association info");
977 }
978 return -1;
979 }
980
981 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
982 "cipher suites");
983 if (!(ie->group_cipher & ssid->group_cipher)) {
984 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
985 "cipher 0x%x (mask 0x%x) - reject",
986 ie->group_cipher, ssid->group_cipher);
987 return -1;
988 }
989 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
990 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
991 "cipher 0x%x (mask 0x%x) - reject",
992 ie->pairwise_cipher, ssid->pairwise_cipher);
993 return -1;
994 }
995 if (!(ie->key_mgmt & ssid->key_mgmt)) {
996 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
997 "management 0x%x (mask 0x%x) - reject",
998 ie->key_mgmt, ssid->key_mgmt);
999 return -1;
1000 }
1001
1002#ifdef CONFIG_IEEE80211W
1003 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001004 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001005 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1006 "that does not support management frame protection - "
1007 "reject");
1008 return -1;
1009 }
1010#endif /* CONFIG_IEEE80211W */
1011
1012 return 0;
1013}
1014
1015
1016/**
1017 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1018 * @wpa_s: Pointer to wpa_supplicant data
1019 * @bss: Scan results for the selected BSS, or %NULL if not available
1020 * @ssid: Configuration data for the selected network
1021 * @wpa_ie: Buffer for the WPA/RSN IE
1022 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1023 * used buffer length in case the functions returns success.
1024 * Returns: 0 on success or -1 on failure
1025 *
1026 * This function is used to configure authentication and encryption parameters
1027 * based on the network configuration and scan result for the selected BSS (if
1028 * available).
1029 */
1030int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1031 struct wpa_bss *bss, struct wpa_ssid *ssid,
1032 u8 *wpa_ie, size_t *wpa_ie_len)
1033{
1034 struct wpa_ie_data ie;
1035 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001036 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037
1038 if (bss) {
1039 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1040 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001041 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001043 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001044
1045 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1046 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1047 (ie.group_cipher & ssid->group_cipher) &&
1048 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1049 (ie.key_mgmt & ssid->key_mgmt)) {
1050 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1051 proto = WPA_PROTO_RSN;
1052 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001053 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001054 (ie.group_cipher & ssid->group_cipher) &&
1055 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1056 (ie.key_mgmt & ssid->key_mgmt)) {
1057 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1058 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001059#ifdef CONFIG_HS20
1060 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1061 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1062 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001063 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001064 ie.group_cipher = WPA_CIPHER_CCMP;
1065 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1066 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1067 proto = WPA_PROTO_OSEN;
1068#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069 } else if (bss) {
1070 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001071 wpa_dbg(wpa_s, MSG_DEBUG,
1072 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1073 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1074 ssid->key_mgmt);
1075 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1076 MAC2STR(bss->bssid),
1077 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1078 bss_wpa ? " WPA" : "",
1079 bss_rsn ? " RSN" : "",
1080 bss_osen ? " OSEN" : "");
1081 if (bss_rsn) {
1082 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1083 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1084 wpa_dbg(wpa_s, MSG_DEBUG,
1085 "Could not parse RSN element");
1086 } else {
1087 wpa_dbg(wpa_s, MSG_DEBUG,
1088 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1089 ie.pairwise_cipher, ie.group_cipher,
1090 ie.key_mgmt);
1091 }
1092 }
1093 if (bss_wpa) {
1094 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1095 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1096 wpa_dbg(wpa_s, MSG_DEBUG,
1097 "Could not parse WPA element");
1098 } else {
1099 wpa_dbg(wpa_s, MSG_DEBUG,
1100 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1101 ie.pairwise_cipher, ie.group_cipher,
1102 ie.key_mgmt);
1103 }
1104 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105 return -1;
1106 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001107 if (ssid->proto & WPA_PROTO_OSEN)
1108 proto = WPA_PROTO_OSEN;
1109 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001110 proto = WPA_PROTO_RSN;
1111 else
1112 proto = WPA_PROTO_WPA;
1113 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1114 os_memset(&ie, 0, sizeof(ie));
1115 ie.group_cipher = ssid->group_cipher;
1116 ie.pairwise_cipher = ssid->pairwise_cipher;
1117 ie.key_mgmt = ssid->key_mgmt;
1118#ifdef CONFIG_IEEE80211W
1119 ie.mgmt_group_cipher =
1120 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1121 WPA_CIPHER_AES_128_CMAC : 0;
1122#endif /* CONFIG_IEEE80211W */
1123 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1124 "based on configuration");
1125 } else
1126 proto = ie.proto;
1127 }
1128
1129 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1130 "pairwise %d key_mgmt %d proto %d",
1131 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1132#ifdef CONFIG_IEEE80211W
1133 if (ssid->ieee80211w) {
1134 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1135 ie.mgmt_group_cipher);
1136 }
1137#endif /* CONFIG_IEEE80211W */
1138
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001139 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001140 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1141 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001142 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001143
1144 if (bss || !wpa_s->ap_ies_from_associnfo) {
1145 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1146 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1147 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1148 bss_rsn ? 2 + bss_rsn[1] : 0))
1149 return -1;
1150 }
1151
1152 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001153 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1154 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001155 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1156 "cipher");
1157 return -1;
1158 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001159 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1160 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001161
1162 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001163 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1164 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1166 "cipher");
1167 return -1;
1168 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001169 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1170 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001171
1172 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001173#ifdef CONFIG_SAE
1174 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1175 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1176#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001177 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001178#ifdef CONFIG_SUITEB192
1179 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1180 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1181 wpa_dbg(wpa_s, MSG_DEBUG,
1182 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1183#endif /* CONFIG_SUITEB192 */
1184#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001185 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1186 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1187 wpa_dbg(wpa_s, MSG_DEBUG,
1188 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001189#endif /* CONFIG_SUITEB */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190#ifdef CONFIG_IEEE80211R
1191 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1192 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1193 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1194 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1195 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1196 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1197#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001198#ifdef CONFIG_SAE
1199 } else if (sel & WPA_KEY_MGMT_SAE) {
1200 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1201 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1202 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1203 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1204 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1205#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001206#ifdef CONFIG_IEEE80211W
1207 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1208 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1209 wpa_dbg(wpa_s, MSG_DEBUG,
1210 "WPA: using KEY_MGMT 802.1X with SHA256");
1211 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1212 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1213 wpa_dbg(wpa_s, MSG_DEBUG,
1214 "WPA: using KEY_MGMT PSK with SHA256");
1215#endif /* CONFIG_IEEE80211W */
1216 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1217 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1218 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1219 } else if (sel & WPA_KEY_MGMT_PSK) {
1220 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1221 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1222 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1223 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1224 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001225#ifdef CONFIG_HS20
1226 } else if (sel & WPA_KEY_MGMT_OSEN) {
1227 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1228 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1229#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001230 } else {
1231 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1232 "authenticated key management type");
1233 return -1;
1234 }
1235
1236 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1237 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1238 wpa_s->pairwise_cipher);
1239 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1240
1241#ifdef CONFIG_IEEE80211W
1242 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001243 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001244 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1245 sel = 0;
1246 if (sel & WPA_CIPHER_AES_128_CMAC) {
1247 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1248 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1249 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001250 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1251 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1252 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1253 "BIP-GMAC-128");
1254 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1255 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1256 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1257 "BIP-GMAC-256");
1258 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1259 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1260 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1261 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001262 } else {
1263 wpa_s->mgmt_group_cipher = 0;
1264 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1265 }
1266 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1267 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001268 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001269 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001270#endif /* CONFIG_IEEE80211W */
1271
1272 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1273 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1274 return -1;
1275 }
1276
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001277 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001278 int psk_set = 0;
1279
1280 if (ssid->psk_set) {
1281 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
1282 psk_set = 1;
1283 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001284#ifndef CONFIG_NO_PBKDF2
1285 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1286 ssid->passphrase) {
1287 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001288 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1289 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001290 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1291 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001292 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001293 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001294 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001295 }
1296#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001297#ifdef CONFIG_EXT_PASSWORD
1298 if (ssid->ext_psk) {
1299 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1300 ssid->ext_psk);
1301 char pw_str[64 + 1];
1302 u8 psk[PMK_LEN];
1303
1304 if (pw == NULL) {
1305 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1306 "found from external storage");
1307 return -1;
1308 }
1309
1310 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1311 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1312 "PSK length %d in external storage",
1313 (int) wpabuf_len(pw));
1314 ext_password_free(pw);
1315 return -1;
1316 }
1317
1318 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1319 pw_str[wpabuf_len(pw)] = '\0';
1320
1321#ifndef CONFIG_NO_PBKDF2
1322 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1323 {
1324 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1325 4096, psk, PMK_LEN);
1326 os_memset(pw_str, 0, sizeof(pw_str));
1327 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1328 "external passphrase)",
1329 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001330 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001331 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001332 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001333 } else
1334#endif /* CONFIG_NO_PBKDF2 */
1335 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1336 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1337 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1338 "Invalid PSK hex string");
1339 os_memset(pw_str, 0, sizeof(pw_str));
1340 ext_password_free(pw);
1341 return -1;
1342 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001343 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001344 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001345 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001346 } else {
1347 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1348 "PSK available");
1349 os_memset(pw_str, 0, sizeof(pw_str));
1350 ext_password_free(pw);
1351 return -1;
1352 }
1353
1354 os_memset(pw_str, 0, sizeof(pw_str));
1355 ext_password_free(pw);
1356 }
1357#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001358
1359 if (!psk_set) {
1360 wpa_msg(wpa_s, MSG_INFO,
1361 "No PSK available for association");
1362 return -1;
1363 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001364 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001365 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1366
1367 return 0;
1368}
1369
1370
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001371static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1372{
1373 *pos = 0x00;
1374
1375 switch (idx) {
1376 case 0: /* Bits 0-7 */
1377 break;
1378 case 1: /* Bits 8-15 */
1379 break;
1380 case 2: /* Bits 16-23 */
1381#ifdef CONFIG_WNM
1382 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1383 *pos |= 0x08; /* Bit 19 - BSS Transition */
1384#endif /* CONFIG_WNM */
1385 break;
1386 case 3: /* Bits 24-31 */
1387#ifdef CONFIG_WNM
1388 *pos |= 0x02; /* Bit 25 - SSID List */
1389#endif /* CONFIG_WNM */
1390#ifdef CONFIG_INTERWORKING
1391 if (wpa_s->conf->interworking)
1392 *pos |= 0x80; /* Bit 31 - Interworking */
1393#endif /* CONFIG_INTERWORKING */
1394 break;
1395 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001396#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001397 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1398 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001399#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001400 break;
1401 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001402#ifdef CONFIG_HS20
1403 if (wpa_s->conf->hs20)
1404 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1405#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001406 break;
1407 case 6: /* Bits 48-55 */
1408 break;
1409 }
1410}
1411
1412
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001413int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001414{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001415 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001416 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001417
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001418 if (len < wpa_s->extended_capa_len)
1419 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001420 if (buflen < (size_t) len + 2) {
1421 wpa_printf(MSG_INFO,
1422 "Not enough room for building extended capabilities element");
1423 return -1;
1424 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001425
1426 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001427 *pos++ = len;
1428 for (i = 0; i < len; i++, pos++) {
1429 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001430
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001431 if (i < wpa_s->extended_capa_len) {
1432 *pos &= ~wpa_s->extended_capa_mask[i];
1433 *pos |= wpa_s->extended_capa[i];
1434 }
1435 }
1436
1437 while (len > 0 && buf[1 + len] == 0) {
1438 len--;
1439 buf[1] = len;
1440 }
1441 if (len == 0)
1442 return 0;
1443
1444 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001445}
1446
1447
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001448static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1449 struct wpa_bss *test_bss)
1450{
1451 struct wpa_bss *bss;
1452
1453 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1454 if (bss == test_bss)
1455 return 1;
1456 }
1457
1458 return 0;
1459}
1460
1461
1462static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1463 struct wpa_ssid *test_ssid)
1464{
1465 struct wpa_ssid *ssid;
1466
1467 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1468 if (ssid == test_ssid)
1469 return 1;
1470 }
1471
1472 return 0;
1473}
1474
1475
1476int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1477 struct wpa_ssid *test_ssid)
1478{
1479 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1480 return 0;
1481
1482 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1483}
1484
1485
1486void wpas_connect_work_free(struct wpa_connect_work *cwork)
1487{
1488 if (cwork == NULL)
1489 return;
1490 os_free(cwork);
1491}
1492
1493
1494void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1495{
1496 struct wpa_connect_work *cwork;
1497 struct wpa_radio_work *work = wpa_s->connect_work;
1498
1499 if (!work)
1500 return;
1501
1502 wpa_s->connect_work = NULL;
1503 cwork = work->ctx;
1504 work->ctx = NULL;
1505 wpas_connect_work_free(cwork);
1506 radio_work_done(work);
1507}
1508
1509
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001510int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1511{
1512 struct os_reltime now;
1513 u8 addr[ETH_ALEN];
1514
1515 os_get_reltime(&now);
1516 if (wpa_s->last_mac_addr_style == style &&
1517 wpa_s->last_mac_addr_change.sec != 0 &&
1518 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1519 wpa_s->conf->rand_addr_lifetime)) {
1520 wpa_msg(wpa_s, MSG_DEBUG,
1521 "Previously selected random MAC address has not yet expired");
1522 return 0;
1523 }
1524
1525 switch (style) {
1526 case 1:
1527 if (random_mac_addr(addr) < 0)
1528 return -1;
1529 break;
1530 case 2:
1531 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1532 if (random_mac_addr_keep_oui(addr) < 0)
1533 return -1;
1534 break;
1535 default:
1536 return -1;
1537 }
1538
1539 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1540 wpa_msg(wpa_s, MSG_INFO,
1541 "Failed to set random MAC address");
1542 return -1;
1543 }
1544
1545 os_get_reltime(&wpa_s->last_mac_addr_change);
1546 wpa_s->mac_addr_changed = 1;
1547 wpa_s->last_mac_addr_style = style;
1548
1549 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1550 wpa_msg(wpa_s, MSG_INFO,
1551 "Could not update MAC address information");
1552 return -1;
1553 }
1554
1555 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1556 MAC2STR(addr));
1557
1558 return 0;
1559}
1560
1561
1562int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1563{
1564 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1565 !wpa_s->conf->preassoc_mac_addr)
1566 return 0;
1567
1568 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1569}
1570
1571
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001572static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1573
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001574/**
1575 * wpa_supplicant_associate - Request association
1576 * @wpa_s: Pointer to wpa_supplicant data
1577 * @bss: Scan results for the selected BSS, or %NULL if not available
1578 * @ssid: Configuration data for the selected network
1579 *
1580 * This function is used to request %wpa_supplicant to associate with a BSS.
1581 */
1582void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1583 struct wpa_bss *bss, struct wpa_ssid *ssid)
1584{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001585 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001586 int rand_style;
1587
1588 if (ssid->mac_addr == -1)
1589 rand_style = wpa_s->conf->mac_addr;
1590 else
1591 rand_style = ssid->mac_addr;
1592
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001593 wmm_ac_clear_saved_tspecs(wpa_s);
1594 wpa_s->reassoc_same_bss = 0;
1595
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001596 if (wpa_s->last_ssid == ssid) {
1597 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001598 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1599 wmm_ac_save_tspecs(wpa_s);
1600 wpa_s->reassoc_same_bss = 1;
1601 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001602 } else if (rand_style > 0) {
1603 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1604 return;
1605 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1606 } else if (wpa_s->mac_addr_changed) {
1607 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1608 wpa_msg(wpa_s, MSG_INFO,
1609 "Could not restore permanent MAC address");
1610 return;
1611 }
1612 wpa_s->mac_addr_changed = 0;
1613 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1614 wpa_msg(wpa_s, MSG_INFO,
1615 "Could not update MAC address information");
1616 return;
1617 }
1618 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1619 }
1620 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001621
1622#ifdef CONFIG_IBSS_RSN
1623 ibss_rsn_deinit(wpa_s->ibss_rsn);
1624 wpa_s->ibss_rsn = NULL;
1625#endif /* CONFIG_IBSS_RSN */
1626
1627 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1628 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1629#ifdef CONFIG_AP
1630 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1631 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1632 "mode");
1633 return;
1634 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001635 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1636 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001637 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1638 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001639 return;
1640 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641 wpa_s->current_bss = bss;
1642#else /* CONFIG_AP */
1643 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1644 "the build");
1645#endif /* CONFIG_AP */
1646 return;
1647 }
1648
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001649 if (ssid->mode == WPAS_MODE_MESH) {
1650#ifdef CONFIG_MESH
1651 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1652 wpa_msg(wpa_s, MSG_INFO,
1653 "Driver does not support mesh mode");
1654 return;
1655 }
1656 if (bss)
1657 ssid->frequency = bss->freq;
1658 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1659 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1660 return;
1661 }
1662 wpa_s->current_bss = bss;
1663 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
1664 "ssid=\"%s\" id=%d",
1665 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1666 ssid->id);
1667#else /* CONFIG_MESH */
1668 wpa_msg(wpa_s, MSG_ERROR,
1669 "mesh mode support not included in the build");
1670#endif /* CONFIG_MESH */
1671 return;
1672 }
1673
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001674#ifdef CONFIG_TDLS
1675 if (bss)
1676 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1677 bss->ie_len);
1678#endif /* CONFIG_TDLS */
1679
1680 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1681 ssid->mode == IEEE80211_MODE_INFRA) {
1682 sme_authenticate(wpa_s, bss, ssid);
1683 return;
1684 }
1685
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001686 if (wpa_s->connect_work) {
1687 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1688 return;
1689 }
1690
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001691 if (radio_work_pending(wpa_s, "connect")) {
1692 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1693 return;
1694 }
1695
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001696 cwork = os_zalloc(sizeof(*cwork));
1697 if (cwork == NULL)
1698 return;
1699
1700 cwork->bss = bss;
1701 cwork->ssid = ssid;
1702
1703 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1704 wpas_start_assoc_cb, cwork) < 0) {
1705 os_free(cwork);
1706 }
1707}
1708
1709
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001710static int bss_is_ibss(struct wpa_bss *bss)
1711{
1712 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1713 IEEE80211_CAP_IBSS;
1714}
1715
1716
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001717void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1718 const struct wpa_ssid *ssid,
1719 struct hostapd_freq_params *freq)
1720{
1721 enum hostapd_hw_mode hw_mode;
1722 struct hostapd_hw_modes *mode = NULL;
1723 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1724 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001725 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001726 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1727 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001728 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001729 unsigned int j;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001730 struct hostapd_freq_params vht_freq;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001731
1732 freq->freq = ssid->frequency;
1733
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001734 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1735 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1736
1737 if (ssid->mode != WPAS_MODE_IBSS)
1738 break;
1739
1740 /* Don't adjust control freq in case of fixed_freq */
1741 if (ssid->fixed_freq)
1742 break;
1743
1744 if (!bss_is_ibss(bss))
1745 continue;
1746
1747 if (ssid->ssid_len == bss->ssid_len &&
1748 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1749 wpa_printf(MSG_DEBUG,
1750 "IBSS already found in scan results, adjust control freq: %d",
1751 bss->freq);
1752 freq->freq = bss->freq;
1753 obss_scan = 0;
1754 break;
1755 }
1756 }
1757
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001758 /* For IBSS check HT_IBSS flag */
1759 if (ssid->mode == WPAS_MODE_IBSS &&
1760 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1761 return;
1762
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001763 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1764 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1765 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1766 wpa_printf(MSG_DEBUG,
1767 "IBSS: WEP/TKIP detected, do not try to enable HT");
1768 return;
1769 }
1770
1771 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001772 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1773 if (wpa_s->hw.modes[i].mode == hw_mode) {
1774 mode = &wpa_s->hw.modes[i];
1775 break;
1776 }
1777 }
1778
1779 if (!mode)
1780 return;
1781
1782 freq->ht_enabled = ht_supported(mode);
1783 if (!freq->ht_enabled)
1784 return;
1785
1786 /* Setup higher BW only for 5 GHz */
1787 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1788 return;
1789
1790 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1791 pri_chan = &mode->channels[chan_idx];
1792 if (pri_chan->chan == channel)
1793 break;
1794 pri_chan = NULL;
1795 }
1796 if (!pri_chan)
1797 return;
1798
1799 /* Check primary channel flags */
1800 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1801 return;
1802
1803 /* Check/setup HT40+/HT40- */
1804 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1805 if (ht40plus[j] == channel) {
1806 ht40 = 1;
1807 break;
1808 }
1809 }
1810
1811 /* Find secondary channel */
1812 for (i = 0; i < mode->num_channels; i++) {
1813 sec_chan = &mode->channels[i];
1814 if (sec_chan->chan == channel + ht40 * 4)
1815 break;
1816 sec_chan = NULL;
1817 }
1818 if (!sec_chan)
1819 return;
1820
1821 /* Check secondary channel flags */
1822 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1823 return;
1824
1825 freq->channel = pri_chan->chan;
1826
1827 switch (ht40) {
1828 case -1:
1829 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1830 return;
1831 freq->sec_channel_offset = -1;
1832 break;
1833 case 1:
1834 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1835 return;
1836 freq->sec_channel_offset = 1;
1837 break;
1838 default:
1839 break;
1840 }
1841
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001842 if (freq->sec_channel_offset && obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001843 struct wpa_scan_results *scan_res;
1844
1845 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1846 if (scan_res == NULL) {
1847 /* Back to HT20 */
1848 freq->sec_channel_offset = 0;
1849 return;
1850 }
1851
1852 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1853 sec_chan->chan);
1854 switch (res) {
1855 case 0:
1856 /* Back to HT20 */
1857 freq->sec_channel_offset = 0;
1858 break;
1859 case 1:
1860 /* Configuration allowed */
1861 break;
1862 case 2:
1863 /* Switch pri/sec channels */
1864 freq->freq = hw_get_freq(mode, sec_chan->chan);
1865 freq->sec_channel_offset = -freq->sec_channel_offset;
1866 freq->channel = sec_chan->chan;
1867 break;
1868 default:
1869 freq->sec_channel_offset = 0;
1870 break;
1871 }
1872
1873 wpa_scan_results_free(scan_res);
1874 }
1875
1876 wpa_printf(MSG_DEBUG,
1877 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
1878 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001879
1880 /* Not sure if mesh is ready for VHT */
1881 if (ssid->mode != WPAS_MODE_IBSS)
1882 return;
1883
1884 /* For IBSS check VHT_IBSS flag */
1885 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
1886 return;
1887
1888 vht_freq = *freq;
1889
1890 vht_freq.vht_enabled = vht_supported(mode);
1891 if (!vht_freq.vht_enabled)
1892 return;
1893
1894 /* setup center_freq1, bandwidth */
1895 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
1896 if (freq->channel >= vht80[j] &&
1897 freq->channel < vht80[j] + 16)
1898 break;
1899 }
1900
1901 if (j == ARRAY_SIZE(vht80))
1902 return;
1903
1904 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
1905 struct hostapd_channel_data *chan;
1906
1907 chan = hw_get_channel_chan(mode, i, NULL);
1908 if (!chan)
1909 return;
1910
1911 /* Back to HT configuration if channel not usable */
1912 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1913 return;
1914 }
1915
1916 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
1917 freq->channel, freq->ht_enabled,
1918 vht_freq.vht_enabled,
1919 freq->sec_channel_offset,
1920 VHT_CHANWIDTH_80MHZ,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08001921 vht80[j] + 6, 0, 0) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001922 return;
1923
1924 *freq = vht_freq;
1925
1926 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
1927 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001928}
1929
1930
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001931static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1932{
1933 struct wpa_connect_work *cwork = work->ctx;
1934 struct wpa_bss *bss = cwork->bss;
1935 struct wpa_ssid *ssid = cwork->ssid;
1936 struct wpa_supplicant *wpa_s = work->wpa_s;
1937 u8 wpa_ie[200];
1938 size_t wpa_ie_len;
1939 int use_crypt, ret, i, bssid_changed;
1940 int algs = WPA_AUTH_ALG_OPEN;
1941 unsigned int cipher_pairwise, cipher_group;
1942 struct wpa_driver_associate_params params;
1943 int wep_keys_set = 0;
1944 int assoc_failed = 0;
1945 struct wpa_ssid *old_ssid;
1946#ifdef CONFIG_HT_OVERRIDES
1947 struct ieee80211_ht_capabilities htcaps;
1948 struct ieee80211_ht_capabilities htcaps_mask;
1949#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001950#ifdef CONFIG_VHT_OVERRIDES
1951 struct ieee80211_vht_capabilities vhtcaps;
1952 struct ieee80211_vht_capabilities vhtcaps_mask;
1953#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001954
1955 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001956 if (work->started) {
1957 wpa_s->connect_work = NULL;
1958
1959 /* cancel possible auth. timeout */
1960 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1961 NULL);
1962 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001963 wpas_connect_work_free(cwork);
1964 return;
1965 }
1966
1967 wpa_s->connect_work = work;
1968
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001969 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001970 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1971 wpas_connect_work_done(wpa_s);
1972 return;
1973 }
1974
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001975 os_memset(&params, 0, sizeof(params));
1976 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001977 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001978 if (bss &&
1979 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001980#ifdef CONFIG_IEEE80211R
1981 const u8 *ie, *md = NULL;
1982#endif /* CONFIG_IEEE80211R */
1983 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1984 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1985 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1986 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1987 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1988 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1989 if (bssid_changed)
1990 wpas_notify_bssid_changed(wpa_s);
1991#ifdef CONFIG_IEEE80211R
1992 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1993 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1994 md = ie + 2;
1995 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1996 if (md) {
1997 /* Prepare for the next transition */
1998 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1999 }
2000#endif /* CONFIG_IEEE80211R */
2001#ifdef CONFIG_WPS
2002 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2003 wpa_s->conf->ap_scan == 2 &&
2004 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2005 /* Use ap_scan==1 style network selection to find the network
2006 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002007 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002008 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009 wpa_s->reassociate = 1;
2010 wpa_supplicant_req_scan(wpa_s, 0, 0);
2011 return;
2012#endif /* CONFIG_WPS */
2013 } else {
2014 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2015 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2016 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2017 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002018 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002019 wpa_supplicant_cancel_scan(wpa_s);
2020
2021 /* Starting new association, so clear the possibly used WPA IE from the
2022 * previous association. */
2023 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2024
2025#ifdef IEEE8021X_EAPOL
2026 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2027 if (ssid->leap) {
2028 if (ssid->non_leap == 0)
2029 algs = WPA_AUTH_ALG_LEAP;
2030 else
2031 algs |= WPA_AUTH_ALG_LEAP;
2032 }
2033 }
2034#endif /* IEEE8021X_EAPOL */
2035 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2036 if (ssid->auth_alg) {
2037 algs = ssid->auth_alg;
2038 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2039 "0x%x", algs);
2040 }
2041
2042 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2043 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002044 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002045 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002046 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2047 wpa_s->conf->okc :
2048 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002049 (ssid->proto & WPA_PROTO_RSN);
2050 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002051 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002052 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053 wpa_ie_len = sizeof(wpa_ie);
2054 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2055 wpa_ie, &wpa_ie_len)) {
2056 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2057 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002058 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002059 return;
2060 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002061 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2062 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2063 /*
2064 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2065 * use non-WPA since the scan results did not indicate that the
2066 * AP is using WPA or WPA2.
2067 */
2068 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2069 wpa_ie_len = 0;
2070 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002071 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002072 wpa_ie_len = sizeof(wpa_ie);
2073 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2074 wpa_ie, &wpa_ie_len)) {
2075 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2076 "key management and encryption suites (no "
2077 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002078 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002079 return;
2080 }
2081#ifdef CONFIG_WPS
2082 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2083 struct wpabuf *wps_ie;
2084 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2085 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2086 wpa_ie_len = wpabuf_len(wps_ie);
2087 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2088 } else
2089 wpa_ie_len = 0;
2090 wpabuf_free(wps_ie);
2091 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2092 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2093 params.wps = WPS_MODE_PRIVACY;
2094 else
2095 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002096 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097#endif /* CONFIG_WPS */
2098 } else {
2099 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2100 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002101 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102 }
2103
2104#ifdef CONFIG_P2P
2105 if (wpa_s->global->p2p) {
2106 u8 *pos;
2107 size_t len;
2108 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002109 pos = wpa_ie + wpa_ie_len;
2110 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002111 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2112 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002113 if (res >= 0)
2114 wpa_ie_len += res;
2115 }
2116
2117 wpa_s->cross_connect_disallowed = 0;
2118 if (bss) {
2119 struct wpabuf *p2p;
2120 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2121 if (p2p) {
2122 wpa_s->cross_connect_disallowed =
2123 p2p_get_cross_connect_disallowed(p2p);
2124 wpabuf_free(p2p);
2125 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2126 "connection",
2127 wpa_s->cross_connect_disallowed ?
2128 "disallows" : "allows");
2129 }
2130 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002131
2132 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002133#endif /* CONFIG_P2P */
2134
Dmitry Shmidt04949592012-07-19 12:16:46 -07002135#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002136 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002137 struct wpabuf *hs20;
2138 hs20 = wpabuf_alloc(20);
2139 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002140 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002141 size_t len;
2142
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002143 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002144 len = sizeof(wpa_ie) - wpa_ie_len;
2145 if (wpabuf_len(hs20) <= len) {
2146 os_memcpy(wpa_ie + wpa_ie_len,
2147 wpabuf_head(hs20), wpabuf_len(hs20));
2148 wpa_ie_len += wpabuf_len(hs20);
2149 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002150 wpabuf_free(hs20);
2151 }
2152 }
2153#endif /* CONFIG_HS20 */
2154
Dmitry Shmidt56052862013-10-04 10:23:25 -07002155 /*
2156 * Workaround: Add Extended Capabilities element only if the AP
2157 * included this element in Beacon/Probe Response frames. Some older
2158 * APs seem to have interoperability issues if this element is
2159 * included, so while the standard may require us to include the
2160 * element in all cases, it is justifiable to skip it to avoid
2161 * interoperability issues.
2162 */
2163 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002164 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002165 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002166 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2167 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002168 if (ext_capab_len > 0) {
2169 u8 *pos = wpa_ie;
2170 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2171 pos += 2 + pos[1];
2172 os_memmove(pos + ext_capab_len, pos,
2173 wpa_ie_len - (pos - wpa_ie));
2174 wpa_ie_len += ext_capab_len;
2175 os_memcpy(pos, ext_capab, ext_capab_len);
2176 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002177 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002178
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002179 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2180 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2181 size_t len;
2182
2183 len = sizeof(wpa_ie) - wpa_ie_len;
2184 if (wpabuf_len(buf) <= len) {
2185 os_memcpy(wpa_ie + wpa_ie_len,
2186 wpabuf_head(buf), wpabuf_len(buf));
2187 wpa_ie_len += wpabuf_len(buf);
2188 }
2189 }
2190
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002191 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2192 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002193 cipher_pairwise = wpa_s->pairwise_cipher;
2194 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002195 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2196 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2197 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2198 use_crypt = 0;
2199 if (wpa_set_wep_keys(wpa_s, ssid)) {
2200 use_crypt = 1;
2201 wep_keys_set = 1;
2202 }
2203 }
2204 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2205 use_crypt = 0;
2206
2207#ifdef IEEE8021X_EAPOL
2208 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2209 if ((ssid->eapol_flags &
2210 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2211 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2212 !wep_keys_set) {
2213 use_crypt = 0;
2214 } else {
2215 /* Assume that dynamic WEP-104 keys will be used and
2216 * set cipher suites in order for drivers to expect
2217 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002218 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002219 }
2220 }
2221#endif /* IEEE8021X_EAPOL */
2222
2223 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2224 /* Set the key before (and later after) association */
2225 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2226 }
2227
2228 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2229 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002230 params.ssid = bss->ssid;
2231 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002232 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
2233 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2234 MACSTR " freq=%u MHz based on scan results "
2235 "(bssid_set=%d)",
2236 MAC2STR(bss->bssid), bss->freq,
2237 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002238 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002239 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002240 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002241 params.bssid_hint = bss->bssid;
2242 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002243 } else {
2244 params.ssid = ssid->ssid;
2245 params.ssid_len = ssid->ssid_len;
2246 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002247
2248 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2249 wpa_s->conf->ap_scan == 2) {
2250 params.bssid = ssid->bssid;
2251 params.fixed_bssid = 1;
2252 }
2253
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002254 /* Initial frequency for IBSS/mesh */
2255 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002256 ssid->frequency > 0 && params.freq.freq == 0)
2257 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002258
2259 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002260 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002261 if (ssid->beacon_int)
2262 params.beacon_int = ssid->beacon_int;
2263 else
2264 params.beacon_int = wpa_s->conf->beacon_int;
2265 }
2266
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002267 params.wpa_ie = wpa_ie;
2268 params.wpa_ie_len = wpa_ie_len;
2269 params.pairwise_suite = cipher_pairwise;
2270 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002271 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002272 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002273 params.auth_alg = algs;
2274 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002275 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276 for (i = 0; i < NUM_WEP_KEYS; i++) {
2277 if (ssid->wep_key_len[i])
2278 params.wep_key[i] = ssid->wep_key[i];
2279 params.wep_key_len[i] = ssid->wep_key_len[i];
2280 }
2281 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2282
2283 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002284 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2285 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002286 params.passphrase = ssid->passphrase;
2287 if (ssid->psk_set)
2288 params.psk = ssid->psk;
2289 }
2290
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002291 if (wpa_s->conf->key_mgmt_offload) {
2292 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2293 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002294 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2295 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002296 params.req_key_mgmt_offload =
2297 ssid->proactive_key_caching < 0 ?
2298 wpa_s->conf->okc : ssid->proactive_key_caching;
2299 else
2300 params.req_key_mgmt_offload = 1;
2301
2302 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2303 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2304 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2305 ssid->psk_set)
2306 params.psk = ssid->psk;
2307 }
2308
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002309 params.drop_unencrypted = use_crypt;
2310
2311#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002312 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002313 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2315 struct wpa_ie_data ie;
2316 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2317 ie.capabilities &
2318 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2319 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2320 "MFP: require MFP");
2321 params.mgmt_frame_protection =
2322 MGMT_FRAME_PROTECTION_REQUIRED;
2323 }
2324 }
2325#endif /* CONFIG_IEEE80211W */
2326
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002327 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002328
2329 if (wpa_s->parent->set_sta_uapsd)
2330 params.uapsd = wpa_s->parent->sta_uapsd;
2331 else
2332 params.uapsd = -1;
2333
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002334#ifdef CONFIG_HT_OVERRIDES
2335 os_memset(&htcaps, 0, sizeof(htcaps));
2336 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2337 params.htcaps = (u8 *) &htcaps;
2338 params.htcaps_mask = (u8 *) &htcaps_mask;
2339 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2340#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002341#ifdef CONFIG_VHT_OVERRIDES
2342 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2343 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2344 params.vhtcaps = &vhtcaps;
2345 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002346 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002347#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002348
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002349#ifdef CONFIG_P2P
2350 /*
2351 * If multi-channel concurrency is not supported, check for any
2352 * frequency conflict. In case of any frequency conflict, remove the
2353 * least prioritized connection.
2354 */
2355 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002356 int freq, num;
2357 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002358 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002359 wpa_printf(MSG_DEBUG,
2360 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002361 freq, params.freq.freq);
2362 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002363 wpa_s, params.freq.freq, ssid) < 0) {
2364 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002365 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002366 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002367 }
2368 }
2369#endif /* CONFIG_P2P */
2370
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002371 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002372 if (ret < 0) {
2373 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2374 "failed");
2375 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2376 /*
2377 * The driver is known to mean what is saying, so we
2378 * can stop right here; the association will not
2379 * succeed.
2380 */
2381 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002382 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002383 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2384 return;
2385 }
2386 /* try to continue anyway; new association will be tried again
2387 * after timeout */
2388 assoc_failed = 1;
2389 }
2390
2391 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2392 /* Set the key after the association just in case association
2393 * cleared the previously configured key. */
2394 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2395 /* No need to timeout authentication since there is no key
2396 * management. */
2397 wpa_supplicant_cancel_auth_timeout(wpa_s);
2398 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2399#ifdef CONFIG_IBSS_RSN
2400 } else if (ssid->mode == WPAS_MODE_IBSS &&
2401 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2402 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2403 /*
2404 * RSN IBSS authentication is per-STA and we can disable the
2405 * per-BSSID authentication.
2406 */
2407 wpa_supplicant_cancel_auth_timeout(wpa_s);
2408#endif /* CONFIG_IBSS_RSN */
2409 } else {
2410 /* Timeout for IEEE 802.11 authentication and association */
2411 int timeout = 60;
2412
2413 if (assoc_failed) {
2414 /* give IBSS a bit more time */
2415 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2416 } else if (wpa_s->conf->ap_scan == 1) {
2417 /* give IBSS a bit more time */
2418 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2419 }
2420 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2421 }
2422
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002423 if (wep_keys_set &&
2424 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002425 /* Set static WEP keys again */
2426 wpa_set_wep_keys(wpa_s, ssid);
2427 }
2428
2429 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2430 /*
2431 * Do not allow EAP session resumption between different
2432 * network configurations.
2433 */
2434 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2435 }
2436 old_ssid = wpa_s->current_ssid;
2437 wpa_s->current_ssid = ssid;
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002438 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set)
2439 wpa_s->current_bss = bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002440 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2441 wpa_supplicant_initiate_eapol(wpa_s);
2442 if (old_ssid != wpa_s->current_ssid)
2443 wpas_notify_network_changed(wpa_s);
2444}
2445
2446
2447static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2448 const u8 *addr)
2449{
2450 struct wpa_ssid *old_ssid;
2451
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002452 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002453 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002454 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002455 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002456 wpa_sm_set_config(wpa_s->wpa, NULL);
2457 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2458 if (old_ssid != wpa_s->current_ssid)
2459 wpas_notify_network_changed(wpa_s);
2460 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2461}
2462
2463
2464/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2466 * @wpa_s: Pointer to wpa_supplicant data
2467 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2468 *
2469 * This function is used to request %wpa_supplicant to deauthenticate from the
2470 * current AP.
2471 */
2472void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2473 int reason_code)
2474{
2475 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002476 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002477 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002479 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2480 " pending_bssid=" MACSTR " reason=%d state=%s",
2481 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2482 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2483
2484 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002486 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2487 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2488 wpa_s->wpa_state == WPA_ASSOCIATING))
2489 addr = wpa_s->pending_bssid;
2490 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2491 /*
2492 * When using driver-based BSS selection, we may not know the
2493 * BSSID with which we are currently trying to associate. We
2494 * need to notify the driver of this disconnection even in such
2495 * a case, so use the all zeros address here.
2496 */
2497 addr = wpa_s->bssid;
2498 zero_addr = 1;
2499 }
2500
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002501#ifdef CONFIG_TDLS
2502 wpa_tdls_teardown_peers(wpa_s->wpa);
2503#endif /* CONFIG_TDLS */
2504
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002505#ifdef CONFIG_MESH
2506 if (wpa_s->ifmsh) {
2507 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2508 wpa_s->ifname);
2509 wpa_supplicant_leave_mesh(wpa_s);
2510 }
2511#endif /* CONFIG_MESH */
2512
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002513 if (addr) {
2514 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002515 os_memset(&event, 0, sizeof(event));
2516 event.deauth_info.reason_code = (u16) reason_code;
2517 event.deauth_info.locally_generated = 1;
2518 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002519 if (zero_addr)
2520 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 }
2522
2523 wpa_supplicant_clear_connection(wpa_s, addr);
2524}
2525
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002526static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2527 struct wpa_ssid *ssid)
2528{
2529 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2530 return;
2531
2532 ssid->disabled = 0;
2533 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2534 wpas_notify_network_enabled_changed(wpa_s, ssid);
2535
2536 /*
2537 * Try to reassociate since there is no current configuration and a new
2538 * network was made available.
2539 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002540 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002541 wpa_s->reassociate = 1;
2542}
2543
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544
2545/**
2546 * wpa_supplicant_enable_network - Mark a configured network as enabled
2547 * @wpa_s: wpa_supplicant structure for a network interface
2548 * @ssid: wpa_ssid structure for a configured network or %NULL
2549 *
2550 * Enables the specified network or all networks if no network specified.
2551 */
2552void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2553 struct wpa_ssid *ssid)
2554{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002556 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2557 wpa_supplicant_enable_one_network(wpa_s, ssid);
2558 } else
2559 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002561 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002562 if (wpa_s->sched_scanning) {
2563 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2564 "new network to scan filters");
2565 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566 }
2567
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002568 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2569 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570 }
2571}
2572
2573
2574/**
2575 * wpa_supplicant_disable_network - Mark a configured network as disabled
2576 * @wpa_s: wpa_supplicant structure for a network interface
2577 * @ssid: wpa_ssid structure for a configured network or %NULL
2578 *
2579 * Disables the specified network or all networks if no network specified.
2580 */
2581void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2582 struct wpa_ssid *ssid)
2583{
2584 struct wpa_ssid *other_ssid;
2585 int was_disabled;
2586
2587 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002588 if (wpa_s->sched_scanning)
2589 wpa_supplicant_cancel_sched_scan(wpa_s);
2590
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2592 other_ssid = other_ssid->next) {
2593 was_disabled = other_ssid->disabled;
2594 if (was_disabled == 2)
2595 continue; /* do not change persistent P2P group
2596 * data */
2597
2598 other_ssid->disabled = 1;
2599
2600 if (was_disabled != other_ssid->disabled)
2601 wpas_notify_network_enabled_changed(
2602 wpa_s, other_ssid);
2603 }
2604 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002605 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002606 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2607 } else if (ssid->disabled != 2) {
2608 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002609 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002610 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2611
2612 was_disabled = ssid->disabled;
2613
2614 ssid->disabled = 1;
2615
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002616 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002618 if (wpa_s->sched_scanning) {
2619 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2620 "to remove network from filters");
2621 wpa_supplicant_cancel_sched_scan(wpa_s);
2622 wpa_supplicant_req_scan(wpa_s, 0, 0);
2623 }
2624 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002625 }
2626}
2627
2628
2629/**
2630 * wpa_supplicant_select_network - Attempt association with a network
2631 * @wpa_s: wpa_supplicant structure for a network interface
2632 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2633 */
2634void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2635 struct wpa_ssid *ssid)
2636{
2637
2638 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002639 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002641 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002642 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2643 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002644 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002646 disconnected = 1;
2647 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002649 if (ssid)
2650 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2651
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 /*
2653 * Mark all other networks disabled or mark all networks enabled if no
2654 * network specified.
2655 */
2656 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2657 other_ssid = other_ssid->next) {
2658 int was_disabled = other_ssid->disabled;
2659 if (was_disabled == 2)
2660 continue; /* do not change persistent P2P group data */
2661
2662 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 if (was_disabled && !other_ssid->disabled)
2664 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002665
2666 if (was_disabled != other_ssid->disabled)
2667 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2668 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002669
2670 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2671 /* We are already associated with the selected network */
2672 wpa_printf(MSG_DEBUG, "Already associated with the "
2673 "selected network - do nothing");
2674 return;
2675 }
2676
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002677 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002678 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002679 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002680 wpa_s->connect_without_scan =
2681 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002682
2683 /*
2684 * Don't optimize next scan freqs since a new ESS has been
2685 * selected.
2686 */
2687 os_free(wpa_s->next_scan_freqs);
2688 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002689 } else {
2690 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002691 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002692
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 wpa_s->disconnected = 0;
2694 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002695
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002696 if (wpa_s->connect_without_scan ||
2697 wpa_supplicant_fast_associate(wpa_s) != 1)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002698 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002699
2700 if (ssid)
2701 wpas_notify_network_selected(wpa_s, ssid);
2702}
2703
2704
2705/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002706 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2707 * @wpa_s: wpa_supplicant structure for a network interface
2708 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2709 * @pkcs11_module_path: PKCS #11 module path or NULL
2710 * Returns: 0 on success; -1 on failure
2711 *
2712 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2713 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2714 * module path fails the paths will be reset to the default value (NULL).
2715 */
2716int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2717 const char *pkcs11_engine_path,
2718 const char *pkcs11_module_path)
2719{
2720 char *pkcs11_engine_path_copy = NULL;
2721 char *pkcs11_module_path_copy = NULL;
2722
2723 if (pkcs11_engine_path != NULL) {
2724 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2725 if (pkcs11_engine_path_copy == NULL)
2726 return -1;
2727 }
2728 if (pkcs11_module_path != NULL) {
2729 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002730 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002731 os_free(pkcs11_engine_path_copy);
2732 return -1;
2733 }
2734 }
2735
2736 os_free(wpa_s->conf->pkcs11_engine_path);
2737 os_free(wpa_s->conf->pkcs11_module_path);
2738 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2739 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2740
2741 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2742 eapol_sm_deinit(wpa_s->eapol);
2743 wpa_s->eapol = NULL;
2744 if (wpa_supplicant_init_eapol(wpa_s)) {
2745 /* Error -> Reset paths to the default value (NULL) once. */
2746 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2747 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2748 NULL);
2749
2750 return -1;
2751 }
2752 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2753
2754 return 0;
2755}
2756
2757
2758/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002759 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2760 * @wpa_s: wpa_supplicant structure for a network interface
2761 * @ap_scan: AP scan mode
2762 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2763 *
2764 */
2765int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2766{
2767
2768 int old_ap_scan;
2769
2770 if (ap_scan < 0 || ap_scan > 2)
2771 return -1;
2772
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002773#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002774 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2775 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2776 wpa_s->wpa_state < WPA_COMPLETED) {
2777 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2778 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002779 return 0;
2780 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002781#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002782
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 old_ap_scan = wpa_s->conf->ap_scan;
2784 wpa_s->conf->ap_scan = ap_scan;
2785
2786 if (old_ap_scan != wpa_s->conf->ap_scan)
2787 wpas_notify_ap_scan_changed(wpa_s);
2788
2789 return 0;
2790}
2791
2792
2793/**
2794 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2795 * @wpa_s: wpa_supplicant structure for a network interface
2796 * @expire_age: Expiration age in seconds
2797 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2798 *
2799 */
2800int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2801 unsigned int bss_expire_age)
2802{
2803 if (bss_expire_age < 10) {
2804 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2805 bss_expire_age);
2806 return -1;
2807 }
2808 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2809 bss_expire_age);
2810 wpa_s->conf->bss_expiration_age = bss_expire_age;
2811
2812 return 0;
2813}
2814
2815
2816/**
2817 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2818 * @wpa_s: wpa_supplicant structure for a network interface
2819 * @expire_count: number of scans after which an unseen BSS is reclaimed
2820 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2821 *
2822 */
2823int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2824 unsigned int bss_expire_count)
2825{
2826 if (bss_expire_count < 1) {
2827 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2828 bss_expire_count);
2829 return -1;
2830 }
2831 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2832 bss_expire_count);
2833 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2834
2835 return 0;
2836}
2837
2838
2839/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002840 * wpa_supplicant_set_scan_interval - Set scan interval
2841 * @wpa_s: wpa_supplicant structure for a network interface
2842 * @scan_interval: scan interval in seconds
2843 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2844 *
2845 */
2846int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2847 int scan_interval)
2848{
2849 if (scan_interval < 0) {
2850 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2851 scan_interval);
2852 return -1;
2853 }
2854 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2855 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002856 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002857
2858 return 0;
2859}
2860
2861
2862/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002863 * wpa_supplicant_set_debug_params - Set global debug params
2864 * @global: wpa_global structure
2865 * @debug_level: debug level
2866 * @debug_timestamp: determines if show timestamp in debug data
2867 * @debug_show_keys: determines if show keys in debug data
2868 * Returns: 0 if succeed or -1 if debug_level has wrong value
2869 */
2870int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2871 int debug_timestamp, int debug_show_keys)
2872{
2873
2874 int old_level, old_timestamp, old_show_keys;
2875
2876 /* check for allowed debuglevels */
2877 if (debug_level != MSG_EXCESSIVE &&
2878 debug_level != MSG_MSGDUMP &&
2879 debug_level != MSG_DEBUG &&
2880 debug_level != MSG_INFO &&
2881 debug_level != MSG_WARNING &&
2882 debug_level != MSG_ERROR)
2883 return -1;
2884
2885 old_level = wpa_debug_level;
2886 old_timestamp = wpa_debug_timestamp;
2887 old_show_keys = wpa_debug_show_keys;
2888
2889 wpa_debug_level = debug_level;
2890 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2891 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2892
2893 if (wpa_debug_level != old_level)
2894 wpas_notify_debug_level_changed(global);
2895 if (wpa_debug_timestamp != old_timestamp)
2896 wpas_notify_debug_timestamp_changed(global);
2897 if (wpa_debug_show_keys != old_show_keys)
2898 wpas_notify_debug_show_keys_changed(global);
2899
2900 return 0;
2901}
2902
2903
2904/**
2905 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2906 * @wpa_s: Pointer to wpa_supplicant data
2907 * Returns: A pointer to the current network structure or %NULL on failure
2908 */
2909struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2910{
2911 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002912 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002913 int res;
2914 size_t ssid_len;
2915 u8 bssid[ETH_ALEN];
2916 int wired;
2917
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002918 res = wpa_drv_get_ssid(wpa_s, ssid);
2919 if (res < 0) {
2920 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2921 "driver");
2922 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002923 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002924 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002925
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002926 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002927 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2928 "driver");
2929 return NULL;
2930 }
2931
2932 wired = wpa_s->conf->ap_scan == 0 &&
2933 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2934
2935 entry = wpa_s->conf->ssid;
2936 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002937 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002938 ((ssid_len == entry->ssid_len &&
2939 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2940 (!entry->bssid_set ||
2941 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2942 return entry;
2943#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002944 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002945 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2946 (entry->ssid == NULL || entry->ssid_len == 0) &&
2947 (!entry->bssid_set ||
2948 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2949 return entry;
2950#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002951
Dmitry Shmidt04949592012-07-19 12:16:46 -07002952 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002953 entry->ssid_len == 0 &&
2954 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2955 return entry;
2956
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002957 entry = entry->next;
2958 }
2959
2960 return NULL;
2961}
2962
2963
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002964static int select_driver(struct wpa_supplicant *wpa_s, int i)
2965{
2966 struct wpa_global *global = wpa_s->global;
2967
2968 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2969 global->drv_priv[i] = wpa_drivers[i]->global_init();
2970 if (global->drv_priv[i] == NULL) {
2971 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2972 "'%s'", wpa_drivers[i]->name);
2973 return -1;
2974 }
2975 }
2976
2977 wpa_s->driver = wpa_drivers[i];
2978 wpa_s->global_drv_priv = global->drv_priv[i];
2979
2980 return 0;
2981}
2982
2983
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002984static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2985 const char *name)
2986{
2987 int i;
2988 size_t len;
2989 const char *pos, *driver = name;
2990
2991 if (wpa_s == NULL)
2992 return -1;
2993
2994 if (wpa_drivers[0] == NULL) {
2995 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2996 "wpa_supplicant");
2997 return -1;
2998 }
2999
3000 if (name == NULL) {
3001 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003002 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003003 }
3004
3005 do {
3006 pos = os_strchr(driver, ',');
3007 if (pos)
3008 len = pos - driver;
3009 else
3010 len = os_strlen(driver);
3011
3012 for (i = 0; wpa_drivers[i]; i++) {
3013 if (os_strlen(wpa_drivers[i]->name) == len &&
3014 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003015 0) {
3016 /* First driver that succeeds wins */
3017 if (select_driver(wpa_s, i) == 0)
3018 return 0;
3019 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003020 }
3021
3022 driver = pos + 1;
3023 } while (pos);
3024
3025 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3026 return -1;
3027}
3028
3029
3030/**
3031 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3032 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3033 * with struct wpa_driver_ops::init()
3034 * @src_addr: Source address of the EAPOL frame
3035 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3036 * @len: Length of the EAPOL data
3037 *
3038 * This function is called for each received EAPOL frame. Most driver
3039 * interfaces rely on more generic OS mechanism for receiving frames through
3040 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3041 * take care of received EAPOL frames and deliver them to the core supplicant
3042 * code by calling this function.
3043 */
3044void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3045 const u8 *buf, size_t len)
3046{
3047 struct wpa_supplicant *wpa_s = ctx;
3048
3049 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3050 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3051
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003052#ifdef CONFIG_PEERKEY
3053 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3054 wpa_s->current_ssid->peerkey &&
3055 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3056 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3057 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3058 return;
3059 }
3060#endif /* CONFIG_PEERKEY */
3061
Jouni Malinena05074c2012-12-21 21:35:35 +02003062 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3063 (wpa_s->last_eapol_matches_bssid &&
3064#ifdef CONFIG_AP
3065 !wpa_s->ap_iface &&
3066#endif /* CONFIG_AP */
3067 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003068 /*
3069 * There is possible race condition between receiving the
3070 * association event and the EAPOL frame since they are coming
3071 * through different paths from the driver. In order to avoid
3072 * issues in trying to process the EAPOL frame before receiving
3073 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003074 * the association event is received. This may also be needed in
3075 * driver-based roaming case, so also use src_addr != BSSID as a
3076 * trigger if we have previously confirmed that the
3077 * Authenticator uses BSSID as the src_addr (which is not the
3078 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003079 */
3080 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003081 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3082 wpa_supplicant_state_txt(wpa_s->wpa_state),
3083 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003084 wpabuf_free(wpa_s->pending_eapol_rx);
3085 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3086 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003087 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003088 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3089 ETH_ALEN);
3090 }
3091 return;
3092 }
3093
Jouni Malinena05074c2012-12-21 21:35:35 +02003094 wpa_s->last_eapol_matches_bssid =
3095 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3096
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003097#ifdef CONFIG_AP
3098 if (wpa_s->ap_iface) {
3099 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3100 return;
3101 }
3102#endif /* CONFIG_AP */
3103
3104 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3105 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3106 "no key management is configured");
3107 return;
3108 }
3109
3110 if (wpa_s->eapol_received == 0 &&
3111 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3112 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3113 wpa_s->wpa_state != WPA_COMPLETED) &&
3114 (wpa_s->current_ssid == NULL ||
3115 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3116 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003117 int timeout = 10;
3118
3119 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3120 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3121 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3122 /* Use longer timeout for IEEE 802.1X/EAP */
3123 timeout = 70;
3124 }
3125
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003126#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003127 if (wpa_s->current_ssid && wpa_s->current_bss &&
3128 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3129 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3130 /*
3131 * Use shorter timeout if going through WPS AP iteration
3132 * for PIN config method with an AP that does not
3133 * advertise Selected Registrar.
3134 */
3135 struct wpabuf *wps_ie;
3136
3137 wps_ie = wpa_bss_get_vendor_ie_multi(
3138 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3139 if (wps_ie &&
3140 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3141 timeout = 10;
3142 wpabuf_free(wps_ie);
3143 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003144#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003145
3146 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003147 }
3148 wpa_s->eapol_received++;
3149
3150 if (wpa_s->countermeasures) {
3151 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3152 "EAPOL packet");
3153 return;
3154 }
3155
3156#ifdef CONFIG_IBSS_RSN
3157 if (wpa_s->current_ssid &&
3158 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3159 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3160 return;
3161 }
3162#endif /* CONFIG_IBSS_RSN */
3163
3164 /* Source address of the incoming EAPOL frame could be compared to the
3165 * current BSSID. However, it is possible that a centralized
3166 * Authenticator could be using another MAC address than the BSSID of
3167 * an AP, so just allow any address to be used for now. The replies are
3168 * still sent to the current BSSID (if available), though. */
3169
3170 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3171 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3172 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3173 return;
3174 wpa_drv_poll(wpa_s);
3175 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3176 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3177 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3178 /*
3179 * Set portValid = TRUE here since we are going to skip 4-way
3180 * handshake processing which would normally set portValid. We
3181 * need this to allow the EAPOL state machines to be completed
3182 * without going through EAPOL-Key handshake.
3183 */
3184 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3185 }
3186}
3187
3188
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003189int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003190{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003191 if ((!wpa_s->p2p_mgmt ||
3192 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3193 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003194 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003195 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3196 wpa_drv_get_mac_addr(wpa_s),
3197 ETH_P_EAPOL,
3198 wpa_supplicant_rx_eapol, wpa_s, 0);
3199 if (wpa_s->l2 == NULL)
3200 return -1;
3201 } else {
3202 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3203 if (addr)
3204 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3205 }
3206
3207 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3208 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3209 return -1;
3210 }
3211
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003212 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3213
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003214 return 0;
3215}
3216
3217
Dmitry Shmidt04949592012-07-19 12:16:46 -07003218static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3219 const u8 *buf, size_t len)
3220{
3221 struct wpa_supplicant *wpa_s = ctx;
3222 const struct l2_ethhdr *eth;
3223
3224 if (len < sizeof(*eth))
3225 return;
3226 eth = (const struct l2_ethhdr *) buf;
3227
3228 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3229 !(eth->h_dest[0] & 0x01)) {
3230 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3231 " (bridge - not for this interface - ignore)",
3232 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3233 return;
3234 }
3235
3236 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3237 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3238 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3239 len - sizeof(*eth));
3240}
3241
3242
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003243/**
3244 * wpa_supplicant_driver_init - Initialize driver interface parameters
3245 * @wpa_s: Pointer to wpa_supplicant data
3246 * Returns: 0 on success, -1 on failure
3247 *
3248 * This function is called to initialize driver interface parameters.
3249 * wpa_drv_init() must have been called before this function to initialize the
3250 * driver interface.
3251 */
3252int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3253{
3254 static int interface_count = 0;
3255
3256 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3257 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003258
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003259 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3260 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003261 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003262 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3263
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003264 if (wpa_s->bridge_ifname[0]) {
3265 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3266 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003267 wpa_s->l2_br = l2_packet_init_bridge(
3268 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3269 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003270 if (wpa_s->l2_br == NULL) {
3271 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3272 "connection for the bridge interface '%s'",
3273 wpa_s->bridge_ifname);
3274 return -1;
3275 }
3276 }
3277
3278 wpa_clear_keys(wpa_s, NULL);
3279
3280 /* Make sure that TKIP countermeasures are not left enabled (could
3281 * happen if wpa_supplicant is killed during countermeasures. */
3282 wpa_drv_set_countermeasures(wpa_s, 0);
3283
3284 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3285 wpa_drv_flush_pmkid(wpa_s);
3286
3287 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003288 wpa_s->prev_scan_wildcard = 0;
3289
Dmitry Shmidt04949592012-07-19 12:16:46 -07003290 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003291 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3292 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3293 interface_count = 0;
3294 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003295#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003296 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003297 wpa_supplicant_delayed_sched_scan(wpa_s,
3298 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003299 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003300 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003301 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003302#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003303 interface_count++;
3304 } else
3305 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3306
3307 return 0;
3308}
3309
3310
3311static int wpa_supplicant_daemon(const char *pid_file)
3312{
3313 wpa_printf(MSG_DEBUG, "Daemonize..");
3314 return os_daemonize(pid_file);
3315}
3316
3317
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003318static struct wpa_supplicant *
3319wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003320{
3321 struct wpa_supplicant *wpa_s;
3322
3323 wpa_s = os_zalloc(sizeof(*wpa_s));
3324 if (wpa_s == NULL)
3325 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003326 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327 wpa_s->scan_interval = 5;
3328 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003329 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003330 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003331
3332 return wpa_s;
3333}
3334
3335
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003336#ifdef CONFIG_HT_OVERRIDES
3337
3338static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3339 struct ieee80211_ht_capabilities *htcaps,
3340 struct ieee80211_ht_capabilities *htcaps_mask,
3341 const char *ht_mcs)
3342{
3343 /* parse ht_mcs into hex array */
3344 int i;
3345 const char *tmp = ht_mcs;
3346 char *end = NULL;
3347
3348 /* If ht_mcs is null, do not set anything */
3349 if (!ht_mcs)
3350 return 0;
3351
3352 /* This is what we are setting in the kernel */
3353 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3354
3355 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3356
3357 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3358 errno = 0;
3359 long v = strtol(tmp, &end, 16);
3360 if (errno == 0) {
3361 wpa_msg(wpa_s, MSG_DEBUG,
3362 "htcap value[%i]: %ld end: %p tmp: %p",
3363 i, v, end, tmp);
3364 if (end == tmp)
3365 break;
3366
3367 htcaps->supported_mcs_set[i] = v;
3368 tmp = end;
3369 } else {
3370 wpa_msg(wpa_s, MSG_ERROR,
3371 "Failed to parse ht-mcs: %s, error: %s\n",
3372 ht_mcs, strerror(errno));
3373 return -1;
3374 }
3375 }
3376
3377 /*
3378 * If we were able to parse any values, then set mask for the MCS set.
3379 */
3380 if (i) {
3381 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3382 IEEE80211_HT_MCS_MASK_LEN - 1);
3383 /* skip the 3 reserved bits */
3384 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3385 0x1f;
3386 }
3387
3388 return 0;
3389}
3390
3391
3392static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3393 struct ieee80211_ht_capabilities *htcaps,
3394 struct ieee80211_ht_capabilities *htcaps_mask,
3395 int disabled)
3396{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003397 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003398
3399 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3400
3401 if (disabled == -1)
3402 return 0;
3403
3404 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3405 htcaps_mask->ht_capabilities_info |= msk;
3406 if (disabled)
3407 htcaps->ht_capabilities_info &= msk;
3408 else
3409 htcaps->ht_capabilities_info |= msk;
3410
3411 return 0;
3412}
3413
3414
3415static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3416 struct ieee80211_ht_capabilities *htcaps,
3417 struct ieee80211_ht_capabilities *htcaps_mask,
3418 int factor)
3419{
3420 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3421
3422 if (factor == -1)
3423 return 0;
3424
3425 if (factor < 0 || factor > 3) {
3426 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3427 "Must be 0-3 or -1", factor);
3428 return -EINVAL;
3429 }
3430
3431 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3432 htcaps->a_mpdu_params &= ~0x3;
3433 htcaps->a_mpdu_params |= factor & 0x3;
3434
3435 return 0;
3436}
3437
3438
3439static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3440 struct ieee80211_ht_capabilities *htcaps,
3441 struct ieee80211_ht_capabilities *htcaps_mask,
3442 int density)
3443{
3444 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3445
3446 if (density == -1)
3447 return 0;
3448
3449 if (density < 0 || density > 7) {
3450 wpa_msg(wpa_s, MSG_ERROR,
3451 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3452 density);
3453 return -EINVAL;
3454 }
3455
3456 htcaps_mask->a_mpdu_params |= 0x1C;
3457 htcaps->a_mpdu_params &= ~(0x1C);
3458 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3459
3460 return 0;
3461}
3462
3463
3464static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3465 struct ieee80211_ht_capabilities *htcaps,
3466 struct ieee80211_ht_capabilities *htcaps_mask,
3467 int disabled)
3468{
3469 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003470 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3471 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003472
3473 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3474
3475 if (disabled)
3476 htcaps->ht_capabilities_info &= ~msk;
3477 else
3478 htcaps->ht_capabilities_info |= msk;
3479
3480 htcaps_mask->ht_capabilities_info |= msk;
3481
3482 return 0;
3483}
3484
3485
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003486static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3487 struct ieee80211_ht_capabilities *htcaps,
3488 struct ieee80211_ht_capabilities *htcaps_mask,
3489 int disabled)
3490{
3491 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003492 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3493 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003494
3495 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3496
3497 if (disabled)
3498 htcaps->ht_capabilities_info &= ~msk;
3499 else
3500 htcaps->ht_capabilities_info |= msk;
3501
3502 htcaps_mask->ht_capabilities_info |= msk;
3503
3504 return 0;
3505}
3506
3507
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003508static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3509 struct ieee80211_ht_capabilities *htcaps,
3510 struct ieee80211_ht_capabilities *htcaps_mask,
3511 int disabled)
3512{
3513 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003514 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003515
3516 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3517
3518 if (disabled)
3519 htcaps->ht_capabilities_info &= ~msk;
3520 else
3521 htcaps->ht_capabilities_info |= msk;
3522
3523 htcaps_mask->ht_capabilities_info |= msk;
3524
3525 return 0;
3526}
3527
3528
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003529void wpa_supplicant_apply_ht_overrides(
3530 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3531 struct wpa_driver_associate_params *params)
3532{
3533 struct ieee80211_ht_capabilities *htcaps;
3534 struct ieee80211_ht_capabilities *htcaps_mask;
3535
3536 if (!ssid)
3537 return;
3538
3539 params->disable_ht = ssid->disable_ht;
3540 if (!params->htcaps || !params->htcaps_mask)
3541 return;
3542
3543 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3544 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3545 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3546 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3547 ssid->disable_max_amsdu);
3548 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3549 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3550 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003551 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003552 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003553
3554 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003555 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003556 htcaps->ht_capabilities_info |= bit;
3557 htcaps_mask->ht_capabilities_info |= bit;
3558 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003559}
3560
3561#endif /* CONFIG_HT_OVERRIDES */
3562
3563
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003564#ifdef CONFIG_VHT_OVERRIDES
3565void wpa_supplicant_apply_vht_overrides(
3566 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3567 struct wpa_driver_associate_params *params)
3568{
3569 struct ieee80211_vht_capabilities *vhtcaps;
3570 struct ieee80211_vht_capabilities *vhtcaps_mask;
3571
3572 if (!ssid)
3573 return;
3574
3575 params->disable_vht = ssid->disable_vht;
3576
3577 vhtcaps = (void *) params->vhtcaps;
3578 vhtcaps_mask = (void *) params->vhtcaps_mask;
3579
3580 if (!vhtcaps || !vhtcaps_mask)
3581 return;
3582
3583 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3584 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3585
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003586#ifdef CONFIG_HT_OVERRIDES
3587 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003588 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3589 int max_ampdu;
3590
3591 max_ampdu = (ssid->vht_capa &
3592 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3593 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003594
3595 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3596 wpa_set_ampdu_factor(wpa_s,
3597 (void *) params->htcaps,
3598 (void *) params->htcaps_mask,
3599 max_ampdu);
3600 }
3601#endif /* CONFIG_HT_OVERRIDES */
3602
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003603#define OVERRIDE_MCS(i) \
3604 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3605 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3606 3 << 2 * (i - 1); \
3607 vhtcaps->vht_supported_mcs_set.tx_map |= \
3608 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3609 } \
3610 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3611 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3612 3 << 2 * (i - 1); \
3613 vhtcaps->vht_supported_mcs_set.rx_map |= \
3614 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3615 }
3616
3617 OVERRIDE_MCS(1);
3618 OVERRIDE_MCS(2);
3619 OVERRIDE_MCS(3);
3620 OVERRIDE_MCS(4);
3621 OVERRIDE_MCS(5);
3622 OVERRIDE_MCS(6);
3623 OVERRIDE_MCS(7);
3624 OVERRIDE_MCS(8);
3625}
3626#endif /* CONFIG_VHT_OVERRIDES */
3627
3628
Dmitry Shmidt04949592012-07-19 12:16:46 -07003629static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3630{
3631#ifdef PCSC_FUNCS
3632 size_t len;
3633
3634 if (!wpa_s->conf->pcsc_reader)
3635 return 0;
3636
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003637 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003638 if (!wpa_s->scard)
3639 return 1;
3640
3641 if (wpa_s->conf->pcsc_pin &&
3642 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3643 scard_deinit(wpa_s->scard);
3644 wpa_s->scard = NULL;
3645 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3646 return -1;
3647 }
3648
3649 len = sizeof(wpa_s->imsi) - 1;
3650 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3651 scard_deinit(wpa_s->scard);
3652 wpa_s->scard = NULL;
3653 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3654 return -1;
3655 }
3656 wpa_s->imsi[len] = '\0';
3657
3658 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3659
3660 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3661 wpa_s->imsi, wpa_s->mnc_len);
3662
3663 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3664 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3665#endif /* PCSC_FUNCS */
3666
3667 return 0;
3668}
3669
3670
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003671int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3672{
3673 char *val, *pos;
3674
3675 ext_password_deinit(wpa_s->ext_pw);
3676 wpa_s->ext_pw = NULL;
3677 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3678
3679 if (!wpa_s->conf->ext_password_backend)
3680 return 0;
3681
3682 val = os_strdup(wpa_s->conf->ext_password_backend);
3683 if (val == NULL)
3684 return -1;
3685 pos = os_strchr(val, ':');
3686 if (pos)
3687 *pos++ = '\0';
3688
3689 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3690
3691 wpa_s->ext_pw = ext_password_init(val, pos);
3692 os_free(val);
3693 if (wpa_s->ext_pw == NULL) {
3694 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3695 return -1;
3696 }
3697 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3698
3699 return 0;
3700}
3701
3702
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003703static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003704 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003705{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003706 struct wowlan_triggers *triggers;
3707 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003708
3709 if (!wpa_s->conf->wowlan_triggers)
3710 return 0;
3711
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003712 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3713 if (triggers) {
3714 ret = wpa_drv_wowlan(wpa_s, triggers);
3715 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003716 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003717 return ret;
3718}
3719
3720
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003721static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3722 const char *rn)
3723{
3724 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3725 struct wpa_radio *radio;
3726
3727 while (rn && iface) {
3728 radio = iface->radio;
3729 if (radio && os_strcmp(rn, radio->name) == 0) {
3730 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3731 wpa_s->ifname, rn);
3732 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3733 return radio;
3734 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003735
3736 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003737 }
3738
3739 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3740 wpa_s->ifname, rn ? rn : "N/A");
3741 radio = os_zalloc(sizeof(*radio));
3742 if (radio == NULL)
3743 return NULL;
3744
3745 if (rn)
3746 os_strlcpy(radio->name, rn, sizeof(radio->name));
3747 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003748 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003749 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3750
3751 return radio;
3752}
3753
3754
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003755static void radio_work_free(struct wpa_radio_work *work)
3756{
3757 if (work->wpa_s->scan_work == work) {
3758 /* This should not really happen. */
3759 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3760 work->type, work, work->started);
3761 work->wpa_s->scan_work = NULL;
3762 }
3763
3764#ifdef CONFIG_P2P
3765 if (work->wpa_s->p2p_scan_work == work) {
3766 /* This should not really happen. */
3767 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3768 work->type, work, work->started);
3769 work->wpa_s->p2p_scan_work = NULL;
3770 }
3771#endif /* CONFIG_P2P */
3772
3773 dl_list_del(&work->list);
3774 os_free(work);
3775}
3776
3777
3778static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3779{
3780 struct wpa_radio *radio = eloop_ctx;
3781 struct wpa_radio_work *work;
3782 struct os_reltime now, diff;
3783 struct wpa_supplicant *wpa_s;
3784
3785 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3786 if (work == NULL)
3787 return;
3788
3789 if (work->started)
3790 return; /* already started and still in progress */
3791
3792 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3793 radio_list);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003794 if (wpa_s && wpa_s->radio->external_scan_running) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003795 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3796 return;
3797 }
3798
3799 os_get_reltime(&now);
3800 os_reltime_sub(&now, &work->time, &diff);
3801 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3802 work->type, work, diff.sec, diff.usec);
3803 work->started = 1;
3804 work->time = now;
3805 work->cb(work, 0);
3806}
3807
3808
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003809/*
3810 * This function removes both started and pending radio works running on
3811 * the provided interface's radio.
3812 * Prior to the removal of the radio work, its callback (cb) is called with
3813 * deinit set to be 1. Each work's callback is responsible for clearing its
3814 * internal data and restoring to a correct state.
3815 * @wpa_s: wpa_supplicant data
3816 * @type: type of works to be removed
3817 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3818 * this interface's works.
3819 */
3820void radio_remove_works(struct wpa_supplicant *wpa_s,
3821 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003822{
3823 struct wpa_radio_work *work, *tmp;
3824 struct wpa_radio *radio = wpa_s->radio;
3825
3826 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3827 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003828 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003829 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003830
3831 /* skip other ifaces' works */
3832 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003833 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003834
3835 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3836 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003837 work->cb(work, 1);
3838 radio_work_free(work);
3839 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003840
3841 /* in case we removed the started work */
3842 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003843}
3844
3845
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003846static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3847{
3848 struct wpa_radio *radio = wpa_s->radio;
3849
3850 if (!radio)
3851 return;
3852
3853 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3854 wpa_s->ifname, radio->name);
3855 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003856 radio_remove_works(wpa_s, NULL, 0);
3857 wpa_s->radio = NULL;
3858 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003859 return; /* Interfaces remain for this radio */
3860
3861 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003862 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003863 os_free(radio);
3864}
3865
3866
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003867void radio_work_check_next(struct wpa_supplicant *wpa_s)
3868{
3869 struct wpa_radio *radio = wpa_s->radio;
3870
3871 if (dl_list_empty(&radio->work))
3872 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003873 if (wpa_s->ext_work_in_progress) {
3874 wpa_printf(MSG_DEBUG,
3875 "External radio work in progress - delay start of pending item");
3876 return;
3877 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003878 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3879 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3880}
3881
3882
3883/**
3884 * radio_add_work - Add a radio work item
3885 * @wpa_s: Pointer to wpa_supplicant data
3886 * @freq: Frequency of the offchannel operation in MHz or 0
3887 * @type: Unique identifier for each type of work
3888 * @next: Force as the next work to be executed
3889 * @cb: Callback function for indicating when radio is available
3890 * @ctx: Context pointer for the work (work->ctx in cb())
3891 * Returns: 0 on success, -1 on failure
3892 *
3893 * This function is used to request time for an operation that requires
3894 * exclusive radio control. Once the radio is available, the registered callback
3895 * function will be called. radio_work_done() must be called once the exclusive
3896 * radio operation has been completed, so that the radio is freed for other
3897 * operations. The special case of deinit=1 is used to free the context data
3898 * during interface removal. That does not allow the callback function to start
3899 * the radio operation, i.e., it must free any resources allocated for the radio
3900 * work and return.
3901 *
3902 * The @freq parameter can be used to indicate a single channel on which the
3903 * offchannel operation will occur. This may allow multiple radio work
3904 * operations to be performed in parallel if they apply for the same channel.
3905 * Setting this to 0 indicates that the work item may use multiple channels or
3906 * requires exclusive control of the radio.
3907 */
3908int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3909 const char *type, int next,
3910 void (*cb)(struct wpa_radio_work *work, int deinit),
3911 void *ctx)
3912{
3913 struct wpa_radio_work *work;
3914 int was_empty;
3915
3916 work = os_zalloc(sizeof(*work));
3917 if (work == NULL)
3918 return -1;
3919 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3920 os_get_reltime(&work->time);
3921 work->freq = freq;
3922 work->type = type;
3923 work->wpa_s = wpa_s;
3924 work->cb = cb;
3925 work->ctx = ctx;
3926
3927 was_empty = dl_list_empty(&wpa_s->radio->work);
3928 if (next)
3929 dl_list_add(&wpa_s->radio->work, &work->list);
3930 else
3931 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3932 if (was_empty) {
3933 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3934 radio_work_check_next(wpa_s);
3935 }
3936
3937 return 0;
3938}
3939
3940
3941/**
3942 * radio_work_done - Indicate that a radio work item has been completed
3943 * @work: Completed work
3944 *
3945 * This function is called once the callback function registered with
3946 * radio_add_work() has completed its work.
3947 */
3948void radio_work_done(struct wpa_radio_work *work)
3949{
3950 struct wpa_supplicant *wpa_s = work->wpa_s;
3951 struct os_reltime now, diff;
3952 unsigned int started = work->started;
3953
3954 os_get_reltime(&now);
3955 os_reltime_sub(&now, &work->time, &diff);
3956 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3957 work->type, work, started ? "done" : "canceled",
3958 diff.sec, diff.usec);
3959 radio_work_free(work);
3960 if (started)
3961 radio_work_check_next(wpa_s);
3962}
3963
3964
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003965struct wpa_radio_work *
3966radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003967{
3968 struct wpa_radio_work *work;
3969 struct wpa_radio *radio = wpa_s->radio;
3970
3971 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3972 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003973 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003974 }
3975
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003976 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003977}
3978
3979
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003980static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3981 struct wpa_interface *iface)
3982{
3983 const char *ifname, *driver, *rn;
3984
3985 driver = iface->driver;
3986next_driver:
3987 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3988 return -1;
3989
3990 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3991 if (wpa_s->drv_priv == NULL) {
3992 const char *pos;
3993 pos = driver ? os_strchr(driver, ',') : NULL;
3994 if (pos) {
3995 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3996 "driver interface - try next driver wrapper");
3997 driver = pos + 1;
3998 goto next_driver;
3999 }
4000 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4001 "interface");
4002 return -1;
4003 }
4004 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4005 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4006 "driver_param '%s'", wpa_s->conf->driver_param);
4007 return -1;
4008 }
4009
4010 ifname = wpa_drv_get_ifname(wpa_s);
4011 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4012 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4013 "interface name with '%s'", ifname);
4014 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4015 }
4016
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004017 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004018 if (rn && rn[0] == '\0')
4019 rn = NULL;
4020
4021 wpa_s->radio = radio_add_interface(wpa_s, rn);
4022 if (wpa_s->radio == NULL)
4023 return -1;
4024
4025 return 0;
4026}
4027
4028
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004029static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4030 struct wpa_interface *iface)
4031{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004032 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004033 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004034
4035 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4036 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4037 iface->confname ? iface->confname : "N/A",
4038 iface->driver ? iface->driver : "default",
4039 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4040 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4041
4042 if (iface->confname) {
4043#ifdef CONFIG_BACKEND_FILE
4044 wpa_s->confname = os_rel2abs_path(iface->confname);
4045 if (wpa_s->confname == NULL) {
4046 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4047 "for configuration file '%s'.",
4048 iface->confname);
4049 return -1;
4050 }
4051 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4052 iface->confname, wpa_s->confname);
4053#else /* CONFIG_BACKEND_FILE */
4054 wpa_s->confname = os_strdup(iface->confname);
4055#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004056 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004057 if (wpa_s->conf == NULL) {
4058 wpa_printf(MSG_ERROR, "Failed to read or parse "
4059 "configuration '%s'.", wpa_s->confname);
4060 return -1;
4061 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004062 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4063 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004064
4065 /*
4066 * Override ctrl_interface and driver_param if set on command
4067 * line.
4068 */
4069 if (iface->ctrl_interface) {
4070 os_free(wpa_s->conf->ctrl_interface);
4071 wpa_s->conf->ctrl_interface =
4072 os_strdup(iface->ctrl_interface);
4073 }
4074
4075 if (iface->driver_param) {
4076 os_free(wpa_s->conf->driver_param);
4077 wpa_s->conf->driver_param =
4078 os_strdup(iface->driver_param);
4079 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004080
4081 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4082 os_free(wpa_s->conf->ctrl_interface);
4083 wpa_s->conf->ctrl_interface = NULL;
4084 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004085 } else
4086 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4087 iface->driver_param);
4088
4089 if (wpa_s->conf == NULL) {
4090 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4091 return -1;
4092 }
4093
4094 if (iface->ifname == NULL) {
4095 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4096 return -1;
4097 }
4098 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4099 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4100 iface->ifname);
4101 return -1;
4102 }
4103 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4104
4105 if (iface->bridge_ifname) {
4106 if (os_strlen(iface->bridge_ifname) >=
4107 sizeof(wpa_s->bridge_ifname)) {
4108 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4109 "name '%s'.", iface->bridge_ifname);
4110 return -1;
4111 }
4112 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4113 sizeof(wpa_s->bridge_ifname));
4114 }
4115
4116 /* RSNA Supplicant Key Management - INITIALIZE */
4117 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4118 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4119
4120 /* Initialize driver interface and register driver event handler before
4121 * L2 receive handler so that association events are processed before
4122 * EAPOL-Key packets if both become available for the same select()
4123 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004124 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004125 return -1;
4126
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004127 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4128 return -1;
4129
4130 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4131 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4132 NULL);
4133 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4134
4135 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4136 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4137 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4138 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4139 "dot11RSNAConfigPMKLifetime");
4140 return -1;
4141 }
4142
4143 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4144 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4145 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4146 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4147 "dot11RSNAConfigPMKReauthThreshold");
4148 return -1;
4149 }
4150
4151 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4152 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4153 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4154 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4155 "dot11RSNAConfigSATimeout");
4156 return -1;
4157 }
4158
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004159 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4160 &wpa_s->hw.num_modes,
4161 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004162 if (wpa_s->hw.modes) {
4163 u16 i;
4164
4165 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4166 if (wpa_s->hw.modes[i].vht_capab) {
4167 wpa_s->hw_capab = CAPAB_VHT;
4168 break;
4169 }
4170
4171 if (wpa_s->hw.modes[i].ht_capab &
4172 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4173 wpa_s->hw_capab = CAPAB_HT40;
4174 else if (wpa_s->hw.modes[i].ht_capab &&
4175 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4176 wpa_s->hw_capab = CAPAB_HT;
4177 }
4178 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004179
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004180 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4181 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004182 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004183 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004184 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004185 wpa_s->drv_smps_modes = capa.smps_modes;
4186 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004187 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004188 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004189 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
4190 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4191 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004192 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4193 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004194 wpa_s->extended_capa = capa.extended_capa;
4195 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4196 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004197 wpa_s->num_multichan_concurrent =
4198 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004199 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4200
4201 if (capa.mac_addr_rand_scan_supported)
4202 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4203 if (wpa_s->sched_scan_supported &&
4204 capa.mac_addr_rand_sched_scan_supported)
4205 wpa_s->mac_addr_rand_supported |=
4206 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004207 }
4208 if (wpa_s->max_remain_on_chan == 0)
4209 wpa_s->max_remain_on_chan = 1000;
4210
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004211 /*
4212 * Only take p2p_mgmt parameters when P2P Device is supported.
4213 * Doing it here as it determines whether l2_packet_init() will be done
4214 * during wpa_supplicant_driver_init().
4215 */
4216 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4217 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4218 else
4219 iface->p2p_mgmt = 1;
4220
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004221 if (wpa_s->num_multichan_concurrent == 0)
4222 wpa_s->num_multichan_concurrent = 1;
4223
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004224 if (wpa_supplicant_driver_init(wpa_s) < 0)
4225 return -1;
4226
4227#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004228 if ((!iface->p2p_mgmt ||
4229 !(wpa_s->drv_flags &
4230 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4231 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004232 return -1;
4233#endif /* CONFIG_TDLS */
4234
4235 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4236 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4237 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4238 return -1;
4239 }
4240
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004241 if (wpas_wps_init(wpa_s))
4242 return -1;
4243
4244 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4245 return -1;
4246 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4247
4248 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4249 if (wpa_s->ctrl_iface == NULL) {
4250 wpa_printf(MSG_ERROR,
4251 "Failed to initialize control interface '%s'.\n"
4252 "You may have another wpa_supplicant process "
4253 "already running or the file was\n"
4254 "left by an unclean termination of wpa_supplicant "
4255 "in which case you will need\n"
4256 "to manually remove this file before starting "
4257 "wpa_supplicant again.\n",
4258 wpa_s->conf->ctrl_interface);
4259 return -1;
4260 }
4261
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004262 wpa_s->gas = gas_query_init(wpa_s);
4263 if (wpa_s->gas == NULL) {
4264 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4265 return -1;
4266 }
4267
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004268 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004269 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4270 return -1;
4271 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004272
4273 if (wpa_bss_init(wpa_s) < 0)
4274 return -1;
4275
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004276 /*
4277 * Set Wake-on-WLAN triggers, if configured.
4278 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4279 * have effect anyway when the interface is down).
4280 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004281 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004282 return -1;
4283
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004284#ifdef CONFIG_EAP_PROXY
4285{
4286 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004287 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4288 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004289 if (wpa_s->mnc_len > 0) {
4290 wpa_s->imsi[len] = '\0';
4291 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4292 wpa_s->imsi, wpa_s->mnc_len);
4293 } else {
4294 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4295 }
4296}
4297#endif /* CONFIG_EAP_PROXY */
4298
Dmitry Shmidt04949592012-07-19 12:16:46 -07004299 if (pcsc_reader_init(wpa_s) < 0)
4300 return -1;
4301
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004302 if (wpas_init_ext_pw(wpa_s) < 0)
4303 return -1;
4304
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004305 wpas_rrm_reset(wpa_s);
4306
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004307 return 0;
4308}
4309
4310
4311static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004312 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004313{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004314 struct wpa_global *global = wpa_s->global;
4315 struct wpa_supplicant *iface, *prev;
4316
4317 if (wpa_s == wpa_s->parent)
4318 wpas_p2p_group_remove(wpa_s, "*");
4319
4320 iface = global->ifaces;
4321 while (iface) {
4322 if (iface == wpa_s || iface->parent != wpa_s) {
4323 iface = iface->next;
4324 continue;
4325 }
4326 wpa_printf(MSG_DEBUG,
4327 "Remove remaining child interface %s from parent %s",
4328 iface->ifname, wpa_s->ifname);
4329 prev = iface;
4330 iface = iface->next;
4331 wpa_supplicant_remove_iface(global, prev, terminate);
4332 }
4333
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004334 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004335 if (wpa_s->drv_priv) {
4336 wpa_supplicant_deauthenticate(wpa_s,
4337 WLAN_REASON_DEAUTH_LEAVING);
4338
4339 wpa_drv_set_countermeasures(wpa_s, 0);
4340 wpa_clear_keys(wpa_s, NULL);
4341 }
4342
4343 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004344 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004345
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004346 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004347 radio_remove_interface(wpa_s);
4348
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349 if (wpa_s->drv_priv)
4350 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004351
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004352 if (notify)
4353 wpas_notify_iface_removed(wpa_s);
4354
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004355 if (terminate)
4356 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004357
4358 if (wpa_s->ctrl_iface) {
4359 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
4360 wpa_s->ctrl_iface = NULL;
4361 }
4362
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004363#ifdef CONFIG_MESH
4364 if (wpa_s->ifmsh) {
4365 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
4366 wpa_s->ifmsh = NULL;
4367 }
4368#endif /* CONFIG_MESH */
4369
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004370 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004371 wpa_config_free(wpa_s->conf);
4372 wpa_s->conf = NULL;
4373 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004374
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004375 os_free(wpa_s->ssids_from_scan_req);
4376
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004377 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004378}
4379
4380
4381/**
4382 * wpa_supplicant_add_iface - Add a new network interface
4383 * @global: Pointer to global data from wpa_supplicant_init()
4384 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004385 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004386 * Returns: Pointer to the created interface or %NULL on failure
4387 *
4388 * This function is used to add new network interfaces for %wpa_supplicant.
4389 * This can be called before wpa_supplicant_run() to add interfaces before the
4390 * main event loop has been started. In addition, new interfaces can be added
4391 * dynamically while %wpa_supplicant is already running. This could happen,
4392 * e.g., when a hotplug network adapter is inserted.
4393 */
4394struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004395 struct wpa_interface *iface,
4396 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004397{
4398 struct wpa_supplicant *wpa_s;
4399 struct wpa_interface t_iface;
4400 struct wpa_ssid *ssid;
4401
4402 if (global == NULL || iface == NULL)
4403 return NULL;
4404
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004405 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004406 if (wpa_s == NULL)
4407 return NULL;
4408
4409 wpa_s->global = global;
4410
4411 t_iface = *iface;
4412 if (global->params.override_driver) {
4413 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
4414 "('%s' -> '%s')",
4415 iface->driver, global->params.override_driver);
4416 t_iface.driver = global->params.override_driver;
4417 }
4418 if (global->params.override_ctrl_interface) {
4419 wpa_printf(MSG_DEBUG, "Override interface parameter: "
4420 "ctrl_interface ('%s' -> '%s')",
4421 iface->ctrl_interface,
4422 global->params.override_ctrl_interface);
4423 t_iface.ctrl_interface =
4424 global->params.override_ctrl_interface;
4425 }
4426 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
4427 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
4428 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004429 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004430 return NULL;
4431 }
4432
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004433 if (iface->p2p_mgmt == 0) {
4434 /* Notify the control interfaces about new iface */
4435 if (wpas_notify_iface_added(wpa_s)) {
4436 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
4437 return NULL;
4438 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004439
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004440 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4441 wpas_notify_network_added(wpa_s, ssid);
4442 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004443
4444 wpa_s->next = global->ifaces;
4445 global->ifaces = wpa_s;
4446
4447 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004448 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004449
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004450#ifdef CONFIG_P2P
4451 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004452 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004453 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07004454 wpas_p2p_add_p2pdev_interface(
4455 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004456 wpa_printf(MSG_INFO,
4457 "P2P: Failed to enable P2P Device interface");
4458 /* Try to continue without. P2P will be disabled. */
4459 }
4460#endif /* CONFIG_P2P */
4461
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004462 return wpa_s;
4463}
4464
4465
4466/**
4467 * wpa_supplicant_remove_iface - Remove a network interface
4468 * @global: Pointer to global data from wpa_supplicant_init()
4469 * @wpa_s: Pointer to the network interface to be removed
4470 * Returns: 0 if interface was removed, -1 if interface was not found
4471 *
4472 * This function can be used to dynamically remove network interfaces from
4473 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
4474 * addition, this function is used to remove all remaining interfaces when
4475 * %wpa_supplicant is terminated.
4476 */
4477int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004478 struct wpa_supplicant *wpa_s,
4479 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004480{
4481 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004482#ifdef CONFIG_MESH
4483 unsigned int mesh_if_created = wpa_s->mesh_if_created;
4484 char *ifname = NULL;
4485#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004486
4487 /* Remove interface from the global list of interfaces */
4488 prev = global->ifaces;
4489 if (prev == wpa_s) {
4490 global->ifaces = wpa_s->next;
4491 } else {
4492 while (prev && prev->next != wpa_s)
4493 prev = prev->next;
4494 if (prev == NULL)
4495 return -1;
4496 prev->next = wpa_s->next;
4497 }
4498
4499 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
4500
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004501#ifdef CONFIG_MESH
4502 if (mesh_if_created) {
4503 ifname = os_strdup(wpa_s->ifname);
4504 if (ifname == NULL) {
4505 wpa_dbg(wpa_s, MSG_ERROR,
4506 "mesh: Failed to malloc ifname");
4507 return -1;
4508 }
4509 }
4510#endif /* CONFIG_MESH */
4511
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004512 if (global->p2p_group_formation == wpa_s)
4513 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004514 if (global->p2p_invite_group == wpa_s)
4515 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004516 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004517
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004518#ifdef CONFIG_MESH
4519 if (mesh_if_created) {
4520 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
4521 os_free(ifname);
4522 }
4523#endif /* CONFIG_MESH */
4524
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004525 return 0;
4526}
4527
4528
4529/**
4530 * wpa_supplicant_get_eap_mode - Get the current EAP mode
4531 * @wpa_s: Pointer to the network interface
4532 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
4533 */
4534const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
4535{
4536 const char *eapol_method;
4537
4538 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
4539 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4540 return "NO-EAP";
4541 }
4542
4543 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
4544 if (eapol_method == NULL)
4545 return "UNKNOWN-EAP";
4546
4547 return eapol_method;
4548}
4549
4550
4551/**
4552 * wpa_supplicant_get_iface - Get a new network interface
4553 * @global: Pointer to global data from wpa_supplicant_init()
4554 * @ifname: Interface name
4555 * Returns: Pointer to the interface or %NULL if not found
4556 */
4557struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4558 const char *ifname)
4559{
4560 struct wpa_supplicant *wpa_s;
4561
4562 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4563 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4564 return wpa_s;
4565 }
4566 return NULL;
4567}
4568
4569
4570#ifndef CONFIG_NO_WPA_MSG
4571static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4572{
4573 struct wpa_supplicant *wpa_s = ctx;
4574 if (wpa_s == NULL)
4575 return NULL;
4576 return wpa_s->ifname;
4577}
4578#endif /* CONFIG_NO_WPA_MSG */
4579
4580
4581/**
4582 * wpa_supplicant_init - Initialize %wpa_supplicant
4583 * @params: Parameters for %wpa_supplicant
4584 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4585 *
4586 * This function is used to initialize %wpa_supplicant. After successful
4587 * initialization, the returned data pointer can be used to add and remove
4588 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4589 */
4590struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4591{
4592 struct wpa_global *global;
4593 int ret, i;
4594
4595 if (params == NULL)
4596 return NULL;
4597
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004598#ifdef CONFIG_DRIVER_NDIS
4599 {
4600 void driver_ndis_init_ops(void);
4601 driver_ndis_init_ops();
4602 }
4603#endif /* CONFIG_DRIVER_NDIS */
4604
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004605#ifndef CONFIG_NO_WPA_MSG
4606 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4607#endif /* CONFIG_NO_WPA_MSG */
4608
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004609 if (params->wpa_debug_file_path)
4610 wpa_debug_open_file(params->wpa_debug_file_path);
4611 else
4612 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004613 if (params->wpa_debug_syslog)
4614 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004615 if (params->wpa_debug_tracing) {
4616 ret = wpa_debug_open_linux_tracing();
4617 if (ret) {
4618 wpa_printf(MSG_ERROR,
4619 "Failed to enable trace logging");
4620 return NULL;
4621 }
4622 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004623
4624 ret = eap_register_methods();
4625 if (ret) {
4626 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4627 if (ret == -2)
4628 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4629 "the same EAP type.");
4630 return NULL;
4631 }
4632
4633 global = os_zalloc(sizeof(*global));
4634 if (global == NULL)
4635 return NULL;
4636 dl_list_init(&global->p2p_srv_bonjour);
4637 dl_list_init(&global->p2p_srv_upnp);
4638 global->params.daemonize = params->daemonize;
4639 global->params.wait_for_monitor = params->wait_for_monitor;
4640 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4641 if (params->pid_file)
4642 global->params.pid_file = os_strdup(params->pid_file);
4643 if (params->ctrl_interface)
4644 global->params.ctrl_interface =
4645 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004646 if (params->ctrl_interface_group)
4647 global->params.ctrl_interface_group =
4648 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004649 if (params->override_driver)
4650 global->params.override_driver =
4651 os_strdup(params->override_driver);
4652 if (params->override_ctrl_interface)
4653 global->params.override_ctrl_interface =
4654 os_strdup(params->override_ctrl_interface);
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07004655 if (params->conf_p2p_dev)
4656 global->params.conf_p2p_dev =
4657 os_strdup(params->conf_p2p_dev);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004658 wpa_debug_level = global->params.wpa_debug_level =
4659 params->wpa_debug_level;
4660 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4661 params->wpa_debug_show_keys;
4662 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4663 params->wpa_debug_timestamp;
4664
4665 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4666
4667 if (eloop_init()) {
4668 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4669 wpa_supplicant_deinit(global);
4670 return NULL;
4671 }
4672
Jouni Malinen75ecf522011-06-27 15:19:46 -07004673 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004674
4675 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4676 if (global->ctrl_iface == NULL) {
4677 wpa_supplicant_deinit(global);
4678 return NULL;
4679 }
4680
4681 if (wpas_notify_supplicant_initialized(global)) {
4682 wpa_supplicant_deinit(global);
4683 return NULL;
4684 }
4685
4686 for (i = 0; wpa_drivers[i]; i++)
4687 global->drv_count++;
4688 if (global->drv_count == 0) {
4689 wpa_printf(MSG_ERROR, "No drivers enabled");
4690 wpa_supplicant_deinit(global);
4691 return NULL;
4692 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004693 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004694 if (global->drv_priv == NULL) {
4695 wpa_supplicant_deinit(global);
4696 return NULL;
4697 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004698
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004699#ifdef CONFIG_WIFI_DISPLAY
4700 if (wifi_display_init(global) < 0) {
4701 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4702 wpa_supplicant_deinit(global);
4703 return NULL;
4704 }
4705#endif /* CONFIG_WIFI_DISPLAY */
4706
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004707 return global;
4708}
4709
4710
4711/**
4712 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4713 * @global: Pointer to global data from wpa_supplicant_init()
4714 * Returns: 0 after successful event loop run, -1 on failure
4715 *
4716 * This function starts the main event loop and continues running as long as
4717 * there are any remaining events. In most cases, this function is running as
4718 * long as the %wpa_supplicant process in still in use.
4719 */
4720int wpa_supplicant_run(struct wpa_global *global)
4721{
4722 struct wpa_supplicant *wpa_s;
4723
4724 if (global->params.daemonize &&
4725 wpa_supplicant_daemon(global->params.pid_file))
4726 return -1;
4727
4728 if (global->params.wait_for_monitor) {
4729 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4730 if (wpa_s->ctrl_iface)
4731 wpa_supplicant_ctrl_iface_wait(
4732 wpa_s->ctrl_iface);
4733 }
4734
4735 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4736 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4737
4738 eloop_run();
4739
4740 return 0;
4741}
4742
4743
4744/**
4745 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4746 * @global: Pointer to global data from wpa_supplicant_init()
4747 *
4748 * This function is called to deinitialize %wpa_supplicant and to free all
4749 * allocated resources. Remaining network interfaces will also be removed.
4750 */
4751void wpa_supplicant_deinit(struct wpa_global *global)
4752{
4753 int i;
4754
4755 if (global == NULL)
4756 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004757
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004758#ifdef CONFIG_WIFI_DISPLAY
4759 wifi_display_deinit(global);
4760#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004761
4762 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004763 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004764
4765 if (global->ctrl_iface)
4766 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4767
4768 wpas_notify_supplicant_deinitialized(global);
4769
4770 eap_peer_unregister_methods();
4771#ifdef CONFIG_AP
4772 eap_server_unregister_methods();
4773#endif /* CONFIG_AP */
4774
4775 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4776 if (!global->drv_priv[i])
4777 continue;
4778 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4779 }
4780 os_free(global->drv_priv);
4781
4782 random_deinit();
4783
4784 eloop_destroy();
4785
4786 if (global->params.pid_file) {
4787 os_daemonize_terminate(global->params.pid_file);
4788 os_free(global->params.pid_file);
4789 }
4790 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004791 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004792 os_free(global->params.override_driver);
4793 os_free(global->params.override_ctrl_interface);
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07004794 os_free(global->params.conf_p2p_dev);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004795
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004796 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004797 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004798 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004799
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004800 os_free(global);
4801 wpa_debug_close_syslog();
4802 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004803 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004804}
4805
4806
4807void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4808{
4809 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4810 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4811 char country[3];
4812 country[0] = wpa_s->conf->country[0];
4813 country[1] = wpa_s->conf->country[1];
4814 country[2] = '\0';
4815 if (wpa_drv_set_country(wpa_s, country) < 0) {
4816 wpa_printf(MSG_ERROR, "Failed to set country code "
4817 "'%s'", country);
4818 }
4819 }
4820
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004821 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4822 wpas_init_ext_pw(wpa_s);
4823
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004824#ifdef CONFIG_WPS
4825 wpas_wps_update_config(wpa_s);
4826#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004827 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004828 wpa_s->conf->changed_parameters = 0;
4829}
4830
4831
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004832void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004833{
4834 int i;
4835
4836 for (i = 0; i < *num_freqs; i++) {
4837 if (freqs[i] == freq)
4838 return;
4839 }
4840
4841 freqs[*num_freqs] = freq;
4842 (*num_freqs)++;
4843}
4844
4845
4846static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4847{
4848 struct wpa_bss *bss, *cbss;
4849 const int max_freqs = 10;
4850 int *freqs;
4851 int num_freqs = 0;
4852
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004853 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004854 if (freqs == NULL)
4855 return NULL;
4856
4857 cbss = wpa_s->current_bss;
4858
4859 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4860 if (bss == cbss)
4861 continue;
4862 if (bss->ssid_len == cbss->ssid_len &&
4863 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4864 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4865 add_freq(freqs, &num_freqs, bss->freq);
4866 if (num_freqs == max_freqs)
4867 break;
4868 }
4869 }
4870
4871 if (num_freqs == 0) {
4872 os_free(freqs);
4873 freqs = NULL;
4874 }
4875
4876 return freqs;
4877}
4878
4879
4880void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4881{
4882 int timeout;
4883 int count;
4884 int *freqs = NULL;
4885
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004886 wpas_connect_work_done(wpa_s);
4887
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004888 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004889 * Remove possible authentication timeout since the connection failed.
4890 */
4891 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4892
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004893 /*
4894 * There is no point in blacklisting the AP if this event is
4895 * generated based on local request to disconnect.
4896 */
4897 if (wpa_s->own_disconnect_req) {
4898 wpa_s->own_disconnect_req = 0;
4899 wpa_dbg(wpa_s, MSG_DEBUG,
4900 "Ignore connection failure due to local request to disconnect");
4901 return;
4902 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004903 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004904 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4905 "indication since interface has been put into "
4906 "disconnected state");
4907 return;
4908 }
4909
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004910 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004911 * Add the failed BSSID into the blacklist and speed up next scan
4912 * attempt if there could be other APs that could accept association.
4913 * The current blacklist count indicates how many times we have tried
4914 * connecting to this AP and multiple attempts mean that other APs are
4915 * either not available or has already been tried, so that we can start
4916 * increasing the delay here to avoid constant scanning.
4917 */
4918 count = wpa_blacklist_add(wpa_s, bssid);
4919 if (count == 1 && wpa_s->current_bss) {
4920 /*
4921 * This BSS was not in the blacklist before. If there is
4922 * another BSS available for the same ESS, we should try that
4923 * next. Otherwise, we may as well try this one once more
4924 * before allowing other, likely worse, ESSes to be considered.
4925 */
4926 freqs = get_bss_freqs_in_ess(wpa_s);
4927 if (freqs) {
4928 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4929 "has been seen; try it next");
4930 wpa_blacklist_add(wpa_s, bssid);
4931 /*
4932 * On the next scan, go through only the known channels
4933 * used in this ESS based on previous scans to speed up
4934 * common load balancing use case.
4935 */
4936 os_free(wpa_s->next_scan_freqs);
4937 wpa_s->next_scan_freqs = freqs;
4938 }
4939 }
4940
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004941 /*
4942 * Add previous failure count in case the temporary blacklist was
4943 * cleared due to no other BSSes being available.
4944 */
4945 count += wpa_s->extra_blacklist_count;
4946
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004947 if (count > 3 && wpa_s->current_ssid) {
4948 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4949 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004950 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004951 }
4952
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004953 switch (count) {
4954 case 1:
4955 timeout = 100;
4956 break;
4957 case 2:
4958 timeout = 500;
4959 break;
4960 case 3:
4961 timeout = 1000;
4962 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004963 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004964 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004965 break;
4966 default:
4967 timeout = 10000;
4968 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004969 }
4970
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004971 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4972 "ms", count, timeout);
4973
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004974 /*
4975 * TODO: if more than one possible AP is available in scan results,
4976 * could try the other ones before requesting a new scan.
4977 */
4978 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4979 1000 * (timeout % 1000));
4980}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004981
4982
4983int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4984{
4985 return wpa_s->conf->ap_scan == 2 ||
4986 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4987}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004988
Dmitry Shmidt04949592012-07-19 12:16:46 -07004989
4990#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4991int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4992 struct wpa_ssid *ssid,
4993 const char *field,
4994 const char *value)
4995{
4996#ifdef IEEE8021X_EAPOL
4997 struct eap_peer_config *eap = &ssid->eap;
4998
4999 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5000 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5001 (const u8 *) value, os_strlen(value));
5002
5003 switch (wpa_supplicant_ctrl_req_from_string(field)) {
5004 case WPA_CTRL_REQ_EAP_IDENTITY:
5005 os_free(eap->identity);
5006 eap->identity = (u8 *) os_strdup(value);
5007 eap->identity_len = os_strlen(value);
5008 eap->pending_req_identity = 0;
5009 if (ssid == wpa_s->current_ssid)
5010 wpa_s->reassociate = 1;
5011 break;
5012 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005013 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005014 eap->password = (u8 *) os_strdup(value);
5015 eap->password_len = os_strlen(value);
5016 eap->pending_req_password = 0;
5017 if (ssid == wpa_s->current_ssid)
5018 wpa_s->reassociate = 1;
5019 break;
5020 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005021 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005022 eap->new_password = (u8 *) os_strdup(value);
5023 eap->new_password_len = os_strlen(value);
5024 eap->pending_req_new_password = 0;
5025 if (ssid == wpa_s->current_ssid)
5026 wpa_s->reassociate = 1;
5027 break;
5028 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005029 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005030 eap->pin = os_strdup(value);
5031 eap->pending_req_pin = 0;
5032 if (ssid == wpa_s->current_ssid)
5033 wpa_s->reassociate = 1;
5034 break;
5035 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005036 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005037 eap->otp = (u8 *) os_strdup(value);
5038 eap->otp_len = os_strlen(value);
5039 os_free(eap->pending_req_otp);
5040 eap->pending_req_otp = NULL;
5041 eap->pending_req_otp_len = 0;
5042 break;
5043 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005044 str_clear_free(eap->private_key_passwd);
5045 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005046 eap->pending_req_passphrase = 0;
5047 if (ssid == wpa_s->current_ssid)
5048 wpa_s->reassociate = 1;
5049 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005050 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005051 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005052 eap->external_sim_resp = os_strdup(value);
5053 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005054 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5055 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5056 return -1;
5057 ssid->mem_only_psk = 1;
5058 if (ssid->passphrase)
5059 wpa_config_update_psk(ssid);
5060 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5061 wpa_supplicant_req_scan(wpa_s, 0, 0);
5062 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005063 default:
5064 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
5065 return -1;
5066 }
5067
5068 return 0;
5069#else /* IEEE8021X_EAPOL */
5070 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5071 return -1;
5072#endif /* IEEE8021X_EAPOL */
5073}
5074#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
5075
5076
5077int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5078{
5079 int i;
5080 unsigned int drv_enc;
5081
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005082 if (wpa_s->p2p_mgmt)
5083 return 1; /* no normal network profiles on p2p_mgmt interface */
5084
Dmitry Shmidt04949592012-07-19 12:16:46 -07005085 if (ssid == NULL)
5086 return 1;
5087
5088 if (ssid->disabled)
5089 return 1;
5090
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005091 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005092 drv_enc = wpa_s->drv_enc;
5093 else
5094 drv_enc = (unsigned int) -1;
5095
5096 for (i = 0; i < NUM_WEP_KEYS; i++) {
5097 size_t len = ssid->wep_key_len[i];
5098 if (len == 0)
5099 continue;
5100 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5101 continue;
5102 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5103 continue;
5104 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5105 continue;
5106 return 1; /* invalid WEP key */
5107 }
5108
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005109 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005110 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5111 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005112 return 1;
5113
Dmitry Shmidt04949592012-07-19 12:16:46 -07005114 return 0;
5115}
5116
5117
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005118int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5119{
5120#ifdef CONFIG_IEEE80211W
5121 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
5122 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
5123 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
5124 /*
5125 * Driver does not support BIP -- ignore pmf=1 default
5126 * since the connection with PMF would fail and the
5127 * configuration does not require PMF to be enabled.
5128 */
5129 return NO_MGMT_FRAME_PROTECTION;
5130 }
5131
5132 return wpa_s->conf->pmf;
5133 }
5134
5135 return ssid->ieee80211w;
5136#else /* CONFIG_IEEE80211W */
5137 return NO_MGMT_FRAME_PROTECTION;
5138#endif /* CONFIG_IEEE80211W */
5139}
5140
5141
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005142int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005143{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005144 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005145 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005146 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005147 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005148 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005149}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005150
5151
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005152void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005153{
5154 struct wpa_ssid *ssid = wpa_s->current_ssid;
5155 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005156 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005157
5158 if (ssid == NULL) {
5159 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
5160 "SSID block");
5161 return;
5162 }
5163
5164 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
5165 return;
5166
5167 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005168
5169#ifdef CONFIG_P2P
5170 if (ssid->p2p_group &&
5171 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
5172 /*
5173 * Skip the wait time since there is a short timeout on the
5174 * connection to a P2P group.
5175 */
5176 return;
5177 }
5178#endif /* CONFIG_P2P */
5179
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005180 if (ssid->auth_failures > 50)
5181 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005182 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005183 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005184 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005185 dur = 90;
5186 else if (ssid->auth_failures > 3)
5187 dur = 60;
5188 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005189 dur = 30;
5190 else if (ssid->auth_failures > 1)
5191 dur = 20;
5192 else
5193 dur = 10;
5194
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005195 if (ssid->auth_failures > 1 &&
5196 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
5197 dur += os_random() % (ssid->auth_failures * 10);
5198
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005199 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005200 if (now.sec + dur <= ssid->disabled_until.sec)
5201 return;
5202
5203 ssid->disabled_until.sec = now.sec + dur;
5204
5205 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005206 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005207 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005208 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005209}
5210
5211
5212void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
5213 struct wpa_ssid *ssid, int clear_failures)
5214{
5215 if (ssid == NULL)
5216 return;
5217
5218 if (ssid->disabled_until.sec) {
5219 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
5220 "id=%d ssid=\"%s\"",
5221 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
5222 }
5223 ssid->disabled_until.sec = 0;
5224 ssid->disabled_until.usec = 0;
5225 if (clear_failures)
5226 ssid->auth_failures = 0;
5227}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005228
5229
5230int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
5231{
5232 size_t i;
5233
5234 if (wpa_s->disallow_aps_bssid == NULL)
5235 return 0;
5236
5237 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
5238 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
5239 bssid, ETH_ALEN) == 0)
5240 return 1;
5241 }
5242
5243 return 0;
5244}
5245
5246
5247int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
5248 size_t ssid_len)
5249{
5250 size_t i;
5251
5252 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
5253 return 0;
5254
5255 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
5256 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
5257 if (ssid_len == s->ssid_len &&
5258 os_memcmp(ssid, s->ssid, ssid_len) == 0)
5259 return 1;
5260 }
5261
5262 return 0;
5263}
5264
5265
5266/**
5267 * wpas_request_connection - Request a new connection
5268 * @wpa_s: Pointer to the network interface
5269 *
5270 * This function is used to request a new connection to be found. It will mark
5271 * the interface to allow reassociation and request a new scan to find a
5272 * suitable network to connect to.
5273 */
5274void wpas_request_connection(struct wpa_supplicant *wpa_s)
5275{
5276 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005277 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005278 wpa_supplicant_reinit_autoscan(wpa_s);
5279 wpa_s->extra_blacklist_count = 0;
5280 wpa_s->disconnected = 0;
5281 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005282
5283 if (wpa_supplicant_fast_associate(wpa_s) != 1)
5284 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005285 else
5286 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005287}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005288
5289
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005290void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
5291 struct wpa_used_freq_data *freqs_data,
5292 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005293{
5294 unsigned int i;
5295
5296 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
5297 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005298 for (i = 0; i < len; i++) {
5299 struct wpa_used_freq_data *cur = &freqs_data[i];
5300 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
5301 i, cur->freq, cur->flags);
5302 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005303}
5304
5305
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005306/*
5307 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005308 * are using the same radio as the current interface, and in addition, get
5309 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005310 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005311int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
5312 struct wpa_used_freq_data *freqs_data,
5313 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005314{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005315 struct wpa_supplicant *ifs;
5316 u8 bssid[ETH_ALEN];
5317 int freq;
5318 unsigned int idx = 0, i;
5319
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005320 wpa_dbg(wpa_s, MSG_DEBUG,
5321 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005322 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005323
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005324 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
5325 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005326 if (idx == len)
5327 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005328
5329 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
5330 continue;
5331
5332 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
5333 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
5334 freq = ifs->current_ssid->frequency;
5335 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
5336 freq = ifs->assoc_freq;
5337 else
5338 continue;
5339
5340 /* Hold only distinct freqs */
5341 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005342 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005343 break;
5344
5345 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005346 freqs_data[idx++].freq = freq;
5347
5348 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
5349 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
5350 WPA_FREQ_USED_BY_P2P_CLIENT :
5351 WPA_FREQ_USED_BY_INFRA_STATION;
5352 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005353 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005354
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005355 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005356 return idx;
5357}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005358
5359
5360/*
5361 * Find the operating frequencies of any of the virtual interfaces that
5362 * are using the same radio as the current interface.
5363 */
5364int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
5365 int *freq_array, unsigned int len)
5366{
5367 struct wpa_used_freq_data *freqs_data;
5368 int num, i;
5369
5370 os_memset(freq_array, 0, sizeof(int) * len);
5371
5372 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
5373 if (!freqs_data)
5374 return -1;
5375
5376 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
5377 for (i = 0; i < num; i++)
5378 freq_array[i] = freqs_data[i].freq;
5379
5380 os_free(freqs_data);
5381
5382 return num;
5383}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005384
5385
5386static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
5387{
5388 struct rrm_data *rrm = data;
5389
5390 if (!rrm->notify_neighbor_rep) {
5391 wpa_printf(MSG_ERROR,
5392 "RRM: Unexpected neighbor report timeout");
5393 return;
5394 }
5395
5396 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
5397 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
5398
5399 rrm->notify_neighbor_rep = NULL;
5400 rrm->neighbor_rep_cb_ctx = NULL;
5401}
5402
5403
5404/*
5405 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
5406 * @wpa_s: Pointer to wpa_supplicant
5407 */
5408void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
5409{
5410 wpa_s->rrm.rrm_used = 0;
5411
5412 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5413 NULL);
5414 if (wpa_s->rrm.notify_neighbor_rep)
5415 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
5416 wpa_s->rrm.next_neighbor_rep_token = 1;
5417}
5418
5419
5420/*
5421 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
5422 * @wpa_s: Pointer to wpa_supplicant
5423 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
5424 * @report_len: Length of neighbor report buffer
5425 */
5426void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
5427 const u8 *report, size_t report_len)
5428{
5429 struct wpabuf *neighbor_rep;
5430
5431 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
5432 if (report_len < 1)
5433 return;
5434
5435 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
5436 wpa_printf(MSG_DEBUG,
5437 "RRM: Discarding neighbor report with token %d (expected %d)",
5438 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
5439 return;
5440 }
5441
5442 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5443 NULL);
5444
5445 if (!wpa_s->rrm.notify_neighbor_rep) {
5446 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
5447 return;
5448 }
5449
5450 /* skipping the first byte, which is only an id (dialog token) */
5451 neighbor_rep = wpabuf_alloc(report_len - 1);
5452 if (neighbor_rep == NULL)
5453 return;
5454 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
5455 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
5456 report[0]);
5457 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
5458 neighbor_rep);
5459 wpa_s->rrm.notify_neighbor_rep = NULL;
5460 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
5461}
5462
5463
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005464#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
5465/* Workaround different, undefined for Windows, error codes used here */
5466#define ENOTCONN -1
5467#define EOPNOTSUPP -1
5468#define ECANCELED -1
5469#endif
5470
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005471/**
5472 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
5473 * @wpa_s: Pointer to wpa_supplicant
5474 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
5475 * is sent in the request.
5476 * @cb: Callback function to be called once the requested report arrives, or
5477 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
5478 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
5479 * the requester's responsibility to free it.
5480 * In the latter case NULL will be sent in 'neighbor_rep'.
5481 * @cb_ctx: Context value to send the callback function
5482 * Returns: 0 in case of success, negative error code otherwise
5483 *
5484 * In case there is a previous request which has not been answered yet, the
5485 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
5486 * Request must contain a callback function.
5487 */
5488int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
5489 const struct wpa_ssid *ssid,
5490 void (*cb)(void *ctx,
5491 struct wpabuf *neighbor_rep),
5492 void *cb_ctx)
5493{
5494 struct wpabuf *buf;
5495 const u8 *rrm_ie;
5496
5497 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
5498 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
5499 return -ENOTCONN;
5500 }
5501
5502 if (!wpa_s->rrm.rrm_used) {
5503 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
5504 return -EOPNOTSUPP;
5505 }
5506
5507 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
5508 WLAN_EID_RRM_ENABLED_CAPABILITIES);
5509 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
5510 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
5511 wpa_printf(MSG_DEBUG,
5512 "RRM: No network support for Neighbor Report.");
5513 return -EOPNOTSUPP;
5514 }
5515
5516 if (!cb) {
5517 wpa_printf(MSG_DEBUG,
5518 "RRM: Neighbor Report request must provide a callback.");
5519 return -EINVAL;
5520 }
5521
5522 /* Refuse if there's a live request */
5523 if (wpa_s->rrm.notify_neighbor_rep) {
5524 wpa_printf(MSG_DEBUG,
5525 "RRM: Currently handling previous Neighbor Report.");
5526 return -EBUSY;
5527 }
5528
5529 /* 3 = action category + action code + dialog token */
5530 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
5531 if (buf == NULL) {
5532 wpa_printf(MSG_DEBUG,
5533 "RRM: Failed to allocate Neighbor Report Request");
5534 return -ENOMEM;
5535 }
5536
5537 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
5538 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
5539 wpa_s->rrm.next_neighbor_rep_token);
5540
5541 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5542 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
5543 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
5544 if (ssid) {
5545 wpabuf_put_u8(buf, WLAN_EID_SSID);
5546 wpabuf_put_u8(buf, ssid->ssid_len);
5547 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
5548 }
5549
5550 wpa_s->rrm.next_neighbor_rep_token++;
5551
5552 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
5553 wpa_s->own_addr, wpa_s->bssid,
5554 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
5555 wpa_printf(MSG_DEBUG,
5556 "RRM: Failed to send Neighbor Report Request");
5557 wpabuf_free(buf);
5558 return -ECANCELED;
5559 }
5560
5561 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
5562 wpa_s->rrm.notify_neighbor_rep = cb;
5563 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
5564 wpas_rrm_neighbor_rep_timeout_handler,
5565 &wpa_s->rrm, NULL);
5566
5567 wpabuf_free(buf);
5568 return 0;
5569}
5570
5571
5572void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
5573 const u8 *src,
5574 const u8 *frame, size_t len,
5575 int rssi)
5576{
5577 struct wpabuf *buf;
5578 const struct rrm_link_measurement_request *req;
5579 struct rrm_link_measurement_report report;
5580
5581 if (wpa_s->wpa_state != WPA_COMPLETED) {
5582 wpa_printf(MSG_INFO,
5583 "RRM: Ignoring link measurement request. Not associated");
5584 return;
5585 }
5586
5587 if (!wpa_s->rrm.rrm_used) {
5588 wpa_printf(MSG_INFO,
5589 "RRM: Ignoring link measurement request. Not RRM network");
5590 return;
5591 }
5592
5593 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
5594 wpa_printf(MSG_INFO,
5595 "RRM: Measurement report failed. TX power insertion not supported");
5596 return;
5597 }
5598
5599 req = (const struct rrm_link_measurement_request *) frame;
5600 if (len < sizeof(*req)) {
5601 wpa_printf(MSG_INFO,
5602 "RRM: Link measurement report failed. Request too short");
5603 return;
5604 }
5605
5606 os_memset(&report, 0, sizeof(report));
5607 report.tpc.eid = WLAN_EID_TPC_REPORT;
5608 report.tpc.len = 2;
5609 report.rsni = 255; /* 255 indicates that RSNI is not available */
5610 report.dialog_token = req->dialog_token;
5611
5612 /*
5613 * It's possible to estimate RCPI based on RSSI in dBm. This
5614 * calculation will not reflect the correct value for high rates,
5615 * but it's good enough for Action frames which are transmitted
5616 * with up to 24 Mbps rates.
5617 */
5618 if (!rssi)
5619 report.rcpi = 255; /* not available */
5620 else if (rssi < -110)
5621 report.rcpi = 0;
5622 else if (rssi > 0)
5623 report.rcpi = 220;
5624 else
5625 report.rcpi = (rssi + 110) * 2;
5626
5627 /* action_category + action_code */
5628 buf = wpabuf_alloc(2 + sizeof(report));
5629 if (buf == NULL) {
5630 wpa_printf(MSG_ERROR,
5631 "RRM: Link measurement report failed. Buffer allocation failed");
5632 return;
5633 }
5634
5635 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5636 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
5637 wpabuf_put_data(buf, &report, sizeof(report));
5638 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
5639 wpabuf_head(buf), wpabuf_len(buf));
5640
5641 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
5642 wpa_s->own_addr, wpa_s->bssid,
5643 wpabuf_head(buf), wpabuf_len(buf), 0)) {
5644 wpa_printf(MSG_ERROR,
5645 "RRM: Link measurement report failed. Send action failed");
5646 }
5647 wpabuf_free(buf);
5648}