blob: eef3d214f5f0b9e68cdec8ddf1336897be575355 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003 * Copyright (c) 2003-2014, 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"
36#include "p2p/p2p.h"
37#include "blacklist.h"
38#include "wpas_glue.h"
39#include "wps_supplicant.h"
40#include "ibss_rsn.h"
41#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080042#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043#include "ap.h"
44#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070045#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "notify.h"
47#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070048#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "bss.h"
50#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080051#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070052#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070053#include "wnm_sta.h"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070054#include "wpas_kay.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070055
56const char *wpa_supplicant_version =
57"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080058"Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070059
60const char *wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080061"This software may be distributed under the terms of the BSD license.\n"
62"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070063#ifdef EAP_TLS_OPENSSL
64"\nThis product includes software developed by the OpenSSL Project\n"
65"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
66#endif /* EAP_TLS_OPENSSL */
67;
68
69#ifndef CONFIG_NO_STDOUT_DEBUG
70/* Long text divided into parts in order to fit in C89 strings size limits. */
71const char *wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080072"";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070073const char *wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080074"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075"\n"
76"Redistribution and use in source and binary forms, with or without\n"
77"modification, are permitted provided that the following conditions are\n"
78"met:\n"
79"\n";
80const char *wpa_supplicant_full_license3 =
81"1. Redistributions of source code must retain the above copyright\n"
82" notice, this list of conditions and the following disclaimer.\n"
83"\n"
84"2. Redistributions in binary form must reproduce the above copyright\n"
85" notice, this list of conditions and the following disclaimer in the\n"
86" documentation and/or other materials provided with the distribution.\n"
87"\n";
88const char *wpa_supplicant_full_license4 =
89"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
90" names of its contributors may be used to endorse or promote products\n"
91" derived from this software without specific prior written permission.\n"
92"\n"
93"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
94"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
95"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
96"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
97const char *wpa_supplicant_full_license5 =
98"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
99"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
100"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
101"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
102"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
103"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
104"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
105"\n";
106#endif /* CONFIG_NO_STDOUT_DEBUG */
107
Dmitry Shmidt0207e232014-09-03 14:58:37 -0700108struct wowlan_triggers *wpa_get_wowlan_triggers(const char *wowlan_triggers,
109 struct wpa_driver_capa *capa);
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 };
137
138 /* IBSS/WPA-None uses only one key (Group) for both receiving and
139 * sending unicast and multicast packets. */
140
141 if (ssid->mode != WPAS_MODE_IBSS) {
142 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
143 "IBSS/ad-hoc) for WPA-None", ssid->mode);
144 return -1;
145 }
146
147 if (!ssid->psk_set) {
148 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
149 "WPA-None");
150 return -1;
151 }
152
153 switch (wpa_s->group_cipher) {
154 case WPA_CIPHER_CCMP:
155 os_memcpy(key, ssid->psk, 16);
156 keylen = 16;
157 alg = WPA_ALG_CCMP;
158 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700159 case WPA_CIPHER_GCMP:
160 os_memcpy(key, ssid->psk, 16);
161 keylen = 16;
162 alg = WPA_ALG_GCMP;
163 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700164 case WPA_CIPHER_TKIP:
165 /* WPA-None uses the same Michael MIC key for both TX and RX */
166 os_memcpy(key, ssid->psk, 16 + 8);
167 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
168 keylen = 32;
169 alg = WPA_ALG_TKIP;
170 break;
171 default:
172 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
173 "WPA-None", wpa_s->group_cipher);
174 return -1;
175 }
176
177 /* TODO: should actually remember the previously used seq#, both for TX
178 * and RX from each STA.. */
179
180 return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
181}
182
183
184static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
185{
186 struct wpa_supplicant *wpa_s = eloop_ctx;
187 const u8 *bssid = wpa_s->bssid;
188 if (is_zero_ether_addr(bssid))
189 bssid = wpa_s->pending_bssid;
190 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
191 MAC2STR(bssid));
192 wpa_blacklist_add(wpa_s, bssid);
193 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800194 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700195 wpa_s->reassociate = 1;
196
197 /*
198 * If we timed out, the AP or the local radio may be busy.
199 * So, wait a second until scanning again.
200 */
201 wpa_supplicant_req_scan(wpa_s, 1, 0);
202}
203
204
205/**
206 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
207 * @wpa_s: Pointer to wpa_supplicant data
208 * @sec: Number of seconds after which to time out authentication
209 * @usec: Number of microseconds after which to time out authentication
210 *
211 * This function is used to schedule a timeout for the current authentication
212 * attempt.
213 */
214void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
215 int sec, int usec)
216{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700217 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700218 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
219 return;
220
221 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
222 "%d usec", sec, usec);
223 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
224 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
225}
226
227
228/**
229 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
230 * @wpa_s: Pointer to wpa_supplicant data
231 *
232 * This function is used to cancel authentication timeout scheduled with
233 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
234 * been completed.
235 */
236void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
237{
238 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
239 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
240 wpa_blacklist_del(wpa_s, wpa_s->bssid);
241}
242
243
244/**
245 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
246 * @wpa_s: Pointer to wpa_supplicant data
247 *
248 * This function is used to configure EAPOL state machine based on the selected
249 * authentication mode.
250 */
251void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
252{
253#ifdef IEEE8021X_EAPOL
254 struct eapol_config eapol_conf;
255 struct wpa_ssid *ssid = wpa_s->current_ssid;
256
257#ifdef CONFIG_IBSS_RSN
258 if (ssid->mode == WPAS_MODE_IBSS &&
259 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
260 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
261 /*
262 * RSN IBSS authentication is per-STA and we can disable the
263 * per-BSSID EAPOL authentication.
264 */
265 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
266 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
267 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
268 return;
269 }
270#endif /* CONFIG_IBSS_RSN */
271
272 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
273 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
274
275 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
276 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
277 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
278 else
279 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
280
281 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
282 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
283 eapol_conf.accept_802_1x_keys = 1;
284 eapol_conf.required_keys = 0;
285 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
286 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
287 }
288 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
289 eapol_conf.required_keys |=
290 EAPOL_REQUIRE_KEY_BROADCAST;
291 }
292
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700293 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700294 eapol_conf.required_keys = 0;
295 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700296 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700297 eapol_conf.workaround = ssid->eap_workaround;
298 eapol_conf.eap_disabled =
299 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
300 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
301 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700302 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700303 eapol_conf.wps = wpa_s->key_mgmt == WPA_KEY_MGMT_WPS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700304 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
305#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700306
307 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700308}
309
310
311/**
312 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
313 * @wpa_s: Pointer to wpa_supplicant data
314 * @ssid: Configuration data for the network
315 *
316 * This function is used to configure WPA state machine and related parameters
317 * to a mode where WPA is not enabled. This is called as part of the
318 * authentication configuration when the selected network does not use WPA.
319 */
320void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
321 struct wpa_ssid *ssid)
322{
323 int i;
324
325 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
326 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
327 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
328 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
329 else
330 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
331 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
332 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
333 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
334 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
335 wpa_s->group_cipher = WPA_CIPHER_NONE;
336 wpa_s->mgmt_group_cipher = 0;
337
338 for (i = 0; i < NUM_WEP_KEYS; i++) {
339 if (ssid->wep_key_len[i] > 5) {
340 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
341 wpa_s->group_cipher = WPA_CIPHER_WEP104;
342 break;
343 } else if (ssid->wep_key_len[i] > 0) {
344 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
345 wpa_s->group_cipher = WPA_CIPHER_WEP40;
346 break;
347 }
348 }
349
350 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
351 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
352 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
353 wpa_s->pairwise_cipher);
354 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
355#ifdef CONFIG_IEEE80211W
356 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
357 wpa_s->mgmt_group_cipher);
358#endif /* CONFIG_IEEE80211W */
359
360 pmksa_cache_clear_current(wpa_s->wpa);
361}
362
363
Dmitry Shmidt04949592012-07-19 12:16:46 -0700364void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800365{
366 int i;
367 if (wpa_s->hw.modes == NULL)
368 return;
369
370 for (i = 0; i < wpa_s->hw.num_modes; i++) {
371 os_free(wpa_s->hw.modes[i].channels);
372 os_free(wpa_s->hw.modes[i].rates);
373 }
374
375 os_free(wpa_s->hw.modes);
376 wpa_s->hw.modes = NULL;
377}
378
379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700380static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
381{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700382 int i;
383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700384 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700385 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700386 scard_deinit(wpa_s->scard);
387 wpa_s->scard = NULL;
388 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
389 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
390 l2_packet_deinit(wpa_s->l2);
391 wpa_s->l2 = NULL;
392 if (wpa_s->l2_br) {
393 l2_packet_deinit(wpa_s->l2_br);
394 wpa_s->l2_br = NULL;
395 }
396
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700397 if (wpa_s->conf != NULL) {
398 struct wpa_ssid *ssid;
399 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
400 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700401 }
402
403 os_free(wpa_s->confname);
404 wpa_s->confname = NULL;
405
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700406 os_free(wpa_s->confanother);
407 wpa_s->confanother = NULL;
408
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700409 wpa_sm_set_eapol(wpa_s->wpa, NULL);
410 eapol_sm_deinit(wpa_s->eapol);
411 wpa_s->eapol = NULL;
412
413 rsn_preauth_deinit(wpa_s->wpa);
414
415#ifdef CONFIG_TDLS
416 wpa_tdls_deinit(wpa_s->wpa);
417#endif /* CONFIG_TDLS */
418
419 pmksa_candidate_free(wpa_s->wpa);
420 wpa_sm_deinit(wpa_s->wpa);
421 wpa_s->wpa = NULL;
422 wpa_blacklist_clear(wpa_s);
423
424 wpa_bss_deinit(wpa_s);
425
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700426 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700427 wpa_supplicant_cancel_scan(wpa_s);
428 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800429 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
430#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
431 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
432 wpa_s, NULL);
433#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700434
435 wpas_wps_deinit(wpa_s);
436
437 wpabuf_free(wpa_s->pending_eapol_rx);
438 wpa_s->pending_eapol_rx = NULL;
439
440#ifdef CONFIG_IBSS_RSN
441 ibss_rsn_deinit(wpa_s->ibss_rsn);
442 wpa_s->ibss_rsn = NULL;
443#endif /* CONFIG_IBSS_RSN */
444
445 sme_deinit(wpa_s);
446
447#ifdef CONFIG_AP
448 wpa_supplicant_ap_deinit(wpa_s);
449#endif /* CONFIG_AP */
450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700452
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800453#ifdef CONFIG_OFFCHANNEL
454 offchannel_deinit(wpa_s);
455#endif /* CONFIG_OFFCHANNEL */
456
457 wpa_supplicant_cancel_sched_scan(wpa_s);
458
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700459 os_free(wpa_s->next_scan_freqs);
460 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800461
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800462 os_free(wpa_s->manual_scan_freqs);
463 wpa_s->manual_scan_freqs = NULL;
464
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700465 os_free(wpa_s->manual_sched_scan_freqs);
466 wpa_s->manual_sched_scan_freqs = NULL;
467
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800468 gas_query_deinit(wpa_s->gas);
469 wpa_s->gas = NULL;
470
471 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700472
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700473 ieee802_1x_dealloc_kay_sm(wpa_s);
474
Dmitry Shmidt04949592012-07-19 12:16:46 -0700475 os_free(wpa_s->bssid_filter);
476 wpa_s->bssid_filter = NULL;
477
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800478 os_free(wpa_s->disallow_aps_bssid);
479 wpa_s->disallow_aps_bssid = NULL;
480 os_free(wpa_s->disallow_aps_ssid);
481 wpa_s->disallow_aps_ssid = NULL;
482
Dmitry Shmidt04949592012-07-19 12:16:46 -0700483 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700484#ifdef CONFIG_WNM
485 wnm_deallocate_memory(wpa_s);
486#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700487
488 ext_password_deinit(wpa_s->ext_pw);
489 wpa_s->ext_pw = NULL;
490
491 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800492 wpa_s->last_gas_resp = NULL;
493 wpabuf_free(wpa_s->prev_gas_resp);
494 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700495
496 os_free(wpa_s->last_scan_res);
497 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800498
499#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700500 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800501#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700502
503 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
504 wpabuf_free(wpa_s->vendor_elem[i]);
505 wpa_s->vendor_elem[i] = NULL;
506 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700507}
508
509
510/**
511 * wpa_clear_keys - Clear keys configured for the driver
512 * @wpa_s: Pointer to wpa_supplicant data
513 * @addr: Previously used BSSID or %NULL if not available
514 *
515 * This function clears the encryption keys that has been previously configured
516 * for the driver.
517 */
518void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
519{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800520 int i, max;
521
522#ifdef CONFIG_IEEE80211W
523 max = 6;
524#else /* CONFIG_IEEE80211W */
525 max = 4;
526#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700527
528 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800529 for (i = 0; i < max; i++) {
530 if (wpa_s->keys_cleared & BIT(i))
531 continue;
532 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
533 NULL, 0);
534 }
535 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
536 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700537 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
538 0);
539 /* MLME-SETPROTECTION.request(None) */
540 wpa_drv_mlme_setprotection(
541 wpa_s, addr,
542 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
543 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
544 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800545 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700546}
547
548
549/**
550 * wpa_supplicant_state_txt - Get the connection state name as a text string
551 * @state: State (wpa_state; WPA_*)
552 * Returns: The state name as a printable text string
553 */
554const char * wpa_supplicant_state_txt(enum wpa_states state)
555{
556 switch (state) {
557 case WPA_DISCONNECTED:
558 return "DISCONNECTED";
559 case WPA_INACTIVE:
560 return "INACTIVE";
561 case WPA_INTERFACE_DISABLED:
562 return "INTERFACE_DISABLED";
563 case WPA_SCANNING:
564 return "SCANNING";
565 case WPA_AUTHENTICATING:
566 return "AUTHENTICATING";
567 case WPA_ASSOCIATING:
568 return "ASSOCIATING";
569 case WPA_ASSOCIATED:
570 return "ASSOCIATED";
571 case WPA_4WAY_HANDSHAKE:
572 return "4WAY_HANDSHAKE";
573 case WPA_GROUP_HANDSHAKE:
574 return "GROUP_HANDSHAKE";
575 case WPA_COMPLETED:
576 return "COMPLETED";
577 default:
578 return "UNKNOWN";
579 }
580}
581
582
583#ifdef CONFIG_BGSCAN
584
585static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
586{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800587 const char *name;
588
589 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
590 name = wpa_s->current_ssid->bgscan;
591 else
592 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800593 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800594 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800595 if (wpas_driver_bss_selection(wpa_s))
596 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700597 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
598 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800599#ifdef CONFIG_P2P
600 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
601 return;
602#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700603
604 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800605 if (wpa_s->current_ssid) {
606 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700607 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
608 "bgscan");
609 /*
610 * Live without bgscan; it is only used as a roaming
611 * optimization, so the initial connection is not
612 * affected.
613 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700614 } else {
615 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700616 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700617 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
618 0);
619 if (scan_res) {
620 bgscan_notify_scan(wpa_s, scan_res);
621 wpa_scan_results_free(scan_res);
622 }
623 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 } else
625 wpa_s->bgscan_ssid = NULL;
626}
627
628
629static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
630{
631 if (wpa_s->bgscan_ssid != NULL) {
632 bgscan_deinit(wpa_s);
633 wpa_s->bgscan_ssid = NULL;
634 }
635}
636
637#endif /* CONFIG_BGSCAN */
638
639
Dmitry Shmidt04949592012-07-19 12:16:46 -0700640static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
641{
642 if (autoscan_init(wpa_s, 0))
643 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
644}
645
646
647static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
648{
649 autoscan_deinit(wpa_s);
650}
651
652
653void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
654{
655 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
656 wpa_s->wpa_state == WPA_SCANNING) {
657 autoscan_deinit(wpa_s);
658 wpa_supplicant_start_autoscan(wpa_s);
659 }
660}
661
662
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700663/**
664 * wpa_supplicant_set_state - Set current connection state
665 * @wpa_s: Pointer to wpa_supplicant data
666 * @state: The new connection state
667 *
668 * This function is called whenever the connection state changes, e.g.,
669 * association is completed for WPA/WPA2 4-Way Handshake is started.
670 */
671void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
672 enum wpa_states state)
673{
674 enum wpa_states old_state = wpa_s->wpa_state;
675
676 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
677 wpa_supplicant_state_txt(wpa_s->wpa_state),
678 wpa_supplicant_state_txt(state));
679
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800680 if (state == WPA_INTERFACE_DISABLED) {
681 /* Assure normal scan when interface is restored */
682 wpa_s->normal_scans = 0;
683 }
684
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700685 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800686 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700687 /* Reinitialize normal_scan counter */
688 wpa_s->normal_scans = 0;
689 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800690
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691 if (state != WPA_SCANNING)
692 wpa_supplicant_notify_scanning(wpa_s, 0);
693
694 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700695 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700696#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800698 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800699 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700700 ssid ? ssid->id : -1,
701 ssid && ssid->id_str ? ssid->id_str : "");
702#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700703 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800704 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700706 wpa_drv_set_operstate(wpa_s, 1);
707#ifndef IEEE8021X_EAPOL
708 wpa_drv_set_supp_port(wpa_s, 1);
709#endif /* IEEE8021X_EAPOL */
710 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700711 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700712 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700713
714 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700715 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
716 state == WPA_ASSOCIATED) {
717 wpa_s->new_connection = 1;
718 wpa_drv_set_operstate(wpa_s, 0);
719#ifndef IEEE8021X_EAPOL
720 wpa_drv_set_supp_port(wpa_s, 0);
721#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700722 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700723 }
724 wpa_s->wpa_state = state;
725
726#ifdef CONFIG_BGSCAN
727 if (state == WPA_COMPLETED)
728 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800729 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730 wpa_supplicant_stop_bgscan(wpa_s);
731#endif /* CONFIG_BGSCAN */
732
Dmitry Shmidt04949592012-07-19 12:16:46 -0700733 if (state == WPA_AUTHENTICATING)
734 wpa_supplicant_stop_autoscan(wpa_s);
735
736 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
737 wpa_supplicant_start_autoscan(wpa_s);
738
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739 if (wpa_s->wpa_state != old_state) {
740 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
741
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700742 /*
743 * Notify the P2P Device interface about a state change in one
744 * of the interfaces.
745 */
746 wpas_p2p_indicate_state_change(wpa_s);
747
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700748 if (wpa_s->wpa_state == WPA_COMPLETED ||
749 old_state == WPA_COMPLETED)
750 wpas_notify_auth_changed(wpa_s);
751 }
752}
753
754
755void wpa_supplicant_terminate_proc(struct wpa_global *global)
756{
757 int pending = 0;
758#ifdef CONFIG_WPS
759 struct wpa_supplicant *wpa_s = global->ifaces;
760 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800761 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700762 if (wpas_wps_terminate_pending(wpa_s) == 1)
763 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700764#ifdef CONFIG_P2P
765 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
766 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
767 wpas_p2p_disconnect(wpa_s);
768#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800769 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700770 }
771#endif /* CONFIG_WPS */
772 if (pending)
773 return;
774 eloop_terminate();
775}
776
777
778static void wpa_supplicant_terminate(int sig, void *signal_ctx)
779{
780 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781 wpa_supplicant_terminate_proc(global);
782}
783
784
785void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
786{
787 enum wpa_states old_state = wpa_s->wpa_state;
788
789 wpa_s->pairwise_cipher = 0;
790 wpa_s->group_cipher = 0;
791 wpa_s->mgmt_group_cipher = 0;
792 wpa_s->key_mgmt = 0;
793 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700794 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700795
796 if (wpa_s->wpa_state != old_state)
797 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
798}
799
800
801/**
802 * wpa_supplicant_reload_configuration - Reload configuration data
803 * @wpa_s: Pointer to wpa_supplicant data
804 * Returns: 0 on success or -1 if configuration parsing failed
805 *
806 * This function can be used to request that the configuration data is reloaded
807 * (e.g., after configuration file change). This function is reloading
808 * configuration only for one interface, so this may need to be called multiple
809 * times if %wpa_supplicant is controlling multiple interfaces and all
810 * interfaces need reconfiguration.
811 */
812int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
813{
814 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700815 int reconf_ctrl;
816 int old_ap_scan;
817
818 if (wpa_s->confname == NULL)
819 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700820 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700821 if (conf == NULL) {
822 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
823 "file '%s' - exiting", wpa_s->confname);
824 return -1;
825 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700826 wpa_config_read(wpa_s->confanother, conf);
827
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700828 conf->changed_parameters = (unsigned int) -1;
829
830 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
831 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
832 os_strcmp(conf->ctrl_interface,
833 wpa_s->conf->ctrl_interface) != 0);
834
835 if (reconf_ctrl && wpa_s->ctrl_iface) {
836 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
837 wpa_s->ctrl_iface = NULL;
838 }
839
840 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800841 if (wpa_s->current_ssid) {
842 wpa_supplicant_deauthenticate(wpa_s,
843 WLAN_REASON_DEAUTH_LEAVING);
844 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700845
846 /*
847 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
848 * pkcs11_engine_path, pkcs11_module_path.
849 */
850 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
851 /*
852 * Clear forced success to clear EAP state for next
853 * authentication.
854 */
855 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
856 }
857 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
858 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800859 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700860 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
861 rsn_preauth_deinit(wpa_s->wpa);
862
863 old_ap_scan = wpa_s->conf->ap_scan;
864 wpa_config_free(wpa_s->conf);
865 wpa_s->conf = conf;
866 if (old_ap_scan != wpa_s->conf->ap_scan)
867 wpas_notify_ap_scan_changed(wpa_s);
868
869 if (reconf_ctrl)
870 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
871
872 wpa_supplicant_update_config(wpa_s);
873
874 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700875 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876 wpa_s->reassociate = 1;
877 wpa_supplicant_req_scan(wpa_s, 0, 0);
878 }
879 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
880 return 0;
881}
882
883
884static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
885{
886 struct wpa_global *global = signal_ctx;
887 struct wpa_supplicant *wpa_s;
888 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
889 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
890 sig);
891 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
892 wpa_supplicant_terminate_proc(global);
893 }
894 }
895}
896
897
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700898static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
899 struct wpa_ssid *ssid,
900 struct wpa_ie_data *ie)
901{
902 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
903 if (ret) {
904 if (ret == -2) {
905 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
906 "from association info");
907 }
908 return -1;
909 }
910
911 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
912 "cipher suites");
913 if (!(ie->group_cipher & ssid->group_cipher)) {
914 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
915 "cipher 0x%x (mask 0x%x) - reject",
916 ie->group_cipher, ssid->group_cipher);
917 return -1;
918 }
919 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
920 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
921 "cipher 0x%x (mask 0x%x) - reject",
922 ie->pairwise_cipher, ssid->pairwise_cipher);
923 return -1;
924 }
925 if (!(ie->key_mgmt & ssid->key_mgmt)) {
926 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
927 "management 0x%x (mask 0x%x) - reject",
928 ie->key_mgmt, ssid->key_mgmt);
929 return -1;
930 }
931
932#ifdef CONFIG_IEEE80211W
933 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800934 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
935 wpa_s->conf->pmf : ssid->ieee80211w) ==
936 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700937 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
938 "that does not support management frame protection - "
939 "reject");
940 return -1;
941 }
942#endif /* CONFIG_IEEE80211W */
943
944 return 0;
945}
946
947
948/**
949 * wpa_supplicant_set_suites - Set authentication and encryption parameters
950 * @wpa_s: Pointer to wpa_supplicant data
951 * @bss: Scan results for the selected BSS, or %NULL if not available
952 * @ssid: Configuration data for the selected network
953 * @wpa_ie: Buffer for the WPA/RSN IE
954 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
955 * used buffer length in case the functions returns success.
956 * Returns: 0 on success or -1 on failure
957 *
958 * This function is used to configure authentication and encryption parameters
959 * based on the network configuration and scan result for the selected BSS (if
960 * available).
961 */
962int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
963 struct wpa_bss *bss, struct wpa_ssid *ssid,
964 u8 *wpa_ie, size_t *wpa_ie_len)
965{
966 struct wpa_ie_data ie;
967 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800968 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700969
970 if (bss) {
971 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
972 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800973 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800975 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700976
977 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
978 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
979 (ie.group_cipher & ssid->group_cipher) &&
980 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
981 (ie.key_mgmt & ssid->key_mgmt)) {
982 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
983 proto = WPA_PROTO_RSN;
984 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
985 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
986 (ie.group_cipher & ssid->group_cipher) &&
987 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
988 (ie.key_mgmt & ssid->key_mgmt)) {
989 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
990 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800991#ifdef CONFIG_HS20
992 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
993 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
994 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -0700995 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800996 ie.group_cipher = WPA_CIPHER_CCMP;
997 ie.pairwise_cipher = WPA_CIPHER_CCMP;
998 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
999 proto = WPA_PROTO_OSEN;
1000#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001 } else if (bss) {
1002 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
1003 return -1;
1004 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001005 if (ssid->proto & WPA_PROTO_OSEN)
1006 proto = WPA_PROTO_OSEN;
1007 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008 proto = WPA_PROTO_RSN;
1009 else
1010 proto = WPA_PROTO_WPA;
1011 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1012 os_memset(&ie, 0, sizeof(ie));
1013 ie.group_cipher = ssid->group_cipher;
1014 ie.pairwise_cipher = ssid->pairwise_cipher;
1015 ie.key_mgmt = ssid->key_mgmt;
1016#ifdef CONFIG_IEEE80211W
1017 ie.mgmt_group_cipher =
1018 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1019 WPA_CIPHER_AES_128_CMAC : 0;
1020#endif /* CONFIG_IEEE80211W */
1021 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1022 "based on configuration");
1023 } else
1024 proto = ie.proto;
1025 }
1026
1027 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1028 "pairwise %d key_mgmt %d proto %d",
1029 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1030#ifdef CONFIG_IEEE80211W
1031 if (ssid->ieee80211w) {
1032 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1033 ie.mgmt_group_cipher);
1034 }
1035#endif /* CONFIG_IEEE80211W */
1036
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001037 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001038 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1039 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001040 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001041
1042 if (bss || !wpa_s->ap_ies_from_associnfo) {
1043 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1044 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1045 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1046 bss_rsn ? 2 + bss_rsn[1] : 0))
1047 return -1;
1048 }
1049
1050 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001051 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1052 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1054 "cipher");
1055 return -1;
1056 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001057 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1058 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001059
1060 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001061 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1062 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001063 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1064 "cipher");
1065 return -1;
1066 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001067 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1068 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069
1070 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001071#ifdef CONFIG_SAE
1072 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1073 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1074#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075 if (0) {
1076#ifdef CONFIG_IEEE80211R
1077 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1078 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1079 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1080 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1081 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1082 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1083#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001084#ifdef CONFIG_SAE
1085 } else if (sel & WPA_KEY_MGMT_SAE) {
1086 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1087 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1088 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1089 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1090 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1091#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001092#ifdef CONFIG_IEEE80211W
1093 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1094 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1095 wpa_dbg(wpa_s, MSG_DEBUG,
1096 "WPA: using KEY_MGMT 802.1X with SHA256");
1097 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1098 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1099 wpa_dbg(wpa_s, MSG_DEBUG,
1100 "WPA: using KEY_MGMT PSK with SHA256");
1101#endif /* CONFIG_IEEE80211W */
1102 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1103 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1104 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1105 } else if (sel & WPA_KEY_MGMT_PSK) {
1106 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1107 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1108 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1109 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1110 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001111#ifdef CONFIG_HS20
1112 } else if (sel & WPA_KEY_MGMT_OSEN) {
1113 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1114 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1115#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001116 } else {
1117 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1118 "authenticated key management type");
1119 return -1;
1120 }
1121
1122 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1123 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1124 wpa_s->pairwise_cipher);
1125 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1126
1127#ifdef CONFIG_IEEE80211W
1128 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001129 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1130 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001131 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1132 sel = 0;
1133 if (sel & WPA_CIPHER_AES_128_CMAC) {
1134 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1135 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1136 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001137 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1138 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1139 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1140 "BIP-GMAC-128");
1141 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1142 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1143 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1144 "BIP-GMAC-256");
1145 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1146 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1147 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1148 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001149 } else {
1150 wpa_s->mgmt_group_cipher = 0;
1151 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1152 }
1153 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1154 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001155 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1156 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1157 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001158#endif /* CONFIG_IEEE80211W */
1159
1160 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1161 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1162 return -1;
1163 }
1164
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001165 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001166 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001167#ifndef CONFIG_NO_PBKDF2
1168 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1169 ssid->passphrase) {
1170 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001171 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1172 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001173 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1174 psk, PMK_LEN);
1175 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1176 }
1177#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001178#ifdef CONFIG_EXT_PASSWORD
1179 if (ssid->ext_psk) {
1180 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1181 ssid->ext_psk);
1182 char pw_str[64 + 1];
1183 u8 psk[PMK_LEN];
1184
1185 if (pw == NULL) {
1186 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1187 "found from external storage");
1188 return -1;
1189 }
1190
1191 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1192 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1193 "PSK length %d in external storage",
1194 (int) wpabuf_len(pw));
1195 ext_password_free(pw);
1196 return -1;
1197 }
1198
1199 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1200 pw_str[wpabuf_len(pw)] = '\0';
1201
1202#ifndef CONFIG_NO_PBKDF2
1203 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1204 {
1205 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1206 4096, psk, PMK_LEN);
1207 os_memset(pw_str, 0, sizeof(pw_str));
1208 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1209 "external passphrase)",
1210 psk, PMK_LEN);
1211 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1212 } else
1213#endif /* CONFIG_NO_PBKDF2 */
1214 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1215 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1216 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1217 "Invalid PSK hex string");
1218 os_memset(pw_str, 0, sizeof(pw_str));
1219 ext_password_free(pw);
1220 return -1;
1221 }
1222 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1223 } else {
1224 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1225 "PSK available");
1226 os_memset(pw_str, 0, sizeof(pw_str));
1227 ext_password_free(pw);
1228 return -1;
1229 }
1230
1231 os_memset(pw_str, 0, sizeof(pw_str));
1232 ext_password_free(pw);
1233 }
1234#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001235 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1237
1238 return 0;
1239}
1240
1241
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001242static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1243{
1244 *pos = 0x00;
1245
1246 switch (idx) {
1247 case 0: /* Bits 0-7 */
1248 break;
1249 case 1: /* Bits 8-15 */
1250 break;
1251 case 2: /* Bits 16-23 */
1252#ifdef CONFIG_WNM
1253 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1254 *pos |= 0x08; /* Bit 19 - BSS Transition */
1255#endif /* CONFIG_WNM */
1256 break;
1257 case 3: /* Bits 24-31 */
1258#ifdef CONFIG_WNM
1259 *pos |= 0x02; /* Bit 25 - SSID List */
1260#endif /* CONFIG_WNM */
1261#ifdef CONFIG_INTERWORKING
1262 if (wpa_s->conf->interworking)
1263 *pos |= 0x80; /* Bit 31 - Interworking */
1264#endif /* CONFIG_INTERWORKING */
1265 break;
1266 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001267#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001268 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1269 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001270#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001271 break;
1272 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001273#ifdef CONFIG_HS20
1274 if (wpa_s->conf->hs20)
1275 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1276#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001277 break;
1278 case 6: /* Bits 48-55 */
1279 break;
1280 }
1281}
1282
1283
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001284int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001285{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001286 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001287 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001288
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001289 if (len < wpa_s->extended_capa_len)
1290 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001291 if (buflen < (size_t) len + 2) {
1292 wpa_printf(MSG_INFO,
1293 "Not enough room for building extended capabilities element");
1294 return -1;
1295 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001296
1297 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001298 *pos++ = len;
1299 for (i = 0; i < len; i++, pos++) {
1300 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001301
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001302 if (i < wpa_s->extended_capa_len) {
1303 *pos &= ~wpa_s->extended_capa_mask[i];
1304 *pos |= wpa_s->extended_capa[i];
1305 }
1306 }
1307
1308 while (len > 0 && buf[1 + len] == 0) {
1309 len--;
1310 buf[1] = len;
1311 }
1312 if (len == 0)
1313 return 0;
1314
1315 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001316}
1317
1318
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001319static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1320 struct wpa_bss *test_bss)
1321{
1322 struct wpa_bss *bss;
1323
1324 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1325 if (bss == test_bss)
1326 return 1;
1327 }
1328
1329 return 0;
1330}
1331
1332
1333static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1334 struct wpa_ssid *test_ssid)
1335{
1336 struct wpa_ssid *ssid;
1337
1338 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1339 if (ssid == test_ssid)
1340 return 1;
1341 }
1342
1343 return 0;
1344}
1345
1346
1347int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1348 struct wpa_ssid *test_ssid)
1349{
1350 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1351 return 0;
1352
1353 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1354}
1355
1356
1357void wpas_connect_work_free(struct wpa_connect_work *cwork)
1358{
1359 if (cwork == NULL)
1360 return;
1361 os_free(cwork);
1362}
1363
1364
1365void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1366{
1367 struct wpa_connect_work *cwork;
1368 struct wpa_radio_work *work = wpa_s->connect_work;
1369
1370 if (!work)
1371 return;
1372
1373 wpa_s->connect_work = NULL;
1374 cwork = work->ctx;
1375 work->ctx = NULL;
1376 wpas_connect_work_free(cwork);
1377 radio_work_done(work);
1378}
1379
1380
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001381int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1382{
1383 struct os_reltime now;
1384 u8 addr[ETH_ALEN];
1385
1386 os_get_reltime(&now);
1387 if (wpa_s->last_mac_addr_style == style &&
1388 wpa_s->last_mac_addr_change.sec != 0 &&
1389 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1390 wpa_s->conf->rand_addr_lifetime)) {
1391 wpa_msg(wpa_s, MSG_DEBUG,
1392 "Previously selected random MAC address has not yet expired");
1393 return 0;
1394 }
1395
1396 switch (style) {
1397 case 1:
1398 if (random_mac_addr(addr) < 0)
1399 return -1;
1400 break;
1401 case 2:
1402 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1403 if (random_mac_addr_keep_oui(addr) < 0)
1404 return -1;
1405 break;
1406 default:
1407 return -1;
1408 }
1409
1410 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1411 wpa_msg(wpa_s, MSG_INFO,
1412 "Failed to set random MAC address");
1413 return -1;
1414 }
1415
1416 os_get_reltime(&wpa_s->last_mac_addr_change);
1417 wpa_s->mac_addr_changed = 1;
1418 wpa_s->last_mac_addr_style = style;
1419
1420 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1421 wpa_msg(wpa_s, MSG_INFO,
1422 "Could not update MAC address information");
1423 return -1;
1424 }
1425
1426 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1427 MAC2STR(addr));
1428
1429 return 0;
1430}
1431
1432
1433int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1434{
1435 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1436 !wpa_s->conf->preassoc_mac_addr)
1437 return 0;
1438
1439 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1440}
1441
1442
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001443static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1444
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001445/**
1446 * wpa_supplicant_associate - Request association
1447 * @wpa_s: Pointer to wpa_supplicant data
1448 * @bss: Scan results for the selected BSS, or %NULL if not available
1449 * @ssid: Configuration data for the selected network
1450 *
1451 * This function is used to request %wpa_supplicant to associate with a BSS.
1452 */
1453void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1454 struct wpa_bss *bss, struct wpa_ssid *ssid)
1455{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001456 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001457 int rand_style;
1458
1459 if (ssid->mac_addr == -1)
1460 rand_style = wpa_s->conf->mac_addr;
1461 else
1462 rand_style = ssid->mac_addr;
1463
1464 if (wpa_s->last_ssid == ssid) {
1465 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
1466 } else if (rand_style > 0) {
1467 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1468 return;
1469 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1470 } else if (wpa_s->mac_addr_changed) {
1471 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1472 wpa_msg(wpa_s, MSG_INFO,
1473 "Could not restore permanent MAC address");
1474 return;
1475 }
1476 wpa_s->mac_addr_changed = 0;
1477 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1478 wpa_msg(wpa_s, MSG_INFO,
1479 "Could not update MAC address information");
1480 return;
1481 }
1482 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1483 }
1484 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001485
1486#ifdef CONFIG_IBSS_RSN
1487 ibss_rsn_deinit(wpa_s->ibss_rsn);
1488 wpa_s->ibss_rsn = NULL;
1489#endif /* CONFIG_IBSS_RSN */
1490
1491 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1492 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1493#ifdef CONFIG_AP
1494 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1495 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1496 "mode");
1497 return;
1498 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001499 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1500 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001501 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1502 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001503 return;
1504 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505 wpa_s->current_bss = bss;
1506#else /* CONFIG_AP */
1507 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1508 "the build");
1509#endif /* CONFIG_AP */
1510 return;
1511 }
1512
1513#ifdef CONFIG_TDLS
1514 if (bss)
1515 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1516 bss->ie_len);
1517#endif /* CONFIG_TDLS */
1518
1519 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1520 ssid->mode == IEEE80211_MODE_INFRA) {
1521 sme_authenticate(wpa_s, bss, ssid);
1522 return;
1523 }
1524
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001525 if (wpa_s->connect_work) {
1526 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1527 return;
1528 }
1529
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001530 if (radio_work_pending(wpa_s, "connect")) {
1531 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1532 return;
1533 }
1534
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001535 cwork = os_zalloc(sizeof(*cwork));
1536 if (cwork == NULL)
1537 return;
1538
1539 cwork->bss = bss;
1540 cwork->ssid = ssid;
1541
1542 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1543 wpas_start_assoc_cb, cwork) < 0) {
1544 os_free(cwork);
1545 }
1546}
1547
1548
1549static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1550{
1551 struct wpa_connect_work *cwork = work->ctx;
1552 struct wpa_bss *bss = cwork->bss;
1553 struct wpa_ssid *ssid = cwork->ssid;
1554 struct wpa_supplicant *wpa_s = work->wpa_s;
1555 u8 wpa_ie[200];
1556 size_t wpa_ie_len;
1557 int use_crypt, ret, i, bssid_changed;
1558 int algs = WPA_AUTH_ALG_OPEN;
1559 unsigned int cipher_pairwise, cipher_group;
1560 struct wpa_driver_associate_params params;
1561 int wep_keys_set = 0;
1562 int assoc_failed = 0;
1563 struct wpa_ssid *old_ssid;
1564#ifdef CONFIG_HT_OVERRIDES
1565 struct ieee80211_ht_capabilities htcaps;
1566 struct ieee80211_ht_capabilities htcaps_mask;
1567#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001568#ifdef CONFIG_VHT_OVERRIDES
1569 struct ieee80211_vht_capabilities vhtcaps;
1570 struct ieee80211_vht_capabilities vhtcaps_mask;
1571#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001572
1573 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001574 if (work->started) {
1575 wpa_s->connect_work = NULL;
1576
1577 /* cancel possible auth. timeout */
1578 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1579 NULL);
1580 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001581 wpas_connect_work_free(cwork);
1582 return;
1583 }
1584
1585 wpa_s->connect_work = work;
1586
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001587 if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001588 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1589 wpas_connect_work_done(wpa_s);
1590 return;
1591 }
1592
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001593 os_memset(&params, 0, sizeof(params));
1594 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001595 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001596 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001597#ifdef CONFIG_IEEE80211R
1598 const u8 *ie, *md = NULL;
1599#endif /* CONFIG_IEEE80211R */
1600 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1601 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1602 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1603 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1604 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1605 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1606 if (bssid_changed)
1607 wpas_notify_bssid_changed(wpa_s);
1608#ifdef CONFIG_IEEE80211R
1609 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1610 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1611 md = ie + 2;
1612 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1613 if (md) {
1614 /* Prepare for the next transition */
1615 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1616 }
1617#endif /* CONFIG_IEEE80211R */
1618#ifdef CONFIG_WPS
1619 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1620 wpa_s->conf->ap_scan == 2 &&
1621 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1622 /* Use ap_scan==1 style network selection to find the network
1623 */
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001624 wpas_connect_work_done(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001625 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001626 wpa_s->reassociate = 1;
1627 wpa_supplicant_req_scan(wpa_s, 0, 0);
1628 return;
1629#endif /* CONFIG_WPS */
1630 } else {
1631 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1632 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1633 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1634 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001635 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001636 wpa_supplicant_cancel_scan(wpa_s);
1637
1638 /* Starting new association, so clear the possibly used WPA IE from the
1639 * previous association. */
1640 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1641
1642#ifdef IEEE8021X_EAPOL
1643 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1644 if (ssid->leap) {
1645 if (ssid->non_leap == 0)
1646 algs = WPA_AUTH_ALG_LEAP;
1647 else
1648 algs |= WPA_AUTH_ALG_LEAP;
1649 }
1650 }
1651#endif /* IEEE8021X_EAPOL */
1652 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1653 if (ssid->auth_alg) {
1654 algs = ssid->auth_alg;
1655 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1656 "0x%x", algs);
1657 }
1658
1659 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1660 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001661 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001662 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001663 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1664 wpa_s->conf->okc :
1665 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001666 (ssid->proto & WPA_PROTO_RSN);
1667 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001668 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001669 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1670 wpa_ie_len = sizeof(wpa_ie);
1671 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1672 wpa_ie, &wpa_ie_len)) {
1673 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1674 "key management and encryption suites");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001675 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001676 return;
1677 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001678 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1679 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1680 /*
1681 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1682 * use non-WPA since the scan results did not indicate that the
1683 * AP is using WPA or WPA2.
1684 */
1685 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1686 wpa_ie_len = 0;
1687 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001688 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001689 wpa_ie_len = sizeof(wpa_ie);
1690 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1691 wpa_ie, &wpa_ie_len)) {
1692 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1693 "key management and encryption suites (no "
1694 "scan results)");
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001695 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001696 return;
1697 }
1698#ifdef CONFIG_WPS
1699 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1700 struct wpabuf *wps_ie;
1701 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1702 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1703 wpa_ie_len = wpabuf_len(wps_ie);
1704 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1705 } else
1706 wpa_ie_len = 0;
1707 wpabuf_free(wps_ie);
1708 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1709 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1710 params.wps = WPS_MODE_PRIVACY;
1711 else
1712 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001713 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001714#endif /* CONFIG_WPS */
1715 } else {
1716 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1717 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001718 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001719 }
1720
1721#ifdef CONFIG_P2P
1722 if (wpa_s->global->p2p) {
1723 u8 *pos;
1724 size_t len;
1725 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726 pos = wpa_ie + wpa_ie_len;
1727 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001728 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1729 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730 if (res >= 0)
1731 wpa_ie_len += res;
1732 }
1733
1734 wpa_s->cross_connect_disallowed = 0;
1735 if (bss) {
1736 struct wpabuf *p2p;
1737 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1738 if (p2p) {
1739 wpa_s->cross_connect_disallowed =
1740 p2p_get_cross_connect_disallowed(p2p);
1741 wpabuf_free(p2p);
1742 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1743 "connection",
1744 wpa_s->cross_connect_disallowed ?
1745 "disallows" : "allows");
1746 }
1747 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001748
1749 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750#endif /* CONFIG_P2P */
1751
Dmitry Shmidt04949592012-07-19 12:16:46 -07001752#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001753 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001754 struct wpabuf *hs20;
1755 hs20 = wpabuf_alloc(20);
1756 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001757 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001758 size_t len;
1759
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001760 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001761 len = sizeof(wpa_ie) - wpa_ie_len;
1762 if (wpabuf_len(hs20) <= len) {
1763 os_memcpy(wpa_ie + wpa_ie_len,
1764 wpabuf_head(hs20), wpabuf_len(hs20));
1765 wpa_ie_len += wpabuf_len(hs20);
1766 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001767 wpabuf_free(hs20);
1768 }
1769 }
1770#endif /* CONFIG_HS20 */
1771
Dmitry Shmidt56052862013-10-04 10:23:25 -07001772 /*
1773 * Workaround: Add Extended Capabilities element only if the AP
1774 * included this element in Beacon/Probe Response frames. Some older
1775 * APs seem to have interoperability issues if this element is
1776 * included, so while the standard may require us to include the
1777 * element in all cases, it is justifiable to skip it to avoid
1778 * interoperability issues.
1779 */
1780 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001781 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07001782 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001783 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
1784 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07001785 if (ext_capab_len > 0) {
1786 u8 *pos = wpa_ie;
1787 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1788 pos += 2 + pos[1];
1789 os_memmove(pos + ext_capab_len, pos,
1790 wpa_ie_len - (pos - wpa_ie));
1791 wpa_ie_len += ext_capab_len;
1792 os_memcpy(pos, ext_capab, ext_capab_len);
1793 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001794 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001795
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001796 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1797 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001798 cipher_pairwise = wpa_s->pairwise_cipher;
1799 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001800 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1801 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1802 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1803 use_crypt = 0;
1804 if (wpa_set_wep_keys(wpa_s, ssid)) {
1805 use_crypt = 1;
1806 wep_keys_set = 1;
1807 }
1808 }
1809 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1810 use_crypt = 0;
1811
1812#ifdef IEEE8021X_EAPOL
1813 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1814 if ((ssid->eapol_flags &
1815 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1816 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1817 !wep_keys_set) {
1818 use_crypt = 0;
1819 } else {
1820 /* Assume that dynamic WEP-104 keys will be used and
1821 * set cipher suites in order for drivers to expect
1822 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001823 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001824 }
1825 }
1826#endif /* IEEE8021X_EAPOL */
1827
1828 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1829 /* Set the key before (and later after) association */
1830 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1831 }
1832
1833 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1834 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001835 params.ssid = bss->ssid;
1836 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001837 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1838 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1839 MACSTR " freq=%u MHz based on scan results "
1840 "(bssid_set=%d)",
1841 MAC2STR(bss->bssid), bss->freq,
1842 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001843 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001844 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001845 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001846 params.bssid_hint = bss->bssid;
1847 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848 } else {
1849 params.ssid = ssid->ssid;
1850 params.ssid_len = ssid->ssid_len;
1851 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001852
1853 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1854 wpa_s->conf->ap_scan == 2) {
1855 params.bssid = ssid->bssid;
1856 params.fixed_bssid = 1;
1857 }
1858
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001859 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001860 params.freq.freq == 0) {
1861 enum hostapd_hw_mode hw_mode;
1862 u8 channel;
1863
1864 params.freq.freq = ssid->frequency;
1865
1866 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1867 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1868 if (wpa_s->hw.modes[i].mode == hw_mode) {
1869 struct hostapd_hw_modes *mode;
1870
1871 mode = &wpa_s->hw.modes[i];
1872 params.freq.ht_enabled = ht_supported(mode);
1873 break;
1874 }
1875 }
1876 }
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08001877
1878 if (ssid->mode == WPAS_MODE_IBSS) {
1879 if (ssid->beacon_int)
1880 params.beacon_int = ssid->beacon_int;
1881 else
1882 params.beacon_int = wpa_s->conf->beacon_int;
1883 }
1884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885 params.wpa_ie = wpa_ie;
1886 params.wpa_ie_len = wpa_ie_len;
1887 params.pairwise_suite = cipher_pairwise;
1888 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001889 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001890 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891 params.auth_alg = algs;
1892 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001893 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001894 for (i = 0; i < NUM_WEP_KEYS; i++) {
1895 if (ssid->wep_key_len[i])
1896 params.wep_key[i] = ssid->wep_key[i];
1897 params.wep_key_len[i] = ssid->wep_key_len[i];
1898 }
1899 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1900
1901 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001902 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1903 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904 params.passphrase = ssid->passphrase;
1905 if (ssid->psk_set)
1906 params.psk = ssid->psk;
1907 }
1908
1909 params.drop_unencrypted = use_crypt;
1910
1911#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001912 params.mgmt_frame_protection =
1913 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1914 wpa_s->conf->pmf : ssid->ieee80211w;
1915 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001916 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1917 struct wpa_ie_data ie;
1918 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1919 ie.capabilities &
1920 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1921 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1922 "MFP: require MFP");
1923 params.mgmt_frame_protection =
1924 MGMT_FRAME_PROTECTION_REQUIRED;
1925 }
1926 }
1927#endif /* CONFIG_IEEE80211W */
1928
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001929 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001930
1931 if (wpa_s->parent->set_sta_uapsd)
1932 params.uapsd = wpa_s->parent->sta_uapsd;
1933 else
1934 params.uapsd = -1;
1935
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001936#ifdef CONFIG_HT_OVERRIDES
1937 os_memset(&htcaps, 0, sizeof(htcaps));
1938 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1939 params.htcaps = (u8 *) &htcaps;
1940 params.htcaps_mask = (u8 *) &htcaps_mask;
1941 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1942#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001943#ifdef CONFIG_VHT_OVERRIDES
1944 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
1945 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
1946 params.vhtcaps = &vhtcaps;
1947 params.vhtcaps_mask = &vhtcaps_mask;
1948 wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
1949#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001950
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001951#ifdef CONFIG_P2P
1952 /*
1953 * If multi-channel concurrency is not supported, check for any
1954 * frequency conflict. In case of any frequency conflict, remove the
1955 * least prioritized connection.
1956 */
1957 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001958 int freq, num;
1959 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001960 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001961 wpa_printf(MSG_DEBUG,
1962 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001963 freq, params.freq.freq);
1964 if (wpas_p2p_handle_frequency_conflicts(
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001965 wpa_s, params.freq.freq, ssid) < 0) {
1966 wpas_connect_work_done(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001967 return;
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001968 }
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001969 }
1970 }
1971#endif /* CONFIG_P2P */
1972
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001973 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974 if (ret < 0) {
1975 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1976 "failed");
1977 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1978 /*
1979 * The driver is known to mean what is saying, so we
1980 * can stop right here; the association will not
1981 * succeed.
1982 */
1983 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001984 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001985 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1986 return;
1987 }
1988 /* try to continue anyway; new association will be tried again
1989 * after timeout */
1990 assoc_failed = 1;
1991 }
1992
1993 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1994 /* Set the key after the association just in case association
1995 * cleared the previously configured key. */
1996 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1997 /* No need to timeout authentication since there is no key
1998 * management. */
1999 wpa_supplicant_cancel_auth_timeout(wpa_s);
2000 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
2001#ifdef CONFIG_IBSS_RSN
2002 } else if (ssid->mode == WPAS_MODE_IBSS &&
2003 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
2004 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2005 /*
2006 * RSN IBSS authentication is per-STA and we can disable the
2007 * per-BSSID authentication.
2008 */
2009 wpa_supplicant_cancel_auth_timeout(wpa_s);
2010#endif /* CONFIG_IBSS_RSN */
2011 } else {
2012 /* Timeout for IEEE 802.11 authentication and association */
2013 int timeout = 60;
2014
2015 if (assoc_failed) {
2016 /* give IBSS a bit more time */
2017 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2018 } else if (wpa_s->conf->ap_scan == 1) {
2019 /* give IBSS a bit more time */
2020 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2021 }
2022 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2023 }
2024
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002025 if (wep_keys_set &&
2026 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002027 /* Set static WEP keys again */
2028 wpa_set_wep_keys(wpa_s, ssid);
2029 }
2030
2031 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2032 /*
2033 * Do not allow EAP session resumption between different
2034 * network configurations.
2035 */
2036 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2037 }
2038 old_ssid = wpa_s->current_ssid;
2039 wpa_s->current_ssid = ssid;
2040 wpa_s->current_bss = bss;
2041 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2042 wpa_supplicant_initiate_eapol(wpa_s);
2043 if (old_ssid != wpa_s->current_ssid)
2044 wpas_notify_network_changed(wpa_s);
2045}
2046
2047
2048static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2049 const u8 *addr)
2050{
2051 struct wpa_ssid *old_ssid;
2052
2053 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002055 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002056 wpa_sm_set_config(wpa_s->wpa, NULL);
2057 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2058 if (old_ssid != wpa_s->current_ssid)
2059 wpas_notify_network_changed(wpa_s);
2060 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2061}
2062
2063
2064/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002065 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2066 * @wpa_s: Pointer to wpa_supplicant data
2067 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2068 *
2069 * This function is used to request %wpa_supplicant to deauthenticate from the
2070 * current AP.
2071 */
2072void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2073 int reason_code)
2074{
2075 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002076 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002077 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002078
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002079 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2080 " pending_bssid=" MACSTR " reason=%d state=%s",
2081 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2082 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2083
2084 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002085 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002086 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2087 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2088 wpa_s->wpa_state == WPA_ASSOCIATING))
2089 addr = wpa_s->pending_bssid;
2090 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2091 /*
2092 * When using driver-based BSS selection, we may not know the
2093 * BSSID with which we are currently trying to associate. We
2094 * need to notify the driver of this disconnection even in such
2095 * a case, so use the all zeros address here.
2096 */
2097 addr = wpa_s->bssid;
2098 zero_addr = 1;
2099 }
2100
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002101#ifdef CONFIG_TDLS
2102 wpa_tdls_teardown_peers(wpa_s->wpa);
2103#endif /* CONFIG_TDLS */
2104
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002105 if (addr) {
2106 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002107 os_memset(&event, 0, sizeof(event));
2108 event.deauth_info.reason_code = (u16) reason_code;
2109 event.deauth_info.locally_generated = 1;
2110 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002111 if (zero_addr)
2112 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002113 }
2114
2115 wpa_supplicant_clear_connection(wpa_s, addr);
2116}
2117
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002118static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2119 struct wpa_ssid *ssid)
2120{
2121 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2122 return;
2123
2124 ssid->disabled = 0;
2125 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2126 wpas_notify_network_enabled_changed(wpa_s, ssid);
2127
2128 /*
2129 * Try to reassociate since there is no current configuration and a new
2130 * network was made available.
2131 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002132 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002133 wpa_s->reassociate = 1;
2134}
2135
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002136
2137/**
2138 * wpa_supplicant_enable_network - Mark a configured network as enabled
2139 * @wpa_s: wpa_supplicant structure for a network interface
2140 * @ssid: wpa_ssid structure for a configured network or %NULL
2141 *
2142 * Enables the specified network or all networks if no network specified.
2143 */
2144void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2145 struct wpa_ssid *ssid)
2146{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002147 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002148 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2149 wpa_supplicant_enable_one_network(wpa_s, ssid);
2150 } else
2151 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002153 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002154 if (wpa_s->sched_scanning) {
2155 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2156 "new network to scan filters");
2157 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002158 }
2159
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002160 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2161 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002162 }
2163}
2164
2165
2166/**
2167 * wpa_supplicant_disable_network - Mark a configured network as disabled
2168 * @wpa_s: wpa_supplicant structure for a network interface
2169 * @ssid: wpa_ssid structure for a configured network or %NULL
2170 *
2171 * Disables the specified network or all networks if no network specified.
2172 */
2173void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2174 struct wpa_ssid *ssid)
2175{
2176 struct wpa_ssid *other_ssid;
2177 int was_disabled;
2178
2179 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002180 if (wpa_s->sched_scanning)
2181 wpa_supplicant_cancel_sched_scan(wpa_s);
2182
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002183 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2184 other_ssid = other_ssid->next) {
2185 was_disabled = other_ssid->disabled;
2186 if (was_disabled == 2)
2187 continue; /* do not change persistent P2P group
2188 * data */
2189
2190 other_ssid->disabled = 1;
2191
2192 if (was_disabled != other_ssid->disabled)
2193 wpas_notify_network_enabled_changed(
2194 wpa_s, other_ssid);
2195 }
2196 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002197 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002198 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2199 } else if (ssid->disabled != 2) {
2200 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002201 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002202 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2203
2204 was_disabled = ssid->disabled;
2205
2206 ssid->disabled = 1;
2207
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002208 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002209 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002210 if (wpa_s->sched_scanning) {
2211 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2212 "to remove network from filters");
2213 wpa_supplicant_cancel_sched_scan(wpa_s);
2214 wpa_supplicant_req_scan(wpa_s, 0, 0);
2215 }
2216 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002217 }
2218}
2219
2220
2221/**
2222 * wpa_supplicant_select_network - Attempt association with a network
2223 * @wpa_s: wpa_supplicant structure for a network interface
2224 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2225 */
2226void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2227 struct wpa_ssid *ssid)
2228{
2229
2230 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002231 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002232
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002233 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002234 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002235 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002236 disconnected = 1;
2237 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002238
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002239 if (ssid)
2240 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2241
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002242 /*
2243 * Mark all other networks disabled or mark all networks enabled if no
2244 * network specified.
2245 */
2246 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2247 other_ssid = other_ssid->next) {
2248 int was_disabled = other_ssid->disabled;
2249 if (was_disabled == 2)
2250 continue; /* do not change persistent P2P group data */
2251
2252 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002253 if (was_disabled && !other_ssid->disabled)
2254 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002255
2256 if (was_disabled != other_ssid->disabled)
2257 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2258 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002259
2260 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2261 /* We are already associated with the selected network */
2262 wpa_printf(MSG_DEBUG, "Already associated with the "
2263 "selected network - do nothing");
2264 return;
2265 }
2266
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002267 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002268 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002269 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2270 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002271 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002272 wpa_s->disconnected = 0;
2273 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002274
2275 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2276 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002277
2278 if (ssid)
2279 wpas_notify_network_selected(wpa_s, ssid);
2280}
2281
2282
2283/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002284 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2285 * @wpa_s: wpa_supplicant structure for a network interface
2286 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2287 * @pkcs11_module_path: PKCS #11 module path or NULL
2288 * Returns: 0 on success; -1 on failure
2289 *
2290 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2291 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2292 * module path fails the paths will be reset to the default value (NULL).
2293 */
2294int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2295 const char *pkcs11_engine_path,
2296 const char *pkcs11_module_path)
2297{
2298 char *pkcs11_engine_path_copy = NULL;
2299 char *pkcs11_module_path_copy = NULL;
2300
2301 if (pkcs11_engine_path != NULL) {
2302 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2303 if (pkcs11_engine_path_copy == NULL)
2304 return -1;
2305 }
2306 if (pkcs11_module_path != NULL) {
2307 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002308 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002309 os_free(pkcs11_engine_path_copy);
2310 return -1;
2311 }
2312 }
2313
2314 os_free(wpa_s->conf->pkcs11_engine_path);
2315 os_free(wpa_s->conf->pkcs11_module_path);
2316 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2317 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2318
2319 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2320 eapol_sm_deinit(wpa_s->eapol);
2321 wpa_s->eapol = NULL;
2322 if (wpa_supplicant_init_eapol(wpa_s)) {
2323 /* Error -> Reset paths to the default value (NULL) once. */
2324 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2325 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2326 NULL);
2327
2328 return -1;
2329 }
2330 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2331
2332 return 0;
2333}
2334
2335
2336/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002337 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2338 * @wpa_s: wpa_supplicant structure for a network interface
2339 * @ap_scan: AP scan mode
2340 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2341 *
2342 */
2343int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2344{
2345
2346 int old_ap_scan;
2347
2348 if (ap_scan < 0 || ap_scan > 2)
2349 return -1;
2350
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002351#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002352 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2353 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2354 wpa_s->wpa_state < WPA_COMPLETED) {
2355 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2356 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002357 return 0;
2358 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002359#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002360
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002361 old_ap_scan = wpa_s->conf->ap_scan;
2362 wpa_s->conf->ap_scan = ap_scan;
2363
2364 if (old_ap_scan != wpa_s->conf->ap_scan)
2365 wpas_notify_ap_scan_changed(wpa_s);
2366
2367 return 0;
2368}
2369
2370
2371/**
2372 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2373 * @wpa_s: wpa_supplicant structure for a network interface
2374 * @expire_age: Expiration age in seconds
2375 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2376 *
2377 */
2378int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2379 unsigned int bss_expire_age)
2380{
2381 if (bss_expire_age < 10) {
2382 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2383 bss_expire_age);
2384 return -1;
2385 }
2386 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2387 bss_expire_age);
2388 wpa_s->conf->bss_expiration_age = bss_expire_age;
2389
2390 return 0;
2391}
2392
2393
2394/**
2395 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2396 * @wpa_s: wpa_supplicant structure for a network interface
2397 * @expire_count: number of scans after which an unseen BSS is reclaimed
2398 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2399 *
2400 */
2401int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2402 unsigned int bss_expire_count)
2403{
2404 if (bss_expire_count < 1) {
2405 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2406 bss_expire_count);
2407 return -1;
2408 }
2409 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2410 bss_expire_count);
2411 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2412
2413 return 0;
2414}
2415
2416
2417/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002418 * wpa_supplicant_set_scan_interval - Set scan interval
2419 * @wpa_s: wpa_supplicant structure for a network interface
2420 * @scan_interval: scan interval in seconds
2421 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2422 *
2423 */
2424int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2425 int scan_interval)
2426{
2427 if (scan_interval < 0) {
2428 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2429 scan_interval);
2430 return -1;
2431 }
2432 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2433 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002434 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002435
2436 return 0;
2437}
2438
2439
2440/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441 * wpa_supplicant_set_debug_params - Set global debug params
2442 * @global: wpa_global structure
2443 * @debug_level: debug level
2444 * @debug_timestamp: determines if show timestamp in debug data
2445 * @debug_show_keys: determines if show keys in debug data
2446 * Returns: 0 if succeed or -1 if debug_level has wrong value
2447 */
2448int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2449 int debug_timestamp, int debug_show_keys)
2450{
2451
2452 int old_level, old_timestamp, old_show_keys;
2453
2454 /* check for allowed debuglevels */
2455 if (debug_level != MSG_EXCESSIVE &&
2456 debug_level != MSG_MSGDUMP &&
2457 debug_level != MSG_DEBUG &&
2458 debug_level != MSG_INFO &&
2459 debug_level != MSG_WARNING &&
2460 debug_level != MSG_ERROR)
2461 return -1;
2462
2463 old_level = wpa_debug_level;
2464 old_timestamp = wpa_debug_timestamp;
2465 old_show_keys = wpa_debug_show_keys;
2466
2467 wpa_debug_level = debug_level;
2468 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2469 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2470
2471 if (wpa_debug_level != old_level)
2472 wpas_notify_debug_level_changed(global);
2473 if (wpa_debug_timestamp != old_timestamp)
2474 wpas_notify_debug_timestamp_changed(global);
2475 if (wpa_debug_show_keys != old_show_keys)
2476 wpas_notify_debug_show_keys_changed(global);
2477
2478 return 0;
2479}
2480
2481
2482/**
2483 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2484 * @wpa_s: Pointer to wpa_supplicant data
2485 * Returns: A pointer to the current network structure or %NULL on failure
2486 */
2487struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2488{
2489 struct wpa_ssid *entry;
2490 u8 ssid[MAX_SSID_LEN];
2491 int res;
2492 size_t ssid_len;
2493 u8 bssid[ETH_ALEN];
2494 int wired;
2495
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002496 res = wpa_drv_get_ssid(wpa_s, ssid);
2497 if (res < 0) {
2498 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2499 "driver");
2500 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002502 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002503
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002504 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2506 "driver");
2507 return NULL;
2508 }
2509
2510 wired = wpa_s->conf->ap_scan == 0 &&
2511 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2512
2513 entry = wpa_s->conf->ssid;
2514 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002515 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 ((ssid_len == entry->ssid_len &&
2517 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2518 (!entry->bssid_set ||
2519 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2520 return entry;
2521#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002522 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2524 (entry->ssid == NULL || entry->ssid_len == 0) &&
2525 (!entry->bssid_set ||
2526 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2527 return entry;
2528#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002529
Dmitry Shmidt04949592012-07-19 12:16:46 -07002530 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002531 entry->ssid_len == 0 &&
2532 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2533 return entry;
2534
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002535 entry = entry->next;
2536 }
2537
2538 return NULL;
2539}
2540
2541
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002542static int select_driver(struct wpa_supplicant *wpa_s, int i)
2543{
2544 struct wpa_global *global = wpa_s->global;
2545
2546 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2547 global->drv_priv[i] = wpa_drivers[i]->global_init();
2548 if (global->drv_priv[i] == NULL) {
2549 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2550 "'%s'", wpa_drivers[i]->name);
2551 return -1;
2552 }
2553 }
2554
2555 wpa_s->driver = wpa_drivers[i];
2556 wpa_s->global_drv_priv = global->drv_priv[i];
2557
2558 return 0;
2559}
2560
2561
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002562static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2563 const char *name)
2564{
2565 int i;
2566 size_t len;
2567 const char *pos, *driver = name;
2568
2569 if (wpa_s == NULL)
2570 return -1;
2571
2572 if (wpa_drivers[0] == NULL) {
2573 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2574 "wpa_supplicant");
2575 return -1;
2576 }
2577
2578 if (name == NULL) {
2579 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002580 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 }
2582
2583 do {
2584 pos = os_strchr(driver, ',');
2585 if (pos)
2586 len = pos - driver;
2587 else
2588 len = os_strlen(driver);
2589
2590 for (i = 0; wpa_drivers[i]; i++) {
2591 if (os_strlen(wpa_drivers[i]->name) == len &&
2592 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002593 0) {
2594 /* First driver that succeeds wins */
2595 if (select_driver(wpa_s, i) == 0)
2596 return 0;
2597 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598 }
2599
2600 driver = pos + 1;
2601 } while (pos);
2602
2603 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2604 return -1;
2605}
2606
2607
2608/**
2609 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2610 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2611 * with struct wpa_driver_ops::init()
2612 * @src_addr: Source address of the EAPOL frame
2613 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2614 * @len: Length of the EAPOL data
2615 *
2616 * This function is called for each received EAPOL frame. Most driver
2617 * interfaces rely on more generic OS mechanism for receiving frames through
2618 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2619 * take care of received EAPOL frames and deliver them to the core supplicant
2620 * code by calling this function.
2621 */
2622void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2623 const u8 *buf, size_t len)
2624{
2625 struct wpa_supplicant *wpa_s = ctx;
2626
2627 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2628 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2629
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002630#ifdef CONFIG_PEERKEY
2631 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2632 wpa_s->current_ssid->peerkey &&
2633 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2634 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2635 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2636 return;
2637 }
2638#endif /* CONFIG_PEERKEY */
2639
Jouni Malinena05074c2012-12-21 21:35:35 +02002640 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2641 (wpa_s->last_eapol_matches_bssid &&
2642#ifdef CONFIG_AP
2643 !wpa_s->ap_iface &&
2644#endif /* CONFIG_AP */
2645 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 /*
2647 * There is possible race condition between receiving the
2648 * association event and the EAPOL frame since they are coming
2649 * through different paths from the driver. In order to avoid
2650 * issues in trying to process the EAPOL frame before receiving
2651 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002652 * the association event is received. This may also be needed in
2653 * driver-based roaming case, so also use src_addr != BSSID as a
2654 * trigger if we have previously confirmed that the
2655 * Authenticator uses BSSID as the src_addr (which is not the
2656 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 */
2658 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002659 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2660 wpa_supplicant_state_txt(wpa_s->wpa_state),
2661 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002662 wpabuf_free(wpa_s->pending_eapol_rx);
2663 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2664 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002665 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002666 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2667 ETH_ALEN);
2668 }
2669 return;
2670 }
2671
Jouni Malinena05074c2012-12-21 21:35:35 +02002672 wpa_s->last_eapol_matches_bssid =
2673 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2674
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675#ifdef CONFIG_AP
2676 if (wpa_s->ap_iface) {
2677 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2678 return;
2679 }
2680#endif /* CONFIG_AP */
2681
2682 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2683 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2684 "no key management is configured");
2685 return;
2686 }
2687
2688 if (wpa_s->eapol_received == 0 &&
2689 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2690 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2691 wpa_s->wpa_state != WPA_COMPLETED) &&
2692 (wpa_s->current_ssid == NULL ||
2693 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2694 /* Timeout for completing IEEE 802.1X and WPA authentication */
2695 wpa_supplicant_req_auth_timeout(
2696 wpa_s,
2697 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2698 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2699 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2700 70 : 10, 0);
2701 }
2702 wpa_s->eapol_received++;
2703
2704 if (wpa_s->countermeasures) {
2705 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2706 "EAPOL packet");
2707 return;
2708 }
2709
2710#ifdef CONFIG_IBSS_RSN
2711 if (wpa_s->current_ssid &&
2712 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2713 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2714 return;
2715 }
2716#endif /* CONFIG_IBSS_RSN */
2717
2718 /* Source address of the incoming EAPOL frame could be compared to the
2719 * current BSSID. However, it is possible that a centralized
2720 * Authenticator could be using another MAC address than the BSSID of
2721 * an AP, so just allow any address to be used for now. The replies are
2722 * still sent to the current BSSID (if available), though. */
2723
2724 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2725 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2726 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2727 return;
2728 wpa_drv_poll(wpa_s);
2729 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2730 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2731 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2732 /*
2733 * Set portValid = TRUE here since we are going to skip 4-way
2734 * handshake processing which would normally set portValid. We
2735 * need this to allow the EAPOL state machines to be completed
2736 * without going through EAPOL-Key handshake.
2737 */
2738 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2739 }
2740}
2741
2742
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002743int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002744{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002745 if (wpa_s->driver->send_eapol) {
2746 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2747 if (addr)
2748 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002749 } else if ((!wpa_s->p2p_mgmt ||
2750 !(wpa_s->drv_flags &
2751 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2752 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002753 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002754 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2756 wpa_drv_get_mac_addr(wpa_s),
2757 ETH_P_EAPOL,
2758 wpa_supplicant_rx_eapol, wpa_s, 0);
2759 if (wpa_s->l2 == NULL)
2760 return -1;
2761 } else {
2762 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2763 if (addr)
2764 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2765 }
2766
2767 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2768 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2769 return -1;
2770 }
2771
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002772 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2773
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002774 return 0;
2775}
2776
2777
Dmitry Shmidt04949592012-07-19 12:16:46 -07002778static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2779 const u8 *buf, size_t len)
2780{
2781 struct wpa_supplicant *wpa_s = ctx;
2782 const struct l2_ethhdr *eth;
2783
2784 if (len < sizeof(*eth))
2785 return;
2786 eth = (const struct l2_ethhdr *) buf;
2787
2788 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2789 !(eth->h_dest[0] & 0x01)) {
2790 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2791 " (bridge - not for this interface - ignore)",
2792 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2793 return;
2794 }
2795
2796 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2797 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2798 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2799 len - sizeof(*eth));
2800}
2801
2802
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002803/**
2804 * wpa_supplicant_driver_init - Initialize driver interface parameters
2805 * @wpa_s: Pointer to wpa_supplicant data
2806 * Returns: 0 on success, -1 on failure
2807 *
2808 * This function is called to initialize driver interface parameters.
2809 * wpa_drv_init() must have been called before this function to initialize the
2810 * driver interface.
2811 */
2812int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2813{
2814 static int interface_count = 0;
2815
2816 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2817 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002818
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002819 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2820 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002821 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002822 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2823
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824 if (wpa_s->bridge_ifname[0]) {
2825 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2826 "interface '%s'", wpa_s->bridge_ifname);
2827 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2828 wpa_s->own_addr,
2829 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002830 wpa_supplicant_rx_eapol_bridge,
2831 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002832 if (wpa_s->l2_br == NULL) {
2833 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2834 "connection for the bridge interface '%s'",
2835 wpa_s->bridge_ifname);
2836 return -1;
2837 }
2838 }
2839
2840 wpa_clear_keys(wpa_s, NULL);
2841
2842 /* Make sure that TKIP countermeasures are not left enabled (could
2843 * happen if wpa_supplicant is killed during countermeasures. */
2844 wpa_drv_set_countermeasures(wpa_s, 0);
2845
2846 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2847 wpa_drv_flush_pmkid(wpa_s);
2848
2849 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002850 wpa_s->prev_scan_wildcard = 0;
2851
Dmitry Shmidt04949592012-07-19 12:16:46 -07002852 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002853 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2854 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2855 interface_count = 0;
2856 }
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002857 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07002858 wpa_supplicant_delayed_sched_scan(wpa_s,
2859 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002860 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07002861 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002862 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002863 interface_count++;
2864 } else
2865 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2866
2867 return 0;
2868}
2869
2870
2871static int wpa_supplicant_daemon(const char *pid_file)
2872{
2873 wpa_printf(MSG_DEBUG, "Daemonize..");
2874 return os_daemonize(pid_file);
2875}
2876
2877
2878static struct wpa_supplicant * wpa_supplicant_alloc(void)
2879{
2880 struct wpa_supplicant *wpa_s;
2881
2882 wpa_s = os_zalloc(sizeof(*wpa_s));
2883 if (wpa_s == NULL)
2884 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002885 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002886 wpa_s->scan_interval = 5;
2887 wpa_s->new_connection = 1;
2888 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002889 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002890
2891 return wpa_s;
2892}
2893
2894
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002895#ifdef CONFIG_HT_OVERRIDES
2896
2897static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2898 struct ieee80211_ht_capabilities *htcaps,
2899 struct ieee80211_ht_capabilities *htcaps_mask,
2900 const char *ht_mcs)
2901{
2902 /* parse ht_mcs into hex array */
2903 int i;
2904 const char *tmp = ht_mcs;
2905 char *end = NULL;
2906
2907 /* If ht_mcs is null, do not set anything */
2908 if (!ht_mcs)
2909 return 0;
2910
2911 /* This is what we are setting in the kernel */
2912 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2913
2914 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2915
2916 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2917 errno = 0;
2918 long v = strtol(tmp, &end, 16);
2919 if (errno == 0) {
2920 wpa_msg(wpa_s, MSG_DEBUG,
2921 "htcap value[%i]: %ld end: %p tmp: %p",
2922 i, v, end, tmp);
2923 if (end == tmp)
2924 break;
2925
2926 htcaps->supported_mcs_set[i] = v;
2927 tmp = end;
2928 } else {
2929 wpa_msg(wpa_s, MSG_ERROR,
2930 "Failed to parse ht-mcs: %s, error: %s\n",
2931 ht_mcs, strerror(errno));
2932 return -1;
2933 }
2934 }
2935
2936 /*
2937 * If we were able to parse any values, then set mask for the MCS set.
2938 */
2939 if (i) {
2940 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2941 IEEE80211_HT_MCS_MASK_LEN - 1);
2942 /* skip the 3 reserved bits */
2943 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2944 0x1f;
2945 }
2946
2947 return 0;
2948}
2949
2950
2951static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2952 struct ieee80211_ht_capabilities *htcaps,
2953 struct ieee80211_ht_capabilities *htcaps_mask,
2954 int disabled)
2955{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002956 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002957
2958 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2959
2960 if (disabled == -1)
2961 return 0;
2962
2963 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2964 htcaps_mask->ht_capabilities_info |= msk;
2965 if (disabled)
2966 htcaps->ht_capabilities_info &= msk;
2967 else
2968 htcaps->ht_capabilities_info |= msk;
2969
2970 return 0;
2971}
2972
2973
2974static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2975 struct ieee80211_ht_capabilities *htcaps,
2976 struct ieee80211_ht_capabilities *htcaps_mask,
2977 int factor)
2978{
2979 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2980
2981 if (factor == -1)
2982 return 0;
2983
2984 if (factor < 0 || factor > 3) {
2985 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2986 "Must be 0-3 or -1", factor);
2987 return -EINVAL;
2988 }
2989
2990 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2991 htcaps->a_mpdu_params &= ~0x3;
2992 htcaps->a_mpdu_params |= factor & 0x3;
2993
2994 return 0;
2995}
2996
2997
2998static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2999 struct ieee80211_ht_capabilities *htcaps,
3000 struct ieee80211_ht_capabilities *htcaps_mask,
3001 int density)
3002{
3003 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
3004
3005 if (density == -1)
3006 return 0;
3007
3008 if (density < 0 || density > 7) {
3009 wpa_msg(wpa_s, MSG_ERROR,
3010 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3011 density);
3012 return -EINVAL;
3013 }
3014
3015 htcaps_mask->a_mpdu_params |= 0x1C;
3016 htcaps->a_mpdu_params &= ~(0x1C);
3017 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3018
3019 return 0;
3020}
3021
3022
3023static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3024 struct ieee80211_ht_capabilities *htcaps,
3025 struct ieee80211_ht_capabilities *htcaps_mask,
3026 int disabled)
3027{
3028 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003029 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3030 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003031
3032 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3033
3034 if (disabled)
3035 htcaps->ht_capabilities_info &= ~msk;
3036 else
3037 htcaps->ht_capabilities_info |= msk;
3038
3039 htcaps_mask->ht_capabilities_info |= msk;
3040
3041 return 0;
3042}
3043
3044
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003045static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3046 struct ieee80211_ht_capabilities *htcaps,
3047 struct ieee80211_ht_capabilities *htcaps_mask,
3048 int disabled)
3049{
3050 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003051 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3052 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003053
3054 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3055
3056 if (disabled)
3057 htcaps->ht_capabilities_info &= ~msk;
3058 else
3059 htcaps->ht_capabilities_info |= msk;
3060
3061 htcaps_mask->ht_capabilities_info |= msk;
3062
3063 return 0;
3064}
3065
3066
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003067static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3068 struct ieee80211_ht_capabilities *htcaps,
3069 struct ieee80211_ht_capabilities *htcaps_mask,
3070 int disabled)
3071{
3072 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003073 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003074
3075 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3076
3077 if (disabled)
3078 htcaps->ht_capabilities_info &= ~msk;
3079 else
3080 htcaps->ht_capabilities_info |= msk;
3081
3082 htcaps_mask->ht_capabilities_info |= msk;
3083
3084 return 0;
3085}
3086
3087
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003088void wpa_supplicant_apply_ht_overrides(
3089 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3090 struct wpa_driver_associate_params *params)
3091{
3092 struct ieee80211_ht_capabilities *htcaps;
3093 struct ieee80211_ht_capabilities *htcaps_mask;
3094
3095 if (!ssid)
3096 return;
3097
3098 params->disable_ht = ssid->disable_ht;
3099 if (!params->htcaps || !params->htcaps_mask)
3100 return;
3101
3102 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3103 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3104 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3105 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3106 ssid->disable_max_amsdu);
3107 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3108 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3109 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003110 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003111 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003112
3113 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003114 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003115 htcaps->ht_capabilities_info |= bit;
3116 htcaps_mask->ht_capabilities_info |= bit;
3117 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003118}
3119
3120#endif /* CONFIG_HT_OVERRIDES */
3121
3122
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003123#ifdef CONFIG_VHT_OVERRIDES
3124void wpa_supplicant_apply_vht_overrides(
3125 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3126 struct wpa_driver_associate_params *params)
3127{
3128 struct ieee80211_vht_capabilities *vhtcaps;
3129 struct ieee80211_vht_capabilities *vhtcaps_mask;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003130#ifdef CONFIG_HT_OVERRIDES
3131 int max_ampdu;
3132 const u32 max_ampdu_mask = VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
3133#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003134
3135 if (!ssid)
3136 return;
3137
3138 params->disable_vht = ssid->disable_vht;
3139
3140 vhtcaps = (void *) params->vhtcaps;
3141 vhtcaps_mask = (void *) params->vhtcaps_mask;
3142
3143 if (!vhtcaps || !vhtcaps_mask)
3144 return;
3145
3146 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3147 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3148
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003149#ifdef CONFIG_HT_OVERRIDES
3150 /* if max ampdu is <= 3, we have to make the HT cap the same */
3151 if (ssid->vht_capa_mask & max_ampdu_mask) {
3152 max_ampdu = (ssid->vht_capa & max_ampdu_mask) >>
3153 find_first_bit(max_ampdu_mask);
3154
3155 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3156 wpa_set_ampdu_factor(wpa_s,
3157 (void *) params->htcaps,
3158 (void *) params->htcaps_mask,
3159 max_ampdu);
3160 }
3161#endif /* CONFIG_HT_OVERRIDES */
3162
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003163#define OVERRIDE_MCS(i) \
3164 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3165 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3166 3 << 2 * (i - 1); \
3167 vhtcaps->vht_supported_mcs_set.tx_map |= \
3168 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3169 } \
3170 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3171 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3172 3 << 2 * (i - 1); \
3173 vhtcaps->vht_supported_mcs_set.rx_map |= \
3174 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3175 }
3176
3177 OVERRIDE_MCS(1);
3178 OVERRIDE_MCS(2);
3179 OVERRIDE_MCS(3);
3180 OVERRIDE_MCS(4);
3181 OVERRIDE_MCS(5);
3182 OVERRIDE_MCS(6);
3183 OVERRIDE_MCS(7);
3184 OVERRIDE_MCS(8);
3185}
3186#endif /* CONFIG_VHT_OVERRIDES */
3187
3188
Dmitry Shmidt04949592012-07-19 12:16:46 -07003189static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3190{
3191#ifdef PCSC_FUNCS
3192 size_t len;
3193
3194 if (!wpa_s->conf->pcsc_reader)
3195 return 0;
3196
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003197 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003198 if (!wpa_s->scard)
3199 return 1;
3200
3201 if (wpa_s->conf->pcsc_pin &&
3202 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3203 scard_deinit(wpa_s->scard);
3204 wpa_s->scard = NULL;
3205 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3206 return -1;
3207 }
3208
3209 len = sizeof(wpa_s->imsi) - 1;
3210 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3211 scard_deinit(wpa_s->scard);
3212 wpa_s->scard = NULL;
3213 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3214 return -1;
3215 }
3216 wpa_s->imsi[len] = '\0';
3217
3218 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3219
3220 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3221 wpa_s->imsi, wpa_s->mnc_len);
3222
3223 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3224 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3225#endif /* PCSC_FUNCS */
3226
3227 return 0;
3228}
3229
3230
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003231int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3232{
3233 char *val, *pos;
3234
3235 ext_password_deinit(wpa_s->ext_pw);
3236 wpa_s->ext_pw = NULL;
3237 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3238
3239 if (!wpa_s->conf->ext_password_backend)
3240 return 0;
3241
3242 val = os_strdup(wpa_s->conf->ext_password_backend);
3243 if (val == NULL)
3244 return -1;
3245 pos = os_strchr(val, ':');
3246 if (pos)
3247 *pos++ = '\0';
3248
3249 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3250
3251 wpa_s->ext_pw = ext_password_init(val, pos);
3252 os_free(val);
3253 if (wpa_s->ext_pw == NULL) {
3254 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3255 return -1;
3256 }
3257 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3258
3259 return 0;
3260}
3261
3262
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003263static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
3264 struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003265{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003266 struct wowlan_triggers *triggers;
3267 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003268
3269 if (!wpa_s->conf->wowlan_triggers)
3270 return 0;
3271
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003272 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3273 if (triggers) {
3274 ret = wpa_drv_wowlan(wpa_s, triggers);
3275 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003276 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003277 return ret;
3278}
3279
3280
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003281static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3282 const char *rn)
3283{
3284 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3285 struct wpa_radio *radio;
3286
3287 while (rn && iface) {
3288 radio = iface->radio;
3289 if (radio && os_strcmp(rn, radio->name) == 0) {
3290 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3291 wpa_s->ifname, rn);
3292 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3293 return radio;
3294 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003295
3296 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003297 }
3298
3299 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3300 wpa_s->ifname, rn ? rn : "N/A");
3301 radio = os_zalloc(sizeof(*radio));
3302 if (radio == NULL)
3303 return NULL;
3304
3305 if (rn)
3306 os_strlcpy(radio->name, rn, sizeof(radio->name));
3307 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003308 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003309 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3310
3311 return radio;
3312}
3313
3314
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003315static void radio_work_free(struct wpa_radio_work *work)
3316{
3317 if (work->wpa_s->scan_work == work) {
3318 /* This should not really happen. */
3319 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3320 work->type, work, work->started);
3321 work->wpa_s->scan_work = NULL;
3322 }
3323
3324#ifdef CONFIG_P2P
3325 if (work->wpa_s->p2p_scan_work == work) {
3326 /* This should not really happen. */
3327 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3328 work->type, work, work->started);
3329 work->wpa_s->p2p_scan_work = NULL;
3330 }
3331#endif /* CONFIG_P2P */
3332
3333 dl_list_del(&work->list);
3334 os_free(work);
3335}
3336
3337
3338static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3339{
3340 struct wpa_radio *radio = eloop_ctx;
3341 struct wpa_radio_work *work;
3342 struct os_reltime now, diff;
3343 struct wpa_supplicant *wpa_s;
3344
3345 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3346 if (work == NULL)
3347 return;
3348
3349 if (work->started)
3350 return; /* already started and still in progress */
3351
3352 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3353 radio_list);
3354 if (wpa_s && wpa_s->external_scan_running) {
3355 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3356 return;
3357 }
3358
3359 os_get_reltime(&now);
3360 os_reltime_sub(&now, &work->time, &diff);
3361 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3362 work->type, work, diff.sec, diff.usec);
3363 work->started = 1;
3364 work->time = now;
3365 work->cb(work, 0);
3366}
3367
3368
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003369/*
3370 * This function removes both started and pending radio works running on
3371 * the provided interface's radio.
3372 * Prior to the removal of the radio work, its callback (cb) is called with
3373 * deinit set to be 1. Each work's callback is responsible for clearing its
3374 * internal data and restoring to a correct state.
3375 * @wpa_s: wpa_supplicant data
3376 * @type: type of works to be removed
3377 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3378 * this interface's works.
3379 */
3380void radio_remove_works(struct wpa_supplicant *wpa_s,
3381 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003382{
3383 struct wpa_radio_work *work, *tmp;
3384 struct wpa_radio *radio = wpa_s->radio;
3385
3386 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3387 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003388 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003389 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003390
3391 /* skip other ifaces' works */
3392 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003393 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003394
3395 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3396 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003397 work->cb(work, 1);
3398 radio_work_free(work);
3399 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003400
3401 /* in case we removed the started work */
3402 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003403}
3404
3405
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003406static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3407{
3408 struct wpa_radio *radio = wpa_s->radio;
3409
3410 if (!radio)
3411 return;
3412
3413 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3414 wpa_s->ifname, radio->name);
3415 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003416 radio_remove_works(wpa_s, NULL, 0);
3417 wpa_s->radio = NULL;
3418 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003419 return; /* Interfaces remain for this radio */
3420
3421 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003422 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003423 os_free(radio);
3424}
3425
3426
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003427void radio_work_check_next(struct wpa_supplicant *wpa_s)
3428{
3429 struct wpa_radio *radio = wpa_s->radio;
3430
3431 if (dl_list_empty(&radio->work))
3432 return;
3433 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3434 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3435}
3436
3437
3438/**
3439 * radio_add_work - Add a radio work item
3440 * @wpa_s: Pointer to wpa_supplicant data
3441 * @freq: Frequency of the offchannel operation in MHz or 0
3442 * @type: Unique identifier for each type of work
3443 * @next: Force as the next work to be executed
3444 * @cb: Callback function for indicating when radio is available
3445 * @ctx: Context pointer for the work (work->ctx in cb())
3446 * Returns: 0 on success, -1 on failure
3447 *
3448 * This function is used to request time for an operation that requires
3449 * exclusive radio control. Once the radio is available, the registered callback
3450 * function will be called. radio_work_done() must be called once the exclusive
3451 * radio operation has been completed, so that the radio is freed for other
3452 * operations. The special case of deinit=1 is used to free the context data
3453 * during interface removal. That does not allow the callback function to start
3454 * the radio operation, i.e., it must free any resources allocated for the radio
3455 * work and return.
3456 *
3457 * The @freq parameter can be used to indicate a single channel on which the
3458 * offchannel operation will occur. This may allow multiple radio work
3459 * operations to be performed in parallel if they apply for the same channel.
3460 * Setting this to 0 indicates that the work item may use multiple channels or
3461 * requires exclusive control of the radio.
3462 */
3463int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3464 const char *type, int next,
3465 void (*cb)(struct wpa_radio_work *work, int deinit),
3466 void *ctx)
3467{
3468 struct wpa_radio_work *work;
3469 int was_empty;
3470
3471 work = os_zalloc(sizeof(*work));
3472 if (work == NULL)
3473 return -1;
3474 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3475 os_get_reltime(&work->time);
3476 work->freq = freq;
3477 work->type = type;
3478 work->wpa_s = wpa_s;
3479 work->cb = cb;
3480 work->ctx = ctx;
3481
3482 was_empty = dl_list_empty(&wpa_s->radio->work);
3483 if (next)
3484 dl_list_add(&wpa_s->radio->work, &work->list);
3485 else
3486 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3487 if (was_empty) {
3488 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3489 radio_work_check_next(wpa_s);
3490 }
3491
3492 return 0;
3493}
3494
3495
3496/**
3497 * radio_work_done - Indicate that a radio work item has been completed
3498 * @work: Completed work
3499 *
3500 * This function is called once the callback function registered with
3501 * radio_add_work() has completed its work.
3502 */
3503void radio_work_done(struct wpa_radio_work *work)
3504{
3505 struct wpa_supplicant *wpa_s = work->wpa_s;
3506 struct os_reltime now, diff;
3507 unsigned int started = work->started;
3508
3509 os_get_reltime(&now);
3510 os_reltime_sub(&now, &work->time, &diff);
3511 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3512 work->type, work, started ? "done" : "canceled",
3513 diff.sec, diff.usec);
3514 radio_work_free(work);
3515 if (started)
3516 radio_work_check_next(wpa_s);
3517}
3518
3519
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003520struct wpa_radio_work *
3521radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003522{
3523 struct wpa_radio_work *work;
3524 struct wpa_radio *radio = wpa_s->radio;
3525
3526 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3527 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003528 return work;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003529 }
3530
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08003531 return NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003532}
3533
3534
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003535static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3536 struct wpa_interface *iface)
3537{
3538 const char *ifname, *driver, *rn;
3539
3540 driver = iface->driver;
3541next_driver:
3542 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3543 return -1;
3544
3545 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3546 if (wpa_s->drv_priv == NULL) {
3547 const char *pos;
3548 pos = driver ? os_strchr(driver, ',') : NULL;
3549 if (pos) {
3550 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3551 "driver interface - try next driver wrapper");
3552 driver = pos + 1;
3553 goto next_driver;
3554 }
3555 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3556 "interface");
3557 return -1;
3558 }
3559 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3560 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3561 "driver_param '%s'", wpa_s->conf->driver_param);
3562 return -1;
3563 }
3564
3565 ifname = wpa_drv_get_ifname(wpa_s);
3566 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3567 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3568 "interface name with '%s'", ifname);
3569 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3570 }
3571
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003572 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003573 if (rn && rn[0] == '\0')
3574 rn = NULL;
3575
3576 wpa_s->radio = radio_add_interface(wpa_s, rn);
3577 if (wpa_s->radio == NULL)
3578 return -1;
3579
3580 return 0;
3581}
3582
3583
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003584static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3585 struct wpa_interface *iface)
3586{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003587 struct wpa_driver_capa capa;
3588
3589 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3590 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3591 iface->confname ? iface->confname : "N/A",
3592 iface->driver ? iface->driver : "default",
3593 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3594 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3595
3596 if (iface->confname) {
3597#ifdef CONFIG_BACKEND_FILE
3598 wpa_s->confname = os_rel2abs_path(iface->confname);
3599 if (wpa_s->confname == NULL) {
3600 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3601 "for configuration file '%s'.",
3602 iface->confname);
3603 return -1;
3604 }
3605 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3606 iface->confname, wpa_s->confname);
3607#else /* CONFIG_BACKEND_FILE */
3608 wpa_s->confname = os_strdup(iface->confname);
3609#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003610 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003611 if (wpa_s->conf == NULL) {
3612 wpa_printf(MSG_ERROR, "Failed to read or parse "
3613 "configuration '%s'.", wpa_s->confname);
3614 return -1;
3615 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003616 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3617 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003618
3619 /*
3620 * Override ctrl_interface and driver_param if set on command
3621 * line.
3622 */
3623 if (iface->ctrl_interface) {
3624 os_free(wpa_s->conf->ctrl_interface);
3625 wpa_s->conf->ctrl_interface =
3626 os_strdup(iface->ctrl_interface);
3627 }
3628
3629 if (iface->driver_param) {
3630 os_free(wpa_s->conf->driver_param);
3631 wpa_s->conf->driver_param =
3632 os_strdup(iface->driver_param);
3633 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003634
3635 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3636 os_free(wpa_s->conf->ctrl_interface);
3637 wpa_s->conf->ctrl_interface = NULL;
3638 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003639 } else
3640 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3641 iface->driver_param);
3642
3643 if (wpa_s->conf == NULL) {
3644 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3645 return -1;
3646 }
3647
3648 if (iface->ifname == NULL) {
3649 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3650 return -1;
3651 }
3652 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3653 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3654 iface->ifname);
3655 return -1;
3656 }
3657 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3658
3659 if (iface->bridge_ifname) {
3660 if (os_strlen(iface->bridge_ifname) >=
3661 sizeof(wpa_s->bridge_ifname)) {
3662 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3663 "name '%s'.", iface->bridge_ifname);
3664 return -1;
3665 }
3666 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3667 sizeof(wpa_s->bridge_ifname));
3668 }
3669
3670 /* RSNA Supplicant Key Management - INITIALIZE */
3671 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3672 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3673
3674 /* Initialize driver interface and register driver event handler before
3675 * L2 receive handler so that association events are processed before
3676 * EAPOL-Key packets if both become available for the same select()
3677 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003678 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003679 return -1;
3680
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003681 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3682 return -1;
3683
3684 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3685 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3686 NULL);
3687 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3688
3689 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3690 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3691 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3692 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3693 "dot11RSNAConfigPMKLifetime");
3694 return -1;
3695 }
3696
3697 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3698 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3699 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3700 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3701 "dot11RSNAConfigPMKReauthThreshold");
3702 return -1;
3703 }
3704
3705 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3706 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3707 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3708 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3709 "dot11RSNAConfigSATimeout");
3710 return -1;
3711 }
3712
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003713 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3714 &wpa_s->hw.num_modes,
3715 &wpa_s->hw.flags);
3716
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003717 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003718 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003719 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003720 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003721 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003722 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003723 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3724 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3725 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003726 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3727 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003728 wpa_s->extended_capa = capa.extended_capa;
3729 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3730 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003731 wpa_s->num_multichan_concurrent =
3732 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003733 }
3734 if (wpa_s->max_remain_on_chan == 0)
3735 wpa_s->max_remain_on_chan = 1000;
3736
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003737 /*
3738 * Only take p2p_mgmt parameters when P2P Device is supported.
3739 * Doing it here as it determines whether l2_packet_init() will be done
3740 * during wpa_supplicant_driver_init().
3741 */
3742 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3743 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3744 else
3745 iface->p2p_mgmt = 1;
3746
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003747 if (wpa_s->num_multichan_concurrent == 0)
3748 wpa_s->num_multichan_concurrent = 1;
3749
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003750 if (wpa_supplicant_driver_init(wpa_s) < 0)
3751 return -1;
3752
3753#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003754 if ((!iface->p2p_mgmt ||
3755 !(wpa_s->drv_flags &
3756 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3757 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003758 return -1;
3759#endif /* CONFIG_TDLS */
3760
3761 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3762 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3763 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3764 return -1;
3765 }
3766
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767 if (wpas_wps_init(wpa_s))
3768 return -1;
3769
3770 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3771 return -1;
3772 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3773
3774 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3775 if (wpa_s->ctrl_iface == NULL) {
3776 wpa_printf(MSG_ERROR,
3777 "Failed to initialize control interface '%s'.\n"
3778 "You may have another wpa_supplicant process "
3779 "already running or the file was\n"
3780 "left by an unclean termination of wpa_supplicant "
3781 "in which case you will need\n"
3782 "to manually remove this file before starting "
3783 "wpa_supplicant again.\n",
3784 wpa_s->conf->ctrl_interface);
3785 return -1;
3786 }
3787
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003788 wpa_s->gas = gas_query_init(wpa_s);
3789 if (wpa_s->gas == NULL) {
3790 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3791 return -1;
3792 }
3793
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003794 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003795 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3796 return -1;
3797 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798
3799 if (wpa_bss_init(wpa_s) < 0)
3800 return -1;
3801
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003802 /*
3803 * Set Wake-on-WLAN triggers, if configured.
3804 * Note: We don't restore/remove the triggers on shutdown (it doesn't
3805 * have effect anyway when the interface is down).
3806 */
3807 if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
3808 return -1;
3809
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003810#ifdef CONFIG_EAP_PROXY
3811{
3812 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003813 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3814 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003815 if (wpa_s->mnc_len > 0) {
3816 wpa_s->imsi[len] = '\0';
3817 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3818 wpa_s->imsi, wpa_s->mnc_len);
3819 } else {
3820 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3821 }
3822}
3823#endif /* CONFIG_EAP_PROXY */
3824
Dmitry Shmidt04949592012-07-19 12:16:46 -07003825 if (pcsc_reader_init(wpa_s) < 0)
3826 return -1;
3827
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003828 if (wpas_init_ext_pw(wpa_s) < 0)
3829 return -1;
3830
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003831 return 0;
3832}
3833
3834
3835static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003836 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003837{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003838 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003839 if (wpa_s->drv_priv) {
3840 wpa_supplicant_deauthenticate(wpa_s,
3841 WLAN_REASON_DEAUTH_LEAVING);
3842
3843 wpa_drv_set_countermeasures(wpa_s, 0);
3844 wpa_clear_keys(wpa_s, NULL);
3845 }
3846
3847 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003848 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003849
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003850 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003851 radio_remove_interface(wpa_s);
3852
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003853 if (wpa_s->drv_priv)
3854 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003855
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003856 if (notify)
3857 wpas_notify_iface_removed(wpa_s);
3858
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003859 if (terminate)
3860 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003861
3862 if (wpa_s->ctrl_iface) {
3863 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3864 wpa_s->ctrl_iface = NULL;
3865 }
3866
3867 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003868 wpa_config_free(wpa_s->conf);
3869 wpa_s->conf = NULL;
3870 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003871
3872 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003873}
3874
3875
3876/**
3877 * wpa_supplicant_add_iface - Add a new network interface
3878 * @global: Pointer to global data from wpa_supplicant_init()
3879 * @iface: Interface configuration options
3880 * Returns: Pointer to the created interface or %NULL on failure
3881 *
3882 * This function is used to add new network interfaces for %wpa_supplicant.
3883 * This can be called before wpa_supplicant_run() to add interfaces before the
3884 * main event loop has been started. In addition, new interfaces can be added
3885 * dynamically while %wpa_supplicant is already running. This could happen,
3886 * e.g., when a hotplug network adapter is inserted.
3887 */
3888struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3889 struct wpa_interface *iface)
3890{
3891 struct wpa_supplicant *wpa_s;
3892 struct wpa_interface t_iface;
3893 struct wpa_ssid *ssid;
3894
3895 if (global == NULL || iface == NULL)
3896 return NULL;
3897
3898 wpa_s = wpa_supplicant_alloc();
3899 if (wpa_s == NULL)
3900 return NULL;
3901
3902 wpa_s->global = global;
3903
3904 t_iface = *iface;
3905 if (global->params.override_driver) {
3906 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3907 "('%s' -> '%s')",
3908 iface->driver, global->params.override_driver);
3909 t_iface.driver = global->params.override_driver;
3910 }
3911 if (global->params.override_ctrl_interface) {
3912 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3913 "ctrl_interface ('%s' -> '%s')",
3914 iface->ctrl_interface,
3915 global->params.override_ctrl_interface);
3916 t_iface.ctrl_interface =
3917 global->params.override_ctrl_interface;
3918 }
3919 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3920 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3921 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003922 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 return NULL;
3924 }
3925
3926 /* Notify the control interfaces about new iface */
3927 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003928 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929 return NULL;
3930 }
3931
3932 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3933 wpas_notify_network_added(wpa_s, ssid);
3934
3935 wpa_s->next = global->ifaces;
3936 global->ifaces = wpa_s;
3937
3938 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003939 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003940
3941 return wpa_s;
3942}
3943
3944
3945/**
3946 * wpa_supplicant_remove_iface - Remove a network interface
3947 * @global: Pointer to global data from wpa_supplicant_init()
3948 * @wpa_s: Pointer to the network interface to be removed
3949 * Returns: 0 if interface was removed, -1 if interface was not found
3950 *
3951 * This function can be used to dynamically remove network interfaces from
3952 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3953 * addition, this function is used to remove all remaining interfaces when
3954 * %wpa_supplicant is terminated.
3955 */
3956int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003957 struct wpa_supplicant *wpa_s,
3958 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003959{
3960 struct wpa_supplicant *prev;
3961
3962 /* Remove interface from the global list of interfaces */
3963 prev = global->ifaces;
3964 if (prev == wpa_s) {
3965 global->ifaces = wpa_s->next;
3966 } else {
3967 while (prev && prev->next != wpa_s)
3968 prev = prev->next;
3969 if (prev == NULL)
3970 return -1;
3971 prev->next = wpa_s->next;
3972 }
3973
3974 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3975
3976 if (global->p2p_group_formation == wpa_s)
3977 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003978 if (global->p2p_invite_group == wpa_s)
3979 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003980 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003981
3982 return 0;
3983}
3984
3985
3986/**
3987 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3988 * @wpa_s: Pointer to the network interface
3989 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3990 */
3991const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3992{
3993 const char *eapol_method;
3994
3995 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3996 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3997 return "NO-EAP";
3998 }
3999
4000 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
4001 if (eapol_method == NULL)
4002 return "UNKNOWN-EAP";
4003
4004 return eapol_method;
4005}
4006
4007
4008/**
4009 * wpa_supplicant_get_iface - Get a new network interface
4010 * @global: Pointer to global data from wpa_supplicant_init()
4011 * @ifname: Interface name
4012 * Returns: Pointer to the interface or %NULL if not found
4013 */
4014struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4015 const char *ifname)
4016{
4017 struct wpa_supplicant *wpa_s;
4018
4019 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4020 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4021 return wpa_s;
4022 }
4023 return NULL;
4024}
4025
4026
4027#ifndef CONFIG_NO_WPA_MSG
4028static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4029{
4030 struct wpa_supplicant *wpa_s = ctx;
4031 if (wpa_s == NULL)
4032 return NULL;
4033 return wpa_s->ifname;
4034}
4035#endif /* CONFIG_NO_WPA_MSG */
4036
4037
4038/**
4039 * wpa_supplicant_init - Initialize %wpa_supplicant
4040 * @params: Parameters for %wpa_supplicant
4041 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4042 *
4043 * This function is used to initialize %wpa_supplicant. After successful
4044 * initialization, the returned data pointer can be used to add and remove
4045 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4046 */
4047struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4048{
4049 struct wpa_global *global;
4050 int ret, i;
4051
4052 if (params == NULL)
4053 return NULL;
4054
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004055#ifdef CONFIG_DRIVER_NDIS
4056 {
4057 void driver_ndis_init_ops(void);
4058 driver_ndis_init_ops();
4059 }
4060#endif /* CONFIG_DRIVER_NDIS */
4061
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004062#ifndef CONFIG_NO_WPA_MSG
4063 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4064#endif /* CONFIG_NO_WPA_MSG */
4065
4066 wpa_debug_open_file(params->wpa_debug_file_path);
4067 if (params->wpa_debug_syslog)
4068 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004069 if (params->wpa_debug_tracing) {
4070 ret = wpa_debug_open_linux_tracing();
4071 if (ret) {
4072 wpa_printf(MSG_ERROR,
4073 "Failed to enable trace logging");
4074 return NULL;
4075 }
4076 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004077
4078 ret = eap_register_methods();
4079 if (ret) {
4080 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4081 if (ret == -2)
4082 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4083 "the same EAP type.");
4084 return NULL;
4085 }
4086
4087 global = os_zalloc(sizeof(*global));
4088 if (global == NULL)
4089 return NULL;
4090 dl_list_init(&global->p2p_srv_bonjour);
4091 dl_list_init(&global->p2p_srv_upnp);
4092 global->params.daemonize = params->daemonize;
4093 global->params.wait_for_monitor = params->wait_for_monitor;
4094 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4095 if (params->pid_file)
4096 global->params.pid_file = os_strdup(params->pid_file);
4097 if (params->ctrl_interface)
4098 global->params.ctrl_interface =
4099 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004100 if (params->ctrl_interface_group)
4101 global->params.ctrl_interface_group =
4102 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004103 if (params->override_driver)
4104 global->params.override_driver =
4105 os_strdup(params->override_driver);
4106 if (params->override_ctrl_interface)
4107 global->params.override_ctrl_interface =
4108 os_strdup(params->override_ctrl_interface);
4109 wpa_debug_level = global->params.wpa_debug_level =
4110 params->wpa_debug_level;
4111 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4112 params->wpa_debug_show_keys;
4113 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4114 params->wpa_debug_timestamp;
4115
4116 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4117
4118 if (eloop_init()) {
4119 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4120 wpa_supplicant_deinit(global);
4121 return NULL;
4122 }
4123
Jouni Malinen75ecf522011-06-27 15:19:46 -07004124 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004125
4126 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4127 if (global->ctrl_iface == NULL) {
4128 wpa_supplicant_deinit(global);
4129 return NULL;
4130 }
4131
4132 if (wpas_notify_supplicant_initialized(global)) {
4133 wpa_supplicant_deinit(global);
4134 return NULL;
4135 }
4136
4137 for (i = 0; wpa_drivers[i]; i++)
4138 global->drv_count++;
4139 if (global->drv_count == 0) {
4140 wpa_printf(MSG_ERROR, "No drivers enabled");
4141 wpa_supplicant_deinit(global);
4142 return NULL;
4143 }
4144 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
4145 if (global->drv_priv == NULL) {
4146 wpa_supplicant_deinit(global);
4147 return NULL;
4148 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004149
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004150#ifdef CONFIG_WIFI_DISPLAY
4151 if (wifi_display_init(global) < 0) {
4152 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4153 wpa_supplicant_deinit(global);
4154 return NULL;
4155 }
4156#endif /* CONFIG_WIFI_DISPLAY */
4157
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004158 return global;
4159}
4160
4161
4162/**
4163 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4164 * @global: Pointer to global data from wpa_supplicant_init()
4165 * Returns: 0 after successful event loop run, -1 on failure
4166 *
4167 * This function starts the main event loop and continues running as long as
4168 * there are any remaining events. In most cases, this function is running as
4169 * long as the %wpa_supplicant process in still in use.
4170 */
4171int wpa_supplicant_run(struct wpa_global *global)
4172{
4173 struct wpa_supplicant *wpa_s;
4174
4175 if (global->params.daemonize &&
4176 wpa_supplicant_daemon(global->params.pid_file))
4177 return -1;
4178
4179 if (global->params.wait_for_monitor) {
4180 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4181 if (wpa_s->ctrl_iface)
4182 wpa_supplicant_ctrl_iface_wait(
4183 wpa_s->ctrl_iface);
4184 }
4185
4186 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4187 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4188
4189 eloop_run();
4190
4191 return 0;
4192}
4193
4194
4195/**
4196 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4197 * @global: Pointer to global data from wpa_supplicant_init()
4198 *
4199 * This function is called to deinitialize %wpa_supplicant and to free all
4200 * allocated resources. Remaining network interfaces will also be removed.
4201 */
4202void wpa_supplicant_deinit(struct wpa_global *global)
4203{
4204 int i;
4205
4206 if (global == NULL)
4207 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004208
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004209#ifdef CONFIG_WIFI_DISPLAY
4210 wifi_display_deinit(global);
4211#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004212
4213 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004214 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004215
4216 if (global->ctrl_iface)
4217 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4218
4219 wpas_notify_supplicant_deinitialized(global);
4220
4221 eap_peer_unregister_methods();
4222#ifdef CONFIG_AP
4223 eap_server_unregister_methods();
4224#endif /* CONFIG_AP */
4225
4226 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4227 if (!global->drv_priv[i])
4228 continue;
4229 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4230 }
4231 os_free(global->drv_priv);
4232
4233 random_deinit();
4234
4235 eloop_destroy();
4236
4237 if (global->params.pid_file) {
4238 os_daemonize_terminate(global->params.pid_file);
4239 os_free(global->params.pid_file);
4240 }
4241 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004242 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004243 os_free(global->params.override_driver);
4244 os_free(global->params.override_ctrl_interface);
4245
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004246 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004247 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004248 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004249
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004250 os_free(global);
4251 wpa_debug_close_syslog();
4252 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004253 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004254}
4255
4256
4257void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4258{
4259 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4260 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4261 char country[3];
4262 country[0] = wpa_s->conf->country[0];
4263 country[1] = wpa_s->conf->country[1];
4264 country[2] = '\0';
4265 if (wpa_drv_set_country(wpa_s, country) < 0) {
4266 wpa_printf(MSG_ERROR, "Failed to set country code "
4267 "'%s'", country);
4268 }
4269 }
4270
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004271 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4272 wpas_init_ext_pw(wpa_s);
4273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004274#ifdef CONFIG_WPS
4275 wpas_wps_update_config(wpa_s);
4276#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004277 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004278 wpa_s->conf->changed_parameters = 0;
4279}
4280
4281
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004282static void add_freq(int *freqs, int *num_freqs, int freq)
4283{
4284 int i;
4285
4286 for (i = 0; i < *num_freqs; i++) {
4287 if (freqs[i] == freq)
4288 return;
4289 }
4290
4291 freqs[*num_freqs] = freq;
4292 (*num_freqs)++;
4293}
4294
4295
4296static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4297{
4298 struct wpa_bss *bss, *cbss;
4299 const int max_freqs = 10;
4300 int *freqs;
4301 int num_freqs = 0;
4302
4303 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
4304 if (freqs == NULL)
4305 return NULL;
4306
4307 cbss = wpa_s->current_bss;
4308
4309 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4310 if (bss == cbss)
4311 continue;
4312 if (bss->ssid_len == cbss->ssid_len &&
4313 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4314 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4315 add_freq(freqs, &num_freqs, bss->freq);
4316 if (num_freqs == max_freqs)
4317 break;
4318 }
4319 }
4320
4321 if (num_freqs == 0) {
4322 os_free(freqs);
4323 freqs = NULL;
4324 }
4325
4326 return freqs;
4327}
4328
4329
4330void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4331{
4332 int timeout;
4333 int count;
4334 int *freqs = NULL;
4335
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004336 wpas_connect_work_done(wpa_s);
4337
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004338 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004339 * Remove possible authentication timeout since the connection failed.
4340 */
4341 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4342
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004343 if (wpa_s->disconnected) {
4344 /*
4345 * There is no point in blacklisting the AP if this event is
4346 * generated based on local request to disconnect.
4347 */
4348 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4349 "indication since interface has been put into "
4350 "disconnected state");
4351 return;
4352 }
4353
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004354 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004355 * Add the failed BSSID into the blacklist and speed up next scan
4356 * attempt if there could be other APs that could accept association.
4357 * The current blacklist count indicates how many times we have tried
4358 * connecting to this AP and multiple attempts mean that other APs are
4359 * either not available or has already been tried, so that we can start
4360 * increasing the delay here to avoid constant scanning.
4361 */
4362 count = wpa_blacklist_add(wpa_s, bssid);
4363 if (count == 1 && wpa_s->current_bss) {
4364 /*
4365 * This BSS was not in the blacklist before. If there is
4366 * another BSS available for the same ESS, we should try that
4367 * next. Otherwise, we may as well try this one once more
4368 * before allowing other, likely worse, ESSes to be considered.
4369 */
4370 freqs = get_bss_freqs_in_ess(wpa_s);
4371 if (freqs) {
4372 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4373 "has been seen; try it next");
4374 wpa_blacklist_add(wpa_s, bssid);
4375 /*
4376 * On the next scan, go through only the known channels
4377 * used in this ESS based on previous scans to speed up
4378 * common load balancing use case.
4379 */
4380 os_free(wpa_s->next_scan_freqs);
4381 wpa_s->next_scan_freqs = freqs;
4382 }
4383 }
4384
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004385 /*
4386 * Add previous failure count in case the temporary blacklist was
4387 * cleared due to no other BSSes being available.
4388 */
4389 count += wpa_s->extra_blacklist_count;
4390
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004391 if (count > 3 && wpa_s->current_ssid) {
4392 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4393 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004394 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004395 }
4396
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004397 switch (count) {
4398 case 1:
4399 timeout = 100;
4400 break;
4401 case 2:
4402 timeout = 500;
4403 break;
4404 case 3:
4405 timeout = 1000;
4406 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004407 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004408 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004409 break;
4410 default:
4411 timeout = 10000;
4412 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004413 }
4414
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004415 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4416 "ms", count, timeout);
4417
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004418 /*
4419 * TODO: if more than one possible AP is available in scan results,
4420 * could try the other ones before requesting a new scan.
4421 */
4422 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4423 1000 * (timeout % 1000));
4424}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004425
4426
4427int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4428{
4429 return wpa_s->conf->ap_scan == 2 ||
4430 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4431}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004432
Dmitry Shmidt04949592012-07-19 12:16:46 -07004433
4434#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4435int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4436 struct wpa_ssid *ssid,
4437 const char *field,
4438 const char *value)
4439{
4440#ifdef IEEE8021X_EAPOL
4441 struct eap_peer_config *eap = &ssid->eap;
4442
4443 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4444 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4445 (const u8 *) value, os_strlen(value));
4446
4447 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4448 case WPA_CTRL_REQ_EAP_IDENTITY:
4449 os_free(eap->identity);
4450 eap->identity = (u8 *) os_strdup(value);
4451 eap->identity_len = os_strlen(value);
4452 eap->pending_req_identity = 0;
4453 if (ssid == wpa_s->current_ssid)
4454 wpa_s->reassociate = 1;
4455 break;
4456 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004457 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004458 eap->password = (u8 *) os_strdup(value);
4459 eap->password_len = os_strlen(value);
4460 eap->pending_req_password = 0;
4461 if (ssid == wpa_s->current_ssid)
4462 wpa_s->reassociate = 1;
4463 break;
4464 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004465 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004466 eap->new_password = (u8 *) os_strdup(value);
4467 eap->new_password_len = os_strlen(value);
4468 eap->pending_req_new_password = 0;
4469 if (ssid == wpa_s->current_ssid)
4470 wpa_s->reassociate = 1;
4471 break;
4472 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004473 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004474 eap->pin = os_strdup(value);
4475 eap->pending_req_pin = 0;
4476 if (ssid == wpa_s->current_ssid)
4477 wpa_s->reassociate = 1;
4478 break;
4479 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004480 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004481 eap->otp = (u8 *) os_strdup(value);
4482 eap->otp_len = os_strlen(value);
4483 os_free(eap->pending_req_otp);
4484 eap->pending_req_otp = NULL;
4485 eap->pending_req_otp_len = 0;
4486 break;
4487 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004488 str_clear_free(eap->private_key_passwd);
4489 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004490 eap->pending_req_passphrase = 0;
4491 if (ssid == wpa_s->current_ssid)
4492 wpa_s->reassociate = 1;
4493 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004494 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004495 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004496 eap->external_sim_resp = os_strdup(value);
4497 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004498 default:
4499 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4500 return -1;
4501 }
4502
4503 return 0;
4504#else /* IEEE8021X_EAPOL */
4505 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4506 return -1;
4507#endif /* IEEE8021X_EAPOL */
4508}
4509#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4510
4511
4512int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4513{
4514 int i;
4515 unsigned int drv_enc;
4516
4517 if (ssid == NULL)
4518 return 1;
4519
4520 if (ssid->disabled)
4521 return 1;
4522
4523 if (wpa_s && wpa_s->drv_capa_known)
4524 drv_enc = wpa_s->drv_enc;
4525 else
4526 drv_enc = (unsigned int) -1;
4527
4528 for (i = 0; i < NUM_WEP_KEYS; i++) {
4529 size_t len = ssid->wep_key_len[i];
4530 if (len == 0)
4531 continue;
4532 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4533 continue;
4534 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4535 continue;
4536 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4537 continue;
4538 return 1; /* invalid WEP key */
4539 }
4540
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004541 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07004542 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004543 return 1;
4544
Dmitry Shmidt04949592012-07-19 12:16:46 -07004545 return 0;
4546}
4547
4548
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004549int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004550{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004551 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004552 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004553 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004554 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004555 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004556}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004557
4558
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004559void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004560{
4561 struct wpa_ssid *ssid = wpa_s->current_ssid;
4562 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004563 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004564
4565 if (ssid == NULL) {
4566 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4567 "SSID block");
4568 return;
4569 }
4570
4571 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4572 return;
4573
4574 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004575
4576#ifdef CONFIG_P2P
4577 if (ssid->p2p_group &&
4578 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4579 /*
4580 * Skip the wait time since there is a short timeout on the
4581 * connection to a P2P group.
4582 */
4583 return;
4584 }
4585#endif /* CONFIG_P2P */
4586
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004587 if (ssid->auth_failures > 50)
4588 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004589 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004590 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004591 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004592 dur = 90;
4593 else if (ssid->auth_failures > 3)
4594 dur = 60;
4595 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004596 dur = 30;
4597 else if (ssid->auth_failures > 1)
4598 dur = 20;
4599 else
4600 dur = 10;
4601
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004602 if (ssid->auth_failures > 1 &&
4603 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
4604 dur += os_random() % (ssid->auth_failures * 10);
4605
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004606 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004607 if (now.sec + dur <= ssid->disabled_until.sec)
4608 return;
4609
4610 ssid->disabled_until.sec = now.sec + dur;
4611
4612 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004613 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004614 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004615 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004616}
4617
4618
4619void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4620 struct wpa_ssid *ssid, int clear_failures)
4621{
4622 if (ssid == NULL)
4623 return;
4624
4625 if (ssid->disabled_until.sec) {
4626 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4627 "id=%d ssid=\"%s\"",
4628 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4629 }
4630 ssid->disabled_until.sec = 0;
4631 ssid->disabled_until.usec = 0;
4632 if (clear_failures)
4633 ssid->auth_failures = 0;
4634}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004635
4636
4637int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4638{
4639 size_t i;
4640
4641 if (wpa_s->disallow_aps_bssid == NULL)
4642 return 0;
4643
4644 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4645 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4646 bssid, ETH_ALEN) == 0)
4647 return 1;
4648 }
4649
4650 return 0;
4651}
4652
4653
4654int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4655 size_t ssid_len)
4656{
4657 size_t i;
4658
4659 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4660 return 0;
4661
4662 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4663 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4664 if (ssid_len == s->ssid_len &&
4665 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4666 return 1;
4667 }
4668
4669 return 0;
4670}
4671
4672
4673/**
4674 * wpas_request_connection - Request a new connection
4675 * @wpa_s: Pointer to the network interface
4676 *
4677 * This function is used to request a new connection to be found. It will mark
4678 * the interface to allow reassociation and request a new scan to find a
4679 * suitable network to connect to.
4680 */
4681void wpas_request_connection(struct wpa_supplicant *wpa_s)
4682{
4683 wpa_s->normal_scans = 0;
4684 wpa_supplicant_reinit_autoscan(wpa_s);
4685 wpa_s->extra_blacklist_count = 0;
4686 wpa_s->disconnected = 0;
4687 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004688
4689 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4690 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004691}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004692
4693
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004694void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
4695 struct wpa_used_freq_data *freqs_data,
4696 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004697{
4698 unsigned int i;
4699
4700 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4701 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004702 for (i = 0; i < len; i++) {
4703 struct wpa_used_freq_data *cur = &freqs_data[i];
4704 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
4705 i, cur->freq, cur->flags);
4706 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004707}
4708
4709
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004710/*
4711 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004712 * are using the same radio as the current interface, and in addition, get
4713 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004714 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004715int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
4716 struct wpa_used_freq_data *freqs_data,
4717 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004718{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004719 struct wpa_supplicant *ifs;
4720 u8 bssid[ETH_ALEN];
4721 int freq;
4722 unsigned int idx = 0, i;
4723
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004724 wpa_dbg(wpa_s, MSG_DEBUG,
4725 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004726 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004727
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004728 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4729 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004730 if (idx == len)
4731 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004732
4733 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4734 continue;
4735
4736 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4737 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4738 freq = ifs->current_ssid->frequency;
4739 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4740 freq = ifs->assoc_freq;
4741 else
4742 continue;
4743
4744 /* Hold only distinct freqs */
4745 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004746 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004747 break;
4748
4749 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004750 freqs_data[idx++].freq = freq;
4751
4752 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
4753 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
4754 WPA_FREQ_USED_BY_P2P_CLIENT :
4755 WPA_FREQ_USED_BY_INFRA_STATION;
4756 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004757 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004758
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004759 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004760 return idx;
4761}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004762
4763
4764/*
4765 * Find the operating frequencies of any of the virtual interfaces that
4766 * are using the same radio as the current interface.
4767 */
4768int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4769 int *freq_array, unsigned int len)
4770{
4771 struct wpa_used_freq_data *freqs_data;
4772 int num, i;
4773
4774 os_memset(freq_array, 0, sizeof(int) * len);
4775
4776 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
4777 if (!freqs_data)
4778 return -1;
4779
4780 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
4781 for (i = 0; i < num; i++)
4782 freq_array[i] = freqs_data[i].freq;
4783
4784 os_free(freqs_data);
4785
4786 return num;
4787}