blob: 7631a7940db885197a7286e1401b93265a1544e0 [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"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080038#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070039#include "blacklist.h"
40#include "wpas_glue.h"
41#include "wps_supplicant.h"
42#include "ibss_rsn.h"
43#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080044#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070045#include "ap.h"
46#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070047#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048#include "notify.h"
49#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070050#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070051#include "bss.h"
52#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080053#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070054#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070055#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070056#include "wpas_kay.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080057#include "mesh.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070058
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070059const char *const wpa_supplicant_version =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070060"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidt807291d2015-01-27 13:40:23 -080061"Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070062
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070063const char *const wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080064"This software may be distributed under the terms of the BSD license.\n"
65"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070066#ifdef EAP_TLS_OPENSSL
67"\nThis product includes software developed by the OpenSSL Project\n"
68"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
69#endif /* EAP_TLS_OPENSSL */
70;
71
72#ifndef CONFIG_NO_STDOUT_DEBUG
73/* Long text divided into parts in order to fit in C89 strings size limits. */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070074const char *const wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080075"";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070076const char *const wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080077"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070078"\n"
79"Redistribution and use in source and binary forms, with or without\n"
80"modification, are permitted provided that the following conditions are\n"
81"met:\n"
82"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070083const char *const wpa_supplicant_full_license3 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070084"1. Redistributions of source code must retain the above copyright\n"
85" notice, this list of conditions and the following disclaimer.\n"
86"\n"
87"2. Redistributions in binary form must reproduce the above copyright\n"
88" notice, this list of conditions and the following disclaimer in the\n"
89" documentation and/or other materials provided with the distribution.\n"
90"\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070091const char *const wpa_supplicant_full_license4 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070092"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
93" names of its contributors may be used to endorse or promote products\n"
94" derived from this software without specific prior written permission.\n"
95"\n"
96"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
97"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
98"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
99"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700100const char *const wpa_supplicant_full_license5 =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700101"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
102"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
103"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
104"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
105"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
106"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
107"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
108"\n";
109#endif /* CONFIG_NO_STDOUT_DEBUG */
110
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700111/* Configure default/group WEP keys for static WEP */
112int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
113{
114 int i, set = 0;
115
116 for (i = 0; i < NUM_WEP_KEYS; i++) {
117 if (ssid->wep_key_len[i] == 0)
118 continue;
119
120 set = 1;
121 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
122 i, i == ssid->wep_tx_keyidx, NULL, 0,
123 ssid->wep_key[i], ssid->wep_key_len[i]);
124 }
125
126 return set;
127}
128
129
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700130int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
131 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700132{
133 u8 key[32];
134 size_t keylen;
135 enum wpa_alg alg;
136 u8 seq[6] = { 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800137 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700138
139 /* IBSS/WPA-None uses only one key (Group) for both receiving and
140 * sending unicast and multicast packets. */
141
142 if (ssid->mode != WPAS_MODE_IBSS) {
143 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
144 "IBSS/ad-hoc) for WPA-None", ssid->mode);
145 return -1;
146 }
147
148 if (!ssid->psk_set) {
149 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
150 "WPA-None");
151 return -1;
152 }
153
154 switch (wpa_s->group_cipher) {
155 case WPA_CIPHER_CCMP:
156 os_memcpy(key, ssid->psk, 16);
157 keylen = 16;
158 alg = WPA_ALG_CCMP;
159 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700160 case WPA_CIPHER_GCMP:
161 os_memcpy(key, ssid->psk, 16);
162 keylen = 16;
163 alg = WPA_ALG_GCMP;
164 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700165 case WPA_CIPHER_TKIP:
166 /* WPA-None uses the same Michael MIC key for both TX and RX */
167 os_memcpy(key, ssid->psk, 16 + 8);
168 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
169 keylen = 32;
170 alg = WPA_ALG_TKIP;
171 break;
172 default:
173 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
174 "WPA-None", wpa_s->group_cipher);
175 return -1;
176 }
177
178 /* TODO: should actually remember the previously used seq#, both for TX
179 * and RX from each STA.. */
180
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800181 ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
182 os_memset(key, 0, sizeof(key));
183 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700184}
185
186
187static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
188{
189 struct wpa_supplicant *wpa_s = eloop_ctx;
190 const u8 *bssid = wpa_s->bssid;
191 if (is_zero_ether_addr(bssid))
192 bssid = wpa_s->pending_bssid;
193 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
194 MAC2STR(bssid));
195 wpa_blacklist_add(wpa_s, bssid);
196 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800197 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700198 wpa_s->reassociate = 1;
199
200 /*
201 * If we timed out, the AP or the local radio may be busy.
202 * So, wait a second until scanning again.
203 */
204 wpa_supplicant_req_scan(wpa_s, 1, 0);
205}
206
207
208/**
209 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
210 * @wpa_s: Pointer to wpa_supplicant data
211 * @sec: Number of seconds after which to time out authentication
212 * @usec: Number of microseconds after which to time out authentication
213 *
214 * This function is used to schedule a timeout for the current authentication
215 * attempt.
216 */
217void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
218 int sec, int usec)
219{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700220 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700221 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
222 return;
223
224 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
225 "%d usec", sec, usec);
226 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
227 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
228}
229
230
231/**
232 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
233 * @wpa_s: Pointer to wpa_supplicant data
234 *
235 * This function is used to cancel authentication timeout scheduled with
236 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
237 * been completed.
238 */
239void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
240{
241 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
242 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
243 wpa_blacklist_del(wpa_s, wpa_s->bssid);
244}
245
246
247/**
248 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
249 * @wpa_s: Pointer to wpa_supplicant data
250 *
251 * This function is used to configure EAPOL state machine based on the selected
252 * authentication mode.
253 */
254void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
255{
256#ifdef IEEE8021X_EAPOL
257 struct eapol_config eapol_conf;
258 struct wpa_ssid *ssid = wpa_s->current_ssid;
259
260#ifdef CONFIG_IBSS_RSN
261 if (ssid->mode == WPAS_MODE_IBSS &&
262 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
263 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
264 /*
265 * RSN IBSS authentication is per-STA and we can disable the
266 * per-BSSID EAPOL authentication.
267 */
268 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
269 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
270 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
271 return;
272 }
273#endif /* CONFIG_IBSS_RSN */
274
275 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
276 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
277
278 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
279 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
280 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
281 else
282 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
283
284 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
285 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
286 eapol_conf.accept_802_1x_keys = 1;
287 eapol_conf.required_keys = 0;
288 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
289 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
290 }
291 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
292 eapol_conf.required_keys |=
293 EAPOL_REQUIRE_KEY_BROADCAST;
294 }
295
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700296 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700297 eapol_conf.required_keys = 0;
298 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700299 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700300 eapol_conf.workaround = ssid->eap_workaround;
301 eapol_conf.eap_disabled =
302 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
303 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
304 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700305 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800306
307#ifdef CONFIG_WPS
308 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
309 eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE;
310 if (wpa_s->current_bss) {
311 struct wpabuf *ie;
312 ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
313 WPS_IE_VENDOR_TYPE);
314 if (ie) {
315 if (wps_is_20(ie))
316 eapol_conf.wps |=
317 EAPOL_PEER_IS_WPS20_AP;
318 wpabuf_free(ie);
319 }
320 }
321 }
322#endif /* CONFIG_WPS */
323
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700324 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700325
326 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800327#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700328}
329
330
331/**
332 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
333 * @wpa_s: Pointer to wpa_supplicant data
334 * @ssid: Configuration data for the network
335 *
336 * This function is used to configure WPA state machine and related parameters
337 * to a mode where WPA is not enabled. This is called as part of the
338 * authentication configuration when the selected network does not use WPA.
339 */
340void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
341 struct wpa_ssid *ssid)
342{
343 int i;
344
345 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
346 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
347 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
348 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
349 else
350 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
351 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
352 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
353 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
354 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
355 wpa_s->group_cipher = WPA_CIPHER_NONE;
356 wpa_s->mgmt_group_cipher = 0;
357
358 for (i = 0; i < NUM_WEP_KEYS; i++) {
359 if (ssid->wep_key_len[i] > 5) {
360 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
361 wpa_s->group_cipher = WPA_CIPHER_WEP104;
362 break;
363 } else if (ssid->wep_key_len[i] > 0) {
364 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
365 wpa_s->group_cipher = WPA_CIPHER_WEP40;
366 break;
367 }
368 }
369
370 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
371 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
372 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
373 wpa_s->pairwise_cipher);
374 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
375#ifdef CONFIG_IEEE80211W
376 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
377 wpa_s->mgmt_group_cipher);
378#endif /* CONFIG_IEEE80211W */
379
380 pmksa_cache_clear_current(wpa_s->wpa);
381}
382
383
Dmitry Shmidt04949592012-07-19 12:16:46 -0700384void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800385{
386 int i;
387 if (wpa_s->hw.modes == NULL)
388 return;
389
390 for (i = 0; i < wpa_s->hw.num_modes; i++) {
391 os_free(wpa_s->hw.modes[i].channels);
392 os_free(wpa_s->hw.modes[i].rates);
393 }
394
395 os_free(wpa_s->hw.modes);
396 wpa_s->hw.modes = NULL;
397}
398
399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700400static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
401{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700402 int i;
403
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700405 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406 scard_deinit(wpa_s->scard);
407 wpa_s->scard = NULL;
408 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
409 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
410 l2_packet_deinit(wpa_s->l2);
411 wpa_s->l2 = NULL;
412 if (wpa_s->l2_br) {
413 l2_packet_deinit(wpa_s->l2_br);
414 wpa_s->l2_br = NULL;
415 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800416#ifdef CONFIG_TESTING_OPTIONS
417 l2_packet_deinit(wpa_s->l2_test);
418 wpa_s->l2_test = NULL;
419#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700420
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700421 if (wpa_s->conf != NULL) {
422 struct wpa_ssid *ssid;
423 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
424 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700425 }
426
427 os_free(wpa_s->confname);
428 wpa_s->confname = NULL;
429
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700430 os_free(wpa_s->confanother);
431 wpa_s->confanother = NULL;
432
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700433 wpa_sm_set_eapol(wpa_s->wpa, NULL);
434 eapol_sm_deinit(wpa_s->eapol);
435 wpa_s->eapol = NULL;
436
437 rsn_preauth_deinit(wpa_s->wpa);
438
439#ifdef CONFIG_TDLS
440 wpa_tdls_deinit(wpa_s->wpa);
441#endif /* CONFIG_TDLS */
442
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800443 wmm_ac_clear_saved_tspecs(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444 pmksa_candidate_free(wpa_s->wpa);
445 wpa_sm_deinit(wpa_s->wpa);
446 wpa_s->wpa = NULL;
447 wpa_blacklist_clear(wpa_s);
448
449 wpa_bss_deinit(wpa_s);
450
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700451 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700452 wpa_supplicant_cancel_scan(wpa_s);
453 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800454 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
455#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
456 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
457 wpa_s, NULL);
458#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700459
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700460 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
461
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700462 wpas_wps_deinit(wpa_s);
463
464 wpabuf_free(wpa_s->pending_eapol_rx);
465 wpa_s->pending_eapol_rx = NULL;
466
467#ifdef CONFIG_IBSS_RSN
468 ibss_rsn_deinit(wpa_s->ibss_rsn);
469 wpa_s->ibss_rsn = NULL;
470#endif /* CONFIG_IBSS_RSN */
471
472 sme_deinit(wpa_s);
473
474#ifdef CONFIG_AP
475 wpa_supplicant_ap_deinit(wpa_s);
476#endif /* CONFIG_AP */
477
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700479
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800480#ifdef CONFIG_OFFCHANNEL
481 offchannel_deinit(wpa_s);
482#endif /* CONFIG_OFFCHANNEL */
483
484 wpa_supplicant_cancel_sched_scan(wpa_s);
485
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700486 os_free(wpa_s->next_scan_freqs);
487 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800488
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800489 os_free(wpa_s->manual_scan_freqs);
490 wpa_s->manual_scan_freqs = NULL;
491
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700492 os_free(wpa_s->manual_sched_scan_freqs);
493 wpa_s->manual_sched_scan_freqs = NULL;
494
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800495 wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
496
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700497 /*
498 * Need to remove any pending gas-query radio work before the
499 * gas_query_deinit() call because gas_query::work has not yet been set
500 * for works that have not been started. gas_query_free() will be unable
501 * to cancel such pending radio works and once the pending gas-query
502 * radio work eventually gets removed, the deinit notification call to
503 * gas_query_start_cb() would result in dereferencing freed memory.
504 */
505 if (wpa_s->radio)
506 radio_remove_works(wpa_s, "gas-query", 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800507 gas_query_deinit(wpa_s->gas);
508 wpa_s->gas = NULL;
509
510 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700511
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700512 ieee802_1x_dealloc_kay_sm(wpa_s);
513
Dmitry Shmidt04949592012-07-19 12:16:46 -0700514 os_free(wpa_s->bssid_filter);
515 wpa_s->bssid_filter = NULL;
516
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800517 os_free(wpa_s->disallow_aps_bssid);
518 wpa_s->disallow_aps_bssid = NULL;
519 os_free(wpa_s->disallow_aps_ssid);
520 wpa_s->disallow_aps_ssid = NULL;
521
Dmitry Shmidt04949592012-07-19 12:16:46 -0700522 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700523#ifdef CONFIG_WNM
524 wnm_deallocate_memory(wpa_s);
525#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700526
527 ext_password_deinit(wpa_s->ext_pw);
528 wpa_s->ext_pw = NULL;
529
530 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800531 wpa_s->last_gas_resp = NULL;
532 wpabuf_free(wpa_s->prev_gas_resp);
533 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700534
535 os_free(wpa_s->last_scan_res);
536 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800537
538#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700539 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800540#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700541
542 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
543 wpabuf_free(wpa_s->vendor_elem[i]);
544 wpa_s->vendor_elem[i] = NULL;
545 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800546
547 wmm_ac_notify_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700548}
549
550
551/**
552 * wpa_clear_keys - Clear keys configured for the driver
553 * @wpa_s: Pointer to wpa_supplicant data
554 * @addr: Previously used BSSID or %NULL if not available
555 *
556 * This function clears the encryption keys that has been previously configured
557 * for the driver.
558 */
559void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
560{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800561 int i, max;
562
563#ifdef CONFIG_IEEE80211W
564 max = 6;
565#else /* CONFIG_IEEE80211W */
566 max = 4;
567#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700568
569 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800570 for (i = 0; i < max; i++) {
571 if (wpa_s->keys_cleared & BIT(i))
572 continue;
573 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
574 NULL, 0);
575 }
576 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
577 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700578 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
579 0);
580 /* MLME-SETPROTECTION.request(None) */
581 wpa_drv_mlme_setprotection(
582 wpa_s, addr,
583 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
584 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
585 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800586 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587}
588
589
590/**
591 * wpa_supplicant_state_txt - Get the connection state name as a text string
592 * @state: State (wpa_state; WPA_*)
593 * Returns: The state name as a printable text string
594 */
595const char * wpa_supplicant_state_txt(enum wpa_states state)
596{
597 switch (state) {
598 case WPA_DISCONNECTED:
599 return "DISCONNECTED";
600 case WPA_INACTIVE:
601 return "INACTIVE";
602 case WPA_INTERFACE_DISABLED:
603 return "INTERFACE_DISABLED";
604 case WPA_SCANNING:
605 return "SCANNING";
606 case WPA_AUTHENTICATING:
607 return "AUTHENTICATING";
608 case WPA_ASSOCIATING:
609 return "ASSOCIATING";
610 case WPA_ASSOCIATED:
611 return "ASSOCIATED";
612 case WPA_4WAY_HANDSHAKE:
613 return "4WAY_HANDSHAKE";
614 case WPA_GROUP_HANDSHAKE:
615 return "GROUP_HANDSHAKE";
616 case WPA_COMPLETED:
617 return "COMPLETED";
618 default:
619 return "UNKNOWN";
620 }
621}
622
623
624#ifdef CONFIG_BGSCAN
625
626static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
627{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800628 const char *name;
629
630 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
631 name = wpa_s->current_ssid->bgscan;
632 else
633 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800634 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800635 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800636 if (wpas_driver_bss_selection(wpa_s))
637 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700638 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
639 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800640#ifdef CONFIG_P2P
641 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
642 return;
643#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700644
645 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800646 if (wpa_s->current_ssid) {
647 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700648 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
649 "bgscan");
650 /*
651 * Live without bgscan; it is only used as a roaming
652 * optimization, so the initial connection is not
653 * affected.
654 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700655 } else {
656 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700657 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700658 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
659 0);
660 if (scan_res) {
661 bgscan_notify_scan(wpa_s, scan_res);
662 wpa_scan_results_free(scan_res);
663 }
664 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700665 } else
666 wpa_s->bgscan_ssid = NULL;
667}
668
669
670static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
671{
672 if (wpa_s->bgscan_ssid != NULL) {
673 bgscan_deinit(wpa_s);
674 wpa_s->bgscan_ssid = NULL;
675 }
676}
677
678#endif /* CONFIG_BGSCAN */
679
680
Dmitry Shmidt04949592012-07-19 12:16:46 -0700681static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
682{
683 if (autoscan_init(wpa_s, 0))
684 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
685}
686
687
688static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
689{
690 autoscan_deinit(wpa_s);
691}
692
693
694void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
695{
696 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
697 wpa_s->wpa_state == WPA_SCANNING) {
698 autoscan_deinit(wpa_s);
699 wpa_supplicant_start_autoscan(wpa_s);
700 }
701}
702
703
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700704/**
705 * wpa_supplicant_set_state - Set current connection state
706 * @wpa_s: Pointer to wpa_supplicant data
707 * @state: The new connection state
708 *
709 * This function is called whenever the connection state changes, e.g.,
710 * association is completed for WPA/WPA2 4-Way Handshake is started.
711 */
712void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
713 enum wpa_states state)
714{
715 enum wpa_states old_state = wpa_s->wpa_state;
716
717 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
718 wpa_supplicant_state_txt(wpa_s->wpa_state),
719 wpa_supplicant_state_txt(state));
720
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800721 if (state == WPA_INTERFACE_DISABLED) {
722 /* Assure normal scan when interface is restored */
723 wpa_s->normal_scans = 0;
724 }
725
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700726 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800727 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700728 /* Reinitialize normal_scan counter */
729 wpa_s->normal_scans = 0;
730 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800731
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700732#ifdef CONFIG_P2P
733 /*
734 * P2PS client has to reply to Probe Request frames received on the
735 * group operating channel. Enable Probe Request frame reporting for
736 * P2P connected client in case p2p_cli_probe configuration property is
737 * set to 1.
738 */
739 if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid &&
740 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
741 wpa_s->current_ssid->p2p_group) {
742 if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) {
743 wpa_dbg(wpa_s, MSG_DEBUG,
744 "P2P: Enable CLI Probe Request RX reporting");
745 wpa_s->p2p_cli_probe =
746 wpa_drv_probe_req_report(wpa_s, 1) >= 0;
747 } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) {
748 wpa_dbg(wpa_s, MSG_DEBUG,
749 "P2P: Disable CLI Probe Request RX reporting");
750 wpa_s->p2p_cli_probe = 0;
751 wpa_drv_probe_req_report(wpa_s, 0);
752 }
753 }
754#endif /* CONFIG_P2P */
755
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700756 if (state != WPA_SCANNING)
757 wpa_supplicant_notify_scanning(wpa_s, 0);
758
759 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700760 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700761#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700762 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800763 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800764 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700765 ssid ? ssid->id : -1,
766 ssid && ssid->id_str ? ssid->id_str : "");
767#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700768 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -0700769 wpa_blacklist_clear(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800770 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700771 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772 wpa_drv_set_operstate(wpa_s, 1);
773#ifndef IEEE8021X_EAPOL
774 wpa_drv_set_supp_port(wpa_s, 1);
775#endif /* IEEE8021X_EAPOL */
776 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700777 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700778 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700779
780 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
782 state == WPA_ASSOCIATED) {
783 wpa_s->new_connection = 1;
784 wpa_drv_set_operstate(wpa_s, 0);
785#ifndef IEEE8021X_EAPOL
786 wpa_drv_set_supp_port(wpa_s, 0);
787#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700788 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700789 }
790 wpa_s->wpa_state = state;
791
792#ifdef CONFIG_BGSCAN
793 if (state == WPA_COMPLETED)
794 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800795 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796 wpa_supplicant_stop_bgscan(wpa_s);
797#endif /* CONFIG_BGSCAN */
798
Dmitry Shmidt04949592012-07-19 12:16:46 -0700799 if (state == WPA_AUTHENTICATING)
800 wpa_supplicant_stop_autoscan(wpa_s);
801
802 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
803 wpa_supplicant_start_autoscan(wpa_s);
804
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800805 if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED)
806 wmm_ac_notify_disassoc(wpa_s);
807
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700808 if (wpa_s->wpa_state != old_state) {
809 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
810
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700811 /*
812 * Notify the P2P Device interface about a state change in one
813 * of the interfaces.
814 */
815 wpas_p2p_indicate_state_change(wpa_s);
816
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700817 if (wpa_s->wpa_state == WPA_COMPLETED ||
818 old_state == WPA_COMPLETED)
819 wpas_notify_auth_changed(wpa_s);
820 }
821}
822
823
824void wpa_supplicant_terminate_proc(struct wpa_global *global)
825{
826 int pending = 0;
827#ifdef CONFIG_WPS
828 struct wpa_supplicant *wpa_s = global->ifaces;
829 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800830 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700831 if (wpas_wps_terminate_pending(wpa_s) == 1)
832 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700833#ifdef CONFIG_P2P
834 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
835 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
836 wpas_p2p_disconnect(wpa_s);
837#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800838 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700839 }
840#endif /* CONFIG_WPS */
841 if (pending)
842 return;
843 eloop_terminate();
844}
845
846
847static void wpa_supplicant_terminate(int sig, void *signal_ctx)
848{
849 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700850 wpa_supplicant_terminate_proc(global);
851}
852
853
854void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
855{
856 enum wpa_states old_state = wpa_s->wpa_state;
857
858 wpa_s->pairwise_cipher = 0;
859 wpa_s->group_cipher = 0;
860 wpa_s->mgmt_group_cipher = 0;
861 wpa_s->key_mgmt = 0;
862 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700863 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700864
865 if (wpa_s->wpa_state != old_state)
866 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
867}
868
869
870/**
871 * wpa_supplicant_reload_configuration - Reload configuration data
872 * @wpa_s: Pointer to wpa_supplicant data
873 * Returns: 0 on success or -1 if configuration parsing failed
874 *
875 * This function can be used to request that the configuration data is reloaded
876 * (e.g., after configuration file change). This function is reloading
877 * configuration only for one interface, so this may need to be called multiple
878 * times if %wpa_supplicant is controlling multiple interfaces and all
879 * interfaces need reconfiguration.
880 */
881int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
882{
883 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884 int reconf_ctrl;
885 int old_ap_scan;
886
887 if (wpa_s->confname == NULL)
888 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700889 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700890 if (conf == NULL) {
891 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
892 "file '%s' - exiting", wpa_s->confname);
893 return -1;
894 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700895 wpa_config_read(wpa_s->confanother, conf);
896
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700897 conf->changed_parameters = (unsigned int) -1;
898
899 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
900 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
901 os_strcmp(conf->ctrl_interface,
902 wpa_s->conf->ctrl_interface) != 0);
903
904 if (reconf_ctrl && wpa_s->ctrl_iface) {
905 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
906 wpa_s->ctrl_iface = NULL;
907 }
908
909 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800910 if (wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -0700911 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
912 wpa_s->own_disconnect_req = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800913 wpa_supplicant_deauthenticate(wpa_s,
914 WLAN_REASON_DEAUTH_LEAVING);
915 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700916
917 /*
918 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800919 * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700920 */
921 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
922 /*
923 * Clear forced success to clear EAP state for next
924 * authentication.
925 */
926 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
927 }
928 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
929 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800930 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700931 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
932 rsn_preauth_deinit(wpa_s->wpa);
933
934 old_ap_scan = wpa_s->conf->ap_scan;
935 wpa_config_free(wpa_s->conf);
936 wpa_s->conf = conf;
937 if (old_ap_scan != wpa_s->conf->ap_scan)
938 wpas_notify_ap_scan_changed(wpa_s);
939
940 if (reconf_ctrl)
941 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
942
943 wpa_supplicant_update_config(wpa_s);
944
945 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700946 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700947 wpa_s->reassociate = 1;
948 wpa_supplicant_req_scan(wpa_s, 0, 0);
949 }
950 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
951 return 0;
952}
953
954
955static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
956{
957 struct wpa_global *global = signal_ctx;
958 struct wpa_supplicant *wpa_s;
959 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
960 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
961 sig);
962 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
963 wpa_supplicant_terminate_proc(global);
964 }
965 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800966
967 if (wpa_debug_reopen_file() < 0) {
968 /* Ignore errors since we cannot really do much to fix this */
969 wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
970 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700971}
972
973
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
975 struct wpa_ssid *ssid,
976 struct wpa_ie_data *ie)
977{
978 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
979 if (ret) {
980 if (ret == -2) {
981 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
982 "from association info");
983 }
984 return -1;
985 }
986
987 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
988 "cipher suites");
989 if (!(ie->group_cipher & ssid->group_cipher)) {
990 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
991 "cipher 0x%x (mask 0x%x) - reject",
992 ie->group_cipher, ssid->group_cipher);
993 return -1;
994 }
995 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
996 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
997 "cipher 0x%x (mask 0x%x) - reject",
998 ie->pairwise_cipher, ssid->pairwise_cipher);
999 return -1;
1000 }
1001 if (!(ie->key_mgmt & ssid->key_mgmt)) {
1002 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
1003 "management 0x%x (mask 0x%x) - reject",
1004 ie->key_mgmt, ssid->key_mgmt);
1005 return -1;
1006 }
1007
1008#ifdef CONFIG_IEEE80211W
1009 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001010 wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001011 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
1012 "that does not support management frame protection - "
1013 "reject");
1014 return -1;
1015 }
1016#endif /* CONFIG_IEEE80211W */
1017
1018 return 0;
1019}
1020
1021
1022/**
1023 * wpa_supplicant_set_suites - Set authentication and encryption parameters
1024 * @wpa_s: Pointer to wpa_supplicant data
1025 * @bss: Scan results for the selected BSS, or %NULL if not available
1026 * @ssid: Configuration data for the selected network
1027 * @wpa_ie: Buffer for the WPA/RSN IE
1028 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
1029 * used buffer length in case the functions returns success.
1030 * Returns: 0 on success or -1 on failure
1031 *
1032 * This function is used to configure authentication and encryption parameters
1033 * based on the network configuration and scan result for the selected BSS (if
1034 * available).
1035 */
1036int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
1037 struct wpa_bss *bss, struct wpa_ssid *ssid,
1038 u8 *wpa_ie, size_t *wpa_ie_len)
1039{
1040 struct wpa_ie_data ie;
1041 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001042 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001043
1044 if (bss) {
1045 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
1046 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001047 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001048 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001049 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001050
1051 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
1052 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
1053 (ie.group_cipher & ssid->group_cipher) &&
1054 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1055 (ie.key_mgmt & ssid->key_mgmt)) {
1056 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
1057 proto = WPA_PROTO_RSN;
1058 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001059 wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001060 (ie.group_cipher & ssid->group_cipher) &&
1061 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
1062 (ie.key_mgmt & ssid->key_mgmt)) {
1063 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
1064 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001065#ifdef CONFIG_HS20
1066 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
1067 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
1068 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001069 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001070 ie.group_cipher = WPA_CIPHER_CCMP;
1071 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1072 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1073 proto = WPA_PROTO_OSEN;
1074#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075 } else if (bss) {
1076 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001077 wpa_dbg(wpa_s, MSG_DEBUG,
1078 "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1079 ssid->proto, ssid->pairwise_cipher, ssid->group_cipher,
1080 ssid->key_mgmt);
1081 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s%s",
1082 MAC2STR(bss->bssid),
1083 wpa_ssid_txt(bss->ssid, bss->ssid_len),
1084 bss_wpa ? " WPA" : "",
1085 bss_rsn ? " RSN" : "",
1086 bss_osen ? " OSEN" : "");
1087 if (bss_rsn) {
1088 wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]);
1089 if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) {
1090 wpa_dbg(wpa_s, MSG_DEBUG,
1091 "Could not parse RSN element");
1092 } else {
1093 wpa_dbg(wpa_s, MSG_DEBUG,
1094 "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1095 ie.pairwise_cipher, ie.group_cipher,
1096 ie.key_mgmt);
1097 }
1098 }
1099 if (bss_wpa) {
1100 wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]);
1101 if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) {
1102 wpa_dbg(wpa_s, MSG_DEBUG,
1103 "Could not parse WPA element");
1104 } else {
1105 wpa_dbg(wpa_s, MSG_DEBUG,
1106 "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x",
1107 ie.pairwise_cipher, ie.group_cipher,
1108 ie.key_mgmt);
1109 }
1110 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001111 return -1;
1112 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001113 if (ssid->proto & WPA_PROTO_OSEN)
1114 proto = WPA_PROTO_OSEN;
1115 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001116 proto = WPA_PROTO_RSN;
1117 else
1118 proto = WPA_PROTO_WPA;
1119 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1120 os_memset(&ie, 0, sizeof(ie));
1121 ie.group_cipher = ssid->group_cipher;
1122 ie.pairwise_cipher = ssid->pairwise_cipher;
1123 ie.key_mgmt = ssid->key_mgmt;
1124#ifdef CONFIG_IEEE80211W
1125 ie.mgmt_group_cipher =
1126 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1127 WPA_CIPHER_AES_128_CMAC : 0;
1128#endif /* CONFIG_IEEE80211W */
1129 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1130 "based on configuration");
1131 } else
1132 proto = ie.proto;
1133 }
1134
1135 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1136 "pairwise %d key_mgmt %d proto %d",
1137 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1138#ifdef CONFIG_IEEE80211W
1139 if (ssid->ieee80211w) {
1140 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1141 ie.mgmt_group_cipher);
1142 }
1143#endif /* CONFIG_IEEE80211W */
1144
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001145 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1147 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001148 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001149
1150 if (bss || !wpa_s->ap_ies_from_associnfo) {
1151 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1152 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1153 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1154 bss_rsn ? 2 + bss_rsn[1] : 0))
1155 return -1;
1156 }
1157
1158 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001159 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1160 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001161 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1162 "cipher");
1163 return -1;
1164 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001165 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1166 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001167
1168 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001169 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1170 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001171 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1172 "cipher");
1173 return -1;
1174 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001175 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1176 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001177
1178 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001179#ifdef CONFIG_SAE
1180 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1181 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1182#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001183 if (0) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001184#ifdef CONFIG_SUITEB192
1185 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
1186 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
1187 wpa_dbg(wpa_s, MSG_DEBUG,
1188 "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
1189#endif /* CONFIG_SUITEB192 */
1190#ifdef CONFIG_SUITEB
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001191 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
1192 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
1193 wpa_dbg(wpa_s, MSG_DEBUG,
1194 "WPA: using KEY_MGMT 802.1X with Suite B");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001195#endif /* CONFIG_SUITEB */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001196#ifdef CONFIG_IEEE80211R
1197 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1198 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1199 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1200 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1201 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1202 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1203#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001204#ifdef CONFIG_SAE
1205 } else if (sel & WPA_KEY_MGMT_SAE) {
1206 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1207 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1208 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1209 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1210 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1211#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001212#ifdef CONFIG_IEEE80211W
1213 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1214 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1215 wpa_dbg(wpa_s, MSG_DEBUG,
1216 "WPA: using KEY_MGMT 802.1X with SHA256");
1217 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1218 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1219 wpa_dbg(wpa_s, MSG_DEBUG,
1220 "WPA: using KEY_MGMT PSK with SHA256");
1221#endif /* CONFIG_IEEE80211W */
1222 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1223 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1224 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1225 } else if (sel & WPA_KEY_MGMT_PSK) {
1226 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1227 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1228 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1229 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1230 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001231#ifdef CONFIG_HS20
1232 } else if (sel & WPA_KEY_MGMT_OSEN) {
1233 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1234 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1235#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236 } else {
1237 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1238 "authenticated key management type");
1239 return -1;
1240 }
1241
1242 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1243 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1244 wpa_s->pairwise_cipher);
1245 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1246
1247#ifdef CONFIG_IEEE80211W
1248 sel = ie.mgmt_group_cipher;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001249 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001250 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1251 sel = 0;
1252 if (sel & WPA_CIPHER_AES_128_CMAC) {
1253 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1254 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1255 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001256 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1257 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1258 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1259 "BIP-GMAC-128");
1260 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1261 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1262 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1263 "BIP-GMAC-256");
1264 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1265 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1266 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1267 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001268 } else {
1269 wpa_s->mgmt_group_cipher = 0;
1270 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1271 }
1272 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1273 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001274 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001275 wpas_get_ssid_pmf(wpa_s, ssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001276#endif /* CONFIG_IEEE80211W */
1277
1278 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1279 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1280 return -1;
1281 }
1282
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001283 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001284 int psk_set = 0;
1285
1286 if (ssid->psk_set) {
1287 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
1288 psk_set = 1;
1289 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001290#ifndef CONFIG_NO_PBKDF2
1291 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1292 ssid->passphrase) {
1293 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001294 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1295 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001296 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1297 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001298 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001299 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001300 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001301 }
1302#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001303#ifdef CONFIG_EXT_PASSWORD
1304 if (ssid->ext_psk) {
1305 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1306 ssid->ext_psk);
1307 char pw_str[64 + 1];
1308 u8 psk[PMK_LEN];
1309
1310 if (pw == NULL) {
1311 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1312 "found from external storage");
1313 return -1;
1314 }
1315
1316 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1317 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1318 "PSK length %d in external storage",
1319 (int) wpabuf_len(pw));
1320 ext_password_free(pw);
1321 return -1;
1322 }
1323
1324 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1325 pw_str[wpabuf_len(pw)] = '\0';
1326
1327#ifndef CONFIG_NO_PBKDF2
1328 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1329 {
1330 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1331 4096, psk, PMK_LEN);
1332 os_memset(pw_str, 0, sizeof(pw_str));
1333 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1334 "external passphrase)",
1335 psk, PMK_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001336 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001337 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001338 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001339 } else
1340#endif /* CONFIG_NO_PBKDF2 */
1341 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1342 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1343 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1344 "Invalid PSK hex string");
1345 os_memset(pw_str, 0, sizeof(pw_str));
1346 ext_password_free(pw);
1347 return -1;
1348 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001349 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001350 psk_set = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001351 os_memset(psk, 0, sizeof(psk));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001352 } else {
1353 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1354 "PSK available");
1355 os_memset(pw_str, 0, sizeof(pw_str));
1356 ext_password_free(pw);
1357 return -1;
1358 }
1359
1360 os_memset(pw_str, 0, sizeof(pw_str));
1361 ext_password_free(pw);
1362 }
1363#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07001364
1365 if (!psk_set) {
1366 wpa_msg(wpa_s, MSG_INFO,
1367 "No PSK available for association");
1368 return -1;
1369 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001370 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001371 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1372
1373 return 0;
1374}
1375
1376
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001377static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1378{
1379 *pos = 0x00;
1380
1381 switch (idx) {
1382 case 0: /* Bits 0-7 */
1383 break;
1384 case 1: /* Bits 8-15 */
1385 break;
1386 case 2: /* Bits 16-23 */
1387#ifdef CONFIG_WNM
1388 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1389 *pos |= 0x08; /* Bit 19 - BSS Transition */
1390#endif /* CONFIG_WNM */
1391 break;
1392 case 3: /* Bits 24-31 */
1393#ifdef CONFIG_WNM
1394 *pos |= 0x02; /* Bit 25 - SSID List */
1395#endif /* CONFIG_WNM */
1396#ifdef CONFIG_INTERWORKING
1397 if (wpa_s->conf->interworking)
1398 *pos |= 0x80; /* Bit 31 - Interworking */
1399#endif /* CONFIG_INTERWORKING */
1400 break;
1401 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001402#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001403 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1404 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001405#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001406 break;
1407 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001408#ifdef CONFIG_HS20
1409 if (wpa_s->conf->hs20)
1410 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1411#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001412 break;
1413 case 6: /* Bits 48-55 */
1414 break;
1415 }
1416}
1417
1418
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001419int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001420{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001421 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001422 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001423
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001424 if (len < wpa_s->extended_capa_len)
1425 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001426 if (buflen < (size_t) len + 2) {
1427 wpa_printf(MSG_INFO,
1428 "Not enough room for building extended capabilities element");
1429 return -1;
1430 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001431
1432 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001433 *pos++ = len;
1434 for (i = 0; i < len; i++, pos++) {
1435 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001436
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001437 if (i < wpa_s->extended_capa_len) {
1438 *pos &= ~wpa_s->extended_capa_mask[i];
1439 *pos |= wpa_s->extended_capa[i];
1440 }
1441 }
1442
1443 while (len > 0 && buf[1 + len] == 0) {
1444 len--;
1445 buf[1] = len;
1446 }
1447 if (len == 0)
1448 return 0;
1449
1450 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001451}
1452
1453
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001454static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1455 struct wpa_bss *test_bss)
1456{
1457 struct wpa_bss *bss;
1458
1459 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1460 if (bss == test_bss)
1461 return 1;
1462 }
1463
1464 return 0;
1465}
1466
1467
1468static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1469 struct wpa_ssid *test_ssid)
1470{
1471 struct wpa_ssid *ssid;
1472
1473 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1474 if (ssid == test_ssid)
1475 return 1;
1476 }
1477
1478 return 0;
1479}
1480
1481
1482int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1483 struct wpa_ssid *test_ssid)
1484{
1485 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1486 return 0;
1487
1488 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1489}
1490
1491
1492void wpas_connect_work_free(struct wpa_connect_work *cwork)
1493{
1494 if (cwork == NULL)
1495 return;
1496 os_free(cwork);
1497}
1498
1499
1500void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1501{
1502 struct wpa_connect_work *cwork;
1503 struct wpa_radio_work *work = wpa_s->connect_work;
1504
1505 if (!work)
1506 return;
1507
1508 wpa_s->connect_work = NULL;
1509 cwork = work->ctx;
1510 work->ctx = NULL;
1511 wpas_connect_work_free(cwork);
1512 radio_work_done(work);
1513}
1514
1515
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001516int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1517{
1518 struct os_reltime now;
1519 u8 addr[ETH_ALEN];
1520
1521 os_get_reltime(&now);
1522 if (wpa_s->last_mac_addr_style == style &&
1523 wpa_s->last_mac_addr_change.sec != 0 &&
1524 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1525 wpa_s->conf->rand_addr_lifetime)) {
1526 wpa_msg(wpa_s, MSG_DEBUG,
1527 "Previously selected random MAC address has not yet expired");
1528 return 0;
1529 }
1530
1531 switch (style) {
1532 case 1:
1533 if (random_mac_addr(addr) < 0)
1534 return -1;
1535 break;
1536 case 2:
1537 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1538 if (random_mac_addr_keep_oui(addr) < 0)
1539 return -1;
1540 break;
1541 default:
1542 return -1;
1543 }
1544
1545 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1546 wpa_msg(wpa_s, MSG_INFO,
1547 "Failed to set random MAC address");
1548 return -1;
1549 }
1550
1551 os_get_reltime(&wpa_s->last_mac_addr_change);
1552 wpa_s->mac_addr_changed = 1;
1553 wpa_s->last_mac_addr_style = style;
1554
1555 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1556 wpa_msg(wpa_s, MSG_INFO,
1557 "Could not update MAC address information");
1558 return -1;
1559 }
1560
1561 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1562 MAC2STR(addr));
1563
1564 return 0;
1565}
1566
1567
1568int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1569{
1570 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1571 !wpa_s->conf->preassoc_mac_addr)
1572 return 0;
1573
1574 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1575}
1576
1577
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001578static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580/**
1581 * wpa_supplicant_associate - Request association
1582 * @wpa_s: Pointer to wpa_supplicant data
1583 * @bss: Scan results for the selected BSS, or %NULL if not available
1584 * @ssid: Configuration data for the selected network
1585 *
1586 * This function is used to request %wpa_supplicant to associate with a BSS.
1587 */
1588void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1589 struct wpa_bss *bss, struct wpa_ssid *ssid)
1590{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001591 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001592 int rand_style;
1593
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001594 wpa_s->own_disconnect_req = 0;
1595
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001596 if (ssid->mac_addr == -1)
1597 rand_style = wpa_s->conf->mac_addr;
1598 else
1599 rand_style = ssid->mac_addr;
1600
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001601 wmm_ac_clear_saved_tspecs(wpa_s);
1602 wpa_s->reassoc_same_bss = 0;
1603
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001604 if (wpa_s->last_ssid == ssid) {
1605 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001606 if (wpa_s->current_bss && wpa_s->current_bss == bss) {
1607 wmm_ac_save_tspecs(wpa_s);
1608 wpa_s->reassoc_same_bss = 1;
1609 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001610 } else if (rand_style > 0) {
1611 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1612 return;
1613 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1614 } else if (wpa_s->mac_addr_changed) {
1615 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1616 wpa_msg(wpa_s, MSG_INFO,
1617 "Could not restore permanent MAC address");
1618 return;
1619 }
1620 wpa_s->mac_addr_changed = 0;
1621 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1622 wpa_msg(wpa_s, MSG_INFO,
1623 "Could not update MAC address information");
1624 return;
1625 }
1626 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1627 }
1628 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629
1630#ifdef CONFIG_IBSS_RSN
1631 ibss_rsn_deinit(wpa_s->ibss_rsn);
1632 wpa_s->ibss_rsn = NULL;
1633#endif /* CONFIG_IBSS_RSN */
1634
1635 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1636 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1637#ifdef CONFIG_AP
1638 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1639 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1640 "mode");
1641 return;
1642 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001643 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1644 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001645 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1646 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001647 return;
1648 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001649 wpa_s->current_bss = bss;
1650#else /* CONFIG_AP */
1651 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1652 "the build");
1653#endif /* CONFIG_AP */
1654 return;
1655 }
1656
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001657 if (ssid->mode == WPAS_MODE_MESH) {
1658#ifdef CONFIG_MESH
1659 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
1660 wpa_msg(wpa_s, MSG_INFO,
1661 "Driver does not support mesh mode");
1662 return;
1663 }
1664 if (bss)
1665 ssid->frequency = bss->freq;
1666 if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
1667 wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
1668 return;
1669 }
1670 wpa_s->current_bss = bss;
1671 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
1672 "ssid=\"%s\" id=%d",
1673 wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
1674 ssid->id);
1675#else /* CONFIG_MESH */
1676 wpa_msg(wpa_s, MSG_ERROR,
1677 "mesh mode support not included in the build");
1678#endif /* CONFIG_MESH */
1679 return;
1680 }
1681
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001682#ifdef CONFIG_TDLS
1683 if (bss)
1684 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1685 bss->ie_len);
1686#endif /* CONFIG_TDLS */
1687
1688 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1689 ssid->mode == IEEE80211_MODE_INFRA) {
1690 sme_authenticate(wpa_s, bss, ssid);
1691 return;
1692 }
1693
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001694 if (wpa_s->connect_work) {
1695 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1696 return;
1697 }
1698
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001699 if (radio_work_pending(wpa_s, "connect")) {
1700 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1701 return;
1702 }
1703
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001704 cwork = os_zalloc(sizeof(*cwork));
1705 if (cwork == NULL)
1706 return;
1707
1708 cwork->bss = bss;
1709 cwork->ssid = ssid;
1710
1711 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1712 wpas_start_assoc_cb, cwork) < 0) {
1713 os_free(cwork);
1714 }
1715}
1716
1717
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001718static int bss_is_ibss(struct wpa_bss *bss)
1719{
1720 return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
1721 IEEE80211_CAP_IBSS;
1722}
1723
1724
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001725void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
1726 const struct wpa_ssid *ssid,
1727 struct hostapd_freq_params *freq)
1728{
1729 enum hostapd_hw_mode hw_mode;
1730 struct hostapd_hw_modes *mode = NULL;
1731 int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
1732 184, 192 };
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001733 int vht80[] = { 36, 52, 100, 116, 132, 149 };
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001734 struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
1735 u8 channel;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001736 int i, chan_idx, ht40 = -1, res, obss_scan = 1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001737 unsigned int j;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001738 struct hostapd_freq_params vht_freq;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001739
1740 freq->freq = ssid->frequency;
1741
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001742 for (j = 0; j < wpa_s->last_scan_res_used; j++) {
1743 struct wpa_bss *bss = wpa_s->last_scan_res[j];
1744
1745 if (ssid->mode != WPAS_MODE_IBSS)
1746 break;
1747
1748 /* Don't adjust control freq in case of fixed_freq */
1749 if (ssid->fixed_freq)
1750 break;
1751
1752 if (!bss_is_ibss(bss))
1753 continue;
1754
1755 if (ssid->ssid_len == bss->ssid_len &&
1756 os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) {
1757 wpa_printf(MSG_DEBUG,
1758 "IBSS already found in scan results, adjust control freq: %d",
1759 bss->freq);
1760 freq->freq = bss->freq;
1761 obss_scan = 0;
1762 break;
1763 }
1764 }
1765
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001766 /* For IBSS check HT_IBSS flag */
1767 if (ssid->mode == WPAS_MODE_IBSS &&
1768 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
1769 return;
1770
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001771 if (wpa_s->group_cipher == WPA_CIPHER_WEP40 ||
1772 wpa_s->group_cipher == WPA_CIPHER_WEP104 ||
1773 wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) {
1774 wpa_printf(MSG_DEBUG,
1775 "IBSS: WEP/TKIP detected, do not try to enable HT");
1776 return;
1777 }
1778
1779 hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001780 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1781 if (wpa_s->hw.modes[i].mode == hw_mode) {
1782 mode = &wpa_s->hw.modes[i];
1783 break;
1784 }
1785 }
1786
1787 if (!mode)
1788 return;
1789
1790 freq->ht_enabled = ht_supported(mode);
1791 if (!freq->ht_enabled)
1792 return;
1793
1794 /* Setup higher BW only for 5 GHz */
1795 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
1796 return;
1797
1798 for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
1799 pri_chan = &mode->channels[chan_idx];
1800 if (pri_chan->chan == channel)
1801 break;
1802 pri_chan = NULL;
1803 }
1804 if (!pri_chan)
1805 return;
1806
1807 /* Check primary channel flags */
1808 if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1809 return;
1810
1811 /* Check/setup HT40+/HT40- */
1812 for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
1813 if (ht40plus[j] == channel) {
1814 ht40 = 1;
1815 break;
1816 }
1817 }
1818
1819 /* Find secondary channel */
1820 for (i = 0; i < mode->num_channels; i++) {
1821 sec_chan = &mode->channels[i];
1822 if (sec_chan->chan == channel + ht40 * 4)
1823 break;
1824 sec_chan = NULL;
1825 }
1826 if (!sec_chan)
1827 return;
1828
1829 /* Check secondary channel flags */
1830 if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1831 return;
1832
1833 freq->channel = pri_chan->chan;
1834
1835 switch (ht40) {
1836 case -1:
1837 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
1838 return;
1839 freq->sec_channel_offset = -1;
1840 break;
1841 case 1:
1842 if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
1843 return;
1844 freq->sec_channel_offset = 1;
1845 break;
1846 default:
1847 break;
1848 }
1849
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001850 if (freq->sec_channel_offset && obss_scan) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001851 struct wpa_scan_results *scan_res;
1852
1853 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
1854 if (scan_res == NULL) {
1855 /* Back to HT20 */
1856 freq->sec_channel_offset = 0;
1857 return;
1858 }
1859
1860 res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
1861 sec_chan->chan);
1862 switch (res) {
1863 case 0:
1864 /* Back to HT20 */
1865 freq->sec_channel_offset = 0;
1866 break;
1867 case 1:
1868 /* Configuration allowed */
1869 break;
1870 case 2:
1871 /* Switch pri/sec channels */
1872 freq->freq = hw_get_freq(mode, sec_chan->chan);
1873 freq->sec_channel_offset = -freq->sec_channel_offset;
1874 freq->channel = sec_chan->chan;
1875 break;
1876 default:
1877 freq->sec_channel_offset = 0;
1878 break;
1879 }
1880
1881 wpa_scan_results_free(scan_res);
1882 }
1883
1884 wpa_printf(MSG_DEBUG,
1885 "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
1886 freq->channel, freq->sec_channel_offset);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001887
1888 /* Not sure if mesh is ready for VHT */
1889 if (ssid->mode != WPAS_MODE_IBSS)
1890 return;
1891
1892 /* For IBSS check VHT_IBSS flag */
1893 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
1894 return;
1895
1896 vht_freq = *freq;
1897
1898 vht_freq.vht_enabled = vht_supported(mode);
1899 if (!vht_freq.vht_enabled)
1900 return;
1901
1902 /* setup center_freq1, bandwidth */
1903 for (j = 0; j < ARRAY_SIZE(vht80); j++) {
1904 if (freq->channel >= vht80[j] &&
1905 freq->channel < vht80[j] + 16)
1906 break;
1907 }
1908
1909 if (j == ARRAY_SIZE(vht80))
1910 return;
1911
1912 for (i = vht80[j]; i < vht80[j] + 16; i += 4) {
1913 struct hostapd_channel_data *chan;
1914
1915 chan = hw_get_channel_chan(mode, i, NULL);
1916 if (!chan)
1917 return;
1918
1919 /* Back to HT configuration if channel not usable */
1920 if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
1921 return;
1922 }
1923
1924 if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
1925 freq->channel, freq->ht_enabled,
1926 vht_freq.vht_enabled,
1927 freq->sec_channel_offset,
1928 VHT_CHANWIDTH_80MHZ,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08001929 vht80[j] + 6, 0, 0) != 0)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001930 return;
1931
1932 *freq = vht_freq;
1933
1934 wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d",
1935 freq->center_freq1, freq->center_freq2, freq->bandwidth);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001936}
1937
1938
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001939static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1940{
1941 struct wpa_connect_work *cwork = work->ctx;
1942 struct wpa_bss *bss = cwork->bss;
1943 struct wpa_ssid *ssid = cwork->ssid;
1944 struct wpa_supplicant *wpa_s = work->wpa_s;
1945 u8 wpa_ie[200];
1946 size_t wpa_ie_len;
1947 int use_crypt, ret, i, bssid_changed;
1948 int algs = WPA_AUTH_ALG_OPEN;
1949 unsigned int cipher_pairwise, cipher_group;
1950 struct wpa_driver_associate_params params;
1951 int wep_keys_set = 0;
1952 int assoc_failed = 0;
1953 struct wpa_ssid *old_ssid;
1954#ifdef CONFIG_HT_OVERRIDES
1955 struct ieee80211_ht_capabilities htcaps;
1956 struct ieee80211_ht_capabilities htcaps_mask;
1957#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001958#ifdef CONFIG_VHT_OVERRIDES
1959 struct ieee80211_vht_capabilities vhtcaps;
1960 struct ieee80211_vht_capabilities vhtcaps_mask;
1961#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001962
1963 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001964 if (work->started) {
1965 wpa_s->connect_work = NULL;
1966
1967 /* cancel possible auth. timeout */
1968 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1969 NULL);
1970 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001971 wpas_connect_work_free(cwork);
1972 return;
1973 }
1974
1975 wpa_s->connect_work = work;
1976
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001977 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) ||
1978 wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001979 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1980 wpas_connect_work_done(wpa_s);
1981 return;
1982 }
1983
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984 os_memset(&params, 0, sizeof(params));
1985 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001986 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001987 if (bss &&
1988 (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001989#ifdef CONFIG_IEEE80211R
1990 const u8 *ie, *md = NULL;
1991#endif /* CONFIG_IEEE80211R */
1992 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1993 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1994 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1995 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1996 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1997 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1998 if (bssid_changed)
1999 wpas_notify_bssid_changed(wpa_s);
2000#ifdef CONFIG_IEEE80211R
2001 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
2002 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
2003 md = ie + 2;
2004 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
2005 if (md) {
2006 /* Prepare for the next transition */
2007 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
2008 }
2009#endif /* CONFIG_IEEE80211R */
2010#ifdef CONFIG_WPS
2011 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
2012 wpa_s->conf->ap_scan == 2 &&
2013 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
2014 /* Use ap_scan==1 style network selection to find the network
2015 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002016 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002017 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002018 wpa_s->reassociate = 1;
2019 wpa_supplicant_req_scan(wpa_s, 0, 0);
2020 return;
2021#endif /* CONFIG_WPS */
2022 } else {
2023 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
2024 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
2025 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2026 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002027 if (!wpa_s->pno)
2028 wpa_supplicant_cancel_sched_scan(wpa_s);
2029
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002030 wpa_supplicant_cancel_scan(wpa_s);
2031
2032 /* Starting new association, so clear the possibly used WPA IE from the
2033 * previous association. */
2034 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2035
2036#ifdef IEEE8021X_EAPOL
2037 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2038 if (ssid->leap) {
2039 if (ssid->non_leap == 0)
2040 algs = WPA_AUTH_ALG_LEAP;
2041 else
2042 algs |= WPA_AUTH_ALG_LEAP;
2043 }
2044 }
2045#endif /* IEEE8021X_EAPOL */
2046 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
2047 if (ssid->auth_alg) {
2048 algs = ssid->auth_alg;
2049 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
2050 "0x%x", algs);
2051 }
2052
2053 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
2054 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002055 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002056 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002057 try_opportunistic = (ssid->proactive_key_caching < 0 ?
2058 wpa_s->conf->okc :
2059 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002060 (ssid->proto & WPA_PROTO_RSN);
2061 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002062 ssid, try_opportunistic) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002063 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002064 wpa_ie_len = sizeof(wpa_ie);
2065 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
2066 wpa_ie, &wpa_ie_len)) {
2067 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2068 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002069 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002070 return;
2071 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002072 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
2073 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
2074 /*
2075 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
2076 * use non-WPA since the scan results did not indicate that the
2077 * AP is using WPA or WPA2.
2078 */
2079 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2080 wpa_ie_len = 0;
2081 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002082 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002083 wpa_ie_len = sizeof(wpa_ie);
2084 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
2085 wpa_ie, &wpa_ie_len)) {
2086 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
2087 "key management and encryption suites (no "
2088 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002089 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002090 return;
2091 }
2092#ifdef CONFIG_WPS
2093 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
2094 struct wpabuf *wps_ie;
2095 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
2096 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
2097 wpa_ie_len = wpabuf_len(wps_ie);
2098 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
2099 } else
2100 wpa_ie_len = 0;
2101 wpabuf_free(wps_ie);
2102 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2103 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
2104 params.wps = WPS_MODE_PRIVACY;
2105 else
2106 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002107 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002108#endif /* CONFIG_WPS */
2109 } else {
2110 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
2111 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002112 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002113 }
2114
2115#ifdef CONFIG_P2P
2116 if (wpa_s->global->p2p) {
2117 u8 *pos;
2118 size_t len;
2119 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002120 pos = wpa_ie + wpa_ie_len;
2121 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002122 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
2123 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002124 if (res >= 0)
2125 wpa_ie_len += res;
2126 }
2127
2128 wpa_s->cross_connect_disallowed = 0;
2129 if (bss) {
2130 struct wpabuf *p2p;
2131 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
2132 if (p2p) {
2133 wpa_s->cross_connect_disallowed =
2134 p2p_get_cross_connect_disallowed(p2p);
2135 wpabuf_free(p2p);
2136 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
2137 "connection",
2138 wpa_s->cross_connect_disallowed ?
2139 "disallows" : "allows");
2140 }
2141 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002142
2143 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002144#endif /* CONFIG_P2P */
2145
Dmitry Shmidt04949592012-07-19 12:16:46 -07002146#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002147 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002148 struct wpabuf *hs20;
2149 hs20 = wpabuf_alloc(20);
2150 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002151 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002152 size_t len;
2153
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002154 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002155 len = sizeof(wpa_ie) - wpa_ie_len;
2156 if (wpabuf_len(hs20) <= len) {
2157 os_memcpy(wpa_ie + wpa_ie_len,
2158 wpabuf_head(hs20), wpabuf_len(hs20));
2159 wpa_ie_len += wpabuf_len(hs20);
2160 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002161 wpabuf_free(hs20);
2162 }
2163 }
2164#endif /* CONFIG_HS20 */
2165
Dmitry Shmidt56052862013-10-04 10:23:25 -07002166 /*
2167 * Workaround: Add Extended Capabilities element only if the AP
2168 * included this element in Beacon/Probe Response frames. Some older
2169 * APs seem to have interoperability issues if this element is
2170 * included, so while the standard may require us to include the
2171 * element in all cases, it is justifiable to skip it to avoid
2172 * interoperability issues.
2173 */
2174 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002175 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07002176 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002177 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
2178 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07002179 if (ext_capab_len > 0) {
2180 u8 *pos = wpa_ie;
2181 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
2182 pos += 2 + pos[1];
2183 os_memmove(pos + ext_capab_len, pos,
2184 wpa_ie_len - (pos - wpa_ie));
2185 wpa_ie_len += ext_capab_len;
2186 os_memcpy(pos, ext_capab, ext_capab_len);
2187 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002188 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002189
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002190 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
2191 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
2192 size_t len;
2193
2194 len = sizeof(wpa_ie) - wpa_ie_len;
2195 if (wpabuf_len(buf) <= len) {
2196 os_memcpy(wpa_ie + wpa_ie_len,
2197 wpabuf_head(buf), wpabuf_len(buf));
2198 wpa_ie_len += wpabuf_len(buf);
2199 }
2200 }
2201
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002202#ifdef CONFIG_FST
2203 if (wpa_s->fst_ies) {
2204 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
2205
2206 if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) {
2207 os_memcpy(wpa_ie + wpa_ie_len,
2208 wpabuf_head(wpa_s->fst_ies), fst_ies_len);
2209 wpa_ie_len += fst_ies_len;
2210 }
2211 }
2212#endif /* CONFIG_FST */
2213
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002214 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
2215 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002216 cipher_pairwise = wpa_s->pairwise_cipher;
2217 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002218 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2219 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2220 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
2221 use_crypt = 0;
2222 if (wpa_set_wep_keys(wpa_s, ssid)) {
2223 use_crypt = 1;
2224 wep_keys_set = 1;
2225 }
2226 }
2227 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
2228 use_crypt = 0;
2229
2230#ifdef IEEE8021X_EAPOL
2231 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
2232 if ((ssid->eapol_flags &
2233 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2234 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
2235 !wep_keys_set) {
2236 use_crypt = 0;
2237 } else {
2238 /* Assume that dynamic WEP-104 keys will be used and
2239 * set cipher suites in order for drivers to expect
2240 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002241 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002242 }
2243 }
2244#endif /* IEEE8021X_EAPOL */
2245
2246 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2247 /* Set the key before (and later after) association */
2248 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2249 }
2250
2251 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2252 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002253 params.ssid = bss->ssid;
2254 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002255 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
2256 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
2257 MACSTR " freq=%u MHz based on scan results "
2258 "(bssid_set=%d)",
2259 MAC2STR(bss->bssid), bss->freq,
2260 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002261 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002262 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002263 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002264 params.bssid_hint = bss->bssid;
2265 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002266 } else {
2267 params.ssid = ssid->ssid;
2268 params.ssid_len = ssid->ssid_len;
2269 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002270
2271 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
2272 wpa_s->conf->ap_scan == 2) {
2273 params.bssid = ssid->bssid;
2274 params.fixed_bssid = 1;
2275 }
2276
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002277 /* Initial frequency for IBSS/mesh */
2278 if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002279 ssid->frequency > 0 && params.freq.freq == 0)
2280 ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002281
2282 if (ssid->mode == WPAS_MODE_IBSS) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002283 params.fixed_freq = ssid->fixed_freq;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08002284 if (ssid->beacon_int)
2285 params.beacon_int = ssid->beacon_int;
2286 else
2287 params.beacon_int = wpa_s->conf->beacon_int;
2288 }
2289
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002290 params.wpa_ie = wpa_ie;
2291 params.wpa_ie_len = wpa_ie_len;
2292 params.pairwise_suite = cipher_pairwise;
2293 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002294 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002295 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296 params.auth_alg = algs;
2297 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002298 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002299 for (i = 0; i < NUM_WEP_KEYS; i++) {
2300 if (ssid->wep_key_len[i])
2301 params.wep_key[i] = ssid->wep_key[i];
2302 params.wep_key_len[i] = ssid->wep_key_len[i];
2303 }
2304 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
2305
2306 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002307 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2308 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002309 params.passphrase = ssid->passphrase;
2310 if (ssid->psk_set)
2311 params.psk = ssid->psk;
2312 }
2313
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002314 if (wpa_s->conf->key_mgmt_offload) {
2315 if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
2316 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002317 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
2318 params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002319 params.req_key_mgmt_offload =
2320 ssid->proactive_key_caching < 0 ?
2321 wpa_s->conf->okc : ssid->proactive_key_caching;
2322 else
2323 params.req_key_mgmt_offload = 1;
2324
2325 if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
2326 params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
2327 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
2328 ssid->psk_set)
2329 params.psk = ssid->psk;
2330 }
2331
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002332 params.drop_unencrypted = use_crypt;
2333
2334#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002335 params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002336 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002337 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2338 struct wpa_ie_data ie;
2339 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
2340 ie.capabilities &
2341 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
2342 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
2343 "MFP: require MFP");
2344 params.mgmt_frame_protection =
2345 MGMT_FRAME_PROTECTION_REQUIRED;
2346 }
2347 }
2348#endif /* CONFIG_IEEE80211W */
2349
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002350 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002351
2352 if (wpa_s->parent->set_sta_uapsd)
2353 params.uapsd = wpa_s->parent->sta_uapsd;
2354 else
2355 params.uapsd = -1;
2356
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002357#ifdef CONFIG_HT_OVERRIDES
2358 os_memset(&htcaps, 0, sizeof(htcaps));
2359 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2360 params.htcaps = (u8 *) &htcaps;
2361 params.htcaps_mask = (u8 *) &htcaps_mask;
2362 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
2363#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002364#ifdef CONFIG_VHT_OVERRIDES
2365 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2366 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2367 params.vhtcaps = &vhtcaps;
2368 params.vhtcaps_mask = &vhtcaps_mask;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002369 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002370#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002371
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002372#ifdef CONFIG_P2P
2373 /*
2374 * If multi-channel concurrency is not supported, check for any
2375 * frequency conflict. In case of any frequency conflict, remove the
2376 * least prioritized connection.
2377 */
2378 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002379 int freq, num;
2380 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002381 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07002382 wpa_printf(MSG_DEBUG,
2383 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002384 freq, params.freq.freq);
2385 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002386 wpa_s, params.freq.freq, ssid) < 0) {
2387 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002388 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08002389 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002390 }
2391 }
2392#endif /* CONFIG_P2P */
2393
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002394 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002395 if (ret < 0) {
2396 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
2397 "failed");
2398 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
2399 /*
2400 * The driver is known to mean what is saying, so we
2401 * can stop right here; the association will not
2402 * succeed.
2403 */
2404 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002405 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002406 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2407 return;
2408 }
2409 /* try to continue anyway; new association will be tried again
2410 * after timeout */
2411 assoc_failed = 1;
2412 }
2413
2414 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2415 /* Set the key after the association just in case association
2416 * cleared the previously configured key. */
2417 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
2418 /* No need to timeout authentication since there is no key
2419 * management. */
2420 wpa_supplicant_cancel_auth_timeout(wpa_s);
2421 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2422#ifdef CONFIG_IBSS_RSN
2423 } else if (ssid->mode == WPAS_MODE_IBSS &&
2424 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2425 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2426 /*
2427 * RSN IBSS authentication is per-STA and we can disable the
2428 * per-BSSID authentication.
2429 */
2430 wpa_supplicant_cancel_auth_timeout(wpa_s);
2431#endif /* CONFIG_IBSS_RSN */
2432 } else {
2433 /* Timeout for IEEE 802.11 authentication and association */
2434 int timeout = 60;
2435
2436 if (assoc_failed) {
2437 /* give IBSS a bit more time */
2438 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2439 } else if (wpa_s->conf->ap_scan == 1) {
2440 /* give IBSS a bit more time */
2441 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2442 }
2443 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2444 }
2445
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002446 if (wep_keys_set &&
2447 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002448 /* Set static WEP keys again */
2449 wpa_set_wep_keys(wpa_s, ssid);
2450 }
2451
2452 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2453 /*
2454 * Do not allow EAP session resumption between different
2455 * network configurations.
2456 */
2457 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2458 }
2459 old_ssid = wpa_s->current_ssid;
2460 wpa_s->current_ssid = ssid;
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07002461 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set)
2462 wpa_s->current_bss = bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002463 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2464 wpa_supplicant_initiate_eapol(wpa_s);
2465 if (old_ssid != wpa_s->current_ssid)
2466 wpas_notify_network_changed(wpa_s);
2467}
2468
2469
2470static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2471 const u8 *addr)
2472{
2473 struct wpa_ssid *old_ssid;
2474
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002475 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002477 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002478 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002479 wpa_sm_set_config(wpa_s->wpa, NULL);
2480 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2481 if (old_ssid != wpa_s->current_ssid)
2482 wpas_notify_network_changed(wpa_s);
2483 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2484}
2485
2486
2487/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2489 * @wpa_s: Pointer to wpa_supplicant data
2490 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2491 *
2492 * This function is used to request %wpa_supplicant to deauthenticate from the
2493 * current AP.
2494 */
2495void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2496 int reason_code)
2497{
2498 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002499 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002500 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002502 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2503 " pending_bssid=" MACSTR " reason=%d state=%s",
2504 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2505 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2506
2507 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002509 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2510 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2511 wpa_s->wpa_state == WPA_ASSOCIATING))
2512 addr = wpa_s->pending_bssid;
2513 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2514 /*
2515 * When using driver-based BSS selection, we may not know the
2516 * BSSID with which we are currently trying to associate. We
2517 * need to notify the driver of this disconnection even in such
2518 * a case, so use the all zeros address here.
2519 */
2520 addr = wpa_s->bssid;
2521 zero_addr = 1;
2522 }
2523
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002524#ifdef CONFIG_TDLS
2525 wpa_tdls_teardown_peers(wpa_s->wpa);
2526#endif /* CONFIG_TDLS */
2527
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002528#ifdef CONFIG_MESH
2529 if (wpa_s->ifmsh) {
2530 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
2531 wpa_s->ifname);
2532 wpa_supplicant_leave_mesh(wpa_s);
2533 }
2534#endif /* CONFIG_MESH */
2535
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002536 if (addr) {
2537 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002538 os_memset(&event, 0, sizeof(event));
2539 event.deauth_info.reason_code = (u16) reason_code;
2540 event.deauth_info.locally_generated = 1;
2541 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002542 if (zero_addr)
2543 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544 }
2545
2546 wpa_supplicant_clear_connection(wpa_s, addr);
2547}
2548
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002549static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2550 struct wpa_ssid *ssid)
2551{
2552 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2553 return;
2554
2555 ssid->disabled = 0;
2556 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2557 wpas_notify_network_enabled_changed(wpa_s, ssid);
2558
2559 /*
2560 * Try to reassociate since there is no current configuration and a new
2561 * network was made available.
2562 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002563 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002564 wpa_s->reassociate = 1;
2565}
2566
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567
2568/**
2569 * wpa_supplicant_enable_network - Mark a configured network as enabled
2570 * @wpa_s: wpa_supplicant structure for a network interface
2571 * @ssid: wpa_ssid structure for a configured network or %NULL
2572 *
2573 * Enables the specified network or all networks if no network specified.
2574 */
2575void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2576 struct wpa_ssid *ssid)
2577{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002579 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2580 wpa_supplicant_enable_one_network(wpa_s, ssid);
2581 } else
2582 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002583
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002584 if (wpa_s->reassociate && !wpa_s->disconnected &&
2585 (!wpa_s->current_ssid ||
2586 wpa_s->wpa_state == WPA_DISCONNECTED ||
2587 wpa_s->wpa_state == WPA_SCANNING)) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002588 if (wpa_s->sched_scanning) {
2589 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2590 "new network to scan filters");
2591 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 }
2593
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002594 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2595 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002596 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002597 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598 }
2599}
2600
2601
2602/**
2603 * wpa_supplicant_disable_network - Mark a configured network as disabled
2604 * @wpa_s: wpa_supplicant structure for a network interface
2605 * @ssid: wpa_ssid structure for a configured network or %NULL
2606 *
2607 * Disables the specified network or all networks if no network specified.
2608 */
2609void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2610 struct wpa_ssid *ssid)
2611{
2612 struct wpa_ssid *other_ssid;
2613 int was_disabled;
2614
2615 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002616 if (wpa_s->sched_scanning)
2617 wpa_supplicant_cancel_sched_scan(wpa_s);
2618
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002619 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2620 other_ssid = other_ssid->next) {
2621 was_disabled = other_ssid->disabled;
2622 if (was_disabled == 2)
2623 continue; /* do not change persistent P2P group
2624 * data */
2625
2626 other_ssid->disabled = 1;
2627
2628 if (was_disabled != other_ssid->disabled)
2629 wpas_notify_network_enabled_changed(
2630 wpa_s, other_ssid);
2631 }
2632 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002633 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002634 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2635 } else if (ssid->disabled != 2) {
2636 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002637 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2639
2640 was_disabled = ssid->disabled;
2641
2642 ssid->disabled = 1;
2643
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002644 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002646 if (wpa_s->sched_scanning) {
2647 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2648 "to remove network from filters");
2649 wpa_supplicant_cancel_sched_scan(wpa_s);
2650 wpa_supplicant_req_scan(wpa_s, 0, 0);
2651 }
2652 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002653 }
2654}
2655
2656
2657/**
2658 * wpa_supplicant_select_network - Attempt association with a network
2659 * @wpa_s: wpa_supplicant structure for a network interface
2660 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2661 */
2662void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2663 struct wpa_ssid *ssid)
2664{
2665
2666 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002667 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002668
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002669 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002670 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2671 wpa_s->own_disconnect_req = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002672 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002673 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002674 disconnected = 1;
2675 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002676
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 if (ssid)
2678 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2679
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 /*
2681 * Mark all other networks disabled or mark all networks enabled if no
2682 * network specified.
2683 */
2684 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2685 other_ssid = other_ssid->next) {
2686 int was_disabled = other_ssid->disabled;
2687 if (was_disabled == 2)
2688 continue; /* do not change persistent P2P group data */
2689
2690 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002691 if (was_disabled && !other_ssid->disabled)
2692 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693
2694 if (was_disabled != other_ssid->disabled)
2695 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2696 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002697
2698 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2699 /* We are already associated with the selected network */
2700 wpa_printf(MSG_DEBUG, "Already associated with the "
2701 "selected network - do nothing");
2702 return;
2703 }
2704
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002705 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002706 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002707 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002708 wpa_s->connect_without_scan =
2709 (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002710
2711 /*
2712 * Don't optimize next scan freqs since a new ESS has been
2713 * selected.
2714 */
2715 os_free(wpa_s->next_scan_freqs);
2716 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002717 } else {
2718 wpa_s->connect_without_scan = NULL;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002719 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002720
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002721 wpa_s->disconnected = 0;
2722 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002723
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002724 if (wpa_s->connect_without_scan ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002725 wpa_supplicant_fast_associate(wpa_s) != 1) {
2726 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002727 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002728 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729
2730 if (ssid)
2731 wpas_notify_network_selected(wpa_s, ssid);
2732}
2733
2734
2735/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002736 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2737 * @wpa_s: wpa_supplicant structure for a network interface
2738 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2739 * @pkcs11_module_path: PKCS #11 module path or NULL
2740 * Returns: 0 on success; -1 on failure
2741 *
2742 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2743 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2744 * module path fails the paths will be reset to the default value (NULL).
2745 */
2746int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2747 const char *pkcs11_engine_path,
2748 const char *pkcs11_module_path)
2749{
2750 char *pkcs11_engine_path_copy = NULL;
2751 char *pkcs11_module_path_copy = NULL;
2752
2753 if (pkcs11_engine_path != NULL) {
2754 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2755 if (pkcs11_engine_path_copy == NULL)
2756 return -1;
2757 }
2758 if (pkcs11_module_path != NULL) {
2759 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002760 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002761 os_free(pkcs11_engine_path_copy);
2762 return -1;
2763 }
2764 }
2765
2766 os_free(wpa_s->conf->pkcs11_engine_path);
2767 os_free(wpa_s->conf->pkcs11_module_path);
2768 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2769 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2770
2771 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2772 eapol_sm_deinit(wpa_s->eapol);
2773 wpa_s->eapol = NULL;
2774 if (wpa_supplicant_init_eapol(wpa_s)) {
2775 /* Error -> Reset paths to the default value (NULL) once. */
2776 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2777 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2778 NULL);
2779
2780 return -1;
2781 }
2782 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2783
2784 return 0;
2785}
2786
2787
2788/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2790 * @wpa_s: wpa_supplicant structure for a network interface
2791 * @ap_scan: AP scan mode
2792 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2793 *
2794 */
2795int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2796{
2797
2798 int old_ap_scan;
2799
2800 if (ap_scan < 0 || ap_scan > 2)
2801 return -1;
2802
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002803 if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
2804 wpa_printf(MSG_INFO,
2805 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
2806 }
2807
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002808#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002809 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2810 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2811 wpa_s->wpa_state < WPA_COMPLETED) {
2812 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2813 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002814 return 0;
2815 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002816#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002817
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002818 old_ap_scan = wpa_s->conf->ap_scan;
2819 wpa_s->conf->ap_scan = ap_scan;
2820
2821 if (old_ap_scan != wpa_s->conf->ap_scan)
2822 wpas_notify_ap_scan_changed(wpa_s);
2823
2824 return 0;
2825}
2826
2827
2828/**
2829 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2830 * @wpa_s: wpa_supplicant structure for a network interface
2831 * @expire_age: Expiration age in seconds
2832 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2833 *
2834 */
2835int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2836 unsigned int bss_expire_age)
2837{
2838 if (bss_expire_age < 10) {
2839 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2840 bss_expire_age);
2841 return -1;
2842 }
2843 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2844 bss_expire_age);
2845 wpa_s->conf->bss_expiration_age = bss_expire_age;
2846
2847 return 0;
2848}
2849
2850
2851/**
2852 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2853 * @wpa_s: wpa_supplicant structure for a network interface
2854 * @expire_count: number of scans after which an unseen BSS is reclaimed
2855 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2856 *
2857 */
2858int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2859 unsigned int bss_expire_count)
2860{
2861 if (bss_expire_count < 1) {
2862 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2863 bss_expire_count);
2864 return -1;
2865 }
2866 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2867 bss_expire_count);
2868 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2869
2870 return 0;
2871}
2872
2873
2874/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002875 * wpa_supplicant_set_scan_interval - Set scan interval
2876 * @wpa_s: wpa_supplicant structure for a network interface
2877 * @scan_interval: scan interval in seconds
2878 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2879 *
2880 */
2881int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2882 int scan_interval)
2883{
2884 if (scan_interval < 0) {
2885 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2886 scan_interval);
2887 return -1;
2888 }
2889 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2890 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002891 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002892
2893 return 0;
2894}
2895
2896
2897/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002898 * wpa_supplicant_set_debug_params - Set global debug params
2899 * @global: wpa_global structure
2900 * @debug_level: debug level
2901 * @debug_timestamp: determines if show timestamp in debug data
2902 * @debug_show_keys: determines if show keys in debug data
2903 * Returns: 0 if succeed or -1 if debug_level has wrong value
2904 */
2905int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2906 int debug_timestamp, int debug_show_keys)
2907{
2908
2909 int old_level, old_timestamp, old_show_keys;
2910
2911 /* check for allowed debuglevels */
2912 if (debug_level != MSG_EXCESSIVE &&
2913 debug_level != MSG_MSGDUMP &&
2914 debug_level != MSG_DEBUG &&
2915 debug_level != MSG_INFO &&
2916 debug_level != MSG_WARNING &&
2917 debug_level != MSG_ERROR)
2918 return -1;
2919
2920 old_level = wpa_debug_level;
2921 old_timestamp = wpa_debug_timestamp;
2922 old_show_keys = wpa_debug_show_keys;
2923
2924 wpa_debug_level = debug_level;
2925 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2926 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2927
2928 if (wpa_debug_level != old_level)
2929 wpas_notify_debug_level_changed(global);
2930 if (wpa_debug_timestamp != old_timestamp)
2931 wpas_notify_debug_timestamp_changed(global);
2932 if (wpa_debug_show_keys != old_show_keys)
2933 wpas_notify_debug_show_keys_changed(global);
2934
2935 return 0;
2936}
2937
2938
2939/**
2940 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2941 * @wpa_s: Pointer to wpa_supplicant data
2942 * Returns: A pointer to the current network structure or %NULL on failure
2943 */
2944struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2945{
2946 struct wpa_ssid *entry;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002947 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002948 int res;
2949 size_t ssid_len;
2950 u8 bssid[ETH_ALEN];
2951 int wired;
2952
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002953 res = wpa_drv_get_ssid(wpa_s, ssid);
2954 if (res < 0) {
2955 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2956 "driver");
2957 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002958 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002959 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002960
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002961 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002962 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2963 "driver");
2964 return NULL;
2965 }
2966
2967 wired = wpa_s->conf->ap_scan == 0 &&
2968 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2969
2970 entry = wpa_s->conf->ssid;
2971 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002972 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002973 ((ssid_len == entry->ssid_len &&
2974 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2975 (!entry->bssid_set ||
2976 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2977 return entry;
2978#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002979 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2981 (entry->ssid == NULL || entry->ssid_len == 0) &&
2982 (!entry->bssid_set ||
2983 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2984 return entry;
2985#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002986
Dmitry Shmidt04949592012-07-19 12:16:46 -07002987 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002988 entry->ssid_len == 0 &&
2989 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2990 return entry;
2991
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002992 entry = entry->next;
2993 }
2994
2995 return NULL;
2996}
2997
2998
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002999static int select_driver(struct wpa_supplicant *wpa_s, int i)
3000{
3001 struct wpa_global *global = wpa_s->global;
3002
3003 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
3004 global->drv_priv[i] = wpa_drivers[i]->global_init();
3005 if (global->drv_priv[i] == NULL) {
3006 wpa_printf(MSG_ERROR, "Failed to initialize driver "
3007 "'%s'", wpa_drivers[i]->name);
3008 return -1;
3009 }
3010 }
3011
3012 wpa_s->driver = wpa_drivers[i];
3013 wpa_s->global_drv_priv = global->drv_priv[i];
3014
3015 return 0;
3016}
3017
3018
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003019static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
3020 const char *name)
3021{
3022 int i;
3023 size_t len;
3024 const char *pos, *driver = name;
3025
3026 if (wpa_s == NULL)
3027 return -1;
3028
3029 if (wpa_drivers[0] == NULL) {
3030 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
3031 "wpa_supplicant");
3032 return -1;
3033 }
3034
3035 if (name == NULL) {
3036 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003037 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003038 }
3039
3040 do {
3041 pos = os_strchr(driver, ',');
3042 if (pos)
3043 len = pos - driver;
3044 else
3045 len = os_strlen(driver);
3046
3047 for (i = 0; wpa_drivers[i]; i++) {
3048 if (os_strlen(wpa_drivers[i]->name) == len &&
3049 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003050 0) {
3051 /* First driver that succeeds wins */
3052 if (select_driver(wpa_s, i) == 0)
3053 return 0;
3054 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003055 }
3056
3057 driver = pos + 1;
3058 } while (pos);
3059
3060 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
3061 return -1;
3062}
3063
3064
3065/**
3066 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
3067 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
3068 * with struct wpa_driver_ops::init()
3069 * @src_addr: Source address of the EAPOL frame
3070 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
3071 * @len: Length of the EAPOL data
3072 *
3073 * This function is called for each received EAPOL frame. Most driver
3074 * interfaces rely on more generic OS mechanism for receiving frames through
3075 * l2_packet, but if such a mechanism is not available, the driver wrapper may
3076 * take care of received EAPOL frames and deliver them to the core supplicant
3077 * code by calling this function.
3078 */
3079void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
3080 const u8 *buf, size_t len)
3081{
3082 struct wpa_supplicant *wpa_s = ctx;
3083
3084 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
3085 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
3086
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003087#ifdef CONFIG_PEERKEY
3088 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
3089 wpa_s->current_ssid->peerkey &&
3090 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
3091 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
3092 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
3093 return;
3094 }
3095#endif /* CONFIG_PEERKEY */
3096
Jouni Malinena05074c2012-12-21 21:35:35 +02003097 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
3098 (wpa_s->last_eapol_matches_bssid &&
3099#ifdef CONFIG_AP
3100 !wpa_s->ap_iface &&
3101#endif /* CONFIG_AP */
3102 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003103 /*
3104 * There is possible race condition between receiving the
3105 * association event and the EAPOL frame since they are coming
3106 * through different paths from the driver. In order to avoid
3107 * issues in trying to process the EAPOL frame before receiving
3108 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02003109 * the association event is received. This may also be needed in
3110 * driver-based roaming case, so also use src_addr != BSSID as a
3111 * trigger if we have previously confirmed that the
3112 * Authenticator uses BSSID as the src_addr (which is not the
3113 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003114 */
3115 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02003116 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
3117 wpa_supplicant_state_txt(wpa_s->wpa_state),
3118 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003119 wpabuf_free(wpa_s->pending_eapol_rx);
3120 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
3121 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003122 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003123 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
3124 ETH_ALEN);
3125 }
3126 return;
3127 }
3128
Jouni Malinena05074c2012-12-21 21:35:35 +02003129 wpa_s->last_eapol_matches_bssid =
3130 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
3131
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003132#ifdef CONFIG_AP
3133 if (wpa_s->ap_iface) {
3134 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
3135 return;
3136 }
3137#endif /* CONFIG_AP */
3138
3139 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
3140 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
3141 "no key management is configured");
3142 return;
3143 }
3144
3145 if (wpa_s->eapol_received == 0 &&
3146 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
3147 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
3148 wpa_s->wpa_state != WPA_COMPLETED) &&
3149 (wpa_s->current_ssid == NULL ||
3150 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
3151 /* Timeout for completing IEEE 802.1X and WPA authentication */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003152 int timeout = 10;
3153
3154 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
3155 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
3156 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) {
3157 /* Use longer timeout for IEEE 802.1X/EAP */
3158 timeout = 70;
3159 }
3160
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003161#ifdef CONFIG_WPS
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003162 if (wpa_s->current_ssid && wpa_s->current_bss &&
3163 (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
3164 eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
3165 /*
3166 * Use shorter timeout if going through WPS AP iteration
3167 * for PIN config method with an AP that does not
3168 * advertise Selected Registrar.
3169 */
3170 struct wpabuf *wps_ie;
3171
3172 wps_ie = wpa_bss_get_vendor_ie_multi(
3173 wpa_s->current_bss, WPS_IE_VENDOR_TYPE);
3174 if (wps_ie &&
3175 !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1))
3176 timeout = 10;
3177 wpabuf_free(wps_ie);
3178 }
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003179#endif /* CONFIG_WPS */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003180
3181 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003182 }
3183 wpa_s->eapol_received++;
3184
3185 if (wpa_s->countermeasures) {
3186 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
3187 "EAPOL packet");
3188 return;
3189 }
3190
3191#ifdef CONFIG_IBSS_RSN
3192 if (wpa_s->current_ssid &&
3193 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
3194 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
3195 return;
3196 }
3197#endif /* CONFIG_IBSS_RSN */
3198
3199 /* Source address of the incoming EAPOL frame could be compared to the
3200 * current BSSID. However, it is possible that a centralized
3201 * Authenticator could be using another MAC address than the BSSID of
3202 * an AP, so just allow any address to be used for now. The replies are
3203 * still sent to the current BSSID (if available), though. */
3204
3205 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
3206 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
3207 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
3208 return;
3209 wpa_drv_poll(wpa_s);
3210 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
3211 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
3212 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
3213 /*
3214 * Set portValid = TRUE here since we are going to skip 4-way
3215 * handshake processing which would normally set portValid. We
3216 * need this to allow the EAPOL state machines to be completed
3217 * without going through EAPOL-Key handshake.
3218 */
3219 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
3220 }
3221}
3222
3223
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003224int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003225{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003226 if ((!wpa_s->p2p_mgmt ||
3227 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3228 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003229 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003230 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
3231 wpa_drv_get_mac_addr(wpa_s),
3232 ETH_P_EAPOL,
3233 wpa_supplicant_rx_eapol, wpa_s, 0);
3234 if (wpa_s->l2 == NULL)
3235 return -1;
3236 } else {
3237 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
3238 if (addr)
3239 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
3240 }
3241
3242 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
3243 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
3244 return -1;
3245 }
3246
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003247 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3248
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003249 return 0;
3250}
3251
3252
Dmitry Shmidt04949592012-07-19 12:16:46 -07003253static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
3254 const u8 *buf, size_t len)
3255{
3256 struct wpa_supplicant *wpa_s = ctx;
3257 const struct l2_ethhdr *eth;
3258
3259 if (len < sizeof(*eth))
3260 return;
3261 eth = (const struct l2_ethhdr *) buf;
3262
3263 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
3264 !(eth->h_dest[0] & 0x01)) {
3265 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3266 " (bridge - not for this interface - ignore)",
3267 MAC2STR(src_addr), MAC2STR(eth->h_dest));
3268 return;
3269 }
3270
3271 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
3272 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
3273 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
3274 len - sizeof(*eth));
3275}
3276
3277
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003278/**
3279 * wpa_supplicant_driver_init - Initialize driver interface parameters
3280 * @wpa_s: Pointer to wpa_supplicant data
3281 * Returns: 0 on success, -1 on failure
3282 *
3283 * This function is called to initialize driver interface parameters.
3284 * wpa_drv_init() must have been called before this function to initialize the
3285 * driver interface.
3286 */
3287int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
3288{
3289 static int interface_count = 0;
3290
3291 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
3292 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003293
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003294 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
3295 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003296 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003297 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
3298
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003299 if (wpa_s->bridge_ifname[0]) {
3300 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
3301 "interface '%s'", wpa_s->bridge_ifname);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003302 wpa_s->l2_br = l2_packet_init_bridge(
3303 wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr,
3304 ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003305 if (wpa_s->l2_br == NULL) {
3306 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
3307 "connection for the bridge interface '%s'",
3308 wpa_s->bridge_ifname);
3309 return -1;
3310 }
3311 }
3312
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003313 if (wpa_s->conf->ap_scan == 2 &&
3314 os_strcmp(wpa_s->driver->name, "nl80211") == 0) {
3315 wpa_printf(MSG_INFO,
3316 "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures");
3317 }
3318
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003319 wpa_clear_keys(wpa_s, NULL);
3320
3321 /* Make sure that TKIP countermeasures are not left enabled (could
3322 * happen if wpa_supplicant is killed during countermeasures. */
3323 wpa_drv_set_countermeasures(wpa_s, 0);
3324
3325 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
3326 wpa_drv_flush_pmkid(wpa_s);
3327
3328 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003329 wpa_s->prev_scan_wildcard = 0;
3330
Dmitry Shmidt04949592012-07-19 12:16:46 -07003331 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08003332 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
3333 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3334 interface_count = 0;
3335 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003336#ifndef ANDROID
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003337 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07003338 wpa_supplicant_delayed_sched_scan(wpa_s,
3339 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003340 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07003341 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003342 100000);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003343#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003344 interface_count++;
3345 } else
3346 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
3347
3348 return 0;
3349}
3350
3351
3352static int wpa_supplicant_daemon(const char *pid_file)
3353{
3354 wpa_printf(MSG_DEBUG, "Daemonize..");
3355 return os_daemonize(pid_file);
3356}
3357
3358
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003359static struct wpa_supplicant *
3360wpa_supplicant_alloc(struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003361{
3362 struct wpa_supplicant *wpa_s;
3363
3364 wpa_s = os_zalloc(sizeof(*wpa_s));
3365 if (wpa_s == NULL)
3366 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003367 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003368 wpa_s->scan_interval = 5;
3369 wpa_s->new_connection = 1;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08003370 wpa_s->parent = parent ? parent : wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003371 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003372
3373 return wpa_s;
3374}
3375
3376
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003377#ifdef CONFIG_HT_OVERRIDES
3378
3379static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
3380 struct ieee80211_ht_capabilities *htcaps,
3381 struct ieee80211_ht_capabilities *htcaps_mask,
3382 const char *ht_mcs)
3383{
3384 /* parse ht_mcs into hex array */
3385 int i;
3386 const char *tmp = ht_mcs;
3387 char *end = NULL;
3388
3389 /* If ht_mcs is null, do not set anything */
3390 if (!ht_mcs)
3391 return 0;
3392
3393 /* This is what we are setting in the kernel */
3394 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
3395
3396 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
3397
3398 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3399 errno = 0;
3400 long v = strtol(tmp, &end, 16);
3401 if (errno == 0) {
3402 wpa_msg(wpa_s, MSG_DEBUG,
3403 "htcap value[%i]: %ld end: %p tmp: %p",
3404 i, v, end, tmp);
3405 if (end == tmp)
3406 break;
3407
3408 htcaps->supported_mcs_set[i] = v;
3409 tmp = end;
3410 } else {
3411 wpa_msg(wpa_s, MSG_ERROR,
3412 "Failed to parse ht-mcs: %s, error: %s\n",
3413 ht_mcs, strerror(errno));
3414 return -1;
3415 }
3416 }
3417
3418 /*
3419 * If we were able to parse any values, then set mask for the MCS set.
3420 */
3421 if (i) {
3422 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
3423 IEEE80211_HT_MCS_MASK_LEN - 1);
3424 /* skip the 3 reserved bits */
3425 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
3426 0x1f;
3427 }
3428
3429 return 0;
3430}
3431
3432
3433static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
3434 struct ieee80211_ht_capabilities *htcaps,
3435 struct ieee80211_ht_capabilities *htcaps_mask,
3436 int disabled)
3437{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003438 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003439
3440 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
3441
3442 if (disabled == -1)
3443 return 0;
3444
3445 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
3446 htcaps_mask->ht_capabilities_info |= msk;
3447 if (disabled)
3448 htcaps->ht_capabilities_info &= msk;
3449 else
3450 htcaps->ht_capabilities_info |= msk;
3451
3452 return 0;
3453}
3454
3455
3456static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
3457 struct ieee80211_ht_capabilities *htcaps,
3458 struct ieee80211_ht_capabilities *htcaps_mask,
3459 int factor)
3460{
3461 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
3462
3463 if (factor == -1)
3464 return 0;
3465
3466 if (factor < 0 || factor > 3) {
3467 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
3468 "Must be 0-3 or -1", factor);
3469 return -EINVAL;
3470 }
3471
3472 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
3473 htcaps->a_mpdu_params &= ~0x3;
3474 htcaps->a_mpdu_params |= factor & 0x3;
3475
3476 return 0;
3477}
3478
3479
3480static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
3481 struct ieee80211_ht_capabilities *htcaps,
3482 struct ieee80211_ht_capabilities *htcaps_mask,
3483 int density)
3484{
3485 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3486
3487 if (density == -1)
3488 return 0;
3489
3490 if (density < 0 || density > 7) {
3491 wpa_msg(wpa_s, MSG_ERROR,
3492 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3493 density);
3494 return -EINVAL;
3495 }
3496
3497 htcaps_mask->a_mpdu_params |= 0x1C;
3498 htcaps->a_mpdu_params &= ~(0x1C);
3499 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3500
3501 return 0;
3502}
3503
3504
3505static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3506 struct ieee80211_ht_capabilities *htcaps,
3507 struct ieee80211_ht_capabilities *htcaps_mask,
3508 int disabled)
3509{
3510 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003511 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3512 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003513
3514 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3515
3516 if (disabled)
3517 htcaps->ht_capabilities_info &= ~msk;
3518 else
3519 htcaps->ht_capabilities_info |= msk;
3520
3521 htcaps_mask->ht_capabilities_info |= msk;
3522
3523 return 0;
3524}
3525
3526
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003527static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3528 struct ieee80211_ht_capabilities *htcaps,
3529 struct ieee80211_ht_capabilities *htcaps_mask,
3530 int disabled)
3531{
3532 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003533 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3534 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003535
3536 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3537
3538 if (disabled)
3539 htcaps->ht_capabilities_info &= ~msk;
3540 else
3541 htcaps->ht_capabilities_info |= msk;
3542
3543 htcaps_mask->ht_capabilities_info |= msk;
3544
3545 return 0;
3546}
3547
3548
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003549static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3550 struct ieee80211_ht_capabilities *htcaps,
3551 struct ieee80211_ht_capabilities *htcaps_mask,
3552 int disabled)
3553{
3554 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003555 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003556
3557 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3558
3559 if (disabled)
3560 htcaps->ht_capabilities_info &= ~msk;
3561 else
3562 htcaps->ht_capabilities_info |= msk;
3563
3564 htcaps_mask->ht_capabilities_info |= msk;
3565
3566 return 0;
3567}
3568
3569
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003570void wpa_supplicant_apply_ht_overrides(
3571 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3572 struct wpa_driver_associate_params *params)
3573{
3574 struct ieee80211_ht_capabilities *htcaps;
3575 struct ieee80211_ht_capabilities *htcaps_mask;
3576
3577 if (!ssid)
3578 return;
3579
3580 params->disable_ht = ssid->disable_ht;
3581 if (!params->htcaps || !params->htcaps_mask)
3582 return;
3583
3584 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3585 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3586 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3587 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3588 ssid->disable_max_amsdu);
3589 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3590 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3591 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003592 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003593 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003594
3595 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003596 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003597 htcaps->ht_capabilities_info |= bit;
3598 htcaps_mask->ht_capabilities_info |= bit;
3599 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003600}
3601
3602#endif /* CONFIG_HT_OVERRIDES */
3603
3604
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003605#ifdef CONFIG_VHT_OVERRIDES
3606void wpa_supplicant_apply_vht_overrides(
3607 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3608 struct wpa_driver_associate_params *params)
3609{
3610 struct ieee80211_vht_capabilities *vhtcaps;
3611 struct ieee80211_vht_capabilities *vhtcaps_mask;
3612
3613 if (!ssid)
3614 return;
3615
3616 params->disable_vht = ssid->disable_vht;
3617
3618 vhtcaps = (void *) params->vhtcaps;
3619 vhtcaps_mask = (void *) params->vhtcaps_mask;
3620
3621 if (!vhtcaps || !vhtcaps_mask)
3622 return;
3623
3624 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3625 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3626
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003627#ifdef CONFIG_HT_OVERRIDES
3628 /* if max ampdu is <= 3, we have to make the HT cap the same */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003629 if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) {
3630 int max_ampdu;
3631
3632 max_ampdu = (ssid->vht_capa &
3633 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
3634 VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003635
3636 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3637 wpa_set_ampdu_factor(wpa_s,
3638 (void *) params->htcaps,
3639 (void *) params->htcaps_mask,
3640 max_ampdu);
3641 }
3642#endif /* CONFIG_HT_OVERRIDES */
3643
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003644#define OVERRIDE_MCS(i) \
3645 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3646 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3647 3 << 2 * (i - 1); \
3648 vhtcaps->vht_supported_mcs_set.tx_map |= \
3649 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3650 } \
3651 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3652 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3653 3 << 2 * (i - 1); \
3654 vhtcaps->vht_supported_mcs_set.rx_map |= \
3655 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3656 }
3657
3658 OVERRIDE_MCS(1);
3659 OVERRIDE_MCS(2);
3660 OVERRIDE_MCS(3);
3661 OVERRIDE_MCS(4);
3662 OVERRIDE_MCS(5);
3663 OVERRIDE_MCS(6);
3664 OVERRIDE_MCS(7);
3665 OVERRIDE_MCS(8);
3666}
3667#endif /* CONFIG_VHT_OVERRIDES */
3668
3669
Dmitry Shmidt04949592012-07-19 12:16:46 -07003670static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3671{
3672#ifdef PCSC_FUNCS
3673 size_t len;
3674
3675 if (!wpa_s->conf->pcsc_reader)
3676 return 0;
3677
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003678 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003679 if (!wpa_s->scard)
3680 return 1;
3681
3682 if (wpa_s->conf->pcsc_pin &&
3683 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3684 scard_deinit(wpa_s->scard);
3685 wpa_s->scard = NULL;
3686 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3687 return -1;
3688 }
3689
3690 len = sizeof(wpa_s->imsi) - 1;
3691 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3692 scard_deinit(wpa_s->scard);
3693 wpa_s->scard = NULL;
3694 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3695 return -1;
3696 }
3697 wpa_s->imsi[len] = '\0';
3698
3699 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3700
3701 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3702 wpa_s->imsi, wpa_s->mnc_len);
3703
3704 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3705 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3706#endif /* PCSC_FUNCS */
3707
3708 return 0;
3709}
3710
3711
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003712int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3713{
3714 char *val, *pos;
3715
3716 ext_password_deinit(wpa_s->ext_pw);
3717 wpa_s->ext_pw = NULL;
3718 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3719
3720 if (!wpa_s->conf->ext_password_backend)
3721 return 0;
3722
3723 val = os_strdup(wpa_s->conf->ext_password_backend);
3724 if (val == NULL)
3725 return -1;
3726 pos = os_strchr(val, ':');
3727 if (pos)
3728 *pos++ = '\0';
3729
3730 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3731
3732 wpa_s->ext_pw = ext_password_init(val, pos);
3733 os_free(val);
3734 if (wpa_s->ext_pw == NULL) {
3735 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3736 return -1;
3737 }
3738 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3739
3740 return 0;
3741}
3742
3743
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003744#ifdef CONFIG_FST
3745
3746static const u8 * wpas_fst_get_bssid_cb(void *ctx)
3747{
3748 struct wpa_supplicant *wpa_s = ctx;
3749
3750 return (is_zero_ether_addr(wpa_s->bssid) ||
3751 wpa_s->wpa_state != WPA_COMPLETED) ? NULL : wpa_s->bssid;
3752}
3753
3754
3755static void wpas_fst_get_channel_info_cb(void *ctx,
3756 enum hostapd_hw_mode *hw_mode,
3757 u8 *channel)
3758{
3759 struct wpa_supplicant *wpa_s = ctx;
3760
3761 if (wpa_s->current_bss) {
3762 *hw_mode = ieee80211_freq_to_chan(wpa_s->current_bss->freq,
3763 channel);
3764 } else if (wpa_s->hw.num_modes) {
3765 *hw_mode = wpa_s->hw.modes[0].mode;
3766 } else {
3767 WPA_ASSERT(0);
3768 *hw_mode = 0;
3769 }
3770}
3771
3772
3773static int wpas_fst_get_hw_modes(void *ctx, struct hostapd_hw_modes **modes)
3774{
3775 struct wpa_supplicant *wpa_s = ctx;
3776
3777 *modes = wpa_s->hw.modes;
3778 return wpa_s->hw.num_modes;
3779}
3780
3781
3782static void wpas_fst_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
3783{
3784 struct wpa_supplicant *wpa_s = ctx;
3785
3786 wpa_hexdump_buf(MSG_DEBUG, "FST: Set IEs", fst_ies);
3787 wpa_s->fst_ies = fst_ies;
3788}
3789
3790
3791static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data)
3792{
3793 struct wpa_supplicant *wpa_s = ctx;
3794
3795 WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
3796 return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3797 wpa_s->own_addr, wpa_s->bssid,
3798 wpabuf_head(data), wpabuf_len(data),
3799 0);
3800}
3801
3802
3803static const struct wpabuf * wpas_fst_get_mb_ie_cb(void *ctx, const u8 *addr)
3804{
3805 struct wpa_supplicant *wpa_s = ctx;
3806
3807 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
3808 return wpa_s->received_mb_ies;
3809}
3810
3811
3812static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr,
3813 const u8 *buf, size_t size)
3814{
3815 struct wpa_supplicant *wpa_s = ctx;
3816 struct mb_ies_info info;
3817
3818 WPA_ASSERT(os_memcmp(wpa_s->bssid, addr, ETH_ALEN) == 0);
3819
3820 if (!mb_ies_info_by_ies(&info, buf, size)) {
3821 wpabuf_free(wpa_s->received_mb_ies);
3822 wpa_s->received_mb_ies = mb_ies_by_info(&info);
3823 }
3824}
3825
3826
3827const u8 * wpas_fst_get_peer_first(void *ctx, struct fst_get_peer_ctx **get_ctx,
3828 Boolean mb_only)
3829{
3830 struct wpa_supplicant *wpa_s = ctx;
3831
3832 *get_ctx = NULL;
3833 if (!is_zero_ether_addr(wpa_s->bssid))
3834 return (wpa_s->received_mb_ies || !mb_only) ?
3835 wpa_s->bssid : NULL;
3836 return NULL;
3837}
3838
3839
3840const u8 * wpas_fst_get_peer_next(void *ctx, struct fst_get_peer_ctx **get_ctx,
3841 Boolean mb_only)
3842{
3843 return NULL;
3844}
3845
3846void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s,
3847 struct fst_wpa_obj *iface_obj)
3848{
3849 iface_obj->ctx = wpa_s;
3850 iface_obj->get_bssid = wpas_fst_get_bssid_cb;
3851 iface_obj->get_channel_info = wpas_fst_get_channel_info_cb;
3852 iface_obj->get_hw_modes = wpas_fst_get_hw_modes;
3853 iface_obj->set_ies = wpas_fst_set_ies_cb;
3854 iface_obj->send_action = wpas_fst_send_action_cb;
3855 iface_obj->get_mb_ie = wpas_fst_get_mb_ie_cb;
3856 iface_obj->update_mb_ie = wpas_fst_update_mb_ie_cb;
3857 iface_obj->get_peer_first = wpas_fst_get_peer_first;
3858 iface_obj->get_peer_next = wpas_fst_get_peer_next;
3859}
3860#endif /* CONFIG_FST */
3861
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003862static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003863 const struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003864{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003865 struct wowlan_triggers *triggers;
3866 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003867
3868 if (!wpa_s->conf->wowlan_triggers)
3869 return 0;
3870
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003871 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3872 if (triggers) {
3873 ret = wpa_drv_wowlan(wpa_s, triggers);
3874 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003875 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003876 return ret;
3877}
3878
3879
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003880static enum wpa_radio_work_band wpas_freq_to_band(int freq)
3881{
3882 if (freq < 3000)
3883 return BAND_2_4_GHZ;
3884 if (freq > 50000)
3885 return BAND_60_GHZ;
3886 return BAND_5_GHZ;
3887}
3888
3889
3890static unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s,
3891 const int *freqs)
3892{
3893 int i;
3894 unsigned int band = 0;
3895
3896 if (freqs) {
3897 /* freqs are specified for the radio work */
3898 for (i = 0; freqs[i]; i++)
3899 band |= wpas_freq_to_band(freqs[i]);
3900 } else {
3901 /*
3902 * freqs are not specified, implies all
3903 * the supported freqs by HW
3904 */
3905 for (i = 0; i < wpa_s->hw.num_modes; i++) {
3906 if (wpa_s->hw.modes[i].num_channels != 0) {
3907 if (wpa_s->hw.modes[i].mode ==
3908 HOSTAPD_MODE_IEEE80211B ||
3909 wpa_s->hw.modes[i].mode ==
3910 HOSTAPD_MODE_IEEE80211G)
3911 band |= BAND_2_4_GHZ;
3912 else if (wpa_s->hw.modes[i].mode ==
3913 HOSTAPD_MODE_IEEE80211A)
3914 band |= BAND_5_GHZ;
3915 else if (wpa_s->hw.modes[i].mode ==
3916 HOSTAPD_MODE_IEEE80211AD)
3917 band |= BAND_60_GHZ;
3918 else if (wpa_s->hw.modes[i].mode ==
3919 HOSTAPD_MODE_IEEE80211ANY)
3920 band = BAND_2_4_GHZ | BAND_5_GHZ |
3921 BAND_60_GHZ;
3922 }
3923 }
3924 }
3925
3926 return band;
3927}
3928
3929
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003930static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3931 const char *rn)
3932{
3933 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3934 struct wpa_radio *radio;
3935
3936 while (rn && iface) {
3937 radio = iface->radio;
3938 if (radio && os_strcmp(rn, radio->name) == 0) {
3939 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3940 wpa_s->ifname, rn);
3941 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3942 return radio;
3943 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003944
3945 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003946 }
3947
3948 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3949 wpa_s->ifname, rn ? rn : "N/A");
3950 radio = os_zalloc(sizeof(*radio));
3951 if (radio == NULL)
3952 return NULL;
3953
3954 if (rn)
3955 os_strlcpy(radio->name, rn, sizeof(radio->name));
3956 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003957 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003958 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3959
3960 return radio;
3961}
3962
3963
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003964static void radio_work_free(struct wpa_radio_work *work)
3965{
3966 if (work->wpa_s->scan_work == work) {
3967 /* This should not really happen. */
3968 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3969 work->type, work, work->started);
3970 work->wpa_s->scan_work = NULL;
3971 }
3972
3973#ifdef CONFIG_P2P
3974 if (work->wpa_s->p2p_scan_work == work) {
3975 /* This should not really happen. */
3976 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3977 work->type, work, work->started);
3978 work->wpa_s->p2p_scan_work = NULL;
3979 }
3980#endif /* CONFIG_P2P */
3981
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003982 if (work->started) {
3983 work->wpa_s->radio->num_active_works--;
3984 wpa_dbg(work->wpa_s, MSG_DEBUG,
3985 "radio_work_free('%s'@%p: num_active_works --> %u",
3986 work->type, work,
3987 work->wpa_s->radio->num_active_works);
3988 }
3989
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003990 dl_list_del(&work->list);
3991 os_free(work);
3992}
3993
3994
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003995static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
3996{
3997 struct wpa_radio_work *active_work = NULL;
3998 struct wpa_radio_work *tmp;
3999
4000 /* Get the active work to know the type and band. */
4001 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4002 if (tmp->started) {
4003 active_work = tmp;
4004 break;
4005 }
4006 }
4007
4008 if (!active_work) {
4009 /* No active work, start one */
4010 radio->num_active_works = 0;
4011 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
4012 list) {
4013 if (os_strcmp(tmp->type, "scan") == 0 &&
4014 radio->external_scan_running &&
4015 (((struct wpa_driver_scan_params *)
4016 tmp->ctx)->only_new_results ||
4017 tmp->wpa_s->clear_driver_scan_cache))
4018 continue;
4019 return tmp;
4020 }
4021 return NULL;
4022 }
4023
4024 if (os_strcmp(active_work->type, "sme-connect") == 0 ||
4025 os_strcmp(active_work->type, "connect") == 0) {
4026 /*
4027 * If the active work is either connect or sme-connect,
4028 * do not parallelize them with other radio works.
4029 */
4030 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4031 "Do not parallelize radio work with %s",
4032 active_work->type);
4033 return NULL;
4034 }
4035
4036 dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
4037 if (tmp->started)
4038 continue;
4039
4040 /*
4041 * If connect or sme-connect are enqueued, parallelize only
4042 * those operations ahead of them in the queue.
4043 */
4044 if (os_strcmp(tmp->type, "connect") == 0 ||
4045 os_strcmp(tmp->type, "sme-connect") == 0)
4046 break;
4047
4048 /*
4049 * Check that the radio works are distinct and
4050 * on different bands.
4051 */
4052 if (os_strcmp(active_work->type, tmp->type) != 0 &&
4053 (active_work->bands != tmp->bands)) {
4054 /*
4055 * If a scan has to be scheduled through nl80211 scan
4056 * interface and if an external scan is already running,
4057 * do not schedule the scan since it is likely to get
4058 * rejected by kernel.
4059 */
4060 if (os_strcmp(tmp->type, "scan") == 0 &&
4061 radio->external_scan_running &&
4062 (((struct wpa_driver_scan_params *)
4063 tmp->ctx)->only_new_results ||
4064 tmp->wpa_s->clear_driver_scan_cache))
4065 continue;
4066
4067 wpa_dbg(active_work->wpa_s, MSG_DEBUG,
4068 "active_work:%s new_work:%s",
4069 active_work->type, tmp->type);
4070 return tmp;
4071 }
4072 }
4073
4074 /* Did not find a radio work to schedule in parallel. */
4075 return NULL;
4076}
4077
4078
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004079static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
4080{
4081 struct wpa_radio *radio = eloop_ctx;
4082 struct wpa_radio_work *work;
4083 struct os_reltime now, diff;
4084 struct wpa_supplicant *wpa_s;
4085
4086 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004087 if (work == NULL) {
4088 radio->num_active_works = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004089 return;
4090 }
4091
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004092 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
4093 radio_list);
4094
4095 if (!(wpa_s &&
4096 wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
4097 if (work->started)
4098 return; /* already started and still in progress */
4099
4100 if (wpa_s && wpa_s->radio->external_scan_running) {
4101 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
4102 return;
4103 }
4104 } else {
4105 work = NULL;
4106 if (radio->num_active_works < MAX_ACTIVE_WORKS) {
4107 /* get the work to schedule next */
4108 work = radio_work_get_next_work(radio);
4109 }
4110 if (!work)
4111 return;
4112 }
4113
4114 wpa_s = work->wpa_s;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004115 os_get_reltime(&now);
4116 os_reltime_sub(&now, &work->time, &diff);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004117 wpa_dbg(wpa_s, MSG_DEBUG,
4118 "Starting radio work '%s'@%p after %ld.%06ld second wait",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004119 work->type, work, diff.sec, diff.usec);
4120 work->started = 1;
4121 work->time = now;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004122 radio->num_active_works++;
4123
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004124 work->cb(work, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004125
4126 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
4127 radio->num_active_works < MAX_ACTIVE_WORKS)
4128 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004129}
4130
4131
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004132/*
4133 * This function removes both started and pending radio works running on
4134 * the provided interface's radio.
4135 * Prior to the removal of the radio work, its callback (cb) is called with
4136 * deinit set to be 1. Each work's callback is responsible for clearing its
4137 * internal data and restoring to a correct state.
4138 * @wpa_s: wpa_supplicant data
4139 * @type: type of works to be removed
4140 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
4141 * this interface's works.
4142 */
4143void radio_remove_works(struct wpa_supplicant *wpa_s,
4144 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004145{
4146 struct wpa_radio_work *work, *tmp;
4147 struct wpa_radio *radio = wpa_s->radio;
4148
4149 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
4150 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004151 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004152 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004153
4154 /* skip other ifaces' works */
4155 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004156 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004157
4158 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
4159 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004160 work->cb(work, 1);
4161 radio_work_free(work);
4162 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004163
4164 /* in case we removed the started work */
4165 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004166}
4167
4168
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004169static void radio_remove_interface(struct wpa_supplicant *wpa_s)
4170{
4171 struct wpa_radio *radio = wpa_s->radio;
4172
4173 if (!radio)
4174 return;
4175
4176 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
4177 wpa_s->ifname, radio->name);
4178 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004179 radio_remove_works(wpa_s, NULL, 0);
4180 wpa_s->radio = NULL;
4181 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004182 return; /* Interfaces remain for this radio */
4183
4184 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004185 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004186 os_free(radio);
4187}
4188
4189
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004190void radio_work_check_next(struct wpa_supplicant *wpa_s)
4191{
4192 struct wpa_radio *radio = wpa_s->radio;
4193
4194 if (dl_list_empty(&radio->work))
4195 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004196 if (wpa_s->ext_work_in_progress) {
4197 wpa_printf(MSG_DEBUG,
4198 "External radio work in progress - delay start of pending item");
4199 return;
4200 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004201 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
4202 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
4203}
4204
4205
4206/**
4207 * radio_add_work - Add a radio work item
4208 * @wpa_s: Pointer to wpa_supplicant data
4209 * @freq: Frequency of the offchannel operation in MHz or 0
4210 * @type: Unique identifier for each type of work
4211 * @next: Force as the next work to be executed
4212 * @cb: Callback function for indicating when radio is available
4213 * @ctx: Context pointer for the work (work->ctx in cb())
4214 * Returns: 0 on success, -1 on failure
4215 *
4216 * This function is used to request time for an operation that requires
4217 * exclusive radio control. Once the radio is available, the registered callback
4218 * function will be called. radio_work_done() must be called once the exclusive
4219 * radio operation has been completed, so that the radio is freed for other
4220 * operations. The special case of deinit=1 is used to free the context data
4221 * during interface removal. That does not allow the callback function to start
4222 * the radio operation, i.e., it must free any resources allocated for the radio
4223 * work and return.
4224 *
4225 * The @freq parameter can be used to indicate a single channel on which the
4226 * offchannel operation will occur. This may allow multiple radio work
4227 * operations to be performed in parallel if they apply for the same channel.
4228 * Setting this to 0 indicates that the work item may use multiple channels or
4229 * requires exclusive control of the radio.
4230 */
4231int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
4232 const char *type, int next,
4233 void (*cb)(struct wpa_radio_work *work, int deinit),
4234 void *ctx)
4235{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004236 struct wpa_radio *radio = wpa_s->radio;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004237 struct wpa_radio_work *work;
4238 int was_empty;
4239
4240 work = os_zalloc(sizeof(*work));
4241 if (work == NULL)
4242 return -1;
4243 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
4244 os_get_reltime(&work->time);
4245 work->freq = freq;
4246 work->type = type;
4247 work->wpa_s = wpa_s;
4248 work->cb = cb;
4249 work->ctx = ctx;
4250
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004251 if (freq)
4252 work->bands = wpas_freq_to_band(freq);
4253 else if (os_strcmp(type, "scan") == 0 ||
4254 os_strcmp(type, "p2p-scan") == 0)
4255 work->bands = wpas_get_bands(wpa_s,
4256 ((struct wpa_driver_scan_params *)
4257 ctx)->freqs);
4258 else
4259 work->bands = wpas_get_bands(wpa_s, NULL);
4260
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004261 was_empty = dl_list_empty(&wpa_s->radio->work);
4262 if (next)
4263 dl_list_add(&wpa_s->radio->work, &work->list);
4264 else
4265 dl_list_add_tail(&wpa_s->radio->work, &work->list);
4266 if (was_empty) {
4267 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
4268 radio_work_check_next(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004269 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
4270 && radio->num_active_works < MAX_ACTIVE_WORKS) {
4271 wpa_dbg(wpa_s, MSG_DEBUG,
4272 "Try to schedule a radio work (num_active_works=%u)",
4273 radio->num_active_works);
4274 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004275 }
4276
4277 return 0;
4278}
4279
4280
4281/**
4282 * radio_work_done - Indicate that a radio work item has been completed
4283 * @work: Completed work
4284 *
4285 * This function is called once the callback function registered with
4286 * radio_add_work() has completed its work.
4287 */
4288void radio_work_done(struct wpa_radio_work *work)
4289{
4290 struct wpa_supplicant *wpa_s = work->wpa_s;
4291 struct os_reltime now, diff;
4292 unsigned int started = work->started;
4293
4294 os_get_reltime(&now);
4295 os_reltime_sub(&now, &work->time, &diff);
4296 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
4297 work->type, work, started ? "done" : "canceled",
4298 diff.sec, diff.usec);
4299 radio_work_free(work);
4300 if (started)
4301 radio_work_check_next(wpa_s);
4302}
4303
4304
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004305struct wpa_radio_work *
4306radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004307{
4308 struct wpa_radio_work *work;
4309 struct wpa_radio *radio = wpa_s->radio;
4310
4311 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
4312 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004313 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004314 }
4315
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08004316 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004317}
4318
4319
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004320static int wpas_init_driver(struct wpa_supplicant *wpa_s,
4321 struct wpa_interface *iface)
4322{
4323 const char *ifname, *driver, *rn;
4324
4325 driver = iface->driver;
4326next_driver:
4327 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
4328 return -1;
4329
4330 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
4331 if (wpa_s->drv_priv == NULL) {
4332 const char *pos;
4333 pos = driver ? os_strchr(driver, ',') : NULL;
4334 if (pos) {
4335 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
4336 "driver interface - try next driver wrapper");
4337 driver = pos + 1;
4338 goto next_driver;
4339 }
4340 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
4341 "interface");
4342 return -1;
4343 }
4344 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
4345 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
4346 "driver_param '%s'", wpa_s->conf->driver_param);
4347 return -1;
4348 }
4349
4350 ifname = wpa_drv_get_ifname(wpa_s);
4351 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
4352 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
4353 "interface name with '%s'", ifname);
4354 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
4355 }
4356
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004357 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004358 if (rn && rn[0] == '\0')
4359 rn = NULL;
4360
4361 wpa_s->radio = radio_add_interface(wpa_s, rn);
4362 if (wpa_s->radio == NULL)
4363 return -1;
4364
4365 return 0;
4366}
4367
4368
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004369static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
4370 struct wpa_interface *iface)
4371{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004372 struct wpa_driver_capa capa;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004373 int capa_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004374
4375 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
4376 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
4377 iface->confname ? iface->confname : "N/A",
4378 iface->driver ? iface->driver : "default",
4379 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
4380 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
4381
4382 if (iface->confname) {
4383#ifdef CONFIG_BACKEND_FILE
4384 wpa_s->confname = os_rel2abs_path(iface->confname);
4385 if (wpa_s->confname == NULL) {
4386 wpa_printf(MSG_ERROR, "Failed to get absolute path "
4387 "for configuration file '%s'.",
4388 iface->confname);
4389 return -1;
4390 }
4391 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
4392 iface->confname, wpa_s->confname);
4393#else /* CONFIG_BACKEND_FILE */
4394 wpa_s->confname = os_strdup(iface->confname);
4395#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004396 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004397 if (wpa_s->conf == NULL) {
4398 wpa_printf(MSG_ERROR, "Failed to read or parse "
4399 "configuration '%s'.", wpa_s->confname);
4400 return -1;
4401 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07004402 wpa_s->confanother = os_rel2abs_path(iface->confanother);
4403 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004404
4405 /*
4406 * Override ctrl_interface and driver_param if set on command
4407 * line.
4408 */
4409 if (iface->ctrl_interface) {
4410 os_free(wpa_s->conf->ctrl_interface);
4411 wpa_s->conf->ctrl_interface =
4412 os_strdup(iface->ctrl_interface);
4413 }
4414
4415 if (iface->driver_param) {
4416 os_free(wpa_s->conf->driver_param);
4417 wpa_s->conf->driver_param =
4418 os_strdup(iface->driver_param);
4419 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004420
4421 if (iface->p2p_mgmt && !iface->ctrl_interface) {
4422 os_free(wpa_s->conf->ctrl_interface);
4423 wpa_s->conf->ctrl_interface = NULL;
4424 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004425 } else
4426 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
4427 iface->driver_param);
4428
4429 if (wpa_s->conf == NULL) {
4430 wpa_printf(MSG_ERROR, "\nNo configuration found.");
4431 return -1;
4432 }
4433
4434 if (iface->ifname == NULL) {
4435 wpa_printf(MSG_ERROR, "\nInterface name is required.");
4436 return -1;
4437 }
4438 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
4439 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
4440 iface->ifname);
4441 return -1;
4442 }
4443 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
4444
4445 if (iface->bridge_ifname) {
4446 if (os_strlen(iface->bridge_ifname) >=
4447 sizeof(wpa_s->bridge_ifname)) {
4448 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
4449 "name '%s'.", iface->bridge_ifname);
4450 return -1;
4451 }
4452 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
4453 sizeof(wpa_s->bridge_ifname));
4454 }
4455
4456 /* RSNA Supplicant Key Management - INITIALIZE */
4457 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
4458 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
4459
4460 /* Initialize driver interface and register driver event handler before
4461 * L2 receive handler so that association events are processed before
4462 * EAPOL-Key packets if both become available for the same select()
4463 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004464 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004465 return -1;
4466
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004467 if (wpa_supplicant_init_wpa(wpa_s) < 0)
4468 return -1;
4469
4470 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
4471 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
4472 NULL);
4473 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
4474
4475 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
4476 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
4477 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
4478 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4479 "dot11RSNAConfigPMKLifetime");
4480 return -1;
4481 }
4482
4483 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
4484 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
4485 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
4486 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4487 "dot11RSNAConfigPMKReauthThreshold");
4488 return -1;
4489 }
4490
4491 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
4492 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
4493 wpa_s->conf->dot11RSNAConfigSATimeout)) {
4494 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
4495 "dot11RSNAConfigSATimeout");
4496 return -1;
4497 }
4498
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004499 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
4500 &wpa_s->hw.num_modes,
4501 &wpa_s->hw.flags);
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004502 if (wpa_s->hw.modes) {
4503 u16 i;
4504
4505 for (i = 0; i < wpa_s->hw.num_modes; i++) {
4506 if (wpa_s->hw.modes[i].vht_capab) {
4507 wpa_s->hw_capab = CAPAB_VHT;
4508 break;
4509 }
4510
4511 if (wpa_s->hw.modes[i].ht_capab &
4512 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
4513 wpa_s->hw_capab = CAPAB_HT40;
4514 else if (wpa_s->hw.modes[i].ht_capab &&
4515 wpa_s->hw_capab == CAPAB_NO_HT_VHT)
4516 wpa_s->hw_capab = CAPAB_HT;
4517 }
4518 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004519
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004520 capa_res = wpa_drv_get_capa(wpa_s, &capa);
4521 if (capa_res == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004522 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004523 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004524 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004525 wpa_s->drv_smps_modes = capa.smps_modes;
4526 wpa_s->drv_rrm_flags = capa.rrm_flags;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004527 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004528 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004529 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
4530 wpa_s->sched_scan_supported = capa.sched_scan_supported;
4531 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004532 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
4533 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004534 wpa_s->extended_capa = capa.extended_capa;
4535 wpa_s->extended_capa_mask = capa.extended_capa_mask;
4536 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004537 wpa_s->num_multichan_concurrent =
4538 capa.num_multichan_concurrent;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004539 wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
4540
4541 if (capa.mac_addr_rand_scan_supported)
4542 wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
4543 if (wpa_s->sched_scan_supported &&
4544 capa.mac_addr_rand_sched_scan_supported)
4545 wpa_s->mac_addr_rand_supported |=
4546 (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004547 }
4548 if (wpa_s->max_remain_on_chan == 0)
4549 wpa_s->max_remain_on_chan = 1000;
4550
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004551 /*
4552 * Only take p2p_mgmt parameters when P2P Device is supported.
4553 * Doing it here as it determines whether l2_packet_init() will be done
4554 * during wpa_supplicant_driver_init().
4555 */
4556 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
4557 wpa_s->p2p_mgmt = iface->p2p_mgmt;
4558 else
4559 iface->p2p_mgmt = 1;
4560
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004561 if (wpa_s->num_multichan_concurrent == 0)
4562 wpa_s->num_multichan_concurrent = 1;
4563
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004564 if (wpa_supplicant_driver_init(wpa_s) < 0)
4565 return -1;
4566
4567#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004568 if ((!iface->p2p_mgmt ||
4569 !(wpa_s->drv_flags &
4570 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
4571 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004572 return -1;
4573#endif /* CONFIG_TDLS */
4574
4575 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
4576 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
4577 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
4578 return -1;
4579 }
4580
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004581#ifdef CONFIG_FST
4582 if (wpa_s->conf->fst_group_id) {
4583 struct fst_iface_cfg cfg;
4584 struct fst_wpa_obj iface_obj;
4585
4586 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);
4587 os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,
4588 sizeof(cfg.group_id));
4589 cfg.priority = wpa_s->conf->fst_priority;
4590 cfg.llt = wpa_s->conf->fst_llt;
4591
4592 wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,
4593 &iface_obj, &cfg);
4594 if (!wpa_s->fst) {
4595 wpa_msg(wpa_s, MSG_ERROR,
4596 "FST: Cannot attach iface %s to group %s",
4597 wpa_s->ifname, cfg.group_id);
4598 return -1;
4599 }
4600 }
4601#endif /* CONFIG_FST */
4602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004603 if (wpas_wps_init(wpa_s))
4604 return -1;
4605
4606 if (wpa_supplicant_init_eapol(wpa_s) < 0)
4607 return -1;
4608 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
4609
4610 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
4611 if (wpa_s->ctrl_iface == NULL) {
4612 wpa_printf(MSG_ERROR,
4613 "Failed to initialize control interface '%s'.\n"
4614 "You may have another wpa_supplicant process "
4615 "already running or the file was\n"
4616 "left by an unclean termination of wpa_supplicant "
4617 "in which case you will need\n"
4618 "to manually remove this file before starting "
4619 "wpa_supplicant again.\n",
4620 wpa_s->conf->ctrl_interface);
4621 return -1;
4622 }
4623
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004624 wpa_s->gas = gas_query_init(wpa_s);
4625 if (wpa_s->gas == NULL) {
4626 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
4627 return -1;
4628 }
4629
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004630 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004631 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
4632 return -1;
4633 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004634
4635 if (wpa_bss_init(wpa_s) < 0)
4636 return -1;
4637
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004638 /*
4639 * Set Wake-on-WLAN triggers, if configured.
4640 * Note: We don't restore/remove the triggers on shutdown (it doesn't
4641 * have effect anyway when the interface is down).
4642 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004643 if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004644 return -1;
4645
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004646#ifdef CONFIG_EAP_PROXY
4647{
4648 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004649 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
4650 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004651 if (wpa_s->mnc_len > 0) {
4652 wpa_s->imsi[len] = '\0';
4653 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
4654 wpa_s->imsi, wpa_s->mnc_len);
4655 } else {
4656 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
4657 }
4658}
4659#endif /* CONFIG_EAP_PROXY */
4660
Dmitry Shmidt04949592012-07-19 12:16:46 -07004661 if (pcsc_reader_init(wpa_s) < 0)
4662 return -1;
4663
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004664 if (wpas_init_ext_pw(wpa_s) < 0)
4665 return -1;
4666
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004667 wpas_rrm_reset(wpa_s);
4668
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004669 return 0;
4670}
4671
4672
4673static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004674 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004675{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004676 struct wpa_global *global = wpa_s->global;
4677 struct wpa_supplicant *iface, *prev;
4678
4679 if (wpa_s == wpa_s->parent)
4680 wpas_p2p_group_remove(wpa_s, "*");
4681
4682 iface = global->ifaces;
4683 while (iface) {
4684 if (iface == wpa_s || iface->parent != wpa_s) {
4685 iface = iface->next;
4686 continue;
4687 }
4688 wpa_printf(MSG_DEBUG,
4689 "Remove remaining child interface %s from parent %s",
4690 iface->ifname, wpa_s->ifname);
4691 prev = iface;
4692 iface = iface->next;
4693 wpa_supplicant_remove_iface(global, prev, terminate);
4694 }
4695
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004696 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004697 if (wpa_s->drv_priv) {
4698 wpa_supplicant_deauthenticate(wpa_s,
4699 WLAN_REASON_DEAUTH_LEAVING);
4700
4701 wpa_drv_set_countermeasures(wpa_s, 0);
4702 wpa_clear_keys(wpa_s, NULL);
4703 }
4704
4705 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004706 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004707
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004708 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004709 radio_remove_interface(wpa_s);
4710
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004711#ifdef CONFIG_FST
4712 if (wpa_s->fst) {
4713 fst_detach(wpa_s->fst);
4714 wpa_s->fst = NULL;
4715 }
4716 if (wpa_s->received_mb_ies) {
4717 wpabuf_free(wpa_s->received_mb_ies);
4718 wpa_s->received_mb_ies = NULL;
4719 }
4720#endif /* CONFIG_FST */
4721
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004722 if (wpa_s->drv_priv)
4723 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004724
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004725 if (notify)
4726 wpas_notify_iface_removed(wpa_s);
4727
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004728 if (terminate)
4729 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004730
4731 if (wpa_s->ctrl_iface) {
4732 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
4733 wpa_s->ctrl_iface = NULL;
4734 }
4735
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004736#ifdef CONFIG_MESH
4737 if (wpa_s->ifmsh) {
4738 wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
4739 wpa_s->ifmsh = NULL;
4740 }
4741#endif /* CONFIG_MESH */
4742
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004743 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07004744 wpa_config_free(wpa_s->conf);
4745 wpa_s->conf = NULL;
4746 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004747
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07004748 os_free(wpa_s->ssids_from_scan_req);
4749
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004750 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004751}
4752
4753
4754/**
4755 * wpa_supplicant_add_iface - Add a new network interface
4756 * @global: Pointer to global data from wpa_supplicant_init()
4757 * @iface: Interface configuration options
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004758 * @parent: Parent interface or %NULL to assign new interface as parent
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004759 * Returns: Pointer to the created interface or %NULL on failure
4760 *
4761 * This function is used to add new network interfaces for %wpa_supplicant.
4762 * This can be called before wpa_supplicant_run() to add interfaces before the
4763 * main event loop has been started. In addition, new interfaces can be added
4764 * dynamically while %wpa_supplicant is already running. This could happen,
4765 * e.g., when a hotplug network adapter is inserted.
4766 */
4767struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004768 struct wpa_interface *iface,
4769 struct wpa_supplicant *parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004770{
4771 struct wpa_supplicant *wpa_s;
4772 struct wpa_interface t_iface;
4773 struct wpa_ssid *ssid;
4774
4775 if (global == NULL || iface == NULL)
4776 return NULL;
4777
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004778 wpa_s = wpa_supplicant_alloc(parent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004779 if (wpa_s == NULL)
4780 return NULL;
4781
4782 wpa_s->global = global;
4783
4784 t_iface = *iface;
4785 if (global->params.override_driver) {
4786 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
4787 "('%s' -> '%s')",
4788 iface->driver, global->params.override_driver);
4789 t_iface.driver = global->params.override_driver;
4790 }
4791 if (global->params.override_ctrl_interface) {
4792 wpa_printf(MSG_DEBUG, "Override interface parameter: "
4793 "ctrl_interface ('%s' -> '%s')",
4794 iface->ctrl_interface,
4795 global->params.override_ctrl_interface);
4796 t_iface.ctrl_interface =
4797 global->params.override_ctrl_interface;
4798 }
4799 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
4800 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
4801 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004802 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004803 return NULL;
4804 }
4805
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004806 if (iface->p2p_mgmt == 0) {
4807 /* Notify the control interfaces about new iface */
4808 if (wpas_notify_iface_added(wpa_s)) {
4809 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
4810 return NULL;
4811 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004812
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004813 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
4814 wpas_notify_network_added(wpa_s, ssid);
4815 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004816
4817 wpa_s->next = global->ifaces;
4818 global->ifaces = wpa_s;
4819
4820 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004821 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004822
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004823#ifdef CONFIG_P2P
4824 if (wpa_s->global->p2p == NULL &&
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004825 !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004826 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07004827 wpas_p2p_add_p2pdev_interface(
4828 wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004829 wpa_printf(MSG_INFO,
4830 "P2P: Failed to enable P2P Device interface");
4831 /* Try to continue without. P2P will be disabled. */
4832 }
4833#endif /* CONFIG_P2P */
4834
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004835 return wpa_s;
4836}
4837
4838
4839/**
4840 * wpa_supplicant_remove_iface - Remove a network interface
4841 * @global: Pointer to global data from wpa_supplicant_init()
4842 * @wpa_s: Pointer to the network interface to be removed
4843 * Returns: 0 if interface was removed, -1 if interface was not found
4844 *
4845 * This function can be used to dynamically remove network interfaces from
4846 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
4847 * addition, this function is used to remove all remaining interfaces when
4848 * %wpa_supplicant is terminated.
4849 */
4850int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004851 struct wpa_supplicant *wpa_s,
4852 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004853{
4854 struct wpa_supplicant *prev;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004855#ifdef CONFIG_MESH
4856 unsigned int mesh_if_created = wpa_s->mesh_if_created;
4857 char *ifname = NULL;
4858#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004859
4860 /* Remove interface from the global list of interfaces */
4861 prev = global->ifaces;
4862 if (prev == wpa_s) {
4863 global->ifaces = wpa_s->next;
4864 } else {
4865 while (prev && prev->next != wpa_s)
4866 prev = prev->next;
4867 if (prev == NULL)
4868 return -1;
4869 prev->next = wpa_s->next;
4870 }
4871
4872 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
4873
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004874#ifdef CONFIG_MESH
4875 if (mesh_if_created) {
4876 ifname = os_strdup(wpa_s->ifname);
4877 if (ifname == NULL) {
4878 wpa_dbg(wpa_s, MSG_ERROR,
4879 "mesh: Failed to malloc ifname");
4880 return -1;
4881 }
4882 }
4883#endif /* CONFIG_MESH */
4884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004885 if (global->p2p_group_formation == wpa_s)
4886 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004887 if (global->p2p_invite_group == wpa_s)
4888 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004889 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004890
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004891#ifdef CONFIG_MESH
4892 if (mesh_if_created) {
4893 wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
4894 os_free(ifname);
4895 }
4896#endif /* CONFIG_MESH */
4897
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004898 return 0;
4899}
4900
4901
4902/**
4903 * wpa_supplicant_get_eap_mode - Get the current EAP mode
4904 * @wpa_s: Pointer to the network interface
4905 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
4906 */
4907const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
4908{
4909 const char *eapol_method;
4910
4911 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
4912 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
4913 return "NO-EAP";
4914 }
4915
4916 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
4917 if (eapol_method == NULL)
4918 return "UNKNOWN-EAP";
4919
4920 return eapol_method;
4921}
4922
4923
4924/**
4925 * wpa_supplicant_get_iface - Get a new network interface
4926 * @global: Pointer to global data from wpa_supplicant_init()
4927 * @ifname: Interface name
4928 * Returns: Pointer to the interface or %NULL if not found
4929 */
4930struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4931 const char *ifname)
4932{
4933 struct wpa_supplicant *wpa_s;
4934
4935 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4936 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4937 return wpa_s;
4938 }
4939 return NULL;
4940}
4941
4942
4943#ifndef CONFIG_NO_WPA_MSG
4944static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4945{
4946 struct wpa_supplicant *wpa_s = ctx;
4947 if (wpa_s == NULL)
4948 return NULL;
4949 return wpa_s->ifname;
4950}
4951#endif /* CONFIG_NO_WPA_MSG */
4952
4953
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004954#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL
4955#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10
4956#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */
4957
4958/* Periodic cleanup tasks */
4959static void wpas_periodic(void *eloop_ctx, void *timeout_ctx)
4960{
4961 struct wpa_global *global = eloop_ctx;
4962 struct wpa_supplicant *wpa_s;
4963
4964 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
4965 wpas_periodic, global, NULL);
4966
4967#ifdef CONFIG_P2P
4968 if (global->p2p)
4969 p2p_expire_peers(global->p2p);
4970#endif /* CONFIG_P2P */
4971
4972 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4973 wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
4974#ifdef CONFIG_AP
4975 ap_periodic(wpa_s);
4976#endif /* CONFIG_AP */
4977 }
4978}
4979
4980
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004981/**
4982 * wpa_supplicant_init - Initialize %wpa_supplicant
4983 * @params: Parameters for %wpa_supplicant
4984 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4985 *
4986 * This function is used to initialize %wpa_supplicant. After successful
4987 * initialization, the returned data pointer can be used to add and remove
4988 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4989 */
4990struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4991{
4992 struct wpa_global *global;
4993 int ret, i;
4994
4995 if (params == NULL)
4996 return NULL;
4997
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004998#ifdef CONFIG_DRIVER_NDIS
4999 {
5000 void driver_ndis_init_ops(void);
5001 driver_ndis_init_ops();
5002 }
5003#endif /* CONFIG_DRIVER_NDIS */
5004
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005005#ifndef CONFIG_NO_WPA_MSG
5006 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
5007#endif /* CONFIG_NO_WPA_MSG */
5008
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005009 if (params->wpa_debug_file_path)
5010 wpa_debug_open_file(params->wpa_debug_file_path);
5011 else
5012 wpa_debug_setup_stdout();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005013 if (params->wpa_debug_syslog)
5014 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005015 if (params->wpa_debug_tracing) {
5016 ret = wpa_debug_open_linux_tracing();
5017 if (ret) {
5018 wpa_printf(MSG_ERROR,
5019 "Failed to enable trace logging");
5020 return NULL;
5021 }
5022 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005023
5024 ret = eap_register_methods();
5025 if (ret) {
5026 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
5027 if (ret == -2)
5028 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
5029 "the same EAP type.");
5030 return NULL;
5031 }
5032
5033 global = os_zalloc(sizeof(*global));
5034 if (global == NULL)
5035 return NULL;
5036 dl_list_init(&global->p2p_srv_bonjour);
5037 dl_list_init(&global->p2p_srv_upnp);
5038 global->params.daemonize = params->daemonize;
5039 global->params.wait_for_monitor = params->wait_for_monitor;
5040 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
5041 if (params->pid_file)
5042 global->params.pid_file = os_strdup(params->pid_file);
5043 if (params->ctrl_interface)
5044 global->params.ctrl_interface =
5045 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005046 if (params->ctrl_interface_group)
5047 global->params.ctrl_interface_group =
5048 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005049 if (params->override_driver)
5050 global->params.override_driver =
5051 os_strdup(params->override_driver);
5052 if (params->override_ctrl_interface)
5053 global->params.override_ctrl_interface =
5054 os_strdup(params->override_ctrl_interface);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005055#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005056 if (params->conf_p2p_dev)
5057 global->params.conf_p2p_dev =
5058 os_strdup(params->conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005059#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005060 wpa_debug_level = global->params.wpa_debug_level =
5061 params->wpa_debug_level;
5062 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
5063 params->wpa_debug_show_keys;
5064 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
5065 params->wpa_debug_timestamp;
5066
5067 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
5068
5069 if (eloop_init()) {
5070 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
5071 wpa_supplicant_deinit(global);
5072 return NULL;
5073 }
5074
Jouni Malinen75ecf522011-06-27 15:19:46 -07005075 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005076
5077 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
5078 if (global->ctrl_iface == NULL) {
5079 wpa_supplicant_deinit(global);
5080 return NULL;
5081 }
5082
5083 if (wpas_notify_supplicant_initialized(global)) {
5084 wpa_supplicant_deinit(global);
5085 return NULL;
5086 }
5087
5088 for (i = 0; wpa_drivers[i]; i++)
5089 global->drv_count++;
5090 if (global->drv_count == 0) {
5091 wpa_printf(MSG_ERROR, "No drivers enabled");
5092 wpa_supplicant_deinit(global);
5093 return NULL;
5094 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005095 global->drv_priv = os_calloc(global->drv_count, sizeof(void *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005096 if (global->drv_priv == NULL) {
5097 wpa_supplicant_deinit(global);
5098 return NULL;
5099 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005100
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005101#ifdef CONFIG_WIFI_DISPLAY
5102 if (wifi_display_init(global) < 0) {
5103 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
5104 wpa_supplicant_deinit(global);
5105 return NULL;
5106 }
5107#endif /* CONFIG_WIFI_DISPLAY */
5108
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005109 eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
5110 wpas_periodic, global, NULL);
5111
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005112 return global;
5113}
5114
5115
5116/**
5117 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
5118 * @global: Pointer to global data from wpa_supplicant_init()
5119 * Returns: 0 after successful event loop run, -1 on failure
5120 *
5121 * This function starts the main event loop and continues running as long as
5122 * there are any remaining events. In most cases, this function is running as
5123 * long as the %wpa_supplicant process in still in use.
5124 */
5125int wpa_supplicant_run(struct wpa_global *global)
5126{
5127 struct wpa_supplicant *wpa_s;
5128
5129 if (global->params.daemonize &&
5130 wpa_supplicant_daemon(global->params.pid_file))
5131 return -1;
5132
5133 if (global->params.wait_for_monitor) {
5134 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
5135 if (wpa_s->ctrl_iface)
5136 wpa_supplicant_ctrl_iface_wait(
5137 wpa_s->ctrl_iface);
5138 }
5139
5140 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
5141 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
5142
5143 eloop_run();
5144
5145 return 0;
5146}
5147
5148
5149/**
5150 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
5151 * @global: Pointer to global data from wpa_supplicant_init()
5152 *
5153 * This function is called to deinitialize %wpa_supplicant and to free all
5154 * allocated resources. Remaining network interfaces will also be removed.
5155 */
5156void wpa_supplicant_deinit(struct wpa_global *global)
5157{
5158 int i;
5159
5160 if (global == NULL)
5161 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005162
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005163 eloop_cancel_timeout(wpas_periodic, global, NULL);
5164
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005165#ifdef CONFIG_WIFI_DISPLAY
5166 wifi_display_deinit(global);
5167#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005168
5169 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07005170 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005171
5172 if (global->ctrl_iface)
5173 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
5174
5175 wpas_notify_supplicant_deinitialized(global);
5176
5177 eap_peer_unregister_methods();
5178#ifdef CONFIG_AP
5179 eap_server_unregister_methods();
5180#endif /* CONFIG_AP */
5181
5182 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
5183 if (!global->drv_priv[i])
5184 continue;
5185 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
5186 }
5187 os_free(global->drv_priv);
5188
5189 random_deinit();
5190
5191 eloop_destroy();
5192
5193 if (global->params.pid_file) {
5194 os_daemonize_terminate(global->params.pid_file);
5195 os_free(global->params.pid_file);
5196 }
5197 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005198 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005199 os_free(global->params.override_driver);
5200 os_free(global->params.override_ctrl_interface);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005201#ifdef CONFIG_P2P
Sasha Levitskiydaa60e52015-08-05 13:02:59 -07005202 os_free(global->params.conf_p2p_dev);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005203#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005204
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07005205 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005206 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07005207 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005208
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005209 os_free(global);
5210 wpa_debug_close_syslog();
5211 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07005212 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005213}
5214
5215
5216void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
5217{
5218 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
5219 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
5220 char country[3];
5221 country[0] = wpa_s->conf->country[0];
5222 country[1] = wpa_s->conf->country[1];
5223 country[2] = '\0';
5224 if (wpa_drv_set_country(wpa_s, country) < 0) {
5225 wpa_printf(MSG_ERROR, "Failed to set country code "
5226 "'%s'", country);
5227 }
5228 }
5229
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005230 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
5231 wpas_init_ext_pw(wpa_s);
5232
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005233#ifdef CONFIG_WPS
5234 wpas_wps_update_config(wpa_s);
5235#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005236 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005237 wpa_s->conf->changed_parameters = 0;
5238}
5239
5240
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005241void add_freq(int *freqs, int *num_freqs, int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005242{
5243 int i;
5244
5245 for (i = 0; i < *num_freqs; i++) {
5246 if (freqs[i] == freq)
5247 return;
5248 }
5249
5250 freqs[*num_freqs] = freq;
5251 (*num_freqs)++;
5252}
5253
5254
5255static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
5256{
5257 struct wpa_bss *bss, *cbss;
5258 const int max_freqs = 10;
5259 int *freqs;
5260 int num_freqs = 0;
5261
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005262 freqs = os_calloc(max_freqs + 1, sizeof(int));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005263 if (freqs == NULL)
5264 return NULL;
5265
5266 cbss = wpa_s->current_bss;
5267
5268 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5269 if (bss == cbss)
5270 continue;
5271 if (bss->ssid_len == cbss->ssid_len &&
5272 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
5273 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
5274 add_freq(freqs, &num_freqs, bss->freq);
5275 if (num_freqs == max_freqs)
5276 break;
5277 }
5278 }
5279
5280 if (num_freqs == 0) {
5281 os_free(freqs);
5282 freqs = NULL;
5283 }
5284
5285 return freqs;
5286}
5287
5288
5289void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
5290{
5291 int timeout;
5292 int count;
5293 int *freqs = NULL;
5294
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005295 wpas_connect_work_done(wpa_s);
5296
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005297 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005298 * Remove possible authentication timeout since the connection failed.
5299 */
5300 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
5301
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005302 /*
5303 * There is no point in blacklisting the AP if this event is
5304 * generated based on local request to disconnect.
5305 */
5306 if (wpa_s->own_disconnect_req) {
5307 wpa_s->own_disconnect_req = 0;
5308 wpa_dbg(wpa_s, MSG_DEBUG,
5309 "Ignore connection failure due to local request to disconnect");
5310 return;
5311 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005312 if (wpa_s->disconnected) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005313 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
5314 "indication since interface has been put into "
5315 "disconnected state");
5316 return;
5317 }
5318
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005319 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005320 * Add the failed BSSID into the blacklist and speed up next scan
5321 * attempt if there could be other APs that could accept association.
5322 * The current blacklist count indicates how many times we have tried
5323 * connecting to this AP and multiple attempts mean that other APs are
5324 * either not available or has already been tried, so that we can start
5325 * increasing the delay here to avoid constant scanning.
5326 */
5327 count = wpa_blacklist_add(wpa_s, bssid);
5328 if (count == 1 && wpa_s->current_bss) {
5329 /*
5330 * This BSS was not in the blacklist before. If there is
5331 * another BSS available for the same ESS, we should try that
5332 * next. Otherwise, we may as well try this one once more
5333 * before allowing other, likely worse, ESSes to be considered.
5334 */
5335 freqs = get_bss_freqs_in_ess(wpa_s);
5336 if (freqs) {
5337 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
5338 "has been seen; try it next");
5339 wpa_blacklist_add(wpa_s, bssid);
5340 /*
5341 * On the next scan, go through only the known channels
5342 * used in this ESS based on previous scans to speed up
5343 * common load balancing use case.
5344 */
5345 os_free(wpa_s->next_scan_freqs);
5346 wpa_s->next_scan_freqs = freqs;
5347 }
5348 }
5349
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005350 /*
5351 * Add previous failure count in case the temporary blacklist was
5352 * cleared due to no other BSSes being available.
5353 */
5354 count += wpa_s->extra_blacklist_count;
5355
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005356 if (count > 3 && wpa_s->current_ssid) {
5357 wpa_printf(MSG_DEBUG, "Continuous association failures - "
5358 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005359 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005360 }
5361
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005362 switch (count) {
5363 case 1:
5364 timeout = 100;
5365 break;
5366 case 2:
5367 timeout = 500;
5368 break;
5369 case 3:
5370 timeout = 1000;
5371 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005372 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005373 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005374 break;
5375 default:
5376 timeout = 10000;
5377 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005378 }
5379
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005380 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
5381 "ms", count, timeout);
5382
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005383 /*
5384 * TODO: if more than one possible AP is available in scan results,
5385 * could try the other ones before requesting a new scan.
5386 */
5387 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
5388 1000 * (timeout % 1000));
5389}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005390
5391
5392int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
5393{
5394 return wpa_s->conf->ap_scan == 2 ||
5395 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
5396}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005397
Dmitry Shmidt04949592012-07-19 12:16:46 -07005398
5399#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
5400int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
5401 struct wpa_ssid *ssid,
5402 const char *field,
5403 const char *value)
5404{
5405#ifdef IEEE8021X_EAPOL
5406 struct eap_peer_config *eap = &ssid->eap;
5407
5408 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
5409 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
5410 (const u8 *) value, os_strlen(value));
5411
5412 switch (wpa_supplicant_ctrl_req_from_string(field)) {
5413 case WPA_CTRL_REQ_EAP_IDENTITY:
5414 os_free(eap->identity);
5415 eap->identity = (u8 *) os_strdup(value);
5416 eap->identity_len = os_strlen(value);
5417 eap->pending_req_identity = 0;
5418 if (ssid == wpa_s->current_ssid)
5419 wpa_s->reassociate = 1;
5420 break;
5421 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005422 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005423 eap->password = (u8 *) os_strdup(value);
5424 eap->password_len = os_strlen(value);
5425 eap->pending_req_password = 0;
5426 if (ssid == wpa_s->current_ssid)
5427 wpa_s->reassociate = 1;
5428 break;
5429 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005430 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005431 eap->new_password = (u8 *) os_strdup(value);
5432 eap->new_password_len = os_strlen(value);
5433 eap->pending_req_new_password = 0;
5434 if (ssid == wpa_s->current_ssid)
5435 wpa_s->reassociate = 1;
5436 break;
5437 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005438 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005439 eap->pin = os_strdup(value);
5440 eap->pending_req_pin = 0;
5441 if (ssid == wpa_s->current_ssid)
5442 wpa_s->reassociate = 1;
5443 break;
5444 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005445 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005446 eap->otp = (u8 *) os_strdup(value);
5447 eap->otp_len = os_strlen(value);
5448 os_free(eap->pending_req_otp);
5449 eap->pending_req_otp = NULL;
5450 eap->pending_req_otp_len = 0;
5451 break;
5452 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005453 str_clear_free(eap->private_key_passwd);
5454 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005455 eap->pending_req_passphrase = 0;
5456 if (ssid == wpa_s->current_ssid)
5457 wpa_s->reassociate = 1;
5458 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07005459 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07005460 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07005461 eap->external_sim_resp = os_strdup(value);
5462 break;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005463 case WPA_CTRL_REQ_PSK_PASSPHRASE:
5464 if (wpa_config_set(ssid, "psk", value, 0) < 0)
5465 return -1;
5466 ssid->mem_only_psk = 1;
5467 if (ssid->passphrase)
5468 wpa_config_update_psk(ssid);
5469 if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
5470 wpa_supplicant_req_scan(wpa_s, 0, 0);
5471 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005472 default:
5473 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
5474 return -1;
5475 }
5476
5477 return 0;
5478#else /* IEEE8021X_EAPOL */
5479 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
5480 return -1;
5481#endif /* IEEE8021X_EAPOL */
5482}
5483#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
5484
5485
5486int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5487{
5488 int i;
5489 unsigned int drv_enc;
5490
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005491 if (wpa_s->p2p_mgmt)
5492 return 1; /* no normal network profiles on p2p_mgmt interface */
5493
Dmitry Shmidt04949592012-07-19 12:16:46 -07005494 if (ssid == NULL)
5495 return 1;
5496
5497 if (ssid->disabled)
5498 return 1;
5499
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005500 if (wpa_s->drv_capa_known)
Dmitry Shmidt04949592012-07-19 12:16:46 -07005501 drv_enc = wpa_s->drv_enc;
5502 else
5503 drv_enc = (unsigned int) -1;
5504
5505 for (i = 0; i < NUM_WEP_KEYS; i++) {
5506 size_t len = ssid->wep_key_len[i];
5507 if (len == 0)
5508 continue;
5509 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
5510 continue;
5511 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
5512 continue;
5513 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
5514 continue;
5515 return 1; /* invalid WEP key */
5516 }
5517
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005518 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07005519 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
5520 !ssid->mem_only_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005521 return 1;
5522
Dmitry Shmidt04949592012-07-19 12:16:46 -07005523 return 0;
5524}
5525
5526
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005527int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
5528{
5529#ifdef CONFIG_IEEE80211W
5530 if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
5531 if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
5532 !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
5533 /*
5534 * Driver does not support BIP -- ignore pmf=1 default
5535 * since the connection with PMF would fail and the
5536 * configuration does not require PMF to be enabled.
5537 */
5538 return NO_MGMT_FRAME_PROTECTION;
5539 }
5540
5541 return wpa_s->conf->pmf;
5542 }
5543
5544 return ssid->ieee80211w;
5545#else /* CONFIG_IEEE80211W */
5546 return NO_MGMT_FRAME_PROTECTION;
5547#endif /* CONFIG_IEEE80211W */
5548}
5549
5550
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005551int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005552{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005553 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005554 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07005555 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005556 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07005557 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005558}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005559
5560
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005561void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005562{
5563 struct wpa_ssid *ssid = wpa_s->current_ssid;
5564 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005565 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005566
5567 if (ssid == NULL) {
5568 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
5569 "SSID block");
5570 return;
5571 }
5572
5573 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
5574 return;
5575
5576 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005577
5578#ifdef CONFIG_P2P
5579 if (ssid->p2p_group &&
5580 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
5581 /*
5582 * Skip the wait time since there is a short timeout on the
5583 * connection to a P2P group.
5584 */
5585 return;
5586 }
5587#endif /* CONFIG_P2P */
5588
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005589 if (ssid->auth_failures > 50)
5590 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005591 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005592 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005593 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005594 dur = 90;
5595 else if (ssid->auth_failures > 3)
5596 dur = 60;
5597 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005598 dur = 30;
5599 else if (ssid->auth_failures > 1)
5600 dur = 20;
5601 else
5602 dur = 10;
5603
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005604 if (ssid->auth_failures > 1 &&
5605 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
5606 dur += os_random() % (ssid->auth_failures * 10);
5607
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005608 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005609 if (now.sec + dur <= ssid->disabled_until.sec)
5610 return;
5611
5612 ssid->disabled_until.sec = now.sec + dur;
5613
5614 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005615 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005616 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005617 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005618}
5619
5620
5621void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
5622 struct wpa_ssid *ssid, int clear_failures)
5623{
5624 if (ssid == NULL)
5625 return;
5626
5627 if (ssid->disabled_until.sec) {
5628 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
5629 "id=%d ssid=\"%s\"",
5630 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
5631 }
5632 ssid->disabled_until.sec = 0;
5633 ssid->disabled_until.usec = 0;
5634 if (clear_failures)
5635 ssid->auth_failures = 0;
5636}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005637
5638
5639int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
5640{
5641 size_t i;
5642
5643 if (wpa_s->disallow_aps_bssid == NULL)
5644 return 0;
5645
5646 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
5647 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
5648 bssid, ETH_ALEN) == 0)
5649 return 1;
5650 }
5651
5652 return 0;
5653}
5654
5655
5656int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
5657 size_t ssid_len)
5658{
5659 size_t i;
5660
5661 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
5662 return 0;
5663
5664 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
5665 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
5666 if (ssid_len == s->ssid_len &&
5667 os_memcmp(ssid, s->ssid, ssid_len) == 0)
5668 return 1;
5669 }
5670
5671 return 0;
5672}
5673
5674
5675/**
5676 * wpas_request_connection - Request a new connection
5677 * @wpa_s: Pointer to the network interface
5678 *
5679 * This function is used to request a new connection to be found. It will mark
5680 * the interface to allow reassociation and request a new scan to find a
5681 * suitable network to connect to.
5682 */
5683void wpas_request_connection(struct wpa_supplicant *wpa_s)
5684{
5685 wpa_s->normal_scans = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005686 wpa_s->scan_req = NORMAL_SCAN_REQ;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005687 wpa_supplicant_reinit_autoscan(wpa_s);
5688 wpa_s->extra_blacklist_count = 0;
5689 wpa_s->disconnected = 0;
5690 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08005691
5692 if (wpa_supplicant_fast_associate(wpa_s) != 1)
5693 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005694 else
5695 wpa_s->reattach = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005696}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005697
5698
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005699void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
5700 struct wpa_used_freq_data *freqs_data,
5701 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005702{
5703 unsigned int i;
5704
5705 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
5706 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005707 for (i = 0; i < len; i++) {
5708 struct wpa_used_freq_data *cur = &freqs_data[i];
5709 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
5710 i, cur->freq, cur->flags);
5711 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005712}
5713
5714
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005715/*
5716 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005717 * are using the same radio as the current interface, and in addition, get
5718 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005719 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005720int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
5721 struct wpa_used_freq_data *freqs_data,
5722 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005723{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005724 struct wpa_supplicant *ifs;
5725 u8 bssid[ETH_ALEN];
5726 int freq;
5727 unsigned int idx = 0, i;
5728
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005729 wpa_dbg(wpa_s, MSG_DEBUG,
5730 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005731 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005732
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005733 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
5734 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005735 if (idx == len)
5736 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005737
5738 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
5739 continue;
5740
5741 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005742 ifs->current_ssid->mode == WPAS_MODE_P2P_GO ||
5743 ifs->current_ssid->mode == WPAS_MODE_MESH)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005744 freq = ifs->current_ssid->frequency;
5745 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
5746 freq = ifs->assoc_freq;
5747 else
5748 continue;
5749
5750 /* Hold only distinct freqs */
5751 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005752 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005753 break;
5754
5755 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005756 freqs_data[idx++].freq = freq;
5757
5758 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005759 freqs_data[i].flags |= ifs->current_ssid->p2p_group ?
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005760 WPA_FREQ_USED_BY_P2P_CLIENT :
5761 WPA_FREQ_USED_BY_INFRA_STATION;
5762 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005763 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08005764
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005765 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005766 return idx;
5767}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005768
5769
5770/*
5771 * Find the operating frequencies of any of the virtual interfaces that
5772 * are using the same radio as the current interface.
5773 */
5774int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
5775 int *freq_array, unsigned int len)
5776{
5777 struct wpa_used_freq_data *freqs_data;
5778 int num, i;
5779
5780 os_memset(freq_array, 0, sizeof(int) * len);
5781
5782 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
5783 if (!freqs_data)
5784 return -1;
5785
5786 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
5787 for (i = 0; i < num; i++)
5788 freq_array[i] = freqs_data[i].freq;
5789
5790 os_free(freqs_data);
5791
5792 return num;
5793}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005794
5795
5796static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx)
5797{
5798 struct rrm_data *rrm = data;
5799
5800 if (!rrm->notify_neighbor_rep) {
5801 wpa_printf(MSG_ERROR,
5802 "RRM: Unexpected neighbor report timeout");
5803 return;
5804 }
5805
5806 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE");
5807 rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL);
5808
5809 rrm->notify_neighbor_rep = NULL;
5810 rrm->neighbor_rep_cb_ctx = NULL;
5811}
5812
5813
5814/*
5815 * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant
5816 * @wpa_s: Pointer to wpa_supplicant
5817 */
5818void wpas_rrm_reset(struct wpa_supplicant *wpa_s)
5819{
5820 wpa_s->rrm.rrm_used = 0;
5821
5822 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5823 NULL);
5824 if (wpa_s->rrm.notify_neighbor_rep)
5825 wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL);
5826 wpa_s->rrm.next_neighbor_rep_token = 1;
5827}
5828
5829
5830/*
5831 * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report
5832 * @wpa_s: Pointer to wpa_supplicant
5833 * @report: Neighbor report buffer, prefixed by a 1-byte dialog token
5834 * @report_len: Length of neighbor report buffer
5835 */
5836void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
5837 const u8 *report, size_t report_len)
5838{
5839 struct wpabuf *neighbor_rep;
5840
5841 wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len);
5842 if (report_len < 1)
5843 return;
5844
5845 if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) {
5846 wpa_printf(MSG_DEBUG,
5847 "RRM: Discarding neighbor report with token %d (expected %d)",
5848 report[0], wpa_s->rrm.next_neighbor_rep_token - 1);
5849 return;
5850 }
5851
5852 eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm,
5853 NULL);
5854
5855 if (!wpa_s->rrm.notify_neighbor_rep) {
5856 wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
5857 return;
5858 }
5859
5860 /* skipping the first byte, which is only an id (dialog token) */
5861 neighbor_rep = wpabuf_alloc(report_len - 1);
5862 if (neighbor_rep == NULL)
5863 return;
5864 wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
5865 wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
5866 report[0]);
5867 wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
5868 neighbor_rep);
5869 wpa_s->rrm.notify_neighbor_rep = NULL;
5870 wpa_s->rrm.neighbor_rep_cb_ctx = NULL;
5871}
5872
5873
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005874#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
5875/* Workaround different, undefined for Windows, error codes used here */
5876#define ENOTCONN -1
5877#define EOPNOTSUPP -1
5878#define ECANCELED -1
5879#endif
5880
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005881/**
5882 * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
5883 * @wpa_s: Pointer to wpa_supplicant
5884 * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
5885 * is sent in the request.
5886 * @cb: Callback function to be called once the requested report arrives, or
5887 * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
5888 * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
5889 * the requester's responsibility to free it.
5890 * In the latter case NULL will be sent in 'neighbor_rep'.
5891 * @cb_ctx: Context value to send the callback function
5892 * Returns: 0 in case of success, negative error code otherwise
5893 *
5894 * In case there is a previous request which has not been answered yet, the
5895 * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT.
5896 * Request must contain a callback function.
5897 */
5898int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
5899 const struct wpa_ssid *ssid,
5900 void (*cb)(void *ctx,
5901 struct wpabuf *neighbor_rep),
5902 void *cb_ctx)
5903{
5904 struct wpabuf *buf;
5905 const u8 *rrm_ie;
5906
5907 if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
5908 wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
5909 return -ENOTCONN;
5910 }
5911
5912 if (!wpa_s->rrm.rrm_used) {
5913 wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
5914 return -EOPNOTSUPP;
5915 }
5916
5917 rrm_ie = wpa_bss_get_ie(wpa_s->current_bss,
5918 WLAN_EID_RRM_ENABLED_CAPABILITIES);
5919 if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
5920 !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
5921 wpa_printf(MSG_DEBUG,
5922 "RRM: No network support for Neighbor Report.");
5923 return -EOPNOTSUPP;
5924 }
5925
5926 if (!cb) {
5927 wpa_printf(MSG_DEBUG,
5928 "RRM: Neighbor Report request must provide a callback.");
5929 return -EINVAL;
5930 }
5931
5932 /* Refuse if there's a live request */
5933 if (wpa_s->rrm.notify_neighbor_rep) {
5934 wpa_printf(MSG_DEBUG,
5935 "RRM: Currently handling previous Neighbor Report.");
5936 return -EBUSY;
5937 }
5938
5939 /* 3 = action category + action code + dialog token */
5940 buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
5941 if (buf == NULL) {
5942 wpa_printf(MSG_DEBUG,
5943 "RRM: Failed to allocate Neighbor Report Request");
5944 return -ENOMEM;
5945 }
5946
5947 wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
5948 (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
5949 wpa_s->rrm.next_neighbor_rep_token);
5950
5951 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
5952 wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
5953 wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token);
5954 if (ssid) {
5955 wpabuf_put_u8(buf, WLAN_EID_SSID);
5956 wpabuf_put_u8(buf, ssid->ssid_len);
5957 wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
5958 }
5959
5960 wpa_s->rrm.next_neighbor_rep_token++;
5961
5962 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
5963 wpa_s->own_addr, wpa_s->bssid,
5964 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
5965 wpa_printf(MSG_DEBUG,
5966 "RRM: Failed to send Neighbor Report Request");
5967 wpabuf_free(buf);
5968 return -ECANCELED;
5969 }
5970
5971 wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx;
5972 wpa_s->rrm.notify_neighbor_rep = cb;
5973 eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0,
5974 wpas_rrm_neighbor_rep_timeout_handler,
5975 &wpa_s->rrm, NULL);
5976
5977 wpabuf_free(buf);
5978 return 0;
5979}
5980
5981
5982void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
5983 const u8 *src,
5984 const u8 *frame, size_t len,
5985 int rssi)
5986{
5987 struct wpabuf *buf;
5988 const struct rrm_link_measurement_request *req;
5989 struct rrm_link_measurement_report report;
5990
5991 if (wpa_s->wpa_state != WPA_COMPLETED) {
5992 wpa_printf(MSG_INFO,
5993 "RRM: Ignoring link measurement request. Not associated");
5994 return;
5995 }
5996
5997 if (!wpa_s->rrm.rrm_used) {
5998 wpa_printf(MSG_INFO,
5999 "RRM: Ignoring link measurement request. Not RRM network");
6000 return;
6001 }
6002
6003 if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
6004 wpa_printf(MSG_INFO,
6005 "RRM: Measurement report failed. TX power insertion not supported");
6006 return;
6007 }
6008
6009 req = (const struct rrm_link_measurement_request *) frame;
6010 if (len < sizeof(*req)) {
6011 wpa_printf(MSG_INFO,
6012 "RRM: Link measurement report failed. Request too short");
6013 return;
6014 }
6015
6016 os_memset(&report, 0, sizeof(report));
6017 report.tpc.eid = WLAN_EID_TPC_REPORT;
6018 report.tpc.len = 2;
6019 report.rsni = 255; /* 255 indicates that RSNI is not available */
6020 report.dialog_token = req->dialog_token;
6021
6022 /*
6023 * It's possible to estimate RCPI based on RSSI in dBm. This
6024 * calculation will not reflect the correct value for high rates,
6025 * but it's good enough for Action frames which are transmitted
6026 * with up to 24 Mbps rates.
6027 */
6028 if (!rssi)
6029 report.rcpi = 255; /* not available */
6030 else if (rssi < -110)
6031 report.rcpi = 0;
6032 else if (rssi > 0)
6033 report.rcpi = 220;
6034 else
6035 report.rcpi = (rssi + 110) * 2;
6036
6037 /* action_category + action_code */
6038 buf = wpabuf_alloc(2 + sizeof(report));
6039 if (buf == NULL) {
6040 wpa_printf(MSG_ERROR,
6041 "RRM: Link measurement report failed. Buffer allocation failed");
6042 return;
6043 }
6044
6045 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
6046 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
6047 wpabuf_put_data(buf, &report, sizeof(report));
6048 wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
6049 wpabuf_head(buf), wpabuf_len(buf));
6050
6051 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
6052 wpa_s->own_addr, wpa_s->bssid,
6053 wpabuf_head(buf), wpabuf_len(buf), 0)) {
6054 wpa_printf(MSG_ERROR,
6055 "RRM: Link measurement report failed. Send action failed");
6056 }
6057 wpabuf_free(buf);
6058}