blob: 874eb48fdd944a3a097c339f055e09885580caf0 [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 Shmidt1f69aa52012-01-24 16:10:04 -0800496 gas_query_deinit(wpa_s->gas);
497 wpa_s->gas = NULL;
498
499 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700500
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700501 ieee802_1x_dealloc_kay_sm(wpa_s);
502
Dmitry Shmidt04949592012-07-19 12:16:46 -0700503 os_free(wpa_s->bssid_filter);
504 wpa_s->bssid_filter = NULL;
505
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800506 os_free(wpa_s->disallow_aps_bssid);
507 wpa_s->disallow_aps_bssid = NULL;
508 os_free(wpa_s->disallow_aps_ssid);
509 wpa_s->disallow_aps_ssid = NULL;
510
Dmitry Shmidt04949592012-07-19 12:16:46 -0700511 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700512#ifdef CONFIG_WNM
513 wnm_deallocate_memory(wpa_s);
514#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700515
516 ext_password_deinit(wpa_s->ext_pw);
517 wpa_s->ext_pw = NULL;
518
519 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800520 wpa_s->last_gas_resp = NULL;
521 wpabuf_free(wpa_s->prev_gas_resp);
522 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700523
524 os_free(wpa_s->last_scan_res);
525 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800526
527#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700528 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800529#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700530
531 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
532 wpabuf_free(wpa_s->vendor_elem[i]);
533 wpa_s->vendor_elem[i] = NULL;
534 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800535
536 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700537}
538
539
540/**
541 * wpa_clear_keys - Clear keys configured for the driver
542 * @wpa_s: Pointer to wpa_supplicant data
543 * @addr: Previously used BSSID or %NULL if not available
544 *
545 * This function clears the encryption keys that has been previously configured
546 * for the driver.
547 */
548void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
549{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800550 int i, max;
551
552#ifdef CONFIG_IEEE80211W
553 max = 6;
554#else /* CONFIG_IEEE80211W */
555 max = 4;
556#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557
558 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800559 for (i = 0; i < max; i++) {
560 if (wpa_s->keys_cleared & BIT(i))
561 continue;
562 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
563 NULL, 0);
564 }
565 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
566 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700567 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
568 0);
569 /* MLME-SETPROTECTION.request(None) */
570 wpa_drv_mlme_setprotection(
571 wpa_s, addr,
572 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
573 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
574 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800575 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700576}
577
578
579/**
580 * wpa_supplicant_state_txt - Get the connection state name as a text string
581 * @state: State (wpa_state; WPA_*)
582 * Returns: The state name as a printable text string
583 */
584const char * wpa_supplicant_state_txt(enum wpa_states state)
585{
586 switch (state) {
587 case WPA_DISCONNECTED:
588 return "DISCONNECTED";
589 case WPA_INACTIVE:
590 return "INACTIVE";
591 case WPA_INTERFACE_DISABLED:
592 return "INTERFACE_DISABLED";
593 case WPA_SCANNING:
594 return "SCANNING";
595 case WPA_AUTHENTICATING:
596 return "AUTHENTICATING";
597 case WPA_ASSOCIATING:
598 return "ASSOCIATING";
599 case WPA_ASSOCIATED:
600 return "ASSOCIATED";
601 case WPA_4WAY_HANDSHAKE:
602 return "4WAY_HANDSHAKE";
603 case WPA_GROUP_HANDSHAKE:
604 return "GROUP_HANDSHAKE";
605 case WPA_COMPLETED:
606 return "COMPLETED";
607 default:
608 return "UNKNOWN";
609 }
610}
611
612
613#ifdef CONFIG_BGSCAN
614
615static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
616{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800617 const char *name;
618
619 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
620 name = wpa_s->current_ssid->bgscan;
621 else
622 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800623 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800624 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800625 if (wpas_driver_bss_selection(wpa_s))
626 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700627 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
628 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800629#ifdef CONFIG_P2P
630 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
631 return;
632#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700633
634 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800635 if (wpa_s->current_ssid) {
636 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
638 "bgscan");
639 /*
640 * Live without bgscan; it is only used as a roaming
641 * optimization, so the initial connection is not
642 * affected.
643 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700644 } else {
645 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700646 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700647 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
648 0);
649 if (scan_res) {
650 bgscan_notify_scan(wpa_s, scan_res);
651 wpa_scan_results_free(scan_res);
652 }
653 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700654 } else
655 wpa_s->bgscan_ssid = NULL;
656}
657
658
659static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
660{
661 if (wpa_s->bgscan_ssid != NULL) {
662 bgscan_deinit(wpa_s);
663 wpa_s->bgscan_ssid = NULL;
664 }
665}
666
667#endif /* CONFIG_BGSCAN */
668
669
Dmitry Shmidt04949592012-07-19 12:16:46 -0700670static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
671{
672 if (autoscan_init(wpa_s, 0))
673 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
674}
675
676
677static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
678{
679 autoscan_deinit(wpa_s);
680}
681
682
683void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
684{
685 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
686 wpa_s->wpa_state == WPA_SCANNING) {
687 autoscan_deinit(wpa_s);
688 wpa_supplicant_start_autoscan(wpa_s);
689 }
690}
691
692
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700693/**
694 * wpa_supplicant_set_state - Set current connection state
695 * @wpa_s: Pointer to wpa_supplicant data
696 * @state: The new connection state
697 *
698 * This function is called whenever the connection state changes, e.g.,
699 * association is completed for WPA/WPA2 4-Way Handshake is started.
700 */
701void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
702 enum wpa_states state)
703{
704 enum wpa_states old_state = wpa_s->wpa_state;
705
706 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
707 wpa_supplicant_state_txt(wpa_s->wpa_state),
708 wpa_supplicant_state_txt(state));
709
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800710 if (state == WPA_INTERFACE_DISABLED) {
711 /* Assure normal scan when interface is restored */
712 wpa_s->normal_scans = 0;
713 }
714
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700715 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800716 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700717 /* Reinitialize normal_scan counter */
718 wpa_s->normal_scans = 0;
719 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800720
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700721 if (state != WPA_SCANNING)
722 wpa_supplicant_notify_scanning(wpa_s, 0);
723
724 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700725 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700726#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700727 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800728 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800729 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730 ssid ? ssid->id : -1,
731 ssid && ssid->id_str ? ssid->id_str : "");
732#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700733 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700734 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800735 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700737 wpa_drv_set_operstate(wpa_s, 1);
738#ifndef IEEE8021X_EAPOL
739 wpa_drv_set_supp_port(wpa_s, 1);
740#endif /* IEEE8021X_EAPOL */
741 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700742 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700744
745 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
747 state == WPA_ASSOCIATED) {
748 wpa_s->new_connection = 1;
749 wpa_drv_set_operstate(wpa_s, 0);
750#ifndef IEEE8021X_EAPOL
751 wpa_drv_set_supp_port(wpa_s, 0);
752#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700753 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700754 }
755 wpa_s->wpa_state = state;
756
757#ifdef CONFIG_BGSCAN
758 if (state == WPA_COMPLETED)
759 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800760 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700761 wpa_supplicant_stop_bgscan(wpa_s);
762#endif /* CONFIG_BGSCAN */
763
Dmitry Shmidt04949592012-07-19 12:16:46 -0700764 if (state == WPA_AUTHENTICATING)
765 wpa_supplicant_stop_autoscan(wpa_s);
766
767 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
768 wpa_supplicant_start_autoscan(wpa_s);
769
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800770 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
771 wmm_ac_notify_disassoc(wpa_s);
772
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773 if (wpa_s->wpa_state != old_state) {
774 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
775
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700776 /*
777 * Notify the P2P Device interface about a state change in one
778 * of the interfaces.
779 */
780 wpas_p2p_indicate_state_change(wpa_s);
781
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700782 if (wpa_s->wpa_state == WPA_COMPLETED ||
783 old_state == WPA_COMPLETED)
784 wpas_notify_auth_changed(wpa_s);
785 }
786}
787
788
789void wpa_supplicant_terminate_proc(struct wpa_global *global)
790{
791 int pending = 0;
792#ifdef CONFIG_WPS
793 struct wpa_supplicant *wpa_s = global->ifaces;
794 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800795 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700796 if (wpas_wps_terminate_pending(wpa_s) == 1)
797 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700798#ifdef CONFIG_P2P
799 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
800 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
801 wpas_p2p_disconnect(wpa_s);
802#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800803 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 }
805#endif /* CONFIG_WPS */
806 if (pending)
807 return;
808 eloop_terminate();
809}
810
811
812static void wpa_supplicant_terminate(int sig, void *signal_ctx)
813{
814 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700815 wpa_supplicant_terminate_proc(global);
816}
817
818
819void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
820{
821 enum wpa_states old_state = wpa_s->wpa_state;
822
823 wpa_s->pairwise_cipher = 0;
824 wpa_s->group_cipher = 0;
825 wpa_s->mgmt_group_cipher = 0;
826 wpa_s->key_mgmt = 0;
827 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700828 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700829
830 if (wpa_s->wpa_state != old_state)
831 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
832}
833
834
835/**
836 * wpa_supplicant_reload_configuration - Reload configuration data
837 * @wpa_s: Pointer to wpa_supplicant data
838 * Returns: 0 on success or -1 if configuration parsing failed
839 *
840 * This function can be used to request that the configuration data is reloaded
841 * (e.g., after configuration file change). This function is reloading
842 * configuration only for one interface, so this may need to be called multiple
843 * times if %wpa_supplicant is controlling multiple interfaces and all
844 * interfaces need reconfiguration.
845 */
846int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
847{
848 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849 int reconf_ctrl;
850 int old_ap_scan;
851
852 if (wpa_s->confname == NULL)
853 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700854 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700855 if (conf == NULL) {
856 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
857 "file '%s' - exiting", wpa_s->confname);
858 return -1;
859 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700860 wpa_config_read(wpa_s->confanother, conf);
861
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700862 conf->changed_parameters = (unsigned int) -1;
863
864 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
865 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
866 os_strcmp(conf->ctrl_interface,
867 wpa_s->conf->ctrl_interface) != 0);
868
869 if (reconf_ctrl && wpa_s->ctrl_iface) {
870 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
871 wpa_s->ctrl_iface = NULL;
872 }
873
874 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800875 if (wpa_s->current_ssid) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -0800876 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800877 wpa_supplicant_deauthenticate(wpa_s,
878 WLAN_REASON_DEAUTH_LEAVING);
879 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880
881 /*
882 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800883 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884 */
885 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
886 /*
887 * Clear forced success to clear EAP state for next
888 * authentication.
889 */
890 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
891 }
892 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
893 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800894 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700895 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
896 rsn_preauth_deinit(wpa_s->wpa);
897
898 old_ap_scan = wpa_s->conf->ap_scan;
899 wpa_config_free(wpa_s->conf);
900 wpa_s->conf = conf;
901 if (old_ap_scan != wpa_s->conf->ap_scan)
902 wpas_notify_ap_scan_changed(wpa_s);
903
904 if (reconf_ctrl)
905 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
906
907 wpa_supplicant_update_config(wpa_s);
908
909 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700910 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700911 wpa_s->reassociate = 1;
912 wpa_supplicant_req_scan(wpa_s, 0, 0);
913 }
914 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
915 return 0;
916}
917
918
919static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
920{
921 struct wpa_global *global = signal_ctx;
922 struct wpa_supplicant *wpa_s;
923 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
924 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
925 sig);
926 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
927 wpa_supplicant_terminate_proc(global);
928 }
929 }
930}
931
932
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700933static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
934 struct wpa_ssid *ssid,
935 struct wpa_ie_data *ie)
936{
937 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
938 if (ret) {
939 if (ret == -2) {
940 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
941 "from association info");
942 }
943 return -1;
944 }
945
946 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
947 "cipher suites");
948 if (!(ie->group_cipher & ssid->group_cipher)) {
949 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
950 "cipher 0x%x (mask 0x%x) - reject",
951 ie->group_cipher, ssid->group_cipher);
952 return -1;
953 }
954 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
955 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
956 "cipher 0x%x (mask 0x%x) - reject",
957 ie->pairwise_cipher, ssid->pairwise_cipher);
958 return -1;
959 }
960 if (!(ie->key_mgmt & ssid->key_mgmt)) {
961 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
962 "management 0x%x (mask 0x%x) - reject",
963 ie->key_mgmt, ssid->key_mgmt);
964 return -1;
965 }
966
967#ifdef CONFIG_IEEE80211W
968 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800969 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700970 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
971 "that does not support management frame protection - "
972 "reject");
973 return -1;
974 }
975#endif /* CONFIG_IEEE80211W */
976
977 return 0;
978}
979
980
981/**
982 * wpa_supplicant_set_suites - Set authentication and encryption parameters
983 * @wpa_s: Pointer to wpa_supplicant data
984 * @bss: Scan results for the selected BSS, or %NULL if not available
985 * @ssid: Configuration data for the selected network
986 * @wpa_ie: Buffer for the WPA/RSN IE
987 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
988 * used buffer length in case the functions returns success.
989 * Returns: 0 on success or -1 on failure
990 *
991 * This function is used to configure authentication and encryption parameters
992 * based on the network configuration and scan result for the selected BSS (if
993 * available).
994 */
995int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
996 struct wpa_bss *bss, struct wpa_ssid *ssid,
997 u8 *wpa_ie, size_t *wpa_ie_len)
998{
999 struct wpa_ie_data ie;
1000 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001001 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002
1003 if (bss) {
1004 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1005 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001006 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001008 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009
1010 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1011 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1012 (ie.group_cipher & ssid->group_cipher) &&
1013 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1014 (ie.key_mgmt & ssid->key_mgmt)) {
1015 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1016 proto = WPA_PROTO_RSN;
1017 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001018 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019 (ie.group_cipher & ssid->group_cipher) &&
1020 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1021 (ie.key_mgmt & ssid->key_mgmt)) {
1022 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1023 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001024#ifdef CONFIG_HS20
1025 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1026 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1027 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001028 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001029 ie.group_cipher = WPA_CIPHER_CCMP;
1030 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1031 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1032 proto = WPA_PROTO_OSEN;
1033#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034 } else if (bss) {
1035 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001036 wpa_dbg(wpa_s, MSG_DEBUG,
1037 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1038 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1039 ssid->key_mgmt);
1040 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1041 MAC2STR(bss->bssid),
1042 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1043 bss_wpa ? " WPA" : "",
1044 bss_rsn ? " RSN" : "",
1045 bss_osen ? " OSEN" : "");
1046 if (bss_rsn) {
1047 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1048 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1049 wpa_dbg(wpa_s, MSG_DEBUG,
1050 "Could not parse RSN element");
1051 } else {
1052 wpa_dbg(wpa_s, MSG_DEBUG,
1053 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1054 ie.pairwise_cipher, ie.group_cipher,
1055 ie.key_mgmt);
1056 }
1057 }
1058 if (bss_wpa) {
1059 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1060 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1061 wpa_dbg(wpa_s, MSG_DEBUG,
1062 "Could not parse WPA element");
1063 } else {
1064 wpa_dbg(wpa_s, MSG_DEBUG,
1065 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1066 ie.pairwise_cipher, ie.group_cipher,
1067 ie.key_mgmt);
1068 }
1069 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070 return -1;
1071 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001072 if (ssid->proto & WPA_PROTO_OSEN)
1073 proto = WPA_PROTO_OSEN;
1074 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075 proto = WPA_PROTO_RSN;
1076 else
1077 proto = WPA_PROTO_WPA;
1078 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1079 os_memset(&ie, 0, sizeof(ie));
1080 ie.group_cipher = ssid->group_cipher;
1081 ie.pairwise_cipher = ssid->pairwise_cipher;
1082 ie.key_mgmt = ssid->key_mgmt;
1083#ifdef CONFIG_IEEE80211W
1084 ie.mgmt_group_cipher =
1085 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1086 WPA_CIPHER_AES_128_CMAC : 0;
1087#endif /* CONFIG_IEEE80211W */
1088 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1089 "based on configuration");
1090 } else
1091 proto = ie.proto;
1092 }
1093
1094 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1095 "pairwise %d key_mgmt %d proto %d",
1096 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1097#ifdef CONFIG_IEEE80211W
1098 if (ssid->ieee80211w) {
1099 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1100 ie.mgmt_group_cipher);
1101 }
1102#endif /* CONFIG_IEEE80211W */
1103
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001104 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1106 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001107 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108
1109 if (bss || !wpa_s->ap_ies_from_associnfo) {
1110 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1111 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1112 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1113 bss_rsn ? 2 + bss_rsn[1] : 0))
1114 return -1;
1115 }
1116
1117 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001118 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1119 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1121 "cipher");
1122 return -1;
1123 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001124 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1125 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001126
1127 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001128 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1129 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001130 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1131 "cipher");
1132 return -1;
1133 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001134 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1135 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001136
1137 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001138#ifdef CONFIG_SAE
1139 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1140 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1141#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001143#ifdef CONFIG_SUITEB192
1144 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1145 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1146 wpa_dbg(wpa_s, MSG_DEBUG,
1147 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1148#endif /* CONFIG_SUITEB192 */
1149#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001150 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1151 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1152 wpa_dbg(wpa_s, MSG_DEBUG,
1153 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001154#endif /* CONFIG_SUITEB */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001155#ifdef CONFIG_IEEE80211R
1156 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1157 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1158 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1159 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1160 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1161 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1162#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001163#ifdef CONFIG_SAE
1164 } else if (sel & WPA_KEY_MGMT_SAE) {
1165 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1166 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1167 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1168 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1169 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1170#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001171#ifdef CONFIG_IEEE80211W
1172 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1173 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1174 wpa_dbg(wpa_s, MSG_DEBUG,
1175 "WPA: using KEY_MGMT 802.1X with SHA256");
1176 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1177 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1178 wpa_dbg(wpa_s, MSG_DEBUG,
1179 "WPA: using KEY_MGMT PSK with SHA256");
1180#endif /* CONFIG_IEEE80211W */
1181 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1182 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1183 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1184 } else if (sel & WPA_KEY_MGMT_PSK) {
1185 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1186 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1187 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1188 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1189 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001190#ifdef CONFIG_HS20
1191 } else if (sel & WPA_KEY_MGMT_OSEN) {
1192 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1193 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1194#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001195 } else {
1196 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1197 "authenticated key management type");
1198 return -1;
1199 }
1200
1201 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1202 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1203 wpa_s->pairwise_cipher);
1204 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1205
1206#ifdef CONFIG_IEEE80211W
1207 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001208 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1210 sel = 0;
1211 if (sel & WPA_CIPHER_AES_128_CMAC) {
1212 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1213 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1214 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001215 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1216 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1217 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1218 "BIP-GMAC-128");
1219 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1220 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1221 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1222 "BIP-GMAC-256");
1223 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1224 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1225 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1226 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001227 } else {
1228 wpa_s->mgmt_group_cipher = 0;
1229 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1230 }
1231 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1232 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001233 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001234 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235#endif /* CONFIG_IEEE80211W */
1236
1237 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1238 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1239 return -1;
1240 }
1241
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001242 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001243 int psk_set = 0;
1244
1245 if (ssid->psk_set) {
1246 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
1247 psk_set = 1;
1248 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001249#ifndef CONFIG_NO_PBKDF2
1250 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1251 ssid->passphrase) {
1252 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001253 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1254 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001255 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1256 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001257 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001258 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001259 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001260 }
1261#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001262#ifdef CONFIG_EXT_PASSWORD
1263 if (ssid->ext_psk) {
1264 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1265 ssid->ext_psk);
1266 char pw_str[64 + 1];
1267 u8 psk[PMK_LEN];
1268
1269 if (pw == NULL) {
1270 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1271 "found from external storage");
1272 return -1;
1273 }
1274
1275 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1276 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1277 "PSK length %d in external storage",
1278 (int) wpabuf_len(pw));
1279 ext_password_free(pw);
1280 return -1;
1281 }
1282
1283 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1284 pw_str[wpabuf_len(pw)] = '\0';
1285
1286#ifndef CONFIG_NO_PBKDF2
1287 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1288 {
1289 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1290 4096, psk, PMK_LEN);
1291 os_memset(pw_str, 0, sizeof(pw_str));
1292 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1293 "external passphrase)",
1294 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001295 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001296 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001297 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001298 } else
1299#endif /* CONFIG_NO_PBKDF2 */
1300 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1301 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1302 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1303 "Invalid PSK hex string");
1304 os_memset(pw_str, 0, sizeof(pw_str));
1305 ext_password_free(pw);
1306 return -1;
1307 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001308 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001309 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001310 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001311 } else {
1312 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1313 "PSK available");
1314 os_memset(pw_str, 0, sizeof(pw_str));
1315 ext_password_free(pw);
1316 return -1;
1317 }
1318
1319 os_memset(pw_str, 0, sizeof(pw_str));
1320 ext_password_free(pw);
1321 }
1322#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001323
1324 if (!psk_set) {
1325 wpa_msg(wpa_s, MSG_INFO,
1326 "No PSK available for association");
1327 return -1;
1328 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001329 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1331
1332 return 0;
1333}
1334
1335
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001336static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1337{
1338 *pos = 0x00;
1339
1340 switch (idx) {
1341 case 0: /* Bits 0-7 */
1342 break;
1343 case 1: /* Bits 8-15 */
1344 break;
1345 case 2: /* Bits 16-23 */
1346#ifdef CONFIG_WNM
1347 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1348 *pos |= 0x08; /* Bit 19 - BSS Transition */
1349#endif /* CONFIG_WNM */
1350 break;
1351 case 3: /* Bits 24-31 */
1352#ifdef CONFIG_WNM
1353 *pos |= 0x02; /* Bit 25 - SSID List */
1354#endif /* CONFIG_WNM */
1355#ifdef CONFIG_INTERWORKING
1356 if (wpa_s->conf->interworking)
1357 *pos |= 0x80; /* Bit 31 - Interworking */
1358#endif /* CONFIG_INTERWORKING */
1359 break;
1360 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001361#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001362 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1363 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001364#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001365 break;
1366 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001367#ifdef CONFIG_HS20
1368 if (wpa_s->conf->hs20)
1369 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1370#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001371 break;
1372 case 6: /* Bits 48-55 */
1373 break;
1374 }
1375}
1376
1377
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001378int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001379{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001380 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001381 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001382
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001383 if (len < wpa_s->extended_capa_len)
1384 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001385 if (buflen < (size_t) len + 2) {
1386 wpa_printf(MSG_INFO,
1387 "Not enough room for building extended capabilities element");
1388 return -1;
1389 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001390
1391 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001392 *pos++ = len;
1393 for (i = 0; i < len; i++, pos++) {
1394 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001395
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001396 if (i < wpa_s->extended_capa_len) {
1397 *pos &= ~wpa_s->extended_capa_mask[i];
1398 *pos |= wpa_s->extended_capa[i];
1399 }
1400 }
1401
1402 while (len > 0 && buf[1 + len] == 0) {
1403 len--;
1404 buf[1] = len;
1405 }
1406 if (len == 0)
1407 return 0;
1408
1409 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001410}
1411
1412
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001413static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1414 struct wpa_bss *test_bss)
1415{
1416 struct wpa_bss *bss;
1417
1418 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1419 if (bss == test_bss)
1420 return 1;
1421 }
1422
1423 return 0;
1424}
1425
1426
1427static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1428 struct wpa_ssid *test_ssid)
1429{
1430 struct wpa_ssid *ssid;
1431
1432 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1433 if (ssid == test_ssid)
1434 return 1;
1435 }
1436
1437 return 0;
1438}
1439
1440
1441int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1442 struct wpa_ssid *test_ssid)
1443{
1444 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1445 return 0;
1446
1447 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1448}
1449
1450
1451void wpas_connect_work_free(struct wpa_connect_work *cwork)
1452{
1453 if (cwork == NULL)
1454 return;
1455 os_free(cwork);
1456}
1457
1458
1459void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1460{
1461 struct wpa_connect_work *cwork;
1462 struct wpa_radio_work *work = wpa_s->connect_work;
1463
1464 if (!work)
1465 return;
1466
1467 wpa_s->connect_work = NULL;
1468 cwork = work->ctx;
1469 work->ctx = NULL;
1470 wpas_connect_work_free(cwork);
1471 radio_work_done(work);
1472}
1473
1474
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001475int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1476{
1477 struct os_reltime now;
1478 u8 addr[ETH_ALEN];
1479
1480 os_get_reltime(&now);
1481 if (wpa_s->last_mac_addr_style == style &&
1482 wpa_s->last_mac_addr_change.sec != 0 &&
1483 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1484 wpa_s->conf->rand_addr_lifetime)) {
1485 wpa_msg(wpa_s, MSG_DEBUG,
1486 "Previously selected random MAC address has not yet expired");
1487 return 0;
1488 }
1489
1490 switch (style) {
1491 case 1:
1492 if (random_mac_addr(addr) < 0)
1493 return -1;
1494 break;
1495 case 2:
1496 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1497 if (random_mac_addr_keep_oui(addr) < 0)
1498 return -1;
1499 break;
1500 default:
1501 return -1;
1502 }
1503
1504 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1505 wpa_msg(wpa_s, MSG_INFO,
1506 "Failed to set random MAC address");
1507 return -1;
1508 }
1509
1510 os_get_reltime(&wpa_s->last_mac_addr_change);
1511 wpa_s->mac_addr_changed = 1;
1512 wpa_s->last_mac_addr_style = style;
1513
1514 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1515 wpa_msg(wpa_s, MSG_INFO,
1516 "Could not update MAC address information");
1517 return -1;
1518 }
1519
1520 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1521 MAC2STR(addr));
1522
1523 return 0;
1524}
1525
1526
1527int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1528{
1529 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1530 !wpa_s->conf->preassoc_mac_addr)
1531 return 0;
1532
1533 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1534}
1535
1536
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001537static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1538
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001539/**
1540 * wpa_supplicant_associate - Request association
1541 * @wpa_s: Pointer to wpa_supplicant data
1542 * @bss: Scan results for the selected BSS, or %NULL if not available
1543 * @ssid: Configuration data for the selected network
1544 *
1545 * This function is used to request %wpa_supplicant to associate with a BSS.
1546 */
1547void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1548 struct wpa_bss *bss, struct wpa_ssid *ssid)
1549{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001550 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001551 int rand_style;
1552
1553 if (ssid->mac_addr == -1)
1554 rand_style = wpa_s->conf->mac_addr;
1555 else
1556 rand_style = ssid->mac_addr;
1557
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001558 wmm_ac_clear_saved_tspecs(wpa_s);
1559 wpa_s->reassoc_same_bss = 0;
1560
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001561 if (wpa_s->last_ssid == ssid) {
1562 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001563 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1564 wmm_ac_save_tspecs(wpa_s);
1565 wpa_s->reassoc_same_bss = 1;
1566 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001567 } else if (rand_style > 0) {
1568 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1569 return;
1570 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1571 } else if (wpa_s->mac_addr_changed) {
1572 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1573 wpa_msg(wpa_s, MSG_INFO,
1574 "Could not restore permanent MAC address");
1575 return;
1576 }
1577 wpa_s->mac_addr_changed = 0;
1578 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1579 wpa_msg(wpa_s, MSG_INFO,
1580 "Could not update MAC address information");
1581 return;
1582 }
1583 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1584 }
1585 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001586
1587#ifdef CONFIG_IBSS_RSN
1588 ibss_rsn_deinit(wpa_s->ibss_rsn);
1589 wpa_s->ibss_rsn = NULL;
1590#endif /* CONFIG_IBSS_RSN */
1591
1592 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1593 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1594#ifdef CONFIG_AP
1595 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1596 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1597 "mode");
1598 return;
1599 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001600 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1601 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001602 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1603 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001604 return;
1605 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001606 wpa_s->current_bss = bss;
1607#else /* CONFIG_AP */
1608 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1609 "the build");
1610#endif /* CONFIG_AP */
1611 return;
1612 }
1613
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001614 if (ssid->mode == WPAS_MODE_MESH) {
1615#ifdef CONFIG_MESH
1616 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1617 wpa_msg(wpa_s, MSG_INFO,
1618 "Driver does not support mesh mode");
1619 return;
1620 }
1621 if (bss)
1622 ssid->frequency = bss->freq;
1623 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1624 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1625 return;
1626 }
1627 wpa_s->current_bss = bss;
1628 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
1629 "ssid=\"%s\" id=%d",
1630 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1631 ssid->id);
1632#else /* CONFIG_MESH */
1633 wpa_msg(wpa_s, MSG_ERROR,
1634 "mesh mode support not included in the build");
1635#endif /* CONFIG_MESH */
1636 return;
1637 }
1638
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001639#ifdef CONFIG_TDLS
1640 if (bss)
1641 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1642 bss->ie_len);
1643#endif /* CONFIG_TDLS */
1644
1645 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1646 ssid->mode == IEEE80211_MODE_INFRA) {
1647 sme_authenticate(wpa_s, bss, ssid);
1648 return;
1649 }
1650
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001651 if (wpa_s->connect_work) {
1652 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1653 return;
1654 }
1655
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001656 if (radio_work_pending(wpa_s, "connect")) {
1657 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1658 return;
1659 }
1660
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001661 cwork = os_zalloc(sizeof(*cwork));
1662 if (cwork == NULL)
1663 return;
1664
1665 cwork->bss = bss;
1666 cwork->ssid = ssid;
1667
1668 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1669 wpas_start_assoc_cb, cwork) < 0) {
1670 os_free(cwork);
1671 }
1672}
1673
1674
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001675static int bss_is_ibss(struct wpa_bss *bss)
1676{
1677 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1678 IEEE80211_CAP_IBSS;
1679}
1680
1681
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001682void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1683 const struct wpa_ssid *ssid,
1684 struct hostapd_freq_params *freq)
1685{
1686 enum hostapd_hw_mode hw_mode;
1687 struct hostapd_hw_modes *mode = NULL;
1688 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1689 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001690 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001691 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1692 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001693 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001694 unsigned int j;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001695 struct hostapd_freq_params vht_freq;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001696
1697 freq->freq = ssid->frequency;
1698
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001699 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1700 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1701
1702 if (ssid->mode != WPAS_MODE_IBSS)
1703 break;
1704
1705 /* Don't adjust control freq in case of fixed_freq */
1706 if (ssid->fixed_freq)
1707 break;
1708
1709 if (!bss_is_ibss(bss))
1710 continue;
1711
1712 if (ssid->ssid_len == bss->ssid_len &&
1713 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1714 wpa_printf(MSG_DEBUG,
1715 "IBSS already found in scan results, adjust control freq: %d",
1716 bss->freq);
1717 freq->freq = bss->freq;
1718 obss_scan = 0;
1719 break;
1720 }
1721 }
1722
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001723 /* For IBSS check HT_IBSS flag */
1724 if (ssid->mode == WPAS_MODE_IBSS &&
1725 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1726 return;
1727
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001728 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1729 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1730 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1731 wpa_printf(MSG_DEBUG,
1732 "IBSS: WEP/TKIP detected, do not try to enable HT");
1733 return;
1734 }
1735
1736 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001737 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1738 if (wpa_s->hw.modes[i].mode == hw_mode) {
1739 mode = &wpa_s->hw.modes[i];
1740 break;
1741 }
1742 }
1743
1744 if (!mode)
1745 return;
1746
1747 freq->ht_enabled = ht_supported(mode);
1748 if (!freq->ht_enabled)
1749 return;
1750
1751 /* Setup higher BW only for 5 GHz */
1752 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1753 return;
1754
1755 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1756 pri_chan = &mode->channels[chan_idx];
1757 if (pri_chan->chan == channel)
1758 break;
1759 pri_chan = NULL;
1760 }
1761 if (!pri_chan)
1762 return;
1763
1764 /* Check primary channel flags */
1765 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1766 return;
1767
1768 /* Check/setup HT40+/HT40- */
1769 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1770 if (ht40plus[j] == channel) {
1771 ht40 = 1;
1772 break;
1773 }
1774 }
1775
1776 /* Find secondary channel */
1777 for (i = 0; i < mode->num_channels; i++) {
1778 sec_chan = &mode->channels[i];
1779 if (sec_chan->chan == channel + ht40 * 4)
1780 break;
1781 sec_chan = NULL;
1782 }
1783 if (!sec_chan)
1784 return;
1785
1786 /* Check secondary channel flags */
1787 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1788 return;
1789
1790 freq->channel = pri_chan->chan;
1791
1792 switch (ht40) {
1793 case -1:
1794 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1795 return;
1796 freq->sec_channel_offset = -1;
1797 break;
1798 case 1:
1799 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1800 return;
1801 freq->sec_channel_offset = 1;
1802 break;
1803 default:
1804 break;
1805 }
1806
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001807 if (freq->sec_channel_offset && obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001808 struct wpa_scan_results *scan_res;
1809
1810 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1811 if (scan_res == NULL) {
1812 /* Back to HT20 */
1813 freq->sec_channel_offset = 0;
1814 return;
1815 }
1816
1817 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1818 sec_chan->chan);
1819 switch (res) {
1820 case 0:
1821 /* Back to HT20 */
1822 freq->sec_channel_offset = 0;
1823 break;
1824 case 1:
1825 /* Configuration allowed */
1826 break;
1827 case 2:
1828 /* Switch pri/sec channels */
1829 freq->freq = hw_get_freq(mode, sec_chan->chan);
1830 freq->sec_channel_offset = -freq->sec_channel_offset;
1831 freq->channel = sec_chan->chan;
1832 break;
1833 default:
1834 freq->sec_channel_offset = 0;
1835 break;
1836 }
1837
1838 wpa_scan_results_free(scan_res);
1839 }
1840
1841 wpa_printf(MSG_DEBUG,
1842 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
1843 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001844
1845 /* Not sure if mesh is ready for VHT */
1846 if (ssid->mode != WPAS_MODE_IBSS)
1847 return;
1848
1849 /* For IBSS check VHT_IBSS flag */
1850 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
1851 return;
1852
1853 vht_freq = *freq;
1854
1855 vht_freq.vht_enabled = vht_supported(mode);
1856 if (!vht_freq.vht_enabled)
1857 return;
1858
1859 /* setup center_freq1, bandwidth */
1860 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
1861 if (freq->channel >= vht80[j] &&
1862 freq->channel < vht80[j] + 16)
1863 break;
1864 }
1865
1866 if (j == ARRAY_SIZE(vht80))
1867 return;
1868
1869 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
1870 struct hostapd_channel_data *chan;
1871
1872 chan = hw_get_channel_chan(mode, i, NULL);
1873 if (!chan)
1874 return;
1875
1876 /* Back to HT configuration if channel not usable */
1877 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1878 return;
1879 }
1880
1881 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
1882 freq->channel, freq->ht_enabled,
1883 vht_freq.vht_enabled,
1884 freq->sec_channel_offset,
1885 VHT_CHANWIDTH_80MHZ,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08001886 vht80[j] + 6, 0, 0) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001887 return;
1888
1889 *freq = vht_freq;
1890
1891 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
1892 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001893}
1894
1895
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001896static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1897{
1898 struct wpa_connect_work *cwork = work->ctx;
1899 struct wpa_bss *bss = cwork->bss;
1900 struct wpa_ssid *ssid = cwork->ssid;
1901 struct wpa_supplicant *wpa_s = work->wpa_s;
1902 u8 wpa_ie[200];
1903 size_t wpa_ie_len;
1904 int use_crypt, ret, i, bssid_changed;
1905 int algs = WPA_AUTH_ALG_OPEN;
1906 unsigned int cipher_pairwise, cipher_group;
1907 struct wpa_driver_associate_params params;
1908 int wep_keys_set = 0;
1909 int assoc_failed = 0;
1910 struct wpa_ssid *old_ssid;
1911#ifdef CONFIG_HT_OVERRIDES
1912 struct ieee80211_ht_capabilities htcaps;
1913 struct ieee80211_ht_capabilities htcaps_mask;
1914#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001915#ifdef CONFIG_VHT_OVERRIDES
1916 struct ieee80211_vht_capabilities vhtcaps;
1917 struct ieee80211_vht_capabilities vhtcaps_mask;
1918#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001919
1920 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001921 if (work->started) {
1922 wpa_s->connect_work = NULL;
1923
1924 /* cancel possible auth. timeout */
1925 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1926 NULL);
1927 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001928 wpas_connect_work_free(cwork);
1929 return;
1930 }
1931
1932 wpa_s->connect_work = work;
1933
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001934 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001935 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1936 wpas_connect_work_done(wpa_s);
1937 return;
1938 }
1939
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001940 os_memset(&params, 0, sizeof(params));
1941 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001942 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001943 if (bss &&
1944 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001945#ifdef CONFIG_IEEE80211R
1946 const u8 *ie, *md = NULL;
1947#endif /* CONFIG_IEEE80211R */
1948 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1949 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1950 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1951 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1952 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1953 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1954 if (bssid_changed)
1955 wpas_notify_bssid_changed(wpa_s);
1956#ifdef CONFIG_IEEE80211R
1957 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1958 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1959 md = ie + 2;
1960 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1961 if (md) {
1962 /* Prepare for the next transition */
1963 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1964 }
1965#endif /* CONFIG_IEEE80211R */
1966#ifdef CONFIG_WPS
1967 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1968 wpa_s->conf->ap_scan == 2 &&
1969 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1970 /* Use ap_scan==1 style network selection to find the network
1971 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001972 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001973 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974 wpa_s->reassociate = 1;
1975 wpa_supplicant_req_scan(wpa_s, 0, 0);
1976 return;
1977#endif /* CONFIG_WPS */
1978 } else {
1979 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1980 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1981 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1982 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001983 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984 wpa_supplicant_cancel_scan(wpa_s);
1985
1986 /* Starting new association, so clear the possibly used WPA IE from the
1987 * previous association. */
1988 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1989
1990#ifdef IEEE8021X_EAPOL
1991 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1992 if (ssid->leap) {
1993 if (ssid->non_leap == 0)
1994 algs = WPA_AUTH_ALG_LEAP;
1995 else
1996 algs |= WPA_AUTH_ALG_LEAP;
1997 }
1998 }
1999#endif /* IEEE8021X_EAPOL */
2000 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2001 if (ssid->auth_alg) {
2002 algs = ssid->auth_alg;
2003 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2004 "0x%x", algs);
2005 }
2006
2007 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2008 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002009 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002011 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2012 wpa_s->conf->okc :
2013 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002014 (ssid->proto & WPA_PROTO_RSN);
2015 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002016 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002017 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002018 wpa_ie_len = sizeof(wpa_ie);
2019 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2020 wpa_ie, &wpa_ie_len)) {
2021 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2022 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002023 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002024 return;
2025 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002026 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2027 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2028 /*
2029 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2030 * use non-WPA since the scan results did not indicate that the
2031 * AP is using WPA or WPA2.
2032 */
2033 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2034 wpa_ie_len = 0;
2035 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002036 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002037 wpa_ie_len = sizeof(wpa_ie);
2038 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2039 wpa_ie, &wpa_ie_len)) {
2040 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2041 "key management and encryption suites (no "
2042 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002043 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002044 return;
2045 }
2046#ifdef CONFIG_WPS
2047 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2048 struct wpabuf *wps_ie;
2049 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2050 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2051 wpa_ie_len = wpabuf_len(wps_ie);
2052 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2053 } else
2054 wpa_ie_len = 0;
2055 wpabuf_free(wps_ie);
2056 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2057 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2058 params.wps = WPS_MODE_PRIVACY;
2059 else
2060 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002061 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002062#endif /* CONFIG_WPS */
2063 } else {
2064 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2065 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002066 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002067 }
2068
2069#ifdef CONFIG_P2P
2070 if (wpa_s->global->p2p) {
2071 u8 *pos;
2072 size_t len;
2073 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002074 pos = wpa_ie + wpa_ie_len;
2075 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002076 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2077 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002078 if (res >= 0)
2079 wpa_ie_len += res;
2080 }
2081
2082 wpa_s->cross_connect_disallowed = 0;
2083 if (bss) {
2084 struct wpabuf *p2p;
2085 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2086 if (p2p) {
2087 wpa_s->cross_connect_disallowed =
2088 p2p_get_cross_connect_disallowed(p2p);
2089 wpabuf_free(p2p);
2090 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2091 "connection",
2092 wpa_s->cross_connect_disallowed ?
2093 "disallows" : "allows");
2094 }
2095 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002096
2097 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002098#endif /* CONFIG_P2P */
2099
Dmitry Shmidt04949592012-07-19 12:16:46 -07002100#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002101 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002102 struct wpabuf *hs20;
2103 hs20 = wpabuf_alloc(20);
2104 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002105 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002106 size_t len;
2107
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002108 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002109 len = sizeof(wpa_ie) - wpa_ie_len;
2110 if (wpabuf_len(hs20) <= len) {
2111 os_memcpy(wpa_ie + wpa_ie_len,
2112 wpabuf_head(hs20), wpabuf_len(hs20));
2113 wpa_ie_len += wpabuf_len(hs20);
2114 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002115 wpabuf_free(hs20);
2116 }
2117 }
2118#endif /* CONFIG_HS20 */
2119
Dmitry Shmidt56052862013-10-04 10:23:25 -07002120 /*
2121 * Workaround: Add Extended Capabilities element only if the AP
2122 * included this element in Beacon/Probe Response frames. Some older
2123 * APs seem to have interoperability issues if this element is
2124 * included, so while the standard may require us to include the
2125 * element in all cases, it is justifiable to skip it to avoid
2126 * interoperability issues.
2127 */
2128 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002129 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002130 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002131 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2132 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002133 if (ext_capab_len > 0) {
2134 u8 *pos = wpa_ie;
2135 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2136 pos += 2 + pos[1];
2137 os_memmove(pos + ext_capab_len, pos,
2138 wpa_ie_len - (pos - wpa_ie));
2139 wpa_ie_len += ext_capab_len;
2140 os_memcpy(pos, ext_capab, ext_capab_len);
2141 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002142 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002143
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002144 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2145 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2146 size_t len;
2147
2148 len = sizeof(wpa_ie) - wpa_ie_len;
2149 if (wpabuf_len(buf) <= len) {
2150 os_memcpy(wpa_ie + wpa_ie_len,
2151 wpabuf_head(buf), wpabuf_len(buf));
2152 wpa_ie_len += wpabuf_len(buf);
2153 }
2154 }
2155
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002156 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2157 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002158 cipher_pairwise = wpa_s->pairwise_cipher;
2159 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002160 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2161 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2162 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2163 use_crypt = 0;
2164 if (wpa_set_wep_keys(wpa_s, ssid)) {
2165 use_crypt = 1;
2166 wep_keys_set = 1;
2167 }
2168 }
2169 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2170 use_crypt = 0;
2171
2172#ifdef IEEE8021X_EAPOL
2173 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2174 if ((ssid->eapol_flags &
2175 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2176 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2177 !wep_keys_set) {
2178 use_crypt = 0;
2179 } else {
2180 /* Assume that dynamic WEP-104 keys will be used and
2181 * set cipher suites in order for drivers to expect
2182 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002183 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002184 }
2185 }
2186#endif /* IEEE8021X_EAPOL */
2187
2188 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2189 /* Set the key before (and later after) association */
2190 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2191 }
2192
2193 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2194 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002195 params.ssid = bss->ssid;
2196 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002197 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
2198 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2199 MACSTR " freq=%u MHz based on scan results "
2200 "(bssid_set=%d)",
2201 MAC2STR(bss->bssid), bss->freq,
2202 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002203 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002204 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002205 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002206 params.bssid_hint = bss->bssid;
2207 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002208 } else {
2209 params.ssid = ssid->ssid;
2210 params.ssid_len = ssid->ssid_len;
2211 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002212
2213 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2214 wpa_s->conf->ap_scan == 2) {
2215 params.bssid = ssid->bssid;
2216 params.fixed_bssid = 1;
2217 }
2218
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002219 /* Initial frequency for IBSS/mesh */
2220 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002221 ssid->frequency > 0 && params.freq.freq == 0)
2222 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002223
2224 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002225 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002226 if (ssid->beacon_int)
2227 params.beacon_int = ssid->beacon_int;
2228 else
2229 params.beacon_int = wpa_s->conf->beacon_int;
2230 }
2231
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002232 params.wpa_ie = wpa_ie;
2233 params.wpa_ie_len = wpa_ie_len;
2234 params.pairwise_suite = cipher_pairwise;
2235 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002236 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002237 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002238 params.auth_alg = algs;
2239 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002240 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241 for (i = 0; i < NUM_WEP_KEYS; i++) {
2242 if (ssid->wep_key_len[i])
2243 params.wep_key[i] = ssid->wep_key[i];
2244 params.wep_key_len[i] = ssid->wep_key_len[i];
2245 }
2246 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2247
2248 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002249 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2250 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002251 params.passphrase = ssid->passphrase;
2252 if (ssid->psk_set)
2253 params.psk = ssid->psk;
2254 }
2255
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002256 if (wpa_s->conf->key_mgmt_offload) {
2257 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2258 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002259 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2260 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002261 params.req_key_mgmt_offload =
2262 ssid->proactive_key_caching < 0 ?
2263 wpa_s->conf->okc : ssid->proactive_key_caching;
2264 else
2265 params.req_key_mgmt_offload = 1;
2266
2267 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2268 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2269 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2270 ssid->psk_set)
2271 params.psk = ssid->psk;
2272 }
2273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002274 params.drop_unencrypted = use_crypt;
2275
2276#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002277 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002278 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002279 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2280 struct wpa_ie_data ie;
2281 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2282 ie.capabilities &
2283 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2284 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2285 "MFP: require MFP");
2286 params.mgmt_frame_protection =
2287 MGMT_FRAME_PROTECTION_REQUIRED;
2288 }
2289 }
2290#endif /* CONFIG_IEEE80211W */
2291
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002292 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002293
2294 if (wpa_s->parent->set_sta_uapsd)
2295 params.uapsd = wpa_s->parent->sta_uapsd;
2296 else
2297 params.uapsd = -1;
2298
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002299#ifdef CONFIG_HT_OVERRIDES
2300 os_memset(&htcaps, 0, sizeof(htcaps));
2301 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2302 params.htcaps = (u8 *) &htcaps;
2303 params.htcaps_mask = (u8 *) &htcaps_mask;
2304 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2305#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002306#ifdef CONFIG_VHT_OVERRIDES
2307 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2308 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2309 params.vhtcaps = &vhtcaps;
2310 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002311 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002312#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002313
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002314#ifdef CONFIG_P2P
2315 /*
2316 * If multi-channel concurrency is not supported, check for any
2317 * frequency conflict. In case of any frequency conflict, remove the
2318 * least prioritized connection.
2319 */
2320 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002321 int freq, num;
2322 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002323 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002324 wpa_printf(MSG_DEBUG,
2325 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002326 freq, params.freq.freq);
2327 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002328 wpa_s, params.freq.freq, ssid) < 0) {
2329 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002330 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002331 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002332 }
2333 }
2334#endif /* CONFIG_P2P */
2335
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002336 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002337 if (ret < 0) {
2338 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2339 "failed");
2340 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2341 /*
2342 * The driver is known to mean what is saying, so we
2343 * can stop right here; the association will not
2344 * succeed.
2345 */
2346 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002347 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2349 return;
2350 }
2351 /* try to continue anyway; new association will be tried again
2352 * after timeout */
2353 assoc_failed = 1;
2354 }
2355
2356 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2357 /* Set the key after the association just in case association
2358 * cleared the previously configured key. */
2359 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2360 /* No need to timeout authentication since there is no key
2361 * management. */
2362 wpa_supplicant_cancel_auth_timeout(wpa_s);
2363 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2364#ifdef CONFIG_IBSS_RSN
2365 } else if (ssid->mode == WPAS_MODE_IBSS &&
2366 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2367 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2368 /*
2369 * RSN IBSS authentication is per-STA and we can disable the
2370 * per-BSSID authentication.
2371 */
2372 wpa_supplicant_cancel_auth_timeout(wpa_s);
2373#endif /* CONFIG_IBSS_RSN */
2374 } else {
2375 /* Timeout for IEEE 802.11 authentication and association */
2376 int timeout = 60;
2377
2378 if (assoc_failed) {
2379 /* give IBSS a bit more time */
2380 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2381 } else if (wpa_s->conf->ap_scan == 1) {
2382 /* give IBSS a bit more time */
2383 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2384 }
2385 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2386 }
2387
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002388 if (wep_keys_set &&
2389 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002390 /* Set static WEP keys again */
2391 wpa_set_wep_keys(wpa_s, ssid);
2392 }
2393
2394 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2395 /*
2396 * Do not allow EAP session resumption between different
2397 * network configurations.
2398 */
2399 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2400 }
2401 old_ssid = wpa_s->current_ssid;
2402 wpa_s->current_ssid = ssid;
2403 wpa_s->current_bss = bss;
2404 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2405 wpa_supplicant_initiate_eapol(wpa_s);
2406 if (old_ssid != wpa_s->current_ssid)
2407 wpas_notify_network_changed(wpa_s);
2408}
2409
2410
2411static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2412 const u8 *addr)
2413{
2414 struct wpa_ssid *old_ssid;
2415
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002416 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002417 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002419 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002420 wpa_sm_set_config(wpa_s->wpa, NULL);
2421 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2422 if (old_ssid != wpa_s->current_ssid)
2423 wpas_notify_network_changed(wpa_s);
2424 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2425}
2426
2427
2428/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002429 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2430 * @wpa_s: Pointer to wpa_supplicant data
2431 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2432 *
2433 * This function is used to request %wpa_supplicant to deauthenticate from the
2434 * current AP.
2435 */
2436void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2437 int reason_code)
2438{
2439 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002440 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002441 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002443 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2444 " pending_bssid=" MACSTR " reason=%d state=%s",
2445 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2446 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2447
2448 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002449 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002450 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2451 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2452 wpa_s->wpa_state == WPA_ASSOCIATING))
2453 addr = wpa_s->pending_bssid;
2454 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2455 /*
2456 * When using driver-based BSS selection, we may not know the
2457 * BSSID with which we are currently trying to associate. We
2458 * need to notify the driver of this disconnection even in such
2459 * a case, so use the all zeros address here.
2460 */
2461 addr = wpa_s->bssid;
2462 zero_addr = 1;
2463 }
2464
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002465#ifdef CONFIG_TDLS
2466 wpa_tdls_teardown_peers(wpa_s->wpa);
2467#endif /* CONFIG_TDLS */
2468
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002469#ifdef CONFIG_MESH
2470 if (wpa_s->ifmsh) {
2471 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2472 wpa_s->ifname);
2473 wpa_supplicant_leave_mesh(wpa_s);
2474 }
2475#endif /* CONFIG_MESH */
2476
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002477 if (addr) {
2478 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002479 os_memset(&event, 0, sizeof(event));
2480 event.deauth_info.reason_code = (u16) reason_code;
2481 event.deauth_info.locally_generated = 1;
2482 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002483 if (zero_addr)
2484 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485 }
2486
2487 wpa_supplicant_clear_connection(wpa_s, addr);
2488}
2489
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002490static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2491 struct wpa_ssid *ssid)
2492{
2493 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2494 return;
2495
2496 ssid->disabled = 0;
2497 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2498 wpas_notify_network_enabled_changed(wpa_s, ssid);
2499
2500 /*
2501 * Try to reassociate since there is no current configuration and a new
2502 * network was made available.
2503 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002504 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002505 wpa_s->reassociate = 1;
2506}
2507
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508
2509/**
2510 * wpa_supplicant_enable_network - Mark a configured network as enabled
2511 * @wpa_s: wpa_supplicant structure for a network interface
2512 * @ssid: wpa_ssid structure for a configured network or %NULL
2513 *
2514 * Enables the specified network or all networks if no network specified.
2515 */
2516void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2517 struct wpa_ssid *ssid)
2518{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002519 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002520 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2521 wpa_supplicant_enable_one_network(wpa_s, ssid);
2522 } else
2523 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002525 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002526 if (wpa_s->sched_scanning) {
2527 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2528 "new network to scan filters");
2529 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530 }
2531
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002532 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2533 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002534 }
2535}
2536
2537
2538/**
2539 * wpa_supplicant_disable_network - Mark a configured network as disabled
2540 * @wpa_s: wpa_supplicant structure for a network interface
2541 * @ssid: wpa_ssid structure for a configured network or %NULL
2542 *
2543 * Disables the specified network or all networks if no network specified.
2544 */
2545void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2546 struct wpa_ssid *ssid)
2547{
2548 struct wpa_ssid *other_ssid;
2549 int was_disabled;
2550
2551 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002552 if (wpa_s->sched_scanning)
2553 wpa_supplicant_cancel_sched_scan(wpa_s);
2554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2556 other_ssid = other_ssid->next) {
2557 was_disabled = other_ssid->disabled;
2558 if (was_disabled == 2)
2559 continue; /* do not change persistent P2P group
2560 * data */
2561
2562 other_ssid->disabled = 1;
2563
2564 if (was_disabled != other_ssid->disabled)
2565 wpas_notify_network_enabled_changed(
2566 wpa_s, other_ssid);
2567 }
2568 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002569 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2571 } else if (ssid->disabled != 2) {
2572 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002573 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002574 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2575
2576 was_disabled = ssid->disabled;
2577
2578 ssid->disabled = 1;
2579
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002580 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002582 if (wpa_s->sched_scanning) {
2583 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2584 "to remove network from filters");
2585 wpa_supplicant_cancel_sched_scan(wpa_s);
2586 wpa_supplicant_req_scan(wpa_s, 0, 0);
2587 }
2588 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589 }
2590}
2591
2592
2593/**
2594 * wpa_supplicant_select_network - Attempt association with a network
2595 * @wpa_s: wpa_supplicant structure for a network interface
2596 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2597 */
2598void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2599 struct wpa_ssid *ssid)
2600{
2601
2602 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002603 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002605 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08002606 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002607 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002608 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002609 disconnected = 1;
2610 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002612 if (ssid)
2613 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2614
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002615 /*
2616 * Mark all other networks disabled or mark all networks enabled if no
2617 * network specified.
2618 */
2619 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2620 other_ssid = other_ssid->next) {
2621 int was_disabled = other_ssid->disabled;
2622 if (was_disabled == 2)
2623 continue; /* do not change persistent P2P group data */
2624
2625 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002626 if (was_disabled && !other_ssid->disabled)
2627 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628
2629 if (was_disabled != other_ssid->disabled)
2630 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2631 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002632
2633 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2634 /* We are already associated with the selected network */
2635 wpa_printf(MSG_DEBUG, "Already associated with the "
2636 "selected network - do nothing");
2637 return;
2638 }
2639
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002640 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002641 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002642 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002643 wpa_s->connect_without_scan =
2644 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002645
2646 /*
2647 * Don't optimize next scan freqs since a new ESS has been
2648 * selected.
2649 */
2650 os_free(wpa_s->next_scan_freqs);
2651 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002652 } else {
2653 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002654 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002655
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002656 wpa_s->disconnected = 0;
2657 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002658
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002659 if (wpa_s->connect_without_scan ||
2660 wpa_supplicant_fast_associate(wpa_s) != 1)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002661 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002662
2663 if (ssid)
2664 wpas_notify_network_selected(wpa_s, ssid);
2665}
2666
2667
2668/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002669 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2670 * @wpa_s: wpa_supplicant structure for a network interface
2671 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2672 * @pkcs11_module_path: PKCS #11 module path or NULL
2673 * Returns: 0 on success; -1 on failure
2674 *
2675 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2676 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2677 * module path fails the paths will be reset to the default value (NULL).
2678 */
2679int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2680 const char *pkcs11_engine_path,
2681 const char *pkcs11_module_path)
2682{
2683 char *pkcs11_engine_path_copy = NULL;
2684 char *pkcs11_module_path_copy = NULL;
2685
2686 if (pkcs11_engine_path != NULL) {
2687 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2688 if (pkcs11_engine_path_copy == NULL)
2689 return -1;
2690 }
2691 if (pkcs11_module_path != NULL) {
2692 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002693 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002694 os_free(pkcs11_engine_path_copy);
2695 return -1;
2696 }
2697 }
2698
2699 os_free(wpa_s->conf->pkcs11_engine_path);
2700 os_free(wpa_s->conf->pkcs11_module_path);
2701 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2702 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2703
2704 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2705 eapol_sm_deinit(wpa_s->eapol);
2706 wpa_s->eapol = NULL;
2707 if (wpa_supplicant_init_eapol(wpa_s)) {
2708 /* Error -> Reset paths to the default value (NULL) once. */
2709 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2710 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2711 NULL);
2712
2713 return -1;
2714 }
2715 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2716
2717 return 0;
2718}
2719
2720
2721/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2723 * @wpa_s: wpa_supplicant structure for a network interface
2724 * @ap_scan: AP scan mode
2725 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2726 *
2727 */
2728int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2729{
2730
2731 int old_ap_scan;
2732
2733 if (ap_scan < 0 || ap_scan > 2)
2734 return -1;
2735
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002736#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002737 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2738 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2739 wpa_s->wpa_state < WPA_COMPLETED) {
2740 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2741 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002742 return 0;
2743 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002744#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002745
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 old_ap_scan = wpa_s->conf->ap_scan;
2747 wpa_s->conf->ap_scan = ap_scan;
2748
2749 if (old_ap_scan != wpa_s->conf->ap_scan)
2750 wpas_notify_ap_scan_changed(wpa_s);
2751
2752 return 0;
2753}
2754
2755
2756/**
2757 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2758 * @wpa_s: wpa_supplicant structure for a network interface
2759 * @expire_age: Expiration age in seconds
2760 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2761 *
2762 */
2763int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2764 unsigned int bss_expire_age)
2765{
2766 if (bss_expire_age < 10) {
2767 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2768 bss_expire_age);
2769 return -1;
2770 }
2771 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2772 bss_expire_age);
2773 wpa_s->conf->bss_expiration_age = bss_expire_age;
2774
2775 return 0;
2776}
2777
2778
2779/**
2780 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2781 * @wpa_s: wpa_supplicant structure for a network interface
2782 * @expire_count: number of scans after which an unseen BSS is reclaimed
2783 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2784 *
2785 */
2786int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2787 unsigned int bss_expire_count)
2788{
2789 if (bss_expire_count < 1) {
2790 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2791 bss_expire_count);
2792 return -1;
2793 }
2794 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2795 bss_expire_count);
2796 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2797
2798 return 0;
2799}
2800
2801
2802/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002803 * wpa_supplicant_set_scan_interval - Set scan interval
2804 * @wpa_s: wpa_supplicant structure for a network interface
2805 * @scan_interval: scan interval in seconds
2806 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2807 *
2808 */
2809int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2810 int scan_interval)
2811{
2812 if (scan_interval < 0) {
2813 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2814 scan_interval);
2815 return -1;
2816 }
2817 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2818 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002819 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002820
2821 return 0;
2822}
2823
2824
2825/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002826 * wpa_supplicant_set_debug_params - Set global debug params
2827 * @global: wpa_global structure
2828 * @debug_level: debug level
2829 * @debug_timestamp: determines if show timestamp in debug data
2830 * @debug_show_keys: determines if show keys in debug data
2831 * Returns: 0 if succeed or -1 if debug_level has wrong value
2832 */
2833int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2834 int debug_timestamp, int debug_show_keys)
2835{
2836
2837 int old_level, old_timestamp, old_show_keys;
2838
2839 /* check for allowed debuglevels */
2840 if (debug_level != MSG_EXCESSIVE &&
2841 debug_level != MSG_MSGDUMP &&
2842 debug_level != MSG_DEBUG &&
2843 debug_level != MSG_INFO &&
2844 debug_level != MSG_WARNING &&
2845 debug_level != MSG_ERROR)
2846 return -1;
2847
2848 old_level = wpa_debug_level;
2849 old_timestamp = wpa_debug_timestamp;
2850 old_show_keys = wpa_debug_show_keys;
2851
2852 wpa_debug_level = debug_level;
2853 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2854 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2855
2856 if (wpa_debug_level != old_level)
2857 wpas_notify_debug_level_changed(global);
2858 if (wpa_debug_timestamp != old_timestamp)
2859 wpas_notify_debug_timestamp_changed(global);
2860 if (wpa_debug_show_keys != old_show_keys)
2861 wpas_notify_debug_show_keys_changed(global);
2862
2863 return 0;
2864}
2865
2866
2867/**
2868 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2869 * @wpa_s: Pointer to wpa_supplicant data
2870 * Returns: A pointer to the current network structure or %NULL on failure
2871 */
2872struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2873{
2874 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002875 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002876 int res;
2877 size_t ssid_len;
2878 u8 bssid[ETH_ALEN];
2879 int wired;
2880
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002881 res = wpa_drv_get_ssid(wpa_s, ssid);
2882 if (res < 0) {
2883 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2884 "driver");
2885 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002886 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002887 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002888
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002889 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002890 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2891 "driver");
2892 return NULL;
2893 }
2894
2895 wired = wpa_s->conf->ap_scan == 0 &&
2896 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2897
2898 entry = wpa_s->conf->ssid;
2899 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002900 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002901 ((ssid_len == entry->ssid_len &&
2902 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2903 (!entry->bssid_set ||
2904 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2905 return entry;
2906#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002907 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2909 (entry->ssid == NULL || entry->ssid_len == 0) &&
2910 (!entry->bssid_set ||
2911 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2912 return entry;
2913#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002914
Dmitry Shmidt04949592012-07-19 12:16:46 -07002915 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002916 entry->ssid_len == 0 &&
2917 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2918 return entry;
2919
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002920 entry = entry->next;
2921 }
2922
2923 return NULL;
2924}
2925
2926
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002927static int select_driver(struct wpa_supplicant *wpa_s, int i)
2928{
2929 struct wpa_global *global = wpa_s->global;
2930
2931 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2932 global->drv_priv[i] = wpa_drivers[i]->global_init();
2933 if (global->drv_priv[i] == NULL) {
2934 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2935 "'%s'", wpa_drivers[i]->name);
2936 return -1;
2937 }
2938 }
2939
2940 wpa_s->driver = wpa_drivers[i];
2941 wpa_s->global_drv_priv = global->drv_priv[i];
2942
2943 return 0;
2944}
2945
2946
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002947static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2948 const char *name)
2949{
2950 int i;
2951 size_t len;
2952 const char *pos, *driver = name;
2953
2954 if (wpa_s == NULL)
2955 return -1;
2956
2957 if (wpa_drivers[0] == NULL) {
2958 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2959 "wpa_supplicant");
2960 return -1;
2961 }
2962
2963 if (name == NULL) {
2964 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002965 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002966 }
2967
2968 do {
2969 pos = os_strchr(driver, ',');
2970 if (pos)
2971 len = pos - driver;
2972 else
2973 len = os_strlen(driver);
2974
2975 for (i = 0; wpa_drivers[i]; i++) {
2976 if (os_strlen(wpa_drivers[i]->name) == len &&
2977 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002978 0) {
2979 /* First driver that succeeds wins */
2980 if (select_driver(wpa_s, i) == 0)
2981 return 0;
2982 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002983 }
2984
2985 driver = pos + 1;
2986 } while (pos);
2987
2988 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2989 return -1;
2990}
2991
2992
2993/**
2994 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2995 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2996 * with struct wpa_driver_ops::init()
2997 * @src_addr: Source address of the EAPOL frame
2998 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2999 * @len: Length of the EAPOL data
3000 *
3001 * This function is called for each received EAPOL frame. Most driver
3002 * interfaces rely on more generic OS mechanism for receiving frames through
3003 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3004 * take care of received EAPOL frames and deliver them to the core supplicant
3005 * code by calling this function.
3006 */
3007void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3008 const u8 *buf, size_t len)
3009{
3010 struct wpa_supplicant *wpa_s = ctx;
3011
3012 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3013 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3014
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003015#ifdef CONFIG_PEERKEY
3016 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3017 wpa_s->current_ssid->peerkey &&
3018 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3019 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3020 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3021 return;
3022 }
3023#endif /* CONFIG_PEERKEY */
3024
Jouni Malinena05074c2012-12-21 21:35:35 +02003025 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3026 (wpa_s->last_eapol_matches_bssid &&
3027#ifdef CONFIG_AP
3028 !wpa_s->ap_iface &&
3029#endif /* CONFIG_AP */
3030 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003031 /*
3032 * There is possible race condition between receiving the
3033 * association event and the EAPOL frame since they are coming
3034 * through different paths from the driver. In order to avoid
3035 * issues in trying to process the EAPOL frame before receiving
3036 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003037 * the association event is received. This may also be needed in
3038 * driver-based roaming case, so also use src_addr != BSSID as a
3039 * trigger if we have previously confirmed that the
3040 * Authenticator uses BSSID as the src_addr (which is not the
3041 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003042 */
3043 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003044 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3045 wpa_supplicant_state_txt(wpa_s->wpa_state),
3046 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003047 wpabuf_free(wpa_s->pending_eapol_rx);
3048 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3049 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003050 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003051 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3052 ETH_ALEN);
3053 }
3054 return;
3055 }
3056
Jouni Malinena05074c2012-12-21 21:35:35 +02003057 wpa_s->last_eapol_matches_bssid =
3058 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3059
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003060#ifdef CONFIG_AP
3061 if (wpa_s->ap_iface) {
3062 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3063 return;
3064 }
3065#endif /* CONFIG_AP */
3066
3067 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3068 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3069 "no key management is configured");
3070 return;
3071 }
3072
3073 if (wpa_s->eapol_received == 0 &&
3074 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3075 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3076 wpa_s->wpa_state != WPA_COMPLETED) &&
3077 (wpa_s->current_ssid == NULL ||
3078 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3079 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003080 int timeout = 10;
3081
3082 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3083 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3084 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3085 /* Use longer timeout for IEEE 802.1X/EAP */
3086 timeout = 70;
3087 }
3088
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003089#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003090 if (wpa_s->current_ssid && wpa_s->current_bss &&
3091 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3092 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3093 /*
3094 * Use shorter timeout if going through WPS AP iteration
3095 * for PIN config method with an AP that does not
3096 * advertise Selected Registrar.
3097 */
3098 struct wpabuf *wps_ie;
3099
3100 wps_ie = wpa_bss_get_vendor_ie_multi(
3101 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3102 if (wps_ie &&
3103 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3104 timeout = 10;
3105 wpabuf_free(wps_ie);
3106 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003107#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003108
3109 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003110 }
3111 wpa_s->eapol_received++;
3112
3113 if (wpa_s->countermeasures) {
3114 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3115 "EAPOL packet");
3116 return;
3117 }
3118
3119#ifdef CONFIG_IBSS_RSN
3120 if (wpa_s->current_ssid &&
3121 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3122 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3123 return;
3124 }
3125#endif /* CONFIG_IBSS_RSN */
3126
3127 /* Source address of the incoming EAPOL frame could be compared to the
3128 * current BSSID. However, it is possible that a centralized
3129 * Authenticator could be using another MAC address than the BSSID of
3130 * an AP, so just allow any address to be used for now. The replies are
3131 * still sent to the current BSSID (if available), though. */
3132
3133 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3134 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3135 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3136 return;
3137 wpa_drv_poll(wpa_s);
3138 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3139 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3140 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3141 /*
3142 * Set portValid = TRUE here since we are going to skip 4-way
3143 * handshake processing which would normally set portValid. We
3144 * need this to allow the EAPOL state machines to be completed
3145 * without going through EAPOL-Key handshake.
3146 */
3147 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3148 }
3149}
3150
3151
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003152int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003153{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003154 if ((!wpa_s->p2p_mgmt ||
3155 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3156 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003157 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003158 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3159 wpa_drv_get_mac_addr(wpa_s),
3160 ETH_P_EAPOL,
3161 wpa_supplicant_rx_eapol, wpa_s, 0);
3162 if (wpa_s->l2 == NULL)
3163 return -1;
3164 } else {
3165 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3166 if (addr)
3167 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3168 }
3169
3170 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3171 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3172 return -1;
3173 }
3174
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003175 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3176
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003177 return 0;
3178}
3179
3180
Dmitry Shmidt04949592012-07-19 12:16:46 -07003181static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3182 const u8 *buf, size_t len)
3183{
3184 struct wpa_supplicant *wpa_s = ctx;
3185 const struct l2_ethhdr *eth;
3186
3187 if (len < sizeof(*eth))
3188 return;
3189 eth = (const struct l2_ethhdr *) buf;
3190
3191 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3192 !(eth->h_dest[0] & 0x01)) {
3193 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3194 " (bridge - not for this interface - ignore)",
3195 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3196 return;
3197 }
3198
3199 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3200 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3201 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3202 len - sizeof(*eth));
3203}
3204
3205
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003206/**
3207 * wpa_supplicant_driver_init - Initialize driver interface parameters
3208 * @wpa_s: Pointer to wpa_supplicant data
3209 * Returns: 0 on success, -1 on failure
3210 *
3211 * This function is called to initialize driver interface parameters.
3212 * wpa_drv_init() must have been called before this function to initialize the
3213 * driver interface.
3214 */
3215int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3216{
3217 static int interface_count = 0;
3218
3219 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3220 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003221
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003222 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3223 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003224 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003225 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3226
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003227 if (wpa_s->bridge_ifname[0]) {
3228 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3229 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003230 wpa_s->l2_br = l2_packet_init_bridge(
3231 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3232 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003233 if (wpa_s->l2_br == NULL) {
3234 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3235 "connection for the bridge interface '%s'",
3236 wpa_s->bridge_ifname);
3237 return -1;
3238 }
3239 }
3240
3241 wpa_clear_keys(wpa_s, NULL);
3242
3243 /* Make sure that TKIP countermeasures are not left enabled (could
3244 * happen if wpa_supplicant is killed during countermeasures. */
3245 wpa_drv_set_countermeasures(wpa_s, 0);
3246
3247 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3248 wpa_drv_flush_pmkid(wpa_s);
3249
3250 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003251 wpa_s->prev_scan_wildcard = 0;
3252
Dmitry Shmidt04949592012-07-19 12:16:46 -07003253 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003254 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3255 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3256 interface_count = 0;
3257 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003258#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003259 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003260 wpa_supplicant_delayed_sched_scan(wpa_s,
3261 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003262 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003263 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003264 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003265#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003266 interface_count++;
3267 } else
3268 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3269
3270 return 0;
3271}
3272
3273
3274static int wpa_supplicant_daemon(const char *pid_file)
3275{
3276 wpa_printf(MSG_DEBUG, "Daemonize..");
3277 return os_daemonize(pid_file);
3278}
3279
3280
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003281static struct wpa_supplicant *
3282wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003283{
3284 struct wpa_supplicant *wpa_s;
3285
3286 wpa_s = os_zalloc(sizeof(*wpa_s));
3287 if (wpa_s == NULL)
3288 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003289 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003290 wpa_s->scan_interval = 5;
3291 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003292 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003293 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003294
3295 return wpa_s;
3296}
3297
3298
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003299#ifdef CONFIG_HT_OVERRIDES
3300
3301static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3302 struct ieee80211_ht_capabilities *htcaps,
3303 struct ieee80211_ht_capabilities *htcaps_mask,
3304 const char *ht_mcs)
3305{
3306 /* parse ht_mcs into hex array */
3307 int i;
3308 const char *tmp = ht_mcs;
3309 char *end = NULL;
3310
3311 /* If ht_mcs is null, do not set anything */
3312 if (!ht_mcs)
3313 return 0;
3314
3315 /* This is what we are setting in the kernel */
3316 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3317
3318 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3319
3320 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3321 errno = 0;
3322 long v = strtol(tmp, &end, 16);
3323 if (errno == 0) {
3324 wpa_msg(wpa_s, MSG_DEBUG,
3325 "htcap value[%i]: %ld end: %p tmp: %p",
3326 i, v, end, tmp);
3327 if (end == tmp)
3328 break;
3329
3330 htcaps->supported_mcs_set[i] = v;
3331 tmp = end;
3332 } else {
3333 wpa_msg(wpa_s, MSG_ERROR,
3334 "Failed to parse ht-mcs: %s, error: %s\n",
3335 ht_mcs, strerror(errno));
3336 return -1;
3337 }
3338 }
3339
3340 /*
3341 * If we were able to parse any values, then set mask for the MCS set.
3342 */
3343 if (i) {
3344 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3345 IEEE80211_HT_MCS_MASK_LEN - 1);
3346 /* skip the 3 reserved bits */
3347 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3348 0x1f;
3349 }
3350
3351 return 0;
3352}
3353
3354
3355static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3356 struct ieee80211_ht_capabilities *htcaps,
3357 struct ieee80211_ht_capabilities *htcaps_mask,
3358 int disabled)
3359{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003360 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003361
3362 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3363
3364 if (disabled == -1)
3365 return 0;
3366
3367 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3368 htcaps_mask->ht_capabilities_info |= msk;
3369 if (disabled)
3370 htcaps->ht_capabilities_info &= msk;
3371 else
3372 htcaps->ht_capabilities_info |= msk;
3373
3374 return 0;
3375}
3376
3377
3378static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3379 struct ieee80211_ht_capabilities *htcaps,
3380 struct ieee80211_ht_capabilities *htcaps_mask,
3381 int factor)
3382{
3383 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3384
3385 if (factor == -1)
3386 return 0;
3387
3388 if (factor < 0 || factor > 3) {
3389 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3390 "Must be 0-3 or -1", factor);
3391 return -EINVAL;
3392 }
3393
3394 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3395 htcaps->a_mpdu_params &= ~0x3;
3396 htcaps->a_mpdu_params |= factor & 0x3;
3397
3398 return 0;
3399}
3400
3401
3402static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3403 struct ieee80211_ht_capabilities *htcaps,
3404 struct ieee80211_ht_capabilities *htcaps_mask,
3405 int density)
3406{
3407 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3408
3409 if (density == -1)
3410 return 0;
3411
3412 if (density < 0 || density > 7) {
3413 wpa_msg(wpa_s, MSG_ERROR,
3414 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3415 density);
3416 return -EINVAL;
3417 }
3418
3419 htcaps_mask->a_mpdu_params |= 0x1C;
3420 htcaps->a_mpdu_params &= ~(0x1C);
3421 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3422
3423 return 0;
3424}
3425
3426
3427static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3428 struct ieee80211_ht_capabilities *htcaps,
3429 struct ieee80211_ht_capabilities *htcaps_mask,
3430 int disabled)
3431{
3432 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003433 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3434 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003435
3436 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3437
3438 if (disabled)
3439 htcaps->ht_capabilities_info &= ~msk;
3440 else
3441 htcaps->ht_capabilities_info |= msk;
3442
3443 htcaps_mask->ht_capabilities_info |= msk;
3444
3445 return 0;
3446}
3447
3448
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003449static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3450 struct ieee80211_ht_capabilities *htcaps,
3451 struct ieee80211_ht_capabilities *htcaps_mask,
3452 int disabled)
3453{
3454 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003455 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3456 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003457
3458 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3459
3460 if (disabled)
3461 htcaps->ht_capabilities_info &= ~msk;
3462 else
3463 htcaps->ht_capabilities_info |= msk;
3464
3465 htcaps_mask->ht_capabilities_info |= msk;
3466
3467 return 0;
3468}
3469
3470
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003471static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3472 struct ieee80211_ht_capabilities *htcaps,
3473 struct ieee80211_ht_capabilities *htcaps_mask,
3474 int disabled)
3475{
3476 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003477 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003478
3479 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3480
3481 if (disabled)
3482 htcaps->ht_capabilities_info &= ~msk;
3483 else
3484 htcaps->ht_capabilities_info |= msk;
3485
3486 htcaps_mask->ht_capabilities_info |= msk;
3487
3488 return 0;
3489}
3490
3491
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003492void wpa_supplicant_apply_ht_overrides(
3493 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3494 struct wpa_driver_associate_params *params)
3495{
3496 struct ieee80211_ht_capabilities *htcaps;
3497 struct ieee80211_ht_capabilities *htcaps_mask;
3498
3499 if (!ssid)
3500 return;
3501
3502 params->disable_ht = ssid->disable_ht;
3503 if (!params->htcaps || !params->htcaps_mask)
3504 return;
3505
3506 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3507 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3508 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3509 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3510 ssid->disable_max_amsdu);
3511 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3512 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3513 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003514 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003515 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003516
3517 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003518 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003519 htcaps->ht_capabilities_info |= bit;
3520 htcaps_mask->ht_capabilities_info |= bit;
3521 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003522}
3523
3524#endif /* CONFIG_HT_OVERRIDES */
3525
3526
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003527#ifdef CONFIG_VHT_OVERRIDES
3528void wpa_supplicant_apply_vht_overrides(
3529 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3530 struct wpa_driver_associate_params *params)
3531{
3532 struct ieee80211_vht_capabilities *vhtcaps;
3533 struct ieee80211_vht_capabilities *vhtcaps_mask;
3534
3535 if (!ssid)
3536 return;
3537
3538 params->disable_vht = ssid->disable_vht;
3539
3540 vhtcaps = (void *) params->vhtcaps;
3541 vhtcaps_mask = (void *) params->vhtcaps_mask;
3542
3543 if (!vhtcaps || !vhtcaps_mask)
3544 return;
3545
3546 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3547 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3548
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003549#ifdef CONFIG_HT_OVERRIDES
3550 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003551 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3552 int max_ampdu;
3553
3554 max_ampdu = (ssid->vht_capa &
3555 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3556 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003557
3558 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3559 wpa_set_ampdu_factor(wpa_s,
3560 (void *) params->htcaps,
3561 (void *) params->htcaps_mask,
3562 max_ampdu);
3563 }
3564#endif /* CONFIG_HT_OVERRIDES */
3565
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003566#define OVERRIDE_MCS(i) \
3567 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3568 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3569 3 << 2 * (i - 1); \
3570 vhtcaps->vht_supported_mcs_set.tx_map |= \
3571 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3572 } \
3573 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3574 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3575 3 << 2 * (i - 1); \
3576 vhtcaps->vht_supported_mcs_set.rx_map |= \
3577 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3578 }
3579
3580 OVERRIDE_MCS(1);
3581 OVERRIDE_MCS(2);
3582 OVERRIDE_MCS(3);
3583 OVERRIDE_MCS(4);
3584 OVERRIDE_MCS(5);
3585 OVERRIDE_MCS(6);
3586 OVERRIDE_MCS(7);
3587 OVERRIDE_MCS(8);
3588}
3589#endif /* CONFIG_VHT_OVERRIDES */
3590
3591
Dmitry Shmidt04949592012-07-19 12:16:46 -07003592static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3593{
3594#ifdef PCSC_FUNCS
3595 size_t len;
3596
3597 if (!wpa_s->conf->pcsc_reader)
3598 return 0;
3599
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003600 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003601 if (!wpa_s->scard)
3602 return 1;
3603
3604 if (wpa_s->conf->pcsc_pin &&
3605 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3606 scard_deinit(wpa_s->scard);
3607 wpa_s->scard = NULL;
3608 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3609 return -1;
3610 }
3611
3612 len = sizeof(wpa_s->imsi) - 1;
3613 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3614 scard_deinit(wpa_s->scard);
3615 wpa_s->scard = NULL;
3616 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3617 return -1;
3618 }
3619 wpa_s->imsi[len] = '\0';
3620
3621 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3622
3623 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3624 wpa_s->imsi, wpa_s->mnc_len);
3625
3626 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3627 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3628#endif /* PCSC_FUNCS */
3629
3630 return 0;
3631}
3632
3633
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003634int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3635{
3636 char *val, *pos;
3637
3638 ext_password_deinit(wpa_s->ext_pw);
3639 wpa_s->ext_pw = NULL;
3640 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3641
3642 if (!wpa_s->conf->ext_password_backend)
3643 return 0;
3644
3645 val = os_strdup(wpa_s->conf->ext_password_backend);
3646 if (val == NULL)
3647 return -1;
3648 pos = os_strchr(val, ':');
3649 if (pos)
3650 *pos++ = '\0';
3651
3652 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3653
3654 wpa_s->ext_pw = ext_password_init(val, pos);
3655 os_free(val);
3656 if (wpa_s->ext_pw == NULL) {
3657 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3658 return -1;
3659 }
3660 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3661
3662 return 0;
3663}
3664
3665
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003666static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003667 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003668{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003669 struct wowlan_triggers *triggers;
3670 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003671
3672 if (!wpa_s->conf->wowlan_triggers)
3673 return 0;
3674
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003675 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3676 if (triggers) {
3677 ret = wpa_drv_wowlan(wpa_s, triggers);
3678 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003679 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003680 return ret;
3681}
3682
3683
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003684static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3685 const char *rn)
3686{
3687 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3688 struct wpa_radio *radio;
3689
3690 while (rn && iface) {
3691 radio = iface->radio;
3692 if (radio && os_strcmp(rn, radio->name) == 0) {
3693 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3694 wpa_s->ifname, rn);
3695 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3696 return radio;
3697 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003698
3699 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003700 }
3701
3702 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3703 wpa_s->ifname, rn ? rn : "N/A");
3704 radio = os_zalloc(sizeof(*radio));
3705 if (radio == NULL)
3706 return NULL;
3707
3708 if (rn)
3709 os_strlcpy(radio->name, rn, sizeof(radio->name));
3710 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003711 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003712 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3713
3714 return radio;
3715}
3716
3717
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003718static void radio_work_free(struct wpa_radio_work *work)
3719{
3720 if (work->wpa_s->scan_work == work) {
3721 /* This should not really happen. */
3722 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3723 work->type, work, work->started);
3724 work->wpa_s->scan_work = NULL;
3725 }
3726
3727#ifdef CONFIG_P2P
3728 if (work->wpa_s->p2p_scan_work == work) {
3729 /* This should not really happen. */
3730 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3731 work->type, work, work->started);
3732 work->wpa_s->p2p_scan_work = NULL;
3733 }
3734#endif /* CONFIG_P2P */
3735
3736 dl_list_del(&work->list);
3737 os_free(work);
3738}
3739
3740
3741static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3742{
3743 struct wpa_radio *radio = eloop_ctx;
3744 struct wpa_radio_work *work;
3745 struct os_reltime now, diff;
3746 struct wpa_supplicant *wpa_s;
3747
3748 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3749 if (work == NULL)
3750 return;
3751
3752 if (work->started)
3753 return; /* already started and still in progress */
3754
3755 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3756 radio_list);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003757 if (wpa_s && wpa_s->radio->external_scan_running) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003758 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3759 return;
3760 }
3761
3762 os_get_reltime(&now);
3763 os_reltime_sub(&now, &work->time, &diff);
3764 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3765 work->type, work, diff.sec, diff.usec);
3766 work->started = 1;
3767 work->time = now;
3768 work->cb(work, 0);
3769}
3770
3771
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003772/*
3773 * This function removes both started and pending radio works running on
3774 * the provided interface's radio.
3775 * Prior to the removal of the radio work, its callback (cb) is called with
3776 * deinit set to be 1. Each work's callback is responsible for clearing its
3777 * internal data and restoring to a correct state.
3778 * @wpa_s: wpa_supplicant data
3779 * @type: type of works to be removed
3780 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3781 * this interface's works.
3782 */
3783void radio_remove_works(struct wpa_supplicant *wpa_s,
3784 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003785{
3786 struct wpa_radio_work *work, *tmp;
3787 struct wpa_radio *radio = wpa_s->radio;
3788
3789 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3790 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003791 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003792 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003793
3794 /* skip other ifaces' works */
3795 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003796 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003797
3798 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3799 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003800 work->cb(work, 1);
3801 radio_work_free(work);
3802 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003803
3804 /* in case we removed the started work */
3805 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003806}
3807
3808
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003809static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3810{
3811 struct wpa_radio *radio = wpa_s->radio;
3812
3813 if (!radio)
3814 return;
3815
3816 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3817 wpa_s->ifname, radio->name);
3818 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003819 radio_remove_works(wpa_s, NULL, 0);
3820 wpa_s->radio = NULL;
3821 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003822 return; /* Interfaces remain for this radio */
3823
3824 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003825 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003826 os_free(radio);
3827}
3828
3829
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003830void radio_work_check_next(struct wpa_supplicant *wpa_s)
3831{
3832 struct wpa_radio *radio = wpa_s->radio;
3833
3834 if (dl_list_empty(&radio->work))
3835 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003836 if (wpa_s->ext_work_in_progress) {
3837 wpa_printf(MSG_DEBUG,
3838 "External radio work in progress - delay start of pending item");
3839 return;
3840 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003841 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3842 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3843}
3844
3845
3846/**
3847 * radio_add_work - Add a radio work item
3848 * @wpa_s: Pointer to wpa_supplicant data
3849 * @freq: Frequency of the offchannel operation in MHz or 0
3850 * @type: Unique identifier for each type of work
3851 * @next: Force as the next work to be executed
3852 * @cb: Callback function for indicating when radio is available
3853 * @ctx: Context pointer for the work (work->ctx in cb())
3854 * Returns: 0 on success, -1 on failure
3855 *
3856 * This function is used to request time for an operation that requires
3857 * exclusive radio control. Once the radio is available, the registered callback
3858 * function will be called. radio_work_done() must be called once the exclusive
3859 * radio operation has been completed, so that the radio is freed for other
3860 * operations. The special case of deinit=1 is used to free the context data
3861 * during interface removal. That does not allow the callback function to start
3862 * the radio operation, i.e., it must free any resources allocated for the radio
3863 * work and return.
3864 *
3865 * The @freq parameter can be used to indicate a single channel on which the
3866 * offchannel operation will occur. This may allow multiple radio work
3867 * operations to be performed in parallel if they apply for the same channel.
3868 * Setting this to 0 indicates that the work item may use multiple channels or
3869 * requires exclusive control of the radio.
3870 */
3871int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3872 const char *type, int next,
3873 void (*cb)(struct wpa_radio_work *work, int deinit),
3874 void *ctx)
3875{
3876 struct wpa_radio_work *work;
3877 int was_empty;
3878
3879 work = os_zalloc(sizeof(*work));
3880 if (work == NULL)
3881 return -1;
3882 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3883 os_get_reltime(&work->time);
3884 work->freq = freq;
3885 work->type = type;
3886 work->wpa_s = wpa_s;
3887 work->cb = cb;
3888 work->ctx = ctx;
3889
3890 was_empty = dl_list_empty(&wpa_s->radio->work);
3891 if (next)
3892 dl_list_add(&wpa_s->radio->work, &work->list);
3893 else
3894 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3895 if (was_empty) {
3896 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3897 radio_work_check_next(wpa_s);
3898 }
3899
3900 return 0;
3901}
3902
3903
3904/**
3905 * radio_work_done - Indicate that a radio work item has been completed
3906 * @work: Completed work
3907 *
3908 * This function is called once the callback function registered with
3909 * radio_add_work() has completed its work.
3910 */
3911void radio_work_done(struct wpa_radio_work *work)
3912{
3913 struct wpa_supplicant *wpa_s = work->wpa_s;
3914 struct os_reltime now, diff;
3915 unsigned int started = work->started;
3916
3917 os_get_reltime(&now);
3918 os_reltime_sub(&now, &work->time, &diff);
3919 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3920 work->type, work, started ? "done" : "canceled",
3921 diff.sec, diff.usec);
3922 radio_work_free(work);
3923 if (started)
3924 radio_work_check_next(wpa_s);
3925}
3926
3927
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003928struct wpa_radio_work *
3929radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003930{
3931 struct wpa_radio_work *work;
3932 struct wpa_radio *radio = wpa_s->radio;
3933
3934 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3935 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003936 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003937 }
3938
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003939 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003940}
3941
3942
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003943static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3944 struct wpa_interface *iface)
3945{
3946 const char *ifname, *driver, *rn;
3947
3948 driver = iface->driver;
3949next_driver:
3950 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3951 return -1;
3952
3953 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3954 if (wpa_s->drv_priv == NULL) {
3955 const char *pos;
3956 pos = driver ? os_strchr(driver, ',') : NULL;
3957 if (pos) {
3958 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3959 "driver interface - try next driver wrapper");
3960 driver = pos + 1;
3961 goto next_driver;
3962 }
3963 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3964 "interface");
3965 return -1;
3966 }
3967 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3968 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3969 "driver_param '%s'", wpa_s->conf->driver_param);
3970 return -1;
3971 }
3972
3973 ifname = wpa_drv_get_ifname(wpa_s);
3974 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3975 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3976 "interface name with '%s'", ifname);
3977 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3978 }
3979
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003980 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003981 if (rn && rn[0] == '\0')
3982 rn = NULL;
3983
3984 wpa_s->radio = radio_add_interface(wpa_s, rn);
3985 if (wpa_s->radio == NULL)
3986 return -1;
3987
3988 return 0;
3989}
3990
3991
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003992static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3993 struct wpa_interface *iface)
3994{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003995 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003996 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003997
3998 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3999 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4000 iface->confname ? iface->confname : "N/A",
4001 iface->driver ? iface->driver : "default",
4002 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4003 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4004
4005 if (iface->confname) {
4006#ifdef CONFIG_BACKEND_FILE
4007 wpa_s->confname = os_rel2abs_path(iface->confname);
4008 if (wpa_s->confname == NULL) {
4009 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4010 "for configuration file '%s'.",
4011 iface->confname);
4012 return -1;
4013 }
4014 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4015 iface->confname, wpa_s->confname);
4016#else /* CONFIG_BACKEND_FILE */
4017 wpa_s->confname = os_strdup(iface->confname);
4018#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004019 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004020 if (wpa_s->conf == NULL) {
4021 wpa_printf(MSG_ERROR, "Failed to read or parse "
4022 "configuration '%s'.", wpa_s->confname);
4023 return -1;
4024 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004025 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4026 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004027
4028 /*
4029 * Override ctrl_interface and driver_param if set on command
4030 * line.
4031 */
4032 if (iface->ctrl_interface) {
4033 os_free(wpa_s->conf->ctrl_interface);
4034 wpa_s->conf->ctrl_interface =
4035 os_strdup(iface->ctrl_interface);
4036 }
4037
4038 if (iface->driver_param) {
4039 os_free(wpa_s->conf->driver_param);
4040 wpa_s->conf->driver_param =
4041 os_strdup(iface->driver_param);
4042 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004043
4044 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4045 os_free(wpa_s->conf->ctrl_interface);
4046 wpa_s->conf->ctrl_interface = NULL;
4047 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004048 } else
4049 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4050 iface->driver_param);
4051
4052 if (wpa_s->conf == NULL) {
4053 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4054 return -1;
4055 }
4056
4057 if (iface->ifname == NULL) {
4058 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4059 return -1;
4060 }
4061 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4062 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4063 iface->ifname);
4064 return -1;
4065 }
4066 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4067
4068 if (iface->bridge_ifname) {
4069 if (os_strlen(iface->bridge_ifname) >=
4070 sizeof(wpa_s->bridge_ifname)) {
4071 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4072 "name '%s'.", iface->bridge_ifname);
4073 return -1;
4074 }
4075 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4076 sizeof(wpa_s->bridge_ifname));
4077 }
4078
4079 /* RSNA Supplicant Key Management - INITIALIZE */
4080 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4081 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4082
4083 /* Initialize driver interface and register driver event handler before
4084 * L2 receive handler so that association events are processed before
4085 * EAPOL-Key packets if both become available for the same select()
4086 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004087 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004088 return -1;
4089
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004090 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4091 return -1;
4092
4093 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4094 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4095 NULL);
4096 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4097
4098 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4099 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4100 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4101 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4102 "dot11RSNAConfigPMKLifetime");
4103 return -1;
4104 }
4105
4106 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4107 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4108 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4109 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4110 "dot11RSNAConfigPMKReauthThreshold");
4111 return -1;
4112 }
4113
4114 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4115 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4116 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4117 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4118 "dot11RSNAConfigSATimeout");
4119 return -1;
4120 }
4121
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004122 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4123 &wpa_s->hw.num_modes,
4124 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004125 if (wpa_s->hw.modes) {
4126 u16 i;
4127
4128 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4129 if (wpa_s->hw.modes[i].vht_capab) {
4130 wpa_s->hw_capab = CAPAB_VHT;
4131 break;
4132 }
4133
4134 if (wpa_s->hw.modes[i].ht_capab &
4135 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4136 wpa_s->hw_capab = CAPAB_HT40;
4137 else if (wpa_s->hw.modes[i].ht_capab &&
4138 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4139 wpa_s->hw_capab = CAPAB_HT;
4140 }
4141 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004142
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004143 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4144 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004145 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004146 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004147 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004148 wpa_s->drv_smps_modes = capa.smps_modes;
4149 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004150 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004151 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004152 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
4153 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4154 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004155 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4156 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004157 wpa_s->extended_capa = capa.extended_capa;
4158 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4159 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004160 wpa_s->num_multichan_concurrent =
4161 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004162 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4163
4164 if (capa.mac_addr_rand_scan_supported)
4165 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4166 if (wpa_s->sched_scan_supported &&
4167 capa.mac_addr_rand_sched_scan_supported)
4168 wpa_s->mac_addr_rand_supported |=
4169 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004170 }
4171 if (wpa_s->max_remain_on_chan == 0)
4172 wpa_s->max_remain_on_chan = 1000;
4173
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004174 /*
4175 * Only take p2p_mgmt parameters when P2P Device is supported.
4176 * Doing it here as it determines whether l2_packet_init() will be done
4177 * during wpa_supplicant_driver_init().
4178 */
4179 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4180 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4181 else
4182 iface->p2p_mgmt = 1;
4183
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004184 if (wpa_s->num_multichan_concurrent == 0)
4185 wpa_s->num_multichan_concurrent = 1;
4186
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004187 if (wpa_supplicant_driver_init(wpa_s) < 0)
4188 return -1;
4189
4190#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004191 if ((!iface->p2p_mgmt ||
4192 !(wpa_s->drv_flags &
4193 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4194 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004195 return -1;
4196#endif /* CONFIG_TDLS */
4197
4198 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4199 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4200 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4201 return -1;
4202 }
4203
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004204 if (wpas_wps_init(wpa_s))
4205 return -1;
4206
4207 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4208 return -1;
4209 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4210
4211 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4212 if (wpa_s->ctrl_iface == NULL) {
4213 wpa_printf(MSG_ERROR,
4214 "Failed to initialize control interface '%s'.\n"
4215 "You may have another wpa_supplicant process "
4216 "already running or the file was\n"
4217 "left by an unclean termination of wpa_supplicant "
4218 "in which case you will need\n"
4219 "to manually remove this file before starting "
4220 "wpa_supplicant again.\n",
4221 wpa_s->conf->ctrl_interface);
4222 return -1;
4223 }
4224
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004225 wpa_s->gas = gas_query_init(wpa_s);
4226 if (wpa_s->gas == NULL) {
4227 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4228 return -1;
4229 }
4230
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004231 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004232 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4233 return -1;
4234 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004235
4236 if (wpa_bss_init(wpa_s) < 0)
4237 return -1;
4238
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004239 /*
4240 * Set Wake-on-WLAN triggers, if configured.
4241 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4242 * have effect anyway when the interface is down).
4243 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004244 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004245 return -1;
4246
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004247#ifdef CONFIG_EAP_PROXY
4248{
4249 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004250 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4251 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004252 if (wpa_s->mnc_len > 0) {
4253 wpa_s->imsi[len] = '\0';
4254 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4255 wpa_s->imsi, wpa_s->mnc_len);
4256 } else {
4257 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4258 }
4259}
4260#endif /* CONFIG_EAP_PROXY */
4261
Dmitry Shmidt04949592012-07-19 12:16:46 -07004262 if (pcsc_reader_init(wpa_s) < 0)
4263 return -1;
4264
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004265 if (wpas_init_ext_pw(wpa_s) < 0)
4266 return -1;
4267
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004268 wpas_rrm_reset(wpa_s);
4269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004270 return 0;
4271}
4272
4273
4274static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004275 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004276{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004277 struct wpa_global *global = wpa_s->global;
4278 struct wpa_supplicant *iface, *prev;
4279
4280 if (wpa_s == wpa_s->parent)
4281 wpas_p2p_group_remove(wpa_s, "*");
4282
4283 iface = global->ifaces;
4284 while (iface) {
4285 if (iface == wpa_s || iface->parent != wpa_s) {
4286 iface = iface->next;
4287 continue;
4288 }
4289 wpa_printf(MSG_DEBUG,
4290 "Remove remaining child interface %s from parent %s",
4291 iface->ifname, wpa_s->ifname);
4292 prev = iface;
4293 iface = iface->next;
4294 wpa_supplicant_remove_iface(global, prev, terminate);
4295 }
4296
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004297 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004298 if (wpa_s->drv_priv) {
4299 wpa_supplicant_deauthenticate(wpa_s,
4300 WLAN_REASON_DEAUTH_LEAVING);
4301
4302 wpa_drv_set_countermeasures(wpa_s, 0);
4303 wpa_clear_keys(wpa_s, NULL);
4304 }
4305
4306 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004307 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004308
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004309 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004310 radio_remove_interface(wpa_s);
4311
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004312 if (wpa_s->drv_priv)
4313 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004314
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004315 if (notify)
4316 wpas_notify_iface_removed(wpa_s);
4317
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004318 if (terminate)
4319 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004320
4321 if (wpa_s->ctrl_iface) {
4322 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
4323 wpa_s->ctrl_iface = NULL;
4324 }
4325
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004326#ifdef CONFIG_MESH
4327 if (wpa_s->ifmsh) {
4328 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
4329 wpa_s->ifmsh = NULL;
4330 }
4331#endif /* CONFIG_MESH */
4332
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004333 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004334 wpa_config_free(wpa_s->conf);
4335 wpa_s->conf = NULL;
4336 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004337
4338 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004339}
4340
4341
4342/**
4343 * wpa_supplicant_add_iface - Add a new network interface
4344 * @global: Pointer to global data from wpa_supplicant_init()
4345 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004346 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347 * Returns: Pointer to the created interface or %NULL on failure
4348 *
4349 * This function is used to add new network interfaces for %wpa_supplicant.
4350 * This can be called before wpa_supplicant_run() to add interfaces before the
4351 * main event loop has been started. In addition, new interfaces can be added
4352 * dynamically while %wpa_supplicant is already running. This could happen,
4353 * e.g., when a hotplug network adapter is inserted.
4354 */
4355struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004356 struct wpa_interface *iface,
4357 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004358{
4359 struct wpa_supplicant *wpa_s;
4360 struct wpa_interface t_iface;
4361 struct wpa_ssid *ssid;
4362
4363 if (global == NULL || iface == NULL)
4364 return NULL;
4365
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004366 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004367 if (wpa_s == NULL)
4368 return NULL;
4369
4370 wpa_s->global = global;
4371
4372 t_iface = *iface;
4373 if (global->params.override_driver) {
4374 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
4375 "('%s' -> '%s')",
4376 iface->driver, global->params.override_driver);
4377 t_iface.driver = global->params.override_driver;
4378 }
4379 if (global->params.override_ctrl_interface) {
4380 wpa_printf(MSG_DEBUG, "Override interface parameter: "
4381 "ctrl_interface ('%s' -> '%s')",
4382 iface->ctrl_interface,
4383 global->params.override_ctrl_interface);
4384 t_iface.ctrl_interface =
4385 global->params.override_ctrl_interface;
4386 }
4387 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
4388 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
4389 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004390 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004391 return NULL;
4392 }
4393
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004394 if (iface->p2p_mgmt == 0) {
4395 /* Notify the control interfaces about new iface */
4396 if (wpas_notify_iface_added(wpa_s)) {
4397 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
4398 return NULL;
4399 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004400
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004401 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4402 wpas_notify_network_added(wpa_s, ssid);
4403 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004404
4405 wpa_s->next = global->ifaces;
4406 global->ifaces = wpa_s;
4407
4408 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004409 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004410
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004411#ifdef CONFIG_P2P
4412 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004413 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004414 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
4415 wpas_p2p_add_p2pdev_interface(wpa_s, iface->conf_p2p_dev) < 0) {
4416 wpa_printf(MSG_INFO,
4417 "P2P: Failed to enable P2P Device interface");
4418 /* Try to continue without. P2P will be disabled. */
4419 }
4420#endif /* CONFIG_P2P */
4421
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004422 return wpa_s;
4423}
4424
4425
4426/**
4427 * wpa_supplicant_remove_iface - Remove a network interface
4428 * @global: Pointer to global data from wpa_supplicant_init()
4429 * @wpa_s: Pointer to the network interface to be removed
4430 * Returns: 0 if interface was removed, -1 if interface was not found
4431 *
4432 * This function can be used to dynamically remove network interfaces from
4433 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
4434 * addition, this function is used to remove all remaining interfaces when
4435 * %wpa_supplicant is terminated.
4436 */
4437int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004438 struct wpa_supplicant *wpa_s,
4439 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004440{
4441 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004442#ifdef CONFIG_MESH
4443 unsigned int mesh_if_created = wpa_s->mesh_if_created;
4444 char *ifname = NULL;
4445#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004446
4447 /* Remove interface from the global list of interfaces */
4448 prev = global->ifaces;
4449 if (prev == wpa_s) {
4450 global->ifaces = wpa_s->next;
4451 } else {
4452 while (prev && prev->next != wpa_s)
4453 prev = prev->next;
4454 if (prev == NULL)
4455 return -1;
4456 prev->next = wpa_s->next;
4457 }
4458
4459 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
4460
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004461#ifdef CONFIG_MESH
4462 if (mesh_if_created) {
4463 ifname = os_strdup(wpa_s->ifname);
4464 if (ifname == NULL) {
4465 wpa_dbg(wpa_s, MSG_ERROR,
4466 "mesh: Failed to malloc ifname");
4467 return -1;
4468 }
4469 }
4470#endif /* CONFIG_MESH */
4471
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004472 if (global->p2p_group_formation == wpa_s)
4473 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004474 if (global->p2p_invite_group == wpa_s)
4475 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004476 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004477
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004478#ifdef CONFIG_MESH
4479 if (mesh_if_created) {
4480 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
4481 os_free(ifname);
4482 }
4483#endif /* CONFIG_MESH */
4484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004485 return 0;
4486}
4487
4488
4489/**
4490 * wpa_supplicant_get_eap_mode - Get the current EAP mode
4491 * @wpa_s: Pointer to the network interface
4492 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
4493 */
4494const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
4495{
4496 const char *eapol_method;
4497
4498 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
4499 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4500 return "NO-EAP";
4501 }
4502
4503 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
4504 if (eapol_method == NULL)
4505 return "UNKNOWN-EAP";
4506
4507 return eapol_method;
4508}
4509
4510
4511/**
4512 * wpa_supplicant_get_iface - Get a new network interface
4513 * @global: Pointer to global data from wpa_supplicant_init()
4514 * @ifname: Interface name
4515 * Returns: Pointer to the interface or %NULL if not found
4516 */
4517struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4518 const char *ifname)
4519{
4520 struct wpa_supplicant *wpa_s;
4521
4522 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4523 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4524 return wpa_s;
4525 }
4526 return NULL;
4527}
4528
4529
4530#ifndef CONFIG_NO_WPA_MSG
4531static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4532{
4533 struct wpa_supplicant *wpa_s = ctx;
4534 if (wpa_s == NULL)
4535 return NULL;
4536 return wpa_s->ifname;
4537}
4538#endif /* CONFIG_NO_WPA_MSG */
4539
4540
4541/**
4542 * wpa_supplicant_init - Initialize %wpa_supplicant
4543 * @params: Parameters for %wpa_supplicant
4544 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4545 *
4546 * This function is used to initialize %wpa_supplicant. After successful
4547 * initialization, the returned data pointer can be used to add and remove
4548 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4549 */
4550struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4551{
4552 struct wpa_global *global;
4553 int ret, i;
4554
4555 if (params == NULL)
4556 return NULL;
4557
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004558#ifdef CONFIG_DRIVER_NDIS
4559 {
4560 void driver_ndis_init_ops(void);
4561 driver_ndis_init_ops();
4562 }
4563#endif /* CONFIG_DRIVER_NDIS */
4564
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004565#ifndef CONFIG_NO_WPA_MSG
4566 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4567#endif /* CONFIG_NO_WPA_MSG */
4568
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004569 if (params->wpa_debug_file_path)
4570 wpa_debug_open_file(params->wpa_debug_file_path);
4571 else
4572 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004573 if (params->wpa_debug_syslog)
4574 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004575 if (params->wpa_debug_tracing) {
4576 ret = wpa_debug_open_linux_tracing();
4577 if (ret) {
4578 wpa_printf(MSG_ERROR,
4579 "Failed to enable trace logging");
4580 return NULL;
4581 }
4582 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004583
4584 ret = eap_register_methods();
4585 if (ret) {
4586 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4587 if (ret == -2)
4588 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4589 "the same EAP type.");
4590 return NULL;
4591 }
4592
4593 global = os_zalloc(sizeof(*global));
4594 if (global == NULL)
4595 return NULL;
4596 dl_list_init(&global->p2p_srv_bonjour);
4597 dl_list_init(&global->p2p_srv_upnp);
4598 global->params.daemonize = params->daemonize;
4599 global->params.wait_for_monitor = params->wait_for_monitor;
4600 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4601 if (params->pid_file)
4602 global->params.pid_file = os_strdup(params->pid_file);
4603 if (params->ctrl_interface)
4604 global->params.ctrl_interface =
4605 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004606 if (params->ctrl_interface_group)
4607 global->params.ctrl_interface_group =
4608 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004609 if (params->override_driver)
4610 global->params.override_driver =
4611 os_strdup(params->override_driver);
4612 if (params->override_ctrl_interface)
4613 global->params.override_ctrl_interface =
4614 os_strdup(params->override_ctrl_interface);
4615 wpa_debug_level = global->params.wpa_debug_level =
4616 params->wpa_debug_level;
4617 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4618 params->wpa_debug_show_keys;
4619 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4620 params->wpa_debug_timestamp;
4621
4622 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4623
4624 if (eloop_init()) {
4625 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4626 wpa_supplicant_deinit(global);
4627 return NULL;
4628 }
4629
Jouni Malinen75ecf522011-06-27 15:19:46 -07004630 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004631
4632 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4633 if (global->ctrl_iface == NULL) {
4634 wpa_supplicant_deinit(global);
4635 return NULL;
4636 }
4637
4638 if (wpas_notify_supplicant_initialized(global)) {
4639 wpa_supplicant_deinit(global);
4640 return NULL;
4641 }
4642
4643 for (i = 0; wpa_drivers[i]; i++)
4644 global->drv_count++;
4645 if (global->drv_count == 0) {
4646 wpa_printf(MSG_ERROR, "No drivers enabled");
4647 wpa_supplicant_deinit(global);
4648 return NULL;
4649 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004650 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004651 if (global->drv_priv == NULL) {
4652 wpa_supplicant_deinit(global);
4653 return NULL;
4654 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004655
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004656#ifdef CONFIG_WIFI_DISPLAY
4657 if (wifi_display_init(global) < 0) {
4658 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4659 wpa_supplicant_deinit(global);
4660 return NULL;
4661 }
4662#endif /* CONFIG_WIFI_DISPLAY */
4663
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004664 return global;
4665}
4666
4667
4668/**
4669 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4670 * @global: Pointer to global data from wpa_supplicant_init()
4671 * Returns: 0 after successful event loop run, -1 on failure
4672 *
4673 * This function starts the main event loop and continues running as long as
4674 * there are any remaining events. In most cases, this function is running as
4675 * long as the %wpa_supplicant process in still in use.
4676 */
4677int wpa_supplicant_run(struct wpa_global *global)
4678{
4679 struct wpa_supplicant *wpa_s;
4680
4681 if (global->params.daemonize &&
4682 wpa_supplicant_daemon(global->params.pid_file))
4683 return -1;
4684
4685 if (global->params.wait_for_monitor) {
4686 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4687 if (wpa_s->ctrl_iface)
4688 wpa_supplicant_ctrl_iface_wait(
4689 wpa_s->ctrl_iface);
4690 }
4691
4692 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4693 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4694
4695 eloop_run();
4696
4697 return 0;
4698}
4699
4700
4701/**
4702 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4703 * @global: Pointer to global data from wpa_supplicant_init()
4704 *
4705 * This function is called to deinitialize %wpa_supplicant and to free all
4706 * allocated resources. Remaining network interfaces will also be removed.
4707 */
4708void wpa_supplicant_deinit(struct wpa_global *global)
4709{
4710 int i;
4711
4712 if (global == NULL)
4713 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004714
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004715#ifdef CONFIG_WIFI_DISPLAY
4716 wifi_display_deinit(global);
4717#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004718
4719 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004720 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004721
4722 if (global->ctrl_iface)
4723 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4724
4725 wpas_notify_supplicant_deinitialized(global);
4726
4727 eap_peer_unregister_methods();
4728#ifdef CONFIG_AP
4729 eap_server_unregister_methods();
4730#endif /* CONFIG_AP */
4731
4732 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4733 if (!global->drv_priv[i])
4734 continue;
4735 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4736 }
4737 os_free(global->drv_priv);
4738
4739 random_deinit();
4740
4741 eloop_destroy();
4742
4743 if (global->params.pid_file) {
4744 os_daemonize_terminate(global->params.pid_file);
4745 os_free(global->params.pid_file);
4746 }
4747 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004748 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004749 os_free(global->params.override_driver);
4750 os_free(global->params.override_ctrl_interface);
4751
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004752 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004753 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004754 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004755
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004756 os_free(global);
4757 wpa_debug_close_syslog();
4758 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004759 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004760}
4761
4762
4763void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4764{
4765 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4766 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4767 char country[3];
4768 country[0] = wpa_s->conf->country[0];
4769 country[1] = wpa_s->conf->country[1];
4770 country[2] = '\0';
4771 if (wpa_drv_set_country(wpa_s, country) < 0) {
4772 wpa_printf(MSG_ERROR, "Failed to set country code "
4773 "'%s'", country);
4774 }
4775 }
4776
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004777 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4778 wpas_init_ext_pw(wpa_s);
4779
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004780#ifdef CONFIG_WPS
4781 wpas_wps_update_config(wpa_s);
4782#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004783 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004784 wpa_s->conf->changed_parameters = 0;
4785}
4786
4787
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004788void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004789{
4790 int i;
4791
4792 for (i = 0; i < *num_freqs; i++) {
4793 if (freqs[i] == freq)
4794 return;
4795 }
4796
4797 freqs[*num_freqs] = freq;
4798 (*num_freqs)++;
4799}
4800
4801
4802static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4803{
4804 struct wpa_bss *bss, *cbss;
4805 const int max_freqs = 10;
4806 int *freqs;
4807 int num_freqs = 0;
4808
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004809 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004810 if (freqs == NULL)
4811 return NULL;
4812
4813 cbss = wpa_s->current_bss;
4814
4815 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4816 if (bss == cbss)
4817 continue;
4818 if (bss->ssid_len == cbss->ssid_len &&
4819 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4820 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4821 add_freq(freqs, &num_freqs, bss->freq);
4822 if (num_freqs == max_freqs)
4823 break;
4824 }
4825 }
4826
4827 if (num_freqs == 0) {
4828 os_free(freqs);
4829 freqs = NULL;
4830 }
4831
4832 return freqs;
4833}
4834
4835
4836void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4837{
4838 int timeout;
4839 int count;
4840 int *freqs = NULL;
4841
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004842 wpas_connect_work_done(wpa_s);
4843
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004844 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004845 * Remove possible authentication timeout since the connection failed.
4846 */
4847 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4848
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004849 /*
4850 * There is no point in blacklisting the AP if this event is
4851 * generated based on local request to disconnect.
4852 */
4853 if (wpa_s->own_disconnect_req) {
4854 wpa_s->own_disconnect_req = 0;
4855 wpa_dbg(wpa_s, MSG_DEBUG,
4856 "Ignore connection failure due to local request to disconnect");
4857 return;
4858 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004859 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004860 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4861 "indication since interface has been put into "
4862 "disconnected state");
4863 return;
4864 }
4865
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004866 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004867 * Add the failed BSSID into the blacklist and speed up next scan
4868 * attempt if there could be other APs that could accept association.
4869 * The current blacklist count indicates how many times we have tried
4870 * connecting to this AP and multiple attempts mean that other APs are
4871 * either not available or has already been tried, so that we can start
4872 * increasing the delay here to avoid constant scanning.
4873 */
4874 count = wpa_blacklist_add(wpa_s, bssid);
4875 if (count == 1 && wpa_s->current_bss) {
4876 /*
4877 * This BSS was not in the blacklist before. If there is
4878 * another BSS available for the same ESS, we should try that
4879 * next. Otherwise, we may as well try this one once more
4880 * before allowing other, likely worse, ESSes to be considered.
4881 */
4882 freqs = get_bss_freqs_in_ess(wpa_s);
4883 if (freqs) {
4884 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4885 "has been seen; try it next");
4886 wpa_blacklist_add(wpa_s, bssid);
4887 /*
4888 * On the next scan, go through only the known channels
4889 * used in this ESS based on previous scans to speed up
4890 * common load balancing use case.
4891 */
4892 os_free(wpa_s->next_scan_freqs);
4893 wpa_s->next_scan_freqs = freqs;
4894 }
4895 }
4896
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004897 /*
4898 * Add previous failure count in case the temporary blacklist was
4899 * cleared due to no other BSSes being available.
4900 */
4901 count += wpa_s->extra_blacklist_count;
4902
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004903 if (count > 3 && wpa_s->current_ssid) {
4904 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4905 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004906 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004907 }
4908
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004909 switch (count) {
4910 case 1:
4911 timeout = 100;
4912 break;
4913 case 2:
4914 timeout = 500;
4915 break;
4916 case 3:
4917 timeout = 1000;
4918 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004919 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004920 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004921 break;
4922 default:
4923 timeout = 10000;
4924 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004925 }
4926
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004927 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4928 "ms", count, timeout);
4929
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004930 /*
4931 * TODO: if more than one possible AP is available in scan results,
4932 * could try the other ones before requesting a new scan.
4933 */
4934 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4935 1000 * (timeout % 1000));
4936}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004937
4938
4939int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4940{
4941 return wpa_s->conf->ap_scan == 2 ||
4942 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4943}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004944
Dmitry Shmidt04949592012-07-19 12:16:46 -07004945
4946#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4947int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4948 struct wpa_ssid *ssid,
4949 const char *field,
4950 const char *value)
4951{
4952#ifdef IEEE8021X_EAPOL
4953 struct eap_peer_config *eap = &ssid->eap;
4954
4955 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4956 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4957 (const u8 *) value, os_strlen(value));
4958
4959 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4960 case WPA_CTRL_REQ_EAP_IDENTITY:
4961 os_free(eap->identity);
4962 eap->identity = (u8 *) os_strdup(value);
4963 eap->identity_len = os_strlen(value);
4964 eap->pending_req_identity = 0;
4965 if (ssid == wpa_s->current_ssid)
4966 wpa_s->reassociate = 1;
4967 break;
4968 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004969 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004970 eap->password = (u8 *) os_strdup(value);
4971 eap->password_len = os_strlen(value);
4972 eap->pending_req_password = 0;
4973 if (ssid == wpa_s->current_ssid)
4974 wpa_s->reassociate = 1;
4975 break;
4976 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004977 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004978 eap->new_password = (u8 *) os_strdup(value);
4979 eap->new_password_len = os_strlen(value);
4980 eap->pending_req_new_password = 0;
4981 if (ssid == wpa_s->current_ssid)
4982 wpa_s->reassociate = 1;
4983 break;
4984 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004985 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004986 eap->pin = os_strdup(value);
4987 eap->pending_req_pin = 0;
4988 if (ssid == wpa_s->current_ssid)
4989 wpa_s->reassociate = 1;
4990 break;
4991 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004992 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004993 eap->otp = (u8 *) os_strdup(value);
4994 eap->otp_len = os_strlen(value);
4995 os_free(eap->pending_req_otp);
4996 eap->pending_req_otp = NULL;
4997 eap->pending_req_otp_len = 0;
4998 break;
4999 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005000 str_clear_free(eap->private_key_passwd);
5001 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005002 eap->pending_req_passphrase = 0;
5003 if (ssid == wpa_s->current_ssid)
5004 wpa_s->reassociate = 1;
5005 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005006 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005007 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005008 eap->external_sim_resp = os_strdup(value);
5009 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005010 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5011 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5012 return -1;
5013 ssid->mem_only_psk = 1;
5014 if (ssid->passphrase)
5015 wpa_config_update_psk(ssid);
5016 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5017 wpa_supplicant_req_scan(wpa_s, 0, 0);
5018 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005019 default:
5020 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
5021 return -1;
5022 }
5023
5024 return 0;
5025#else /* IEEE8021X_EAPOL */
5026 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5027 return -1;
5028#endif /* IEEE8021X_EAPOL */
5029}
5030#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
5031
5032
5033int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5034{
5035 int i;
5036 unsigned int drv_enc;
5037
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005038 if (wpa_s->p2p_mgmt)
5039 return 1; /* no normal network profiles on p2p_mgmt interface */
5040
Dmitry Shmidt04949592012-07-19 12:16:46 -07005041 if (ssid == NULL)
5042 return 1;
5043
5044 if (ssid->disabled)
5045 return 1;
5046
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005047 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005048 drv_enc = wpa_s->drv_enc;
5049 else
5050 drv_enc = (unsigned int) -1;
5051
5052 for (i = 0; i < NUM_WEP_KEYS; i++) {
5053 size_t len = ssid->wep_key_len[i];
5054 if (len == 0)
5055 continue;
5056 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5057 continue;
5058 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5059 continue;
5060 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5061 continue;
5062 return 1; /* invalid WEP key */
5063 }
5064
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005065 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005066 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5067 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005068 return 1;
5069
Dmitry Shmidt04949592012-07-19 12:16:46 -07005070 return 0;
5071}
5072
5073
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005074int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5075{
5076#ifdef CONFIG_IEEE80211W
5077 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
5078 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
5079 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
5080 /*
5081 * Driver does not support BIP -- ignore pmf=1 default
5082 * since the connection with PMF would fail and the
5083 * configuration does not require PMF to be enabled.
5084 */
5085 return NO_MGMT_FRAME_PROTECTION;
5086 }
5087
5088 return wpa_s->conf->pmf;
5089 }
5090
5091 return ssid->ieee80211w;
5092#else /* CONFIG_IEEE80211W */
5093 return NO_MGMT_FRAME_PROTECTION;
5094#endif /* CONFIG_IEEE80211W */
5095}
5096
5097
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005098int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005099{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005100 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005101 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005102 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005103 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005104 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005105}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005106
5107
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005108void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005109{
5110 struct wpa_ssid *ssid = wpa_s->current_ssid;
5111 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005112 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005113
5114 if (ssid == NULL) {
5115 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
5116 "SSID block");
5117 return;
5118 }
5119
5120 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
5121 return;
5122
5123 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005124
5125#ifdef CONFIG_P2P
5126 if (ssid->p2p_group &&
5127 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
5128 /*
5129 * Skip the wait time since there is a short timeout on the
5130 * connection to a P2P group.
5131 */
5132 return;
5133 }
5134#endif /* CONFIG_P2P */
5135
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005136 if (ssid->auth_failures > 50)
5137 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005138 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005139 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005140 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005141 dur = 90;
5142 else if (ssid->auth_failures > 3)
5143 dur = 60;
5144 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005145 dur = 30;
5146 else if (ssid->auth_failures > 1)
5147 dur = 20;
5148 else
5149 dur = 10;
5150
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005151 if (ssid->auth_failures > 1 &&
5152 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
5153 dur += os_random() % (ssid->auth_failures * 10);
5154
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005155 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005156 if (now.sec + dur <= ssid->disabled_until.sec)
5157 return;
5158
5159 ssid->disabled_until.sec = now.sec + dur;
5160
5161 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005162 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005163 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005164 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005165}
5166
5167
5168void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
5169 struct wpa_ssid *ssid, int clear_failures)
5170{
5171 if (ssid == NULL)
5172 return;
5173
5174 if (ssid->disabled_until.sec) {
5175 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
5176 "id=%d ssid=\"%s\"",
5177 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
5178 }
5179 ssid->disabled_until.sec = 0;
5180 ssid->disabled_until.usec = 0;
5181 if (clear_failures)
5182 ssid->auth_failures = 0;
5183}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005184
5185
5186int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
5187{
5188 size_t i;
5189
5190 if (wpa_s->disallow_aps_bssid == NULL)
5191 return 0;
5192
5193 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
5194 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
5195 bssid, ETH_ALEN) == 0)
5196 return 1;
5197 }
5198
5199 return 0;
5200}
5201
5202
5203int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
5204 size_t ssid_len)
5205{
5206 size_t i;
5207
5208 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
5209 return 0;
5210
5211 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
5212 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
5213 if (ssid_len == s->ssid_len &&
5214 os_memcmp(ssid, s->ssid, ssid_len) == 0)
5215 return 1;
5216 }
5217
5218 return 0;
5219}
5220
5221
5222/**
5223 * wpas_request_connection - Request a new connection
5224 * @wpa_s: Pointer to the network interface
5225 *
5226 * This function is used to request a new connection to be found. It will mark
5227 * the interface to allow reassociation and request a new scan to find a
5228 * suitable network to connect to.
5229 */
5230void wpas_request_connection(struct wpa_supplicant *wpa_s)
5231{
5232 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005233 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005234 wpa_supplicant_reinit_autoscan(wpa_s);
5235 wpa_s->extra_blacklist_count = 0;
5236 wpa_s->disconnected = 0;
5237 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005238
5239 if (wpa_supplicant_fast_associate(wpa_s) != 1)
5240 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005241 else
5242 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005243}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005244
5245
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005246void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
5247 struct wpa_used_freq_data *freqs_data,
5248 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005249{
5250 unsigned int i;
5251
5252 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
5253 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005254 for (i = 0; i < len; i++) {
5255 struct wpa_used_freq_data *cur = &freqs_data[i];
5256 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
5257 i, cur->freq, cur->flags);
5258 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005259}
5260
5261
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005262/*
5263 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005264 * are using the same radio as the current interface, and in addition, get
5265 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005266 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005267int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
5268 struct wpa_used_freq_data *freqs_data,
5269 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005270{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005271 struct wpa_supplicant *ifs;
5272 u8 bssid[ETH_ALEN];
5273 int freq;
5274 unsigned int idx = 0, i;
5275
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005276 wpa_dbg(wpa_s, MSG_DEBUG,
5277 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005278 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005279
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005280 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
5281 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005282 if (idx == len)
5283 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005284
5285 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
5286 continue;
5287
5288 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
5289 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
5290 freq = ifs->current_ssid->frequency;
5291 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
5292 freq = ifs->assoc_freq;
5293 else
5294 continue;
5295
5296 /* Hold only distinct freqs */
5297 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005298 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005299 break;
5300
5301 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005302 freqs_data[idx++].freq = freq;
5303
5304 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
5305 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
5306 WPA_FREQ_USED_BY_P2P_CLIENT :
5307 WPA_FREQ_USED_BY_INFRA_STATION;
5308 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005309 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005310
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005311 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005312 return idx;
5313}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005314
5315
5316/*
5317 * Find the operating frequencies of any of the virtual interfaces that
5318 * are using the same radio as the current interface.
5319 */
5320int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
5321 int *freq_array, unsigned int len)
5322{
5323 struct wpa_used_freq_data *freqs_data;
5324 int num, i;
5325
5326 os_memset(freq_array, 0, sizeof(int) * len);
5327
5328 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
5329 if (!freqs_data)
5330 return -1;
5331
5332 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
5333 for (i = 0; i < num; i++)
5334 freq_array[i] = freqs_data[i].freq;
5335
5336 os_free(freqs_data);
5337
5338 return num;
5339}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005340
5341
5342static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
5343{
5344 struct rrm_data *rrm = data;
5345
5346 if (!rrm->notify_neighbor_rep) {
5347 wpa_printf(MSG_ERROR,
5348 "RRM: Unexpected neighbor report timeout");
5349 return;
5350 }
5351
5352 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
5353 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
5354
5355 rrm->notify_neighbor_rep = NULL;
5356 rrm->neighbor_rep_cb_ctx = NULL;
5357}
5358
5359
5360/*
5361 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
5362 * @wpa_s: Pointer to wpa_supplicant
5363 */
5364void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
5365{
5366 wpa_s->rrm.rrm_used = 0;
5367
5368 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5369 NULL);
5370 if (wpa_s->rrm.notify_neighbor_rep)
5371 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
5372 wpa_s->rrm.next_neighbor_rep_token = 1;
5373}
5374
5375
5376/*
5377 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
5378 * @wpa_s: Pointer to wpa_supplicant
5379 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
5380 * @report_len: Length of neighbor report buffer
5381 */
5382void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
5383 const u8 *report, size_t report_len)
5384{
5385 struct wpabuf *neighbor_rep;
5386
5387 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
5388 if (report_len < 1)
5389 return;
5390
5391 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
5392 wpa_printf(MSG_DEBUG,
5393 "RRM: Discarding neighbor report with token %d (expected %d)",
5394 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
5395 return;
5396 }
5397
5398 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5399 NULL);
5400
5401 if (!wpa_s->rrm.notify_neighbor_rep) {
5402 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
5403 return;
5404 }
5405
5406 /* skipping the first byte, which is only an id (dialog token) */
5407 neighbor_rep = wpabuf_alloc(report_len - 1);
5408 if (neighbor_rep == NULL)
5409 return;
5410 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
5411 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
5412 report[0]);
5413 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
5414 neighbor_rep);
5415 wpa_s->rrm.notify_neighbor_rep = NULL;
5416 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
5417}
5418
5419
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005420#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
5421/* Workaround different, undefined for Windows, error codes used here */
5422#define ENOTCONN -1
5423#define EOPNOTSUPP -1
5424#define ECANCELED -1
5425#endif
5426
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005427/**
5428 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
5429 * @wpa_s: Pointer to wpa_supplicant
5430 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
5431 * is sent in the request.
5432 * @cb: Callback function to be called once the requested report arrives, or
5433 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
5434 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
5435 * the requester's responsibility to free it.
5436 * In the latter case NULL will be sent in 'neighbor_rep'.
5437 * @cb_ctx: Context value to send the callback function
5438 * Returns: 0 in case of success, negative error code otherwise
5439 *
5440 * In case there is a previous request which has not been answered yet, the
5441 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
5442 * Request must contain a callback function.
5443 */
5444int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
5445 const struct wpa_ssid *ssid,
5446 void (*cb)(void *ctx,
5447 struct wpabuf *neighbor_rep),
5448 void *cb_ctx)
5449{
5450 struct wpabuf *buf;
5451 const u8 *rrm_ie;
5452
5453 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
5454 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
5455 return -ENOTCONN;
5456 }
5457
5458 if (!wpa_s->rrm.rrm_used) {
5459 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
5460 return -EOPNOTSUPP;
5461 }
5462
5463 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
5464 WLAN_EID_RRM_ENABLED_CAPABILITIES);
5465 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
5466 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
5467 wpa_printf(MSG_DEBUG,
5468 "RRM: No network support for Neighbor Report.");
5469 return -EOPNOTSUPP;
5470 }
5471
5472 if (!cb) {
5473 wpa_printf(MSG_DEBUG,
5474 "RRM: Neighbor Report request must provide a callback.");
5475 return -EINVAL;
5476 }
5477
5478 /* Refuse if there's a live request */
5479 if (wpa_s->rrm.notify_neighbor_rep) {
5480 wpa_printf(MSG_DEBUG,
5481 "RRM: Currently handling previous Neighbor Report.");
5482 return -EBUSY;
5483 }
5484
5485 /* 3 = action category + action code + dialog token */
5486 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
5487 if (buf == NULL) {
5488 wpa_printf(MSG_DEBUG,
5489 "RRM: Failed to allocate Neighbor Report Request");
5490 return -ENOMEM;
5491 }
5492
5493 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
5494 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
5495 wpa_s->rrm.next_neighbor_rep_token);
5496
5497 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5498 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
5499 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
5500 if (ssid) {
5501 wpabuf_put_u8(buf, WLAN_EID_SSID);
5502 wpabuf_put_u8(buf, ssid->ssid_len);
5503 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
5504 }
5505
5506 wpa_s->rrm.next_neighbor_rep_token++;
5507
5508 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
5509 wpa_s->own_addr, wpa_s->bssid,
5510 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
5511 wpa_printf(MSG_DEBUG,
5512 "RRM: Failed to send Neighbor Report Request");
5513 wpabuf_free(buf);
5514 return -ECANCELED;
5515 }
5516
5517 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
5518 wpa_s->rrm.notify_neighbor_rep = cb;
5519 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
5520 wpas_rrm_neighbor_rep_timeout_handler,
5521 &wpa_s->rrm, NULL);
5522
5523 wpabuf_free(buf);
5524 return 0;
5525}
5526
5527
5528void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
5529 const u8 *src,
5530 const u8 *frame, size_t len,
5531 int rssi)
5532{
5533 struct wpabuf *buf;
5534 const struct rrm_link_measurement_request *req;
5535 struct rrm_link_measurement_report report;
5536
5537 if (wpa_s->wpa_state != WPA_COMPLETED) {
5538 wpa_printf(MSG_INFO,
5539 "RRM: Ignoring link measurement request. Not associated");
5540 return;
5541 }
5542
5543 if (!wpa_s->rrm.rrm_used) {
5544 wpa_printf(MSG_INFO,
5545 "RRM: Ignoring link measurement request. Not RRM network");
5546 return;
5547 }
5548
5549 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
5550 wpa_printf(MSG_INFO,
5551 "RRM: Measurement report failed. TX power insertion not supported");
5552 return;
5553 }
5554
5555 req = (const struct rrm_link_measurement_request *) frame;
5556 if (len < sizeof(*req)) {
5557 wpa_printf(MSG_INFO,
5558 "RRM: Link measurement report failed. Request too short");
5559 return;
5560 }
5561
5562 os_memset(&report, 0, sizeof(report));
5563 report.tpc.eid = WLAN_EID_TPC_REPORT;
5564 report.tpc.len = 2;
5565 report.rsni = 255; /* 255 indicates that RSNI is not available */
5566 report.dialog_token = req->dialog_token;
5567
5568 /*
5569 * It's possible to estimate RCPI based on RSSI in dBm. This
5570 * calculation will not reflect the correct value for high rates,
5571 * but it's good enough for Action frames which are transmitted
5572 * with up to 24 Mbps rates.
5573 */
5574 if (!rssi)
5575 report.rcpi = 255; /* not available */
5576 else if (rssi < -110)
5577 report.rcpi = 0;
5578 else if (rssi > 0)
5579 report.rcpi = 220;
5580 else
5581 report.rcpi = (rssi + 110) * 2;
5582
5583 /* action_category + action_code */
5584 buf = wpabuf_alloc(2 + sizeof(report));
5585 if (buf == NULL) {
5586 wpa_printf(MSG_ERROR,
5587 "RRM: Link measurement report failed. Buffer allocation failed");
5588 return;
5589 }
5590
5591 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5592 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
5593 wpabuf_put_data(buf, &report, sizeof(report));
5594 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
5595 wpabuf_head(buf), wpabuf_len(buf));
5596
5597 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
5598 wpa_s->own_addr, wpa_s->bssid,
5599 wpabuf_head(buf), wpabuf_len(buf), 0)) {
5600 wpa_printf(MSG_ERROR,
5601 "RRM: Link measurement report failed. Send action failed");
5602 }
5603 wpabuf_free(buf);
5604}