blob: 06a16967308182464ba33b5a9c014bf51ae39bef [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
3089 if (wpa_s->current_ssid && wpa_s->current_bss &&
3090 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3091 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3092 /*
3093 * Use shorter timeout if going through WPS AP iteration
3094 * for PIN config method with an AP that does not
3095 * advertise Selected Registrar.
3096 */
3097 struct wpabuf *wps_ie;
3098
3099 wps_ie = wpa_bss_get_vendor_ie_multi(
3100 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3101 if (wps_ie &&
3102 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3103 timeout = 10;
3104 wpabuf_free(wps_ie);
3105 }
3106
3107 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003108 }
3109 wpa_s->eapol_received++;
3110
3111 if (wpa_s->countermeasures) {
3112 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3113 "EAPOL packet");
3114 return;
3115 }
3116
3117#ifdef CONFIG_IBSS_RSN
3118 if (wpa_s->current_ssid &&
3119 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3120 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3121 return;
3122 }
3123#endif /* CONFIG_IBSS_RSN */
3124
3125 /* Source address of the incoming EAPOL frame could be compared to the
3126 * current BSSID. However, it is possible that a centralized
3127 * Authenticator could be using another MAC address than the BSSID of
3128 * an AP, so just allow any address to be used for now. The replies are
3129 * still sent to the current BSSID (if available), though. */
3130
3131 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3132 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3133 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3134 return;
3135 wpa_drv_poll(wpa_s);
3136 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3137 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3138 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3139 /*
3140 * Set portValid = TRUE here since we are going to skip 4-way
3141 * handshake processing which would normally set portValid. We
3142 * need this to allow the EAPOL state machines to be completed
3143 * without going through EAPOL-Key handshake.
3144 */
3145 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3146 }
3147}
3148
3149
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003150int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003151{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003152 if ((!wpa_s->p2p_mgmt ||
3153 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3154 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003155 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003156 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3157 wpa_drv_get_mac_addr(wpa_s),
3158 ETH_P_EAPOL,
3159 wpa_supplicant_rx_eapol, wpa_s, 0);
3160 if (wpa_s->l2 == NULL)
3161 return -1;
3162 } else {
3163 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3164 if (addr)
3165 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3166 }
3167
3168 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3169 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3170 return -1;
3171 }
3172
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003173 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3174
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003175 return 0;
3176}
3177
3178
Dmitry Shmidt04949592012-07-19 12:16:46 -07003179static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3180 const u8 *buf, size_t len)
3181{
3182 struct wpa_supplicant *wpa_s = ctx;
3183 const struct l2_ethhdr *eth;
3184
3185 if (len < sizeof(*eth))
3186 return;
3187 eth = (const struct l2_ethhdr *) buf;
3188
3189 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3190 !(eth->h_dest[0] & 0x01)) {
3191 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3192 " (bridge - not for this interface - ignore)",
3193 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3194 return;
3195 }
3196
3197 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3198 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3199 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3200 len - sizeof(*eth));
3201}
3202
3203
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003204/**
3205 * wpa_supplicant_driver_init - Initialize driver interface parameters
3206 * @wpa_s: Pointer to wpa_supplicant data
3207 * Returns: 0 on success, -1 on failure
3208 *
3209 * This function is called to initialize driver interface parameters.
3210 * wpa_drv_init() must have been called before this function to initialize the
3211 * driver interface.
3212 */
3213int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3214{
3215 static int interface_count = 0;
3216
3217 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3218 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003219
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003220 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3221 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003222 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003223 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3224
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003225 if (wpa_s->bridge_ifname[0]) {
3226 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3227 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003228 wpa_s->l2_br = l2_packet_init_bridge(
3229 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3230 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003231 if (wpa_s->l2_br == NULL) {
3232 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3233 "connection for the bridge interface '%s'",
3234 wpa_s->bridge_ifname);
3235 return -1;
3236 }
3237 }
3238
3239 wpa_clear_keys(wpa_s, NULL);
3240
3241 /* Make sure that TKIP countermeasures are not left enabled (could
3242 * happen if wpa_supplicant is killed during countermeasures. */
3243 wpa_drv_set_countermeasures(wpa_s, 0);
3244
3245 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3246 wpa_drv_flush_pmkid(wpa_s);
3247
3248 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003249 wpa_s->prev_scan_wildcard = 0;
3250
Dmitry Shmidt04949592012-07-19 12:16:46 -07003251 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003252 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3253 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3254 interface_count = 0;
3255 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003256#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003257 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003258 wpa_supplicant_delayed_sched_scan(wpa_s,
3259 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003260 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003261 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003262 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003263#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003264 interface_count++;
3265 } else
3266 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3267
3268 return 0;
3269}
3270
3271
3272static int wpa_supplicant_daemon(const char *pid_file)
3273{
3274 wpa_printf(MSG_DEBUG, "Daemonize..");
3275 return os_daemonize(pid_file);
3276}
3277
3278
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003279static struct wpa_supplicant *
3280wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003281{
3282 struct wpa_supplicant *wpa_s;
3283
3284 wpa_s = os_zalloc(sizeof(*wpa_s));
3285 if (wpa_s == NULL)
3286 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003287 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003288 wpa_s->scan_interval = 5;
3289 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003290 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003291 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003292
3293 return wpa_s;
3294}
3295
3296
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003297#ifdef CONFIG_HT_OVERRIDES
3298
3299static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3300 struct ieee80211_ht_capabilities *htcaps,
3301 struct ieee80211_ht_capabilities *htcaps_mask,
3302 const char *ht_mcs)
3303{
3304 /* parse ht_mcs into hex array */
3305 int i;
3306 const char *tmp = ht_mcs;
3307 char *end = NULL;
3308
3309 /* If ht_mcs is null, do not set anything */
3310 if (!ht_mcs)
3311 return 0;
3312
3313 /* This is what we are setting in the kernel */
3314 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3315
3316 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3317
3318 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3319 errno = 0;
3320 long v = strtol(tmp, &end, 16);
3321 if (errno == 0) {
3322 wpa_msg(wpa_s, MSG_DEBUG,
3323 "htcap value[%i]: %ld end: %p tmp: %p",
3324 i, v, end, tmp);
3325 if (end == tmp)
3326 break;
3327
3328 htcaps->supported_mcs_set[i] = v;
3329 tmp = end;
3330 } else {
3331 wpa_msg(wpa_s, MSG_ERROR,
3332 "Failed to parse ht-mcs: %s, error: %s\n",
3333 ht_mcs, strerror(errno));
3334 return -1;
3335 }
3336 }
3337
3338 /*
3339 * If we were able to parse any values, then set mask for the MCS set.
3340 */
3341 if (i) {
3342 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3343 IEEE80211_HT_MCS_MASK_LEN - 1);
3344 /* skip the 3 reserved bits */
3345 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3346 0x1f;
3347 }
3348
3349 return 0;
3350}
3351
3352
3353static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3354 struct ieee80211_ht_capabilities *htcaps,
3355 struct ieee80211_ht_capabilities *htcaps_mask,
3356 int disabled)
3357{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003358 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003359
3360 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3361
3362 if (disabled == -1)
3363 return 0;
3364
3365 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3366 htcaps_mask->ht_capabilities_info |= msk;
3367 if (disabled)
3368 htcaps->ht_capabilities_info &= msk;
3369 else
3370 htcaps->ht_capabilities_info |= msk;
3371
3372 return 0;
3373}
3374
3375
3376static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3377 struct ieee80211_ht_capabilities *htcaps,
3378 struct ieee80211_ht_capabilities *htcaps_mask,
3379 int factor)
3380{
3381 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3382
3383 if (factor == -1)
3384 return 0;
3385
3386 if (factor < 0 || factor > 3) {
3387 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3388 "Must be 0-3 or -1", factor);
3389 return -EINVAL;
3390 }
3391
3392 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3393 htcaps->a_mpdu_params &= ~0x3;
3394 htcaps->a_mpdu_params |= factor & 0x3;
3395
3396 return 0;
3397}
3398
3399
3400static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3401 struct ieee80211_ht_capabilities *htcaps,
3402 struct ieee80211_ht_capabilities *htcaps_mask,
3403 int density)
3404{
3405 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3406
3407 if (density == -1)
3408 return 0;
3409
3410 if (density < 0 || density > 7) {
3411 wpa_msg(wpa_s, MSG_ERROR,
3412 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3413 density);
3414 return -EINVAL;
3415 }
3416
3417 htcaps_mask->a_mpdu_params |= 0x1C;
3418 htcaps->a_mpdu_params &= ~(0x1C);
3419 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3420
3421 return 0;
3422}
3423
3424
3425static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3426 struct ieee80211_ht_capabilities *htcaps,
3427 struct ieee80211_ht_capabilities *htcaps_mask,
3428 int disabled)
3429{
3430 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003431 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3432 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003433
3434 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3435
3436 if (disabled)
3437 htcaps->ht_capabilities_info &= ~msk;
3438 else
3439 htcaps->ht_capabilities_info |= msk;
3440
3441 htcaps_mask->ht_capabilities_info |= msk;
3442
3443 return 0;
3444}
3445
3446
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003447static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3448 struct ieee80211_ht_capabilities *htcaps,
3449 struct ieee80211_ht_capabilities *htcaps_mask,
3450 int disabled)
3451{
3452 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003453 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3454 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003455
3456 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3457
3458 if (disabled)
3459 htcaps->ht_capabilities_info &= ~msk;
3460 else
3461 htcaps->ht_capabilities_info |= msk;
3462
3463 htcaps_mask->ht_capabilities_info |= msk;
3464
3465 return 0;
3466}
3467
3468
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003469static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3470 struct ieee80211_ht_capabilities *htcaps,
3471 struct ieee80211_ht_capabilities *htcaps_mask,
3472 int disabled)
3473{
3474 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003475 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003476
3477 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3478
3479 if (disabled)
3480 htcaps->ht_capabilities_info &= ~msk;
3481 else
3482 htcaps->ht_capabilities_info |= msk;
3483
3484 htcaps_mask->ht_capabilities_info |= msk;
3485
3486 return 0;
3487}
3488
3489
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003490void wpa_supplicant_apply_ht_overrides(
3491 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3492 struct wpa_driver_associate_params *params)
3493{
3494 struct ieee80211_ht_capabilities *htcaps;
3495 struct ieee80211_ht_capabilities *htcaps_mask;
3496
3497 if (!ssid)
3498 return;
3499
3500 params->disable_ht = ssid->disable_ht;
3501 if (!params->htcaps || !params->htcaps_mask)
3502 return;
3503
3504 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3505 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3506 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3507 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3508 ssid->disable_max_amsdu);
3509 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3510 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3511 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003512 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003513 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003514
3515 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003516 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003517 htcaps->ht_capabilities_info |= bit;
3518 htcaps_mask->ht_capabilities_info |= bit;
3519 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003520}
3521
3522#endif /* CONFIG_HT_OVERRIDES */
3523
3524
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003525#ifdef CONFIG_VHT_OVERRIDES
3526void wpa_supplicant_apply_vht_overrides(
3527 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3528 struct wpa_driver_associate_params *params)
3529{
3530 struct ieee80211_vht_capabilities *vhtcaps;
3531 struct ieee80211_vht_capabilities *vhtcaps_mask;
3532
3533 if (!ssid)
3534 return;
3535
3536 params->disable_vht = ssid->disable_vht;
3537
3538 vhtcaps = (void *) params->vhtcaps;
3539 vhtcaps_mask = (void *) params->vhtcaps_mask;
3540
3541 if (!vhtcaps || !vhtcaps_mask)
3542 return;
3543
3544 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3545 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3546
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003547#ifdef CONFIG_HT_OVERRIDES
3548 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003549 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3550 int max_ampdu;
3551
3552 max_ampdu = (ssid->vht_capa &
3553 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3554 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003555
3556 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3557 wpa_set_ampdu_factor(wpa_s,
3558 (void *) params->htcaps,
3559 (void *) params->htcaps_mask,
3560 max_ampdu);
3561 }
3562#endif /* CONFIG_HT_OVERRIDES */
3563
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003564#define OVERRIDE_MCS(i) \
3565 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3566 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3567 3 << 2 * (i - 1); \
3568 vhtcaps->vht_supported_mcs_set.tx_map |= \
3569 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3570 } \
3571 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3572 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3573 3 << 2 * (i - 1); \
3574 vhtcaps->vht_supported_mcs_set.rx_map |= \
3575 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3576 }
3577
3578 OVERRIDE_MCS(1);
3579 OVERRIDE_MCS(2);
3580 OVERRIDE_MCS(3);
3581 OVERRIDE_MCS(4);
3582 OVERRIDE_MCS(5);
3583 OVERRIDE_MCS(6);
3584 OVERRIDE_MCS(7);
3585 OVERRIDE_MCS(8);
3586}
3587#endif /* CONFIG_VHT_OVERRIDES */
3588
3589
Dmitry Shmidt04949592012-07-19 12:16:46 -07003590static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3591{
3592#ifdef PCSC_FUNCS
3593 size_t len;
3594
3595 if (!wpa_s->conf->pcsc_reader)
3596 return 0;
3597
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003598 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003599 if (!wpa_s->scard)
3600 return 1;
3601
3602 if (wpa_s->conf->pcsc_pin &&
3603 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3604 scard_deinit(wpa_s->scard);
3605 wpa_s->scard = NULL;
3606 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3607 return -1;
3608 }
3609
3610 len = sizeof(wpa_s->imsi) - 1;
3611 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3612 scard_deinit(wpa_s->scard);
3613 wpa_s->scard = NULL;
3614 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3615 return -1;
3616 }
3617 wpa_s->imsi[len] = '\0';
3618
3619 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3620
3621 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3622 wpa_s->imsi, wpa_s->mnc_len);
3623
3624 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3625 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3626#endif /* PCSC_FUNCS */
3627
3628 return 0;
3629}
3630
3631
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003632int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3633{
3634 char *val, *pos;
3635
3636 ext_password_deinit(wpa_s->ext_pw);
3637 wpa_s->ext_pw = NULL;
3638 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3639
3640 if (!wpa_s->conf->ext_password_backend)
3641 return 0;
3642
3643 val = os_strdup(wpa_s->conf->ext_password_backend);
3644 if (val == NULL)
3645 return -1;
3646 pos = os_strchr(val, ':');
3647 if (pos)
3648 *pos++ = '\0';
3649
3650 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3651
3652 wpa_s->ext_pw = ext_password_init(val, pos);
3653 os_free(val);
3654 if (wpa_s->ext_pw == NULL) {
3655 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3656 return -1;
3657 }
3658 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3659
3660 return 0;
3661}
3662
3663
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003664static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003665 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003666{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003667 struct wowlan_triggers *triggers;
3668 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003669
3670 if (!wpa_s->conf->wowlan_triggers)
3671 return 0;
3672
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003673 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3674 if (triggers) {
3675 ret = wpa_drv_wowlan(wpa_s, triggers);
3676 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003677 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003678 return ret;
3679}
3680
3681
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003682static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3683 const char *rn)
3684{
3685 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3686 struct wpa_radio *radio;
3687
3688 while (rn && iface) {
3689 radio = iface->radio;
3690 if (radio && os_strcmp(rn, radio->name) == 0) {
3691 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3692 wpa_s->ifname, rn);
3693 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3694 return radio;
3695 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003696
3697 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003698 }
3699
3700 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3701 wpa_s->ifname, rn ? rn : "N/A");
3702 radio = os_zalloc(sizeof(*radio));
3703 if (radio == NULL)
3704 return NULL;
3705
3706 if (rn)
3707 os_strlcpy(radio->name, rn, sizeof(radio->name));
3708 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003709 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003710 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3711
3712 return radio;
3713}
3714
3715
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003716static void radio_work_free(struct wpa_radio_work *work)
3717{
3718 if (work->wpa_s->scan_work == work) {
3719 /* This should not really happen. */
3720 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3721 work->type, work, work->started);
3722 work->wpa_s->scan_work = NULL;
3723 }
3724
3725#ifdef CONFIG_P2P
3726 if (work->wpa_s->p2p_scan_work == work) {
3727 /* This should not really happen. */
3728 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3729 work->type, work, work->started);
3730 work->wpa_s->p2p_scan_work = NULL;
3731 }
3732#endif /* CONFIG_P2P */
3733
3734 dl_list_del(&work->list);
3735 os_free(work);
3736}
3737
3738
3739static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3740{
3741 struct wpa_radio *radio = eloop_ctx;
3742 struct wpa_radio_work *work;
3743 struct os_reltime now, diff;
3744 struct wpa_supplicant *wpa_s;
3745
3746 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3747 if (work == NULL)
3748 return;
3749
3750 if (work->started)
3751 return; /* already started and still in progress */
3752
3753 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3754 radio_list);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003755 if (wpa_s && wpa_s->radio->external_scan_running) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003756 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3757 return;
3758 }
3759
3760 os_get_reltime(&now);
3761 os_reltime_sub(&now, &work->time, &diff);
3762 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3763 work->type, work, diff.sec, diff.usec);
3764 work->started = 1;
3765 work->time = now;
3766 work->cb(work, 0);
3767}
3768
3769
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003770/*
3771 * This function removes both started and pending radio works running on
3772 * the provided interface's radio.
3773 * Prior to the removal of the radio work, its callback (cb) is called with
3774 * deinit set to be 1. Each work's callback is responsible for clearing its
3775 * internal data and restoring to a correct state.
3776 * @wpa_s: wpa_supplicant data
3777 * @type: type of works to be removed
3778 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3779 * this interface's works.
3780 */
3781void radio_remove_works(struct wpa_supplicant *wpa_s,
3782 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003783{
3784 struct wpa_radio_work *work, *tmp;
3785 struct wpa_radio *radio = wpa_s->radio;
3786
3787 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3788 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003789 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003790 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003791
3792 /* skip other ifaces' works */
3793 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003794 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003795
3796 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3797 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003798 work->cb(work, 1);
3799 radio_work_free(work);
3800 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003801
3802 /* in case we removed the started work */
3803 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003804}
3805
3806
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003807static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3808{
3809 struct wpa_radio *radio = wpa_s->radio;
3810
3811 if (!radio)
3812 return;
3813
3814 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3815 wpa_s->ifname, radio->name);
3816 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003817 radio_remove_works(wpa_s, NULL, 0);
3818 wpa_s->radio = NULL;
3819 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003820 return; /* Interfaces remain for this radio */
3821
3822 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003823 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003824 os_free(radio);
3825}
3826
3827
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003828void radio_work_check_next(struct wpa_supplicant *wpa_s)
3829{
3830 struct wpa_radio *radio = wpa_s->radio;
3831
3832 if (dl_list_empty(&radio->work))
3833 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003834 if (wpa_s->ext_work_in_progress) {
3835 wpa_printf(MSG_DEBUG,
3836 "External radio work in progress - delay start of pending item");
3837 return;
3838 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003839 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3840 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3841}
3842
3843
3844/**
3845 * radio_add_work - Add a radio work item
3846 * @wpa_s: Pointer to wpa_supplicant data
3847 * @freq: Frequency of the offchannel operation in MHz or 0
3848 * @type: Unique identifier for each type of work
3849 * @next: Force as the next work to be executed
3850 * @cb: Callback function for indicating when radio is available
3851 * @ctx: Context pointer for the work (work->ctx in cb())
3852 * Returns: 0 on success, -1 on failure
3853 *
3854 * This function is used to request time for an operation that requires
3855 * exclusive radio control. Once the radio is available, the registered callback
3856 * function will be called. radio_work_done() must be called once the exclusive
3857 * radio operation has been completed, so that the radio is freed for other
3858 * operations. The special case of deinit=1 is used to free the context data
3859 * during interface removal. That does not allow the callback function to start
3860 * the radio operation, i.e., it must free any resources allocated for the radio
3861 * work and return.
3862 *
3863 * The @freq parameter can be used to indicate a single channel on which the
3864 * offchannel operation will occur. This may allow multiple radio work
3865 * operations to be performed in parallel if they apply for the same channel.
3866 * Setting this to 0 indicates that the work item may use multiple channels or
3867 * requires exclusive control of the radio.
3868 */
3869int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3870 const char *type, int next,
3871 void (*cb)(struct wpa_radio_work *work, int deinit),
3872 void *ctx)
3873{
3874 struct wpa_radio_work *work;
3875 int was_empty;
3876
3877 work = os_zalloc(sizeof(*work));
3878 if (work == NULL)
3879 return -1;
3880 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3881 os_get_reltime(&work->time);
3882 work->freq = freq;
3883 work->type = type;
3884 work->wpa_s = wpa_s;
3885 work->cb = cb;
3886 work->ctx = ctx;
3887
3888 was_empty = dl_list_empty(&wpa_s->radio->work);
3889 if (next)
3890 dl_list_add(&wpa_s->radio->work, &work->list);
3891 else
3892 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3893 if (was_empty) {
3894 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3895 radio_work_check_next(wpa_s);
3896 }
3897
3898 return 0;
3899}
3900
3901
3902/**
3903 * radio_work_done - Indicate that a radio work item has been completed
3904 * @work: Completed work
3905 *
3906 * This function is called once the callback function registered with
3907 * radio_add_work() has completed its work.
3908 */
3909void radio_work_done(struct wpa_radio_work *work)
3910{
3911 struct wpa_supplicant *wpa_s = work->wpa_s;
3912 struct os_reltime now, diff;
3913 unsigned int started = work->started;
3914
3915 os_get_reltime(&now);
3916 os_reltime_sub(&now, &work->time, &diff);
3917 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3918 work->type, work, started ? "done" : "canceled",
3919 diff.sec, diff.usec);
3920 radio_work_free(work);
3921 if (started)
3922 radio_work_check_next(wpa_s);
3923}
3924
3925
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003926struct wpa_radio_work *
3927radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003928{
3929 struct wpa_radio_work *work;
3930 struct wpa_radio *radio = wpa_s->radio;
3931
3932 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3933 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003934 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003935 }
3936
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003937 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003938}
3939
3940
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003941static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3942 struct wpa_interface *iface)
3943{
3944 const char *ifname, *driver, *rn;
3945
3946 driver = iface->driver;
3947next_driver:
3948 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3949 return -1;
3950
3951 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3952 if (wpa_s->drv_priv == NULL) {
3953 const char *pos;
3954 pos = driver ? os_strchr(driver, ',') : NULL;
3955 if (pos) {
3956 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3957 "driver interface - try next driver wrapper");
3958 driver = pos + 1;
3959 goto next_driver;
3960 }
3961 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3962 "interface");
3963 return -1;
3964 }
3965 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3966 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3967 "driver_param '%s'", wpa_s->conf->driver_param);
3968 return -1;
3969 }
3970
3971 ifname = wpa_drv_get_ifname(wpa_s);
3972 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3973 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3974 "interface name with '%s'", ifname);
3975 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3976 }
3977
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003978 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003979 if (rn && rn[0] == '\0')
3980 rn = NULL;
3981
3982 wpa_s->radio = radio_add_interface(wpa_s, rn);
3983 if (wpa_s->radio == NULL)
3984 return -1;
3985
3986 return 0;
3987}
3988
3989
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003990static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3991 struct wpa_interface *iface)
3992{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003993 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003994 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003995
3996 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3997 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3998 iface->confname ? iface->confname : "N/A",
3999 iface->driver ? iface->driver : "default",
4000 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4001 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4002
4003 if (iface->confname) {
4004#ifdef CONFIG_BACKEND_FILE
4005 wpa_s->confname = os_rel2abs_path(iface->confname);
4006 if (wpa_s->confname == NULL) {
4007 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4008 "for configuration file '%s'.",
4009 iface->confname);
4010 return -1;
4011 }
4012 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4013 iface->confname, wpa_s->confname);
4014#else /* CONFIG_BACKEND_FILE */
4015 wpa_s->confname = os_strdup(iface->confname);
4016#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004017 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004018 if (wpa_s->conf == NULL) {
4019 wpa_printf(MSG_ERROR, "Failed to read or parse "
4020 "configuration '%s'.", wpa_s->confname);
4021 return -1;
4022 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004023 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4024 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004025
4026 /*
4027 * Override ctrl_interface and driver_param if set on command
4028 * line.
4029 */
4030 if (iface->ctrl_interface) {
4031 os_free(wpa_s->conf->ctrl_interface);
4032 wpa_s->conf->ctrl_interface =
4033 os_strdup(iface->ctrl_interface);
4034 }
4035
4036 if (iface->driver_param) {
4037 os_free(wpa_s->conf->driver_param);
4038 wpa_s->conf->driver_param =
4039 os_strdup(iface->driver_param);
4040 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004041
4042 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4043 os_free(wpa_s->conf->ctrl_interface);
4044 wpa_s->conf->ctrl_interface = NULL;
4045 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004046 } else
4047 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4048 iface->driver_param);
4049
4050 if (wpa_s->conf == NULL) {
4051 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4052 return -1;
4053 }
4054
4055 if (iface->ifname == NULL) {
4056 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4057 return -1;
4058 }
4059 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4060 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4061 iface->ifname);
4062 return -1;
4063 }
4064 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4065
4066 if (iface->bridge_ifname) {
4067 if (os_strlen(iface->bridge_ifname) >=
4068 sizeof(wpa_s->bridge_ifname)) {
4069 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4070 "name '%s'.", iface->bridge_ifname);
4071 return -1;
4072 }
4073 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4074 sizeof(wpa_s->bridge_ifname));
4075 }
4076
4077 /* RSNA Supplicant Key Management - INITIALIZE */
4078 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4079 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4080
4081 /* Initialize driver interface and register driver event handler before
4082 * L2 receive handler so that association events are processed before
4083 * EAPOL-Key packets if both become available for the same select()
4084 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004085 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004086 return -1;
4087
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004088 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4089 return -1;
4090
4091 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4092 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4093 NULL);
4094 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4095
4096 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4097 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4098 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4099 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4100 "dot11RSNAConfigPMKLifetime");
4101 return -1;
4102 }
4103
4104 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4105 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4106 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4107 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4108 "dot11RSNAConfigPMKReauthThreshold");
4109 return -1;
4110 }
4111
4112 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4113 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4114 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4115 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4116 "dot11RSNAConfigSATimeout");
4117 return -1;
4118 }
4119
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004120 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4121 &wpa_s->hw.num_modes,
4122 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004123 if (wpa_s->hw.modes) {
4124 u16 i;
4125
4126 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4127 if (wpa_s->hw.modes[i].vht_capab) {
4128 wpa_s->hw_capab = CAPAB_VHT;
4129 break;
4130 }
4131
4132 if (wpa_s->hw.modes[i].ht_capab &
4133 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4134 wpa_s->hw_capab = CAPAB_HT40;
4135 else if (wpa_s->hw.modes[i].ht_capab &&
4136 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4137 wpa_s->hw_capab = CAPAB_HT;
4138 }
4139 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004140
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004141 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4142 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004143 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004144 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004145 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004146 wpa_s->drv_smps_modes = capa.smps_modes;
4147 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004148 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004149 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004150 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
4151 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4152 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004153 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4154 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004155 wpa_s->extended_capa = capa.extended_capa;
4156 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4157 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004158 wpa_s->num_multichan_concurrent =
4159 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004160 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4161
4162 if (capa.mac_addr_rand_scan_supported)
4163 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4164 if (wpa_s->sched_scan_supported &&
4165 capa.mac_addr_rand_sched_scan_supported)
4166 wpa_s->mac_addr_rand_supported |=
4167 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004168 }
4169 if (wpa_s->max_remain_on_chan == 0)
4170 wpa_s->max_remain_on_chan = 1000;
4171
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004172 /*
4173 * Only take p2p_mgmt parameters when P2P Device is supported.
4174 * Doing it here as it determines whether l2_packet_init() will be done
4175 * during wpa_supplicant_driver_init().
4176 */
4177 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4178 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4179 else
4180 iface->p2p_mgmt = 1;
4181
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004182 if (wpa_s->num_multichan_concurrent == 0)
4183 wpa_s->num_multichan_concurrent = 1;
4184
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004185 if (wpa_supplicant_driver_init(wpa_s) < 0)
4186 return -1;
4187
4188#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004189 if ((!iface->p2p_mgmt ||
4190 !(wpa_s->drv_flags &
4191 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4192 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004193 return -1;
4194#endif /* CONFIG_TDLS */
4195
4196 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4197 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4198 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4199 return -1;
4200 }
4201
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004202 if (wpas_wps_init(wpa_s))
4203 return -1;
4204
4205 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4206 return -1;
4207 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4208
4209 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4210 if (wpa_s->ctrl_iface == NULL) {
4211 wpa_printf(MSG_ERROR,
4212 "Failed to initialize control interface '%s'.\n"
4213 "You may have another wpa_supplicant process "
4214 "already running or the file was\n"
4215 "left by an unclean termination of wpa_supplicant "
4216 "in which case you will need\n"
4217 "to manually remove this file before starting "
4218 "wpa_supplicant again.\n",
4219 wpa_s->conf->ctrl_interface);
4220 return -1;
4221 }
4222
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004223 wpa_s->gas = gas_query_init(wpa_s);
4224 if (wpa_s->gas == NULL) {
4225 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4226 return -1;
4227 }
4228
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004229 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004230 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4231 return -1;
4232 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004233
4234 if (wpa_bss_init(wpa_s) < 0)
4235 return -1;
4236
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004237 /*
4238 * Set Wake-on-WLAN triggers, if configured.
4239 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4240 * have effect anyway when the interface is down).
4241 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004242 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004243 return -1;
4244
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004245#ifdef CONFIG_EAP_PROXY
4246{
4247 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004248 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4249 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004250 if (wpa_s->mnc_len > 0) {
4251 wpa_s->imsi[len] = '\0';
4252 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4253 wpa_s->imsi, wpa_s->mnc_len);
4254 } else {
4255 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4256 }
4257}
4258#endif /* CONFIG_EAP_PROXY */
4259
Dmitry Shmidt04949592012-07-19 12:16:46 -07004260 if (pcsc_reader_init(wpa_s) < 0)
4261 return -1;
4262
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004263 if (wpas_init_ext_pw(wpa_s) < 0)
4264 return -1;
4265
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004266 wpas_rrm_reset(wpa_s);
4267
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004268 return 0;
4269}
4270
4271
4272static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004273 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004274{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004275 struct wpa_global *global = wpa_s->global;
4276 struct wpa_supplicant *iface, *prev;
4277
4278 if (wpa_s == wpa_s->parent)
4279 wpas_p2p_group_remove(wpa_s, "*");
4280
4281 iface = global->ifaces;
4282 while (iface) {
4283 if (iface == wpa_s || iface->parent != wpa_s) {
4284 iface = iface->next;
4285 continue;
4286 }
4287 wpa_printf(MSG_DEBUG,
4288 "Remove remaining child interface %s from parent %s",
4289 iface->ifname, wpa_s->ifname);
4290 prev = iface;
4291 iface = iface->next;
4292 wpa_supplicant_remove_iface(global, prev, terminate);
4293 }
4294
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004295 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004296 if (wpa_s->drv_priv) {
4297 wpa_supplicant_deauthenticate(wpa_s,
4298 WLAN_REASON_DEAUTH_LEAVING);
4299
4300 wpa_drv_set_countermeasures(wpa_s, 0);
4301 wpa_clear_keys(wpa_s, NULL);
4302 }
4303
4304 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004305 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004306
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004307 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004308 radio_remove_interface(wpa_s);
4309
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004310 if (wpa_s->drv_priv)
4311 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004312
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004313 if (notify)
4314 wpas_notify_iface_removed(wpa_s);
4315
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004316 if (terminate)
4317 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004318
4319 if (wpa_s->ctrl_iface) {
4320 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
4321 wpa_s->ctrl_iface = NULL;
4322 }
4323
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004324#ifdef CONFIG_MESH
4325 if (wpa_s->ifmsh) {
4326 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
4327 wpa_s->ifmsh = NULL;
4328 }
4329#endif /* CONFIG_MESH */
4330
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004331 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004332 wpa_config_free(wpa_s->conf);
4333 wpa_s->conf = NULL;
4334 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004335
4336 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004337}
4338
4339
4340/**
4341 * wpa_supplicant_add_iface - Add a new network interface
4342 * @global: Pointer to global data from wpa_supplicant_init()
4343 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004344 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004345 * Returns: Pointer to the created interface or %NULL on failure
4346 *
4347 * This function is used to add new network interfaces for %wpa_supplicant.
4348 * This can be called before wpa_supplicant_run() to add interfaces before the
4349 * main event loop has been started. In addition, new interfaces can be added
4350 * dynamically while %wpa_supplicant is already running. This could happen,
4351 * e.g., when a hotplug network adapter is inserted.
4352 */
4353struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004354 struct wpa_interface *iface,
4355 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004356{
4357 struct wpa_supplicant *wpa_s;
4358 struct wpa_interface t_iface;
4359 struct wpa_ssid *ssid;
4360
4361 if (global == NULL || iface == NULL)
4362 return NULL;
4363
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004364 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004365 if (wpa_s == NULL)
4366 return NULL;
4367
4368 wpa_s->global = global;
4369
4370 t_iface = *iface;
4371 if (global->params.override_driver) {
4372 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
4373 "('%s' -> '%s')",
4374 iface->driver, global->params.override_driver);
4375 t_iface.driver = global->params.override_driver;
4376 }
4377 if (global->params.override_ctrl_interface) {
4378 wpa_printf(MSG_DEBUG, "Override interface parameter: "
4379 "ctrl_interface ('%s' -> '%s')",
4380 iface->ctrl_interface,
4381 global->params.override_ctrl_interface);
4382 t_iface.ctrl_interface =
4383 global->params.override_ctrl_interface;
4384 }
4385 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
4386 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
4387 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004388 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004389 return NULL;
4390 }
4391
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004392 if (iface->p2p_mgmt == 0) {
4393 /* Notify the control interfaces about new iface */
4394 if (wpas_notify_iface_added(wpa_s)) {
4395 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
4396 return NULL;
4397 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004398
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004399 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4400 wpas_notify_network_added(wpa_s, ssid);
4401 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004402
4403 wpa_s->next = global->ifaces;
4404 global->ifaces = wpa_s;
4405
4406 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004407 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004408
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004409#ifdef CONFIG_P2P
4410 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004411 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004412 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
4413 wpas_p2p_add_p2pdev_interface(wpa_s, iface->conf_p2p_dev) < 0) {
4414 wpa_printf(MSG_INFO,
4415 "P2P: Failed to enable P2P Device interface");
4416 /* Try to continue without. P2P will be disabled. */
4417 }
4418#endif /* CONFIG_P2P */
4419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004420 return wpa_s;
4421}
4422
4423
4424/**
4425 * wpa_supplicant_remove_iface - Remove a network interface
4426 * @global: Pointer to global data from wpa_supplicant_init()
4427 * @wpa_s: Pointer to the network interface to be removed
4428 * Returns: 0 if interface was removed, -1 if interface was not found
4429 *
4430 * This function can be used to dynamically remove network interfaces from
4431 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
4432 * addition, this function is used to remove all remaining interfaces when
4433 * %wpa_supplicant is terminated.
4434 */
4435int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004436 struct wpa_supplicant *wpa_s,
4437 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004438{
4439 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004440#ifdef CONFIG_MESH
4441 unsigned int mesh_if_created = wpa_s->mesh_if_created;
4442 char *ifname = NULL;
4443#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004444
4445 /* Remove interface from the global list of interfaces */
4446 prev = global->ifaces;
4447 if (prev == wpa_s) {
4448 global->ifaces = wpa_s->next;
4449 } else {
4450 while (prev && prev->next != wpa_s)
4451 prev = prev->next;
4452 if (prev == NULL)
4453 return -1;
4454 prev->next = wpa_s->next;
4455 }
4456
4457 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
4458
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004459#ifdef CONFIG_MESH
4460 if (mesh_if_created) {
4461 ifname = os_strdup(wpa_s->ifname);
4462 if (ifname == NULL) {
4463 wpa_dbg(wpa_s, MSG_ERROR,
4464 "mesh: Failed to malloc ifname");
4465 return -1;
4466 }
4467 }
4468#endif /* CONFIG_MESH */
4469
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004470 if (global->p2p_group_formation == wpa_s)
4471 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004472 if (global->p2p_invite_group == wpa_s)
4473 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004474 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004475
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004476#ifdef CONFIG_MESH
4477 if (mesh_if_created) {
4478 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
4479 os_free(ifname);
4480 }
4481#endif /* CONFIG_MESH */
4482
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004483 return 0;
4484}
4485
4486
4487/**
4488 * wpa_supplicant_get_eap_mode - Get the current EAP mode
4489 * @wpa_s: Pointer to the network interface
4490 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
4491 */
4492const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
4493{
4494 const char *eapol_method;
4495
4496 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
4497 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4498 return "NO-EAP";
4499 }
4500
4501 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
4502 if (eapol_method == NULL)
4503 return "UNKNOWN-EAP";
4504
4505 return eapol_method;
4506}
4507
4508
4509/**
4510 * wpa_supplicant_get_iface - Get a new network interface
4511 * @global: Pointer to global data from wpa_supplicant_init()
4512 * @ifname: Interface name
4513 * Returns: Pointer to the interface or %NULL if not found
4514 */
4515struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4516 const char *ifname)
4517{
4518 struct wpa_supplicant *wpa_s;
4519
4520 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4521 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4522 return wpa_s;
4523 }
4524 return NULL;
4525}
4526
4527
4528#ifndef CONFIG_NO_WPA_MSG
4529static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4530{
4531 struct wpa_supplicant *wpa_s = ctx;
4532 if (wpa_s == NULL)
4533 return NULL;
4534 return wpa_s->ifname;
4535}
4536#endif /* CONFIG_NO_WPA_MSG */
4537
4538
4539/**
4540 * wpa_supplicant_init - Initialize %wpa_supplicant
4541 * @params: Parameters for %wpa_supplicant
4542 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4543 *
4544 * This function is used to initialize %wpa_supplicant. After successful
4545 * initialization, the returned data pointer can be used to add and remove
4546 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4547 */
4548struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4549{
4550 struct wpa_global *global;
4551 int ret, i;
4552
4553 if (params == NULL)
4554 return NULL;
4555
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004556#ifdef CONFIG_DRIVER_NDIS
4557 {
4558 void driver_ndis_init_ops(void);
4559 driver_ndis_init_ops();
4560 }
4561#endif /* CONFIG_DRIVER_NDIS */
4562
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004563#ifndef CONFIG_NO_WPA_MSG
4564 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4565#endif /* CONFIG_NO_WPA_MSG */
4566
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004567 if (params->wpa_debug_file_path)
4568 wpa_debug_open_file(params->wpa_debug_file_path);
4569 else
4570 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004571 if (params->wpa_debug_syslog)
4572 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004573 if (params->wpa_debug_tracing) {
4574 ret = wpa_debug_open_linux_tracing();
4575 if (ret) {
4576 wpa_printf(MSG_ERROR,
4577 "Failed to enable trace logging");
4578 return NULL;
4579 }
4580 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004581
4582 ret = eap_register_methods();
4583 if (ret) {
4584 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4585 if (ret == -2)
4586 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4587 "the same EAP type.");
4588 return NULL;
4589 }
4590
4591 global = os_zalloc(sizeof(*global));
4592 if (global == NULL)
4593 return NULL;
4594 dl_list_init(&global->p2p_srv_bonjour);
4595 dl_list_init(&global->p2p_srv_upnp);
4596 global->params.daemonize = params->daemonize;
4597 global->params.wait_for_monitor = params->wait_for_monitor;
4598 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4599 if (params->pid_file)
4600 global->params.pid_file = os_strdup(params->pid_file);
4601 if (params->ctrl_interface)
4602 global->params.ctrl_interface =
4603 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004604 if (params->ctrl_interface_group)
4605 global->params.ctrl_interface_group =
4606 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004607 if (params->override_driver)
4608 global->params.override_driver =
4609 os_strdup(params->override_driver);
4610 if (params->override_ctrl_interface)
4611 global->params.override_ctrl_interface =
4612 os_strdup(params->override_ctrl_interface);
4613 wpa_debug_level = global->params.wpa_debug_level =
4614 params->wpa_debug_level;
4615 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4616 params->wpa_debug_show_keys;
4617 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4618 params->wpa_debug_timestamp;
4619
4620 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4621
4622 if (eloop_init()) {
4623 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4624 wpa_supplicant_deinit(global);
4625 return NULL;
4626 }
4627
Jouni Malinen75ecf522011-06-27 15:19:46 -07004628 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004629
4630 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4631 if (global->ctrl_iface == NULL) {
4632 wpa_supplicant_deinit(global);
4633 return NULL;
4634 }
4635
4636 if (wpas_notify_supplicant_initialized(global)) {
4637 wpa_supplicant_deinit(global);
4638 return NULL;
4639 }
4640
4641 for (i = 0; wpa_drivers[i]; i++)
4642 global->drv_count++;
4643 if (global->drv_count == 0) {
4644 wpa_printf(MSG_ERROR, "No drivers enabled");
4645 wpa_supplicant_deinit(global);
4646 return NULL;
4647 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004648 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004649 if (global->drv_priv == NULL) {
4650 wpa_supplicant_deinit(global);
4651 return NULL;
4652 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004653
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004654#ifdef CONFIG_WIFI_DISPLAY
4655 if (wifi_display_init(global) < 0) {
4656 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4657 wpa_supplicant_deinit(global);
4658 return NULL;
4659 }
4660#endif /* CONFIG_WIFI_DISPLAY */
4661
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004662 return global;
4663}
4664
4665
4666/**
4667 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4668 * @global: Pointer to global data from wpa_supplicant_init()
4669 * Returns: 0 after successful event loop run, -1 on failure
4670 *
4671 * This function starts the main event loop and continues running as long as
4672 * there are any remaining events. In most cases, this function is running as
4673 * long as the %wpa_supplicant process in still in use.
4674 */
4675int wpa_supplicant_run(struct wpa_global *global)
4676{
4677 struct wpa_supplicant *wpa_s;
4678
4679 if (global->params.daemonize &&
4680 wpa_supplicant_daemon(global->params.pid_file))
4681 return -1;
4682
4683 if (global->params.wait_for_monitor) {
4684 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4685 if (wpa_s->ctrl_iface)
4686 wpa_supplicant_ctrl_iface_wait(
4687 wpa_s->ctrl_iface);
4688 }
4689
4690 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4691 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4692
4693 eloop_run();
4694
4695 return 0;
4696}
4697
4698
4699/**
4700 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4701 * @global: Pointer to global data from wpa_supplicant_init()
4702 *
4703 * This function is called to deinitialize %wpa_supplicant and to free all
4704 * allocated resources. Remaining network interfaces will also be removed.
4705 */
4706void wpa_supplicant_deinit(struct wpa_global *global)
4707{
4708 int i;
4709
4710 if (global == NULL)
4711 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004712
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004713#ifdef CONFIG_WIFI_DISPLAY
4714 wifi_display_deinit(global);
4715#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004716
4717 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004718 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004719
4720 if (global->ctrl_iface)
4721 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4722
4723 wpas_notify_supplicant_deinitialized(global);
4724
4725 eap_peer_unregister_methods();
4726#ifdef CONFIG_AP
4727 eap_server_unregister_methods();
4728#endif /* CONFIG_AP */
4729
4730 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4731 if (!global->drv_priv[i])
4732 continue;
4733 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4734 }
4735 os_free(global->drv_priv);
4736
4737 random_deinit();
4738
4739 eloop_destroy();
4740
4741 if (global->params.pid_file) {
4742 os_daemonize_terminate(global->params.pid_file);
4743 os_free(global->params.pid_file);
4744 }
4745 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004746 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004747 os_free(global->params.override_driver);
4748 os_free(global->params.override_ctrl_interface);
4749
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004750 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004751 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004752 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004753
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004754 os_free(global);
4755 wpa_debug_close_syslog();
4756 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004757 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004758}
4759
4760
4761void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4762{
4763 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4764 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4765 char country[3];
4766 country[0] = wpa_s->conf->country[0];
4767 country[1] = wpa_s->conf->country[1];
4768 country[2] = '\0';
4769 if (wpa_drv_set_country(wpa_s, country) < 0) {
4770 wpa_printf(MSG_ERROR, "Failed to set country code "
4771 "'%s'", country);
4772 }
4773 }
4774
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004775 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4776 wpas_init_ext_pw(wpa_s);
4777
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004778#ifdef CONFIG_WPS
4779 wpas_wps_update_config(wpa_s);
4780#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004781 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004782 wpa_s->conf->changed_parameters = 0;
4783}
4784
4785
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004786void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004787{
4788 int i;
4789
4790 for (i = 0; i < *num_freqs; i++) {
4791 if (freqs[i] == freq)
4792 return;
4793 }
4794
4795 freqs[*num_freqs] = freq;
4796 (*num_freqs)++;
4797}
4798
4799
4800static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4801{
4802 struct wpa_bss *bss, *cbss;
4803 const int max_freqs = 10;
4804 int *freqs;
4805 int num_freqs = 0;
4806
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004807 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004808 if (freqs == NULL)
4809 return NULL;
4810
4811 cbss = wpa_s->current_bss;
4812
4813 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4814 if (bss == cbss)
4815 continue;
4816 if (bss->ssid_len == cbss->ssid_len &&
4817 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4818 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4819 add_freq(freqs, &num_freqs, bss->freq);
4820 if (num_freqs == max_freqs)
4821 break;
4822 }
4823 }
4824
4825 if (num_freqs == 0) {
4826 os_free(freqs);
4827 freqs = NULL;
4828 }
4829
4830 return freqs;
4831}
4832
4833
4834void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4835{
4836 int timeout;
4837 int count;
4838 int *freqs = NULL;
4839
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004840 wpas_connect_work_done(wpa_s);
4841
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004842 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004843 * Remove possible authentication timeout since the connection failed.
4844 */
4845 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4846
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004847 /*
4848 * There is no point in blacklisting the AP if this event is
4849 * generated based on local request to disconnect.
4850 */
4851 if (wpa_s->own_disconnect_req) {
4852 wpa_s->own_disconnect_req = 0;
4853 wpa_dbg(wpa_s, MSG_DEBUG,
4854 "Ignore connection failure due to local request to disconnect");
4855 return;
4856 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004857 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004858 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4859 "indication since interface has been put into "
4860 "disconnected state");
4861 return;
4862 }
4863
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004864 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004865 * Add the failed BSSID into the blacklist and speed up next scan
4866 * attempt if there could be other APs that could accept association.
4867 * The current blacklist count indicates how many times we have tried
4868 * connecting to this AP and multiple attempts mean that other APs are
4869 * either not available or has already been tried, so that we can start
4870 * increasing the delay here to avoid constant scanning.
4871 */
4872 count = wpa_blacklist_add(wpa_s, bssid);
4873 if (count == 1 && wpa_s->current_bss) {
4874 /*
4875 * This BSS was not in the blacklist before. If there is
4876 * another BSS available for the same ESS, we should try that
4877 * next. Otherwise, we may as well try this one once more
4878 * before allowing other, likely worse, ESSes to be considered.
4879 */
4880 freqs = get_bss_freqs_in_ess(wpa_s);
4881 if (freqs) {
4882 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4883 "has been seen; try it next");
4884 wpa_blacklist_add(wpa_s, bssid);
4885 /*
4886 * On the next scan, go through only the known channels
4887 * used in this ESS based on previous scans to speed up
4888 * common load balancing use case.
4889 */
4890 os_free(wpa_s->next_scan_freqs);
4891 wpa_s->next_scan_freqs = freqs;
4892 }
4893 }
4894
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004895 /*
4896 * Add previous failure count in case the temporary blacklist was
4897 * cleared due to no other BSSes being available.
4898 */
4899 count += wpa_s->extra_blacklist_count;
4900
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004901 if (count > 3 && wpa_s->current_ssid) {
4902 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4903 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004904 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004905 }
4906
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004907 switch (count) {
4908 case 1:
4909 timeout = 100;
4910 break;
4911 case 2:
4912 timeout = 500;
4913 break;
4914 case 3:
4915 timeout = 1000;
4916 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004917 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004918 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004919 break;
4920 default:
4921 timeout = 10000;
4922 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004923 }
4924
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004925 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4926 "ms", count, timeout);
4927
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004928 /*
4929 * TODO: if more than one possible AP is available in scan results,
4930 * could try the other ones before requesting a new scan.
4931 */
4932 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4933 1000 * (timeout % 1000));
4934}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004935
4936
4937int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4938{
4939 return wpa_s->conf->ap_scan == 2 ||
4940 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4941}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004942
Dmitry Shmidt04949592012-07-19 12:16:46 -07004943
4944#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4945int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4946 struct wpa_ssid *ssid,
4947 const char *field,
4948 const char *value)
4949{
4950#ifdef IEEE8021X_EAPOL
4951 struct eap_peer_config *eap = &ssid->eap;
4952
4953 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4954 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4955 (const u8 *) value, os_strlen(value));
4956
4957 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4958 case WPA_CTRL_REQ_EAP_IDENTITY:
4959 os_free(eap->identity);
4960 eap->identity = (u8 *) os_strdup(value);
4961 eap->identity_len = os_strlen(value);
4962 eap->pending_req_identity = 0;
4963 if (ssid == wpa_s->current_ssid)
4964 wpa_s->reassociate = 1;
4965 break;
4966 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004967 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004968 eap->password = (u8 *) os_strdup(value);
4969 eap->password_len = os_strlen(value);
4970 eap->pending_req_password = 0;
4971 if (ssid == wpa_s->current_ssid)
4972 wpa_s->reassociate = 1;
4973 break;
4974 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004975 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004976 eap->new_password = (u8 *) os_strdup(value);
4977 eap->new_password_len = os_strlen(value);
4978 eap->pending_req_new_password = 0;
4979 if (ssid == wpa_s->current_ssid)
4980 wpa_s->reassociate = 1;
4981 break;
4982 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004983 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004984 eap->pin = os_strdup(value);
4985 eap->pending_req_pin = 0;
4986 if (ssid == wpa_s->current_ssid)
4987 wpa_s->reassociate = 1;
4988 break;
4989 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004990 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004991 eap->otp = (u8 *) os_strdup(value);
4992 eap->otp_len = os_strlen(value);
4993 os_free(eap->pending_req_otp);
4994 eap->pending_req_otp = NULL;
4995 eap->pending_req_otp_len = 0;
4996 break;
4997 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004998 str_clear_free(eap->private_key_passwd);
4999 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005000 eap->pending_req_passphrase = 0;
5001 if (ssid == wpa_s->current_ssid)
5002 wpa_s->reassociate = 1;
5003 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005004 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005005 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005006 eap->external_sim_resp = os_strdup(value);
5007 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005008 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5009 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5010 return -1;
5011 ssid->mem_only_psk = 1;
5012 if (ssid->passphrase)
5013 wpa_config_update_psk(ssid);
5014 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5015 wpa_supplicant_req_scan(wpa_s, 0, 0);
5016 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005017 default:
5018 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
5019 return -1;
5020 }
5021
5022 return 0;
5023#else /* IEEE8021X_EAPOL */
5024 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5025 return -1;
5026#endif /* IEEE8021X_EAPOL */
5027}
5028#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
5029
5030
5031int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5032{
5033 int i;
5034 unsigned int drv_enc;
5035
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005036 if (wpa_s->p2p_mgmt)
5037 return 1; /* no normal network profiles on p2p_mgmt interface */
5038
Dmitry Shmidt04949592012-07-19 12:16:46 -07005039 if (ssid == NULL)
5040 return 1;
5041
5042 if (ssid->disabled)
5043 return 1;
5044
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005045 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005046 drv_enc = wpa_s->drv_enc;
5047 else
5048 drv_enc = (unsigned int) -1;
5049
5050 for (i = 0; i < NUM_WEP_KEYS; i++) {
5051 size_t len = ssid->wep_key_len[i];
5052 if (len == 0)
5053 continue;
5054 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5055 continue;
5056 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5057 continue;
5058 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5059 continue;
5060 return 1; /* invalid WEP key */
5061 }
5062
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005063 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005064 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5065 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005066 return 1;
5067
Dmitry Shmidt04949592012-07-19 12:16:46 -07005068 return 0;
5069}
5070
5071
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005072int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5073{
5074#ifdef CONFIG_IEEE80211W
5075 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
5076 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
5077 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
5078 /*
5079 * Driver does not support BIP -- ignore pmf=1 default
5080 * since the connection with PMF would fail and the
5081 * configuration does not require PMF to be enabled.
5082 */
5083 return NO_MGMT_FRAME_PROTECTION;
5084 }
5085
5086 return wpa_s->conf->pmf;
5087 }
5088
5089 return ssid->ieee80211w;
5090#else /* CONFIG_IEEE80211W */
5091 return NO_MGMT_FRAME_PROTECTION;
5092#endif /* CONFIG_IEEE80211W */
5093}
5094
5095
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005096int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005097{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005098 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005099 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005100 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005101 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005102 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005103}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005104
5105
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005106void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005107{
5108 struct wpa_ssid *ssid = wpa_s->current_ssid;
5109 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005110 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005111
5112 if (ssid == NULL) {
5113 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
5114 "SSID block");
5115 return;
5116 }
5117
5118 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
5119 return;
5120
5121 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005122
5123#ifdef CONFIG_P2P
5124 if (ssid->p2p_group &&
5125 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
5126 /*
5127 * Skip the wait time since there is a short timeout on the
5128 * connection to a P2P group.
5129 */
5130 return;
5131 }
5132#endif /* CONFIG_P2P */
5133
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005134 if (ssid->auth_failures > 50)
5135 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005136 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005137 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005138 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005139 dur = 90;
5140 else if (ssid->auth_failures > 3)
5141 dur = 60;
5142 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005143 dur = 30;
5144 else if (ssid->auth_failures > 1)
5145 dur = 20;
5146 else
5147 dur = 10;
5148
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005149 if (ssid->auth_failures > 1 &&
5150 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
5151 dur += os_random() % (ssid->auth_failures * 10);
5152
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005153 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005154 if (now.sec + dur <= ssid->disabled_until.sec)
5155 return;
5156
5157 ssid->disabled_until.sec = now.sec + dur;
5158
5159 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005160 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005161 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005162 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005163}
5164
5165
5166void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
5167 struct wpa_ssid *ssid, int clear_failures)
5168{
5169 if (ssid == NULL)
5170 return;
5171
5172 if (ssid->disabled_until.sec) {
5173 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
5174 "id=%d ssid=\"%s\"",
5175 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
5176 }
5177 ssid->disabled_until.sec = 0;
5178 ssid->disabled_until.usec = 0;
5179 if (clear_failures)
5180 ssid->auth_failures = 0;
5181}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005182
5183
5184int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
5185{
5186 size_t i;
5187
5188 if (wpa_s->disallow_aps_bssid == NULL)
5189 return 0;
5190
5191 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
5192 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
5193 bssid, ETH_ALEN) == 0)
5194 return 1;
5195 }
5196
5197 return 0;
5198}
5199
5200
5201int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
5202 size_t ssid_len)
5203{
5204 size_t i;
5205
5206 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
5207 return 0;
5208
5209 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
5210 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
5211 if (ssid_len == s->ssid_len &&
5212 os_memcmp(ssid, s->ssid, ssid_len) == 0)
5213 return 1;
5214 }
5215
5216 return 0;
5217}
5218
5219
5220/**
5221 * wpas_request_connection - Request a new connection
5222 * @wpa_s: Pointer to the network interface
5223 *
5224 * This function is used to request a new connection to be found. It will mark
5225 * the interface to allow reassociation and request a new scan to find a
5226 * suitable network to connect to.
5227 */
5228void wpas_request_connection(struct wpa_supplicant *wpa_s)
5229{
5230 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005231 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005232 wpa_supplicant_reinit_autoscan(wpa_s);
5233 wpa_s->extra_blacklist_count = 0;
5234 wpa_s->disconnected = 0;
5235 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005236
5237 if (wpa_supplicant_fast_associate(wpa_s) != 1)
5238 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005239 else
5240 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005241}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005242
5243
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005244void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
5245 struct wpa_used_freq_data *freqs_data,
5246 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005247{
5248 unsigned int i;
5249
5250 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
5251 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005252 for (i = 0; i < len; i++) {
5253 struct wpa_used_freq_data *cur = &freqs_data[i];
5254 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
5255 i, cur->freq, cur->flags);
5256 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005257}
5258
5259
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005260/*
5261 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005262 * are using the same radio as the current interface, and in addition, get
5263 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005264 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005265int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
5266 struct wpa_used_freq_data *freqs_data,
5267 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005268{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005269 struct wpa_supplicant *ifs;
5270 u8 bssid[ETH_ALEN];
5271 int freq;
5272 unsigned int idx = 0, i;
5273
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005274 wpa_dbg(wpa_s, MSG_DEBUG,
5275 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005276 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005277
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005278 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
5279 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005280 if (idx == len)
5281 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005282
5283 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
5284 continue;
5285
5286 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
5287 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
5288 freq = ifs->current_ssid->frequency;
5289 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
5290 freq = ifs->assoc_freq;
5291 else
5292 continue;
5293
5294 /* Hold only distinct freqs */
5295 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005296 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005297 break;
5298
5299 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005300 freqs_data[idx++].freq = freq;
5301
5302 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
5303 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
5304 WPA_FREQ_USED_BY_P2P_CLIENT :
5305 WPA_FREQ_USED_BY_INFRA_STATION;
5306 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005307 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005308
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005309 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005310 return idx;
5311}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005312
5313
5314/*
5315 * Find the operating frequencies of any of the virtual interfaces that
5316 * are using the same radio as the current interface.
5317 */
5318int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
5319 int *freq_array, unsigned int len)
5320{
5321 struct wpa_used_freq_data *freqs_data;
5322 int num, i;
5323
5324 os_memset(freq_array, 0, sizeof(int) * len);
5325
5326 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
5327 if (!freqs_data)
5328 return -1;
5329
5330 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
5331 for (i = 0; i < num; i++)
5332 freq_array[i] = freqs_data[i].freq;
5333
5334 os_free(freqs_data);
5335
5336 return num;
5337}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005338
5339
5340static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
5341{
5342 struct rrm_data *rrm = data;
5343
5344 if (!rrm->notify_neighbor_rep) {
5345 wpa_printf(MSG_ERROR,
5346 "RRM: Unexpected neighbor report timeout");
5347 return;
5348 }
5349
5350 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
5351 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
5352
5353 rrm->notify_neighbor_rep = NULL;
5354 rrm->neighbor_rep_cb_ctx = NULL;
5355}
5356
5357
5358/*
5359 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
5360 * @wpa_s: Pointer to wpa_supplicant
5361 */
5362void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
5363{
5364 wpa_s->rrm.rrm_used = 0;
5365
5366 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5367 NULL);
5368 if (wpa_s->rrm.notify_neighbor_rep)
5369 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
5370 wpa_s->rrm.next_neighbor_rep_token = 1;
5371}
5372
5373
5374/*
5375 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
5376 * @wpa_s: Pointer to wpa_supplicant
5377 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
5378 * @report_len: Length of neighbor report buffer
5379 */
5380void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
5381 const u8 *report, size_t report_len)
5382{
5383 struct wpabuf *neighbor_rep;
5384
5385 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
5386 if (report_len < 1)
5387 return;
5388
5389 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
5390 wpa_printf(MSG_DEBUG,
5391 "RRM: Discarding neighbor report with token %d (expected %d)",
5392 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
5393 return;
5394 }
5395
5396 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5397 NULL);
5398
5399 if (!wpa_s->rrm.notify_neighbor_rep) {
5400 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
5401 return;
5402 }
5403
5404 /* skipping the first byte, which is only an id (dialog token) */
5405 neighbor_rep = wpabuf_alloc(report_len - 1);
5406 if (neighbor_rep == NULL)
5407 return;
5408 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
5409 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
5410 report[0]);
5411 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
5412 neighbor_rep);
5413 wpa_s->rrm.notify_neighbor_rep = NULL;
5414 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
5415}
5416
5417
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005418#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
5419/* Workaround different, undefined for Windows, error codes used here */
5420#define ENOTCONN -1
5421#define EOPNOTSUPP -1
5422#define ECANCELED -1
5423#endif
5424
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005425/**
5426 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
5427 * @wpa_s: Pointer to wpa_supplicant
5428 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
5429 * is sent in the request.
5430 * @cb: Callback function to be called once the requested report arrives, or
5431 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
5432 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
5433 * the requester's responsibility to free it.
5434 * In the latter case NULL will be sent in 'neighbor_rep'.
5435 * @cb_ctx: Context value to send the callback function
5436 * Returns: 0 in case of success, negative error code otherwise
5437 *
5438 * In case there is a previous request which has not been answered yet, the
5439 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
5440 * Request must contain a callback function.
5441 */
5442int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
5443 const struct wpa_ssid *ssid,
5444 void (*cb)(void *ctx,
5445 struct wpabuf *neighbor_rep),
5446 void *cb_ctx)
5447{
5448 struct wpabuf *buf;
5449 const u8 *rrm_ie;
5450
5451 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
5452 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
5453 return -ENOTCONN;
5454 }
5455
5456 if (!wpa_s->rrm.rrm_used) {
5457 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
5458 return -EOPNOTSUPP;
5459 }
5460
5461 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
5462 WLAN_EID_RRM_ENABLED_CAPABILITIES);
5463 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
5464 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
5465 wpa_printf(MSG_DEBUG,
5466 "RRM: No network support for Neighbor Report.");
5467 return -EOPNOTSUPP;
5468 }
5469
5470 if (!cb) {
5471 wpa_printf(MSG_DEBUG,
5472 "RRM: Neighbor Report request must provide a callback.");
5473 return -EINVAL;
5474 }
5475
5476 /* Refuse if there's a live request */
5477 if (wpa_s->rrm.notify_neighbor_rep) {
5478 wpa_printf(MSG_DEBUG,
5479 "RRM: Currently handling previous Neighbor Report.");
5480 return -EBUSY;
5481 }
5482
5483 /* 3 = action category + action code + dialog token */
5484 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
5485 if (buf == NULL) {
5486 wpa_printf(MSG_DEBUG,
5487 "RRM: Failed to allocate Neighbor Report Request");
5488 return -ENOMEM;
5489 }
5490
5491 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
5492 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
5493 wpa_s->rrm.next_neighbor_rep_token);
5494
5495 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5496 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
5497 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
5498 if (ssid) {
5499 wpabuf_put_u8(buf, WLAN_EID_SSID);
5500 wpabuf_put_u8(buf, ssid->ssid_len);
5501 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
5502 }
5503
5504 wpa_s->rrm.next_neighbor_rep_token++;
5505
5506 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
5507 wpa_s->own_addr, wpa_s->bssid,
5508 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
5509 wpa_printf(MSG_DEBUG,
5510 "RRM: Failed to send Neighbor Report Request");
5511 wpabuf_free(buf);
5512 return -ECANCELED;
5513 }
5514
5515 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
5516 wpa_s->rrm.notify_neighbor_rep = cb;
5517 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
5518 wpas_rrm_neighbor_rep_timeout_handler,
5519 &wpa_s->rrm, NULL);
5520
5521 wpabuf_free(buf);
5522 return 0;
5523}
5524
5525
5526void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
5527 const u8 *src,
5528 const u8 *frame, size_t len,
5529 int rssi)
5530{
5531 struct wpabuf *buf;
5532 const struct rrm_link_measurement_request *req;
5533 struct rrm_link_measurement_report report;
5534
5535 if (wpa_s->wpa_state != WPA_COMPLETED) {
5536 wpa_printf(MSG_INFO,
5537 "RRM: Ignoring link measurement request. Not associated");
5538 return;
5539 }
5540
5541 if (!wpa_s->rrm.rrm_used) {
5542 wpa_printf(MSG_INFO,
5543 "RRM: Ignoring link measurement request. Not RRM network");
5544 return;
5545 }
5546
5547 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
5548 wpa_printf(MSG_INFO,
5549 "RRM: Measurement report failed. TX power insertion not supported");
5550 return;
5551 }
5552
5553 req = (const struct rrm_link_measurement_request *) frame;
5554 if (len < sizeof(*req)) {
5555 wpa_printf(MSG_INFO,
5556 "RRM: Link measurement report failed. Request too short");
5557 return;
5558 }
5559
5560 os_memset(&report, 0, sizeof(report));
5561 report.tpc.eid = WLAN_EID_TPC_REPORT;
5562 report.tpc.len = 2;
5563 report.rsni = 255; /* 255 indicates that RSNI is not available */
5564 report.dialog_token = req->dialog_token;
5565
5566 /*
5567 * It's possible to estimate RCPI based on RSSI in dBm. This
5568 * calculation will not reflect the correct value for high rates,
5569 * but it's good enough for Action frames which are transmitted
5570 * with up to 24 Mbps rates.
5571 */
5572 if (!rssi)
5573 report.rcpi = 255; /* not available */
5574 else if (rssi < -110)
5575 report.rcpi = 0;
5576 else if (rssi > 0)
5577 report.rcpi = 220;
5578 else
5579 report.rcpi = (rssi + 110) * 2;
5580
5581 /* action_category + action_code */
5582 buf = wpabuf_alloc(2 + sizeof(report));
5583 if (buf == NULL) {
5584 wpa_printf(MSG_ERROR,
5585 "RRM: Link measurement report failed. Buffer allocation failed");
5586 return;
5587 }
5588
5589 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5590 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
5591 wpabuf_put_data(buf, &report, sizeof(report));
5592 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
5593 wpabuf_head(buf), wpabuf_len(buf));
5594
5595 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
5596 wpa_s->own_addr, wpa_s->bssid,
5597 wpabuf_head(buf), wpabuf_len(buf), 0)) {
5598 wpa_printf(MSG_ERROR,
5599 "RRM: Link measurement report failed. Send action failed");
5600 }
5601 wpabuf_free(buf);
5602}