blob: 397d2f671573f1793fcfa67118f17d38c7b2de3e [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
1587 if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
1588 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 Shmidtd5e49232012-12-03 15:08:10 -08001624 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001625 wpa_s->reassociate = 1;
1626 wpa_supplicant_req_scan(wpa_s, 0, 0);
1627 return;
1628#endif /* CONFIG_WPS */
1629 } else {
1630 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1631 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1632 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1633 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001634 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001635 wpa_supplicant_cancel_scan(wpa_s);
1636
1637 /* Starting new association, so clear the possibly used WPA IE from the
1638 * previous association. */
1639 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1640
1641#ifdef IEEE8021X_EAPOL
1642 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1643 if (ssid->leap) {
1644 if (ssid->non_leap == 0)
1645 algs = WPA_AUTH_ALG_LEAP;
1646 else
1647 algs |= WPA_AUTH_ALG_LEAP;
1648 }
1649 }
1650#endif /* IEEE8021X_EAPOL */
1651 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1652 if (ssid->auth_alg) {
1653 algs = ssid->auth_alg;
1654 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1655 "0x%x", algs);
1656 }
1657
1658 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1659 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001660 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001662 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1663 wpa_s->conf->okc :
1664 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001665 (ssid->proto & WPA_PROTO_RSN);
1666 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001667 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001668 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1669 wpa_ie_len = sizeof(wpa_ie);
1670 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1671 wpa_ie, &wpa_ie_len)) {
1672 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1673 "key management and encryption suites");
1674 return;
1675 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001676 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1677 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1678 /*
1679 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1680 * use non-WPA since the scan results did not indicate that the
1681 * AP is using WPA or WPA2.
1682 */
1683 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1684 wpa_ie_len = 0;
1685 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001686 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001687 wpa_ie_len = sizeof(wpa_ie);
1688 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1689 wpa_ie, &wpa_ie_len)) {
1690 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1691 "key management and encryption suites (no "
1692 "scan results)");
1693 return;
1694 }
1695#ifdef CONFIG_WPS
1696 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1697 struct wpabuf *wps_ie;
1698 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1699 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1700 wpa_ie_len = wpabuf_len(wps_ie);
1701 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1702 } else
1703 wpa_ie_len = 0;
1704 wpabuf_free(wps_ie);
1705 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1706 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1707 params.wps = WPS_MODE_PRIVACY;
1708 else
1709 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001710 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001711#endif /* CONFIG_WPS */
1712 } else {
1713 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1714 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001715 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716 }
1717
1718#ifdef CONFIG_P2P
1719 if (wpa_s->global->p2p) {
1720 u8 *pos;
1721 size_t len;
1722 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723 pos = wpa_ie + wpa_ie_len;
1724 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001725 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1726 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001727 if (res >= 0)
1728 wpa_ie_len += res;
1729 }
1730
1731 wpa_s->cross_connect_disallowed = 0;
1732 if (bss) {
1733 struct wpabuf *p2p;
1734 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1735 if (p2p) {
1736 wpa_s->cross_connect_disallowed =
1737 p2p_get_cross_connect_disallowed(p2p);
1738 wpabuf_free(p2p);
1739 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1740 "connection",
1741 wpa_s->cross_connect_disallowed ?
1742 "disallows" : "allows");
1743 }
1744 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001745
1746 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001747#endif /* CONFIG_P2P */
1748
Dmitry Shmidt04949592012-07-19 12:16:46 -07001749#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001750 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001751 struct wpabuf *hs20;
1752 hs20 = wpabuf_alloc(20);
1753 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001754 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001755 size_t len;
1756
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001757 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001758 len = sizeof(wpa_ie) - wpa_ie_len;
1759 if (wpabuf_len(hs20) <= len) {
1760 os_memcpy(wpa_ie + wpa_ie_len,
1761 wpabuf_head(hs20), wpabuf_len(hs20));
1762 wpa_ie_len += wpabuf_len(hs20);
1763 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001764 wpabuf_free(hs20);
1765 }
1766 }
1767#endif /* CONFIG_HS20 */
1768
Dmitry Shmidt56052862013-10-04 10:23:25 -07001769 /*
1770 * Workaround: Add Extended Capabilities element only if the AP
1771 * included this element in Beacon/Probe Response frames. Some older
1772 * APs seem to have interoperability issues if this element is
1773 * included, so while the standard may require us to include the
1774 * element in all cases, it is justifiable to skip it to avoid
1775 * interoperability issues.
1776 */
1777 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001778 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07001779 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001780 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
1781 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07001782 if (ext_capab_len > 0) {
1783 u8 *pos = wpa_ie;
1784 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1785 pos += 2 + pos[1];
1786 os_memmove(pos + ext_capab_len, pos,
1787 wpa_ie_len - (pos - wpa_ie));
1788 wpa_ie_len += ext_capab_len;
1789 os_memcpy(pos, ext_capab, ext_capab_len);
1790 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001791 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001792
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001793 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1794 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001795 cipher_pairwise = wpa_s->pairwise_cipher;
1796 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1798 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1799 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1800 use_crypt = 0;
1801 if (wpa_set_wep_keys(wpa_s, ssid)) {
1802 use_crypt = 1;
1803 wep_keys_set = 1;
1804 }
1805 }
1806 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1807 use_crypt = 0;
1808
1809#ifdef IEEE8021X_EAPOL
1810 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1811 if ((ssid->eapol_flags &
1812 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1813 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1814 !wep_keys_set) {
1815 use_crypt = 0;
1816 } else {
1817 /* Assume that dynamic WEP-104 keys will be used and
1818 * set cipher suites in order for drivers to expect
1819 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001820 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001821 }
1822 }
1823#endif /* IEEE8021X_EAPOL */
1824
1825 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1826 /* Set the key before (and later after) association */
1827 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1828 }
1829
1830 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1831 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001832 params.ssid = bss->ssid;
1833 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001834 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1835 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1836 MACSTR " freq=%u MHz based on scan results "
1837 "(bssid_set=%d)",
1838 MAC2STR(bss->bssid), bss->freq,
1839 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001840 params.bssid = bss->bssid;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001841 params.freq.freq = bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001842 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001843 params.bssid_hint = bss->bssid;
1844 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001845 } else {
1846 params.ssid = ssid->ssid;
1847 params.ssid_len = ssid->ssid_len;
1848 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001849
1850 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1851 wpa_s->conf->ap_scan == 2) {
1852 params.bssid = ssid->bssid;
1853 params.fixed_bssid = 1;
1854 }
1855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001857 params.freq.freq == 0) {
1858 enum hostapd_hw_mode hw_mode;
1859 u8 channel;
1860
1861 params.freq.freq = ssid->frequency;
1862
1863 hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
1864 for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
1865 if (wpa_s->hw.modes[i].mode == hw_mode) {
1866 struct hostapd_hw_modes *mode;
1867
1868 mode = &wpa_s->hw.modes[i];
1869 params.freq.ht_enabled = ht_supported(mode);
1870 break;
1871 }
1872 }
1873 }
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08001874
1875 if (ssid->mode == WPAS_MODE_IBSS) {
1876 if (ssid->beacon_int)
1877 params.beacon_int = ssid->beacon_int;
1878 else
1879 params.beacon_int = wpa_s->conf->beacon_int;
1880 }
1881
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001882 params.wpa_ie = wpa_ie;
1883 params.wpa_ie_len = wpa_ie_len;
1884 params.pairwise_suite = cipher_pairwise;
1885 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001886 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001887 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001888 params.auth_alg = algs;
1889 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001890 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891 for (i = 0; i < NUM_WEP_KEYS; i++) {
1892 if (ssid->wep_key_len[i])
1893 params.wep_key[i] = ssid->wep_key[i];
1894 params.wep_key_len[i] = ssid->wep_key_len[i];
1895 }
1896 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1897
1898 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001899 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1900 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001901 params.passphrase = ssid->passphrase;
1902 if (ssid->psk_set)
1903 params.psk = ssid->psk;
1904 }
1905
1906 params.drop_unencrypted = use_crypt;
1907
1908#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001909 params.mgmt_frame_protection =
1910 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1911 wpa_s->conf->pmf : ssid->ieee80211w;
1912 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001913 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1914 struct wpa_ie_data ie;
1915 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1916 ie.capabilities &
1917 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1918 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1919 "MFP: require MFP");
1920 params.mgmt_frame_protection =
1921 MGMT_FRAME_PROTECTION_REQUIRED;
1922 }
1923 }
1924#endif /* CONFIG_IEEE80211W */
1925
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001926 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001927
1928 if (wpa_s->parent->set_sta_uapsd)
1929 params.uapsd = wpa_s->parent->sta_uapsd;
1930 else
1931 params.uapsd = -1;
1932
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001933#ifdef CONFIG_HT_OVERRIDES
1934 os_memset(&htcaps, 0, sizeof(htcaps));
1935 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1936 params.htcaps = (u8 *) &htcaps;
1937 params.htcaps_mask = (u8 *) &htcaps_mask;
1938 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1939#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001940#ifdef CONFIG_VHT_OVERRIDES
1941 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
1942 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
1943 params.vhtcaps = &vhtcaps;
1944 params.vhtcaps_mask = &vhtcaps_mask;
1945 wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
1946#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001947
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001948#ifdef CONFIG_P2P
1949 /*
1950 * If multi-channel concurrency is not supported, check for any
1951 * frequency conflict. In case of any frequency conflict, remove the
1952 * least prioritized connection.
1953 */
1954 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001955 int freq, num;
1956 num = get_shared_radio_freqs(wpa_s, &freq, 1);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001957 if (num > 0 && freq > 0 && freq != params.freq.freq) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001958 wpa_printf(MSG_DEBUG,
1959 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001960 freq, params.freq.freq);
1961 if (wpas_p2p_handle_frequency_conflicts(
1962 wpa_s, params.freq.freq, ssid) < 0)
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001963 return;
1964 }
1965 }
1966#endif /* CONFIG_P2P */
1967
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001968 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001969 if (ret < 0) {
1970 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1971 "failed");
1972 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1973 /*
1974 * The driver is known to mean what is saying, so we
1975 * can stop right here; the association will not
1976 * succeed.
1977 */
1978 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001979 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001980 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1981 return;
1982 }
1983 /* try to continue anyway; new association will be tried again
1984 * after timeout */
1985 assoc_failed = 1;
1986 }
1987
1988 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1989 /* Set the key after the association just in case association
1990 * cleared the previously configured key. */
1991 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1992 /* No need to timeout authentication since there is no key
1993 * management. */
1994 wpa_supplicant_cancel_auth_timeout(wpa_s);
1995 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1996#ifdef CONFIG_IBSS_RSN
1997 } else if (ssid->mode == WPAS_MODE_IBSS &&
1998 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1999 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
2000 /*
2001 * RSN IBSS authentication is per-STA and we can disable the
2002 * per-BSSID authentication.
2003 */
2004 wpa_supplicant_cancel_auth_timeout(wpa_s);
2005#endif /* CONFIG_IBSS_RSN */
2006 } else {
2007 /* Timeout for IEEE 802.11 authentication and association */
2008 int timeout = 60;
2009
2010 if (assoc_failed) {
2011 /* give IBSS a bit more time */
2012 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2013 } else if (wpa_s->conf->ap_scan == 1) {
2014 /* give IBSS a bit more time */
2015 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2016 }
2017 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2018 }
2019
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002020 if (wep_keys_set &&
2021 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022 /* Set static WEP keys again */
2023 wpa_set_wep_keys(wpa_s, ssid);
2024 }
2025
2026 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2027 /*
2028 * Do not allow EAP session resumption between different
2029 * network configurations.
2030 */
2031 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2032 }
2033 old_ssid = wpa_s->current_ssid;
2034 wpa_s->current_ssid = ssid;
2035 wpa_s->current_bss = bss;
2036 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2037 wpa_supplicant_initiate_eapol(wpa_s);
2038 if (old_ssid != wpa_s->current_ssid)
2039 wpas_notify_network_changed(wpa_s);
2040}
2041
2042
2043static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2044 const u8 *addr)
2045{
2046 struct wpa_ssid *old_ssid;
2047
2048 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002049 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002050 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002051 wpa_sm_set_config(wpa_s->wpa, NULL);
2052 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2053 if (old_ssid != wpa_s->current_ssid)
2054 wpas_notify_network_changed(wpa_s);
2055 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2056}
2057
2058
2059/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002060 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2061 * @wpa_s: Pointer to wpa_supplicant data
2062 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2063 *
2064 * This function is used to request %wpa_supplicant to deauthenticate from the
2065 * current AP.
2066 */
2067void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2068 int reason_code)
2069{
2070 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002071 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002072 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002073
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002074 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2075 " pending_bssid=" MACSTR " reason=%d state=%s",
2076 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2077 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2078
2079 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002080 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002081 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2082 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2083 wpa_s->wpa_state == WPA_ASSOCIATING))
2084 addr = wpa_s->pending_bssid;
2085 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2086 /*
2087 * When using driver-based BSS selection, we may not know the
2088 * BSSID with which we are currently trying to associate. We
2089 * need to notify the driver of this disconnection even in such
2090 * a case, so use the all zeros address here.
2091 */
2092 addr = wpa_s->bssid;
2093 zero_addr = 1;
2094 }
2095
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002096#ifdef CONFIG_TDLS
2097 wpa_tdls_teardown_peers(wpa_s->wpa);
2098#endif /* CONFIG_TDLS */
2099
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002100 if (addr) {
2101 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002102 os_memset(&event, 0, sizeof(event));
2103 event.deauth_info.reason_code = (u16) reason_code;
2104 event.deauth_info.locally_generated = 1;
2105 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002106 if (zero_addr)
2107 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002108 }
2109
2110 wpa_supplicant_clear_connection(wpa_s, addr);
2111}
2112
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002113static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2114 struct wpa_ssid *ssid)
2115{
2116 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2117 return;
2118
2119 ssid->disabled = 0;
2120 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2121 wpas_notify_network_enabled_changed(wpa_s, ssid);
2122
2123 /*
2124 * Try to reassociate since there is no current configuration and a new
2125 * network was made available.
2126 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002127 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002128 wpa_s->reassociate = 1;
2129}
2130
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002131
2132/**
2133 * wpa_supplicant_enable_network - Mark a configured network as enabled
2134 * @wpa_s: wpa_supplicant structure for a network interface
2135 * @ssid: wpa_ssid structure for a configured network or %NULL
2136 *
2137 * Enables the specified network or all networks if no network specified.
2138 */
2139void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2140 struct wpa_ssid *ssid)
2141{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002142 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002143 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2144 wpa_supplicant_enable_one_network(wpa_s, ssid);
2145 } else
2146 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002147
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002148 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002149 if (wpa_s->sched_scanning) {
2150 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2151 "new network to scan filters");
2152 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153 }
2154
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002155 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2156 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002157 }
2158}
2159
2160
2161/**
2162 * wpa_supplicant_disable_network - Mark a configured network as disabled
2163 * @wpa_s: wpa_supplicant structure for a network interface
2164 * @ssid: wpa_ssid structure for a configured network or %NULL
2165 *
2166 * Disables the specified network or all networks if no network specified.
2167 */
2168void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2169 struct wpa_ssid *ssid)
2170{
2171 struct wpa_ssid *other_ssid;
2172 int was_disabled;
2173
2174 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002175 if (wpa_s->sched_scanning)
2176 wpa_supplicant_cancel_sched_scan(wpa_s);
2177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002178 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2179 other_ssid = other_ssid->next) {
2180 was_disabled = other_ssid->disabled;
2181 if (was_disabled == 2)
2182 continue; /* do not change persistent P2P group
2183 * data */
2184
2185 other_ssid->disabled = 1;
2186
2187 if (was_disabled != other_ssid->disabled)
2188 wpas_notify_network_enabled_changed(
2189 wpa_s, other_ssid);
2190 }
2191 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002192 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002193 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2194 } else if (ssid->disabled != 2) {
2195 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002196 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002197 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2198
2199 was_disabled = ssid->disabled;
2200
2201 ssid->disabled = 1;
2202
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002203 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002204 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002205 if (wpa_s->sched_scanning) {
2206 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2207 "to remove network from filters");
2208 wpa_supplicant_cancel_sched_scan(wpa_s);
2209 wpa_supplicant_req_scan(wpa_s, 0, 0);
2210 }
2211 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002212 }
2213}
2214
2215
2216/**
2217 * wpa_supplicant_select_network - Attempt association with a network
2218 * @wpa_s: wpa_supplicant structure for a network interface
2219 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2220 */
2221void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2222 struct wpa_ssid *ssid)
2223{
2224
2225 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002226 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002227
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002228 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002229 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002230 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002231 disconnected = 1;
2232 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002233
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002234 if (ssid)
2235 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2236
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002237 /*
2238 * Mark all other networks disabled or mark all networks enabled if no
2239 * network specified.
2240 */
2241 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2242 other_ssid = other_ssid->next) {
2243 int was_disabled = other_ssid->disabled;
2244 if (was_disabled == 2)
2245 continue; /* do not change persistent P2P group data */
2246
2247 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002248 if (was_disabled && !other_ssid->disabled)
2249 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002250
2251 if (was_disabled != other_ssid->disabled)
2252 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2253 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002254
2255 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2256 /* We are already associated with the selected network */
2257 wpa_printf(MSG_DEBUG, "Already associated with the "
2258 "selected network - do nothing");
2259 return;
2260 }
2261
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002262 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002263 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002264 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2265 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002266 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002267 wpa_s->disconnected = 0;
2268 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002269
2270 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2271 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002272
2273 if (ssid)
2274 wpas_notify_network_selected(wpa_s, ssid);
2275}
2276
2277
2278/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002279 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2280 * @wpa_s: wpa_supplicant structure for a network interface
2281 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2282 * @pkcs11_module_path: PKCS #11 module path or NULL
2283 * Returns: 0 on success; -1 on failure
2284 *
2285 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2286 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2287 * module path fails the paths will be reset to the default value (NULL).
2288 */
2289int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2290 const char *pkcs11_engine_path,
2291 const char *pkcs11_module_path)
2292{
2293 char *pkcs11_engine_path_copy = NULL;
2294 char *pkcs11_module_path_copy = NULL;
2295
2296 if (pkcs11_engine_path != NULL) {
2297 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2298 if (pkcs11_engine_path_copy == NULL)
2299 return -1;
2300 }
2301 if (pkcs11_module_path != NULL) {
2302 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002303 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002304 os_free(pkcs11_engine_path_copy);
2305 return -1;
2306 }
2307 }
2308
2309 os_free(wpa_s->conf->pkcs11_engine_path);
2310 os_free(wpa_s->conf->pkcs11_module_path);
2311 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2312 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2313
2314 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2315 eapol_sm_deinit(wpa_s->eapol);
2316 wpa_s->eapol = NULL;
2317 if (wpa_supplicant_init_eapol(wpa_s)) {
2318 /* Error -> Reset paths to the default value (NULL) once. */
2319 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2320 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2321 NULL);
2322
2323 return -1;
2324 }
2325 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2326
2327 return 0;
2328}
2329
2330
2331/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002332 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2333 * @wpa_s: wpa_supplicant structure for a network interface
2334 * @ap_scan: AP scan mode
2335 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2336 *
2337 */
2338int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2339{
2340
2341 int old_ap_scan;
2342
2343 if (ap_scan < 0 || ap_scan > 2)
2344 return -1;
2345
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002346#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002347 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2348 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2349 wpa_s->wpa_state < WPA_COMPLETED) {
2350 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2351 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002352 return 0;
2353 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002354#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002355
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002356 old_ap_scan = wpa_s->conf->ap_scan;
2357 wpa_s->conf->ap_scan = ap_scan;
2358
2359 if (old_ap_scan != wpa_s->conf->ap_scan)
2360 wpas_notify_ap_scan_changed(wpa_s);
2361
2362 return 0;
2363}
2364
2365
2366/**
2367 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2368 * @wpa_s: wpa_supplicant structure for a network interface
2369 * @expire_age: Expiration age in seconds
2370 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2371 *
2372 */
2373int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2374 unsigned int bss_expire_age)
2375{
2376 if (bss_expire_age < 10) {
2377 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2378 bss_expire_age);
2379 return -1;
2380 }
2381 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2382 bss_expire_age);
2383 wpa_s->conf->bss_expiration_age = bss_expire_age;
2384
2385 return 0;
2386}
2387
2388
2389/**
2390 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2391 * @wpa_s: wpa_supplicant structure for a network interface
2392 * @expire_count: number of scans after which an unseen BSS is reclaimed
2393 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2394 *
2395 */
2396int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2397 unsigned int bss_expire_count)
2398{
2399 if (bss_expire_count < 1) {
2400 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2401 bss_expire_count);
2402 return -1;
2403 }
2404 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2405 bss_expire_count);
2406 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2407
2408 return 0;
2409}
2410
2411
2412/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002413 * wpa_supplicant_set_scan_interval - Set scan interval
2414 * @wpa_s: wpa_supplicant structure for a network interface
2415 * @scan_interval: scan interval in seconds
2416 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2417 *
2418 */
2419int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2420 int scan_interval)
2421{
2422 if (scan_interval < 0) {
2423 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2424 scan_interval);
2425 return -1;
2426 }
2427 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2428 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002429 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002430
2431 return 0;
2432}
2433
2434
2435/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436 * wpa_supplicant_set_debug_params - Set global debug params
2437 * @global: wpa_global structure
2438 * @debug_level: debug level
2439 * @debug_timestamp: determines if show timestamp in debug data
2440 * @debug_show_keys: determines if show keys in debug data
2441 * Returns: 0 if succeed or -1 if debug_level has wrong value
2442 */
2443int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2444 int debug_timestamp, int debug_show_keys)
2445{
2446
2447 int old_level, old_timestamp, old_show_keys;
2448
2449 /* check for allowed debuglevels */
2450 if (debug_level != MSG_EXCESSIVE &&
2451 debug_level != MSG_MSGDUMP &&
2452 debug_level != MSG_DEBUG &&
2453 debug_level != MSG_INFO &&
2454 debug_level != MSG_WARNING &&
2455 debug_level != MSG_ERROR)
2456 return -1;
2457
2458 old_level = wpa_debug_level;
2459 old_timestamp = wpa_debug_timestamp;
2460 old_show_keys = wpa_debug_show_keys;
2461
2462 wpa_debug_level = debug_level;
2463 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2464 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2465
2466 if (wpa_debug_level != old_level)
2467 wpas_notify_debug_level_changed(global);
2468 if (wpa_debug_timestamp != old_timestamp)
2469 wpas_notify_debug_timestamp_changed(global);
2470 if (wpa_debug_show_keys != old_show_keys)
2471 wpas_notify_debug_show_keys_changed(global);
2472
2473 return 0;
2474}
2475
2476
2477/**
2478 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2479 * @wpa_s: Pointer to wpa_supplicant data
2480 * Returns: A pointer to the current network structure or %NULL on failure
2481 */
2482struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2483{
2484 struct wpa_ssid *entry;
2485 u8 ssid[MAX_SSID_LEN];
2486 int res;
2487 size_t ssid_len;
2488 u8 bssid[ETH_ALEN];
2489 int wired;
2490
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002491 res = wpa_drv_get_ssid(wpa_s, ssid);
2492 if (res < 0) {
2493 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2494 "driver");
2495 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002497 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002499 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002500 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2501 "driver");
2502 return NULL;
2503 }
2504
2505 wired = wpa_s->conf->ap_scan == 0 &&
2506 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2507
2508 entry = wpa_s->conf->ssid;
2509 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002510 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 ((ssid_len == entry->ssid_len &&
2512 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2513 (!entry->bssid_set ||
2514 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2515 return entry;
2516#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002517 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2519 (entry->ssid == NULL || entry->ssid_len == 0) &&
2520 (!entry->bssid_set ||
2521 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2522 return entry;
2523#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002524
Dmitry Shmidt04949592012-07-19 12:16:46 -07002525 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002526 entry->ssid_len == 0 &&
2527 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2528 return entry;
2529
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530 entry = entry->next;
2531 }
2532
2533 return NULL;
2534}
2535
2536
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002537static int select_driver(struct wpa_supplicant *wpa_s, int i)
2538{
2539 struct wpa_global *global = wpa_s->global;
2540
2541 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2542 global->drv_priv[i] = wpa_drivers[i]->global_init();
2543 if (global->drv_priv[i] == NULL) {
2544 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2545 "'%s'", wpa_drivers[i]->name);
2546 return -1;
2547 }
2548 }
2549
2550 wpa_s->driver = wpa_drivers[i];
2551 wpa_s->global_drv_priv = global->drv_priv[i];
2552
2553 return 0;
2554}
2555
2556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2558 const char *name)
2559{
2560 int i;
2561 size_t len;
2562 const char *pos, *driver = name;
2563
2564 if (wpa_s == NULL)
2565 return -1;
2566
2567 if (wpa_drivers[0] == NULL) {
2568 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2569 "wpa_supplicant");
2570 return -1;
2571 }
2572
2573 if (name == NULL) {
2574 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002575 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002576 }
2577
2578 do {
2579 pos = os_strchr(driver, ',');
2580 if (pos)
2581 len = pos - driver;
2582 else
2583 len = os_strlen(driver);
2584
2585 for (i = 0; wpa_drivers[i]; i++) {
2586 if (os_strlen(wpa_drivers[i]->name) == len &&
2587 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002588 0) {
2589 /* First driver that succeeds wins */
2590 if (select_driver(wpa_s, i) == 0)
2591 return 0;
2592 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002593 }
2594
2595 driver = pos + 1;
2596 } while (pos);
2597
2598 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2599 return -1;
2600}
2601
2602
2603/**
2604 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2605 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2606 * with struct wpa_driver_ops::init()
2607 * @src_addr: Source address of the EAPOL frame
2608 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2609 * @len: Length of the EAPOL data
2610 *
2611 * This function is called for each received EAPOL frame. Most driver
2612 * interfaces rely on more generic OS mechanism for receiving frames through
2613 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2614 * take care of received EAPOL frames and deliver them to the core supplicant
2615 * code by calling this function.
2616 */
2617void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2618 const u8 *buf, size_t len)
2619{
2620 struct wpa_supplicant *wpa_s = ctx;
2621
2622 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2623 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2624
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002625#ifdef CONFIG_PEERKEY
2626 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2627 wpa_s->current_ssid->peerkey &&
2628 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2629 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2630 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2631 return;
2632 }
2633#endif /* CONFIG_PEERKEY */
2634
Jouni Malinena05074c2012-12-21 21:35:35 +02002635 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2636 (wpa_s->last_eapol_matches_bssid &&
2637#ifdef CONFIG_AP
2638 !wpa_s->ap_iface &&
2639#endif /* CONFIG_AP */
2640 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 /*
2642 * There is possible race condition between receiving the
2643 * association event and the EAPOL frame since they are coming
2644 * through different paths from the driver. In order to avoid
2645 * issues in trying to process the EAPOL frame before receiving
2646 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002647 * the association event is received. This may also be needed in
2648 * driver-based roaming case, so also use src_addr != BSSID as a
2649 * trigger if we have previously confirmed that the
2650 * Authenticator uses BSSID as the src_addr (which is not the
2651 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 */
2653 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002654 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2655 wpa_supplicant_state_txt(wpa_s->wpa_state),
2656 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 wpabuf_free(wpa_s->pending_eapol_rx);
2658 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2659 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002660 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2662 ETH_ALEN);
2663 }
2664 return;
2665 }
2666
Jouni Malinena05074c2012-12-21 21:35:35 +02002667 wpa_s->last_eapol_matches_bssid =
2668 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2669
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002670#ifdef CONFIG_AP
2671 if (wpa_s->ap_iface) {
2672 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2673 return;
2674 }
2675#endif /* CONFIG_AP */
2676
2677 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2678 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2679 "no key management is configured");
2680 return;
2681 }
2682
2683 if (wpa_s->eapol_received == 0 &&
2684 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2685 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2686 wpa_s->wpa_state != WPA_COMPLETED) &&
2687 (wpa_s->current_ssid == NULL ||
2688 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2689 /* Timeout for completing IEEE 802.1X and WPA authentication */
2690 wpa_supplicant_req_auth_timeout(
2691 wpa_s,
2692 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2693 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2694 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2695 70 : 10, 0);
2696 }
2697 wpa_s->eapol_received++;
2698
2699 if (wpa_s->countermeasures) {
2700 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2701 "EAPOL packet");
2702 return;
2703 }
2704
2705#ifdef CONFIG_IBSS_RSN
2706 if (wpa_s->current_ssid &&
2707 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2708 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2709 return;
2710 }
2711#endif /* CONFIG_IBSS_RSN */
2712
2713 /* Source address of the incoming EAPOL frame could be compared to the
2714 * current BSSID. However, it is possible that a centralized
2715 * Authenticator could be using another MAC address than the BSSID of
2716 * an AP, so just allow any address to be used for now. The replies are
2717 * still sent to the current BSSID (if available), though. */
2718
2719 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2720 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2721 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2722 return;
2723 wpa_drv_poll(wpa_s);
2724 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2725 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2726 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2727 /*
2728 * Set portValid = TRUE here since we are going to skip 4-way
2729 * handshake processing which would normally set portValid. We
2730 * need this to allow the EAPOL state machines to be completed
2731 * without going through EAPOL-Key handshake.
2732 */
2733 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2734 }
2735}
2736
2737
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002738int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002739{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002740 if (wpa_s->driver->send_eapol) {
2741 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2742 if (addr)
2743 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002744 } else if ((!wpa_s->p2p_mgmt ||
2745 !(wpa_s->drv_flags &
2746 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2747 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002749 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2751 wpa_drv_get_mac_addr(wpa_s),
2752 ETH_P_EAPOL,
2753 wpa_supplicant_rx_eapol, wpa_s, 0);
2754 if (wpa_s->l2 == NULL)
2755 return -1;
2756 } else {
2757 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2758 if (addr)
2759 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2760 }
2761
2762 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2763 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2764 return -1;
2765 }
2766
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002767 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2768
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002769 return 0;
2770}
2771
2772
Dmitry Shmidt04949592012-07-19 12:16:46 -07002773static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2774 const u8 *buf, size_t len)
2775{
2776 struct wpa_supplicant *wpa_s = ctx;
2777 const struct l2_ethhdr *eth;
2778
2779 if (len < sizeof(*eth))
2780 return;
2781 eth = (const struct l2_ethhdr *) buf;
2782
2783 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2784 !(eth->h_dest[0] & 0x01)) {
2785 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2786 " (bridge - not for this interface - ignore)",
2787 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2788 return;
2789 }
2790
2791 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2792 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2793 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2794 len - sizeof(*eth));
2795}
2796
2797
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002798/**
2799 * wpa_supplicant_driver_init - Initialize driver interface parameters
2800 * @wpa_s: Pointer to wpa_supplicant data
2801 * Returns: 0 on success, -1 on failure
2802 *
2803 * This function is called to initialize driver interface parameters.
2804 * wpa_drv_init() must have been called before this function to initialize the
2805 * driver interface.
2806 */
2807int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2808{
2809 static int interface_count = 0;
2810
2811 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2812 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002813
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002814 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2815 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002816 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002817 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2818
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002819 if (wpa_s->bridge_ifname[0]) {
2820 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2821 "interface '%s'", wpa_s->bridge_ifname);
2822 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2823 wpa_s->own_addr,
2824 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002825 wpa_supplicant_rx_eapol_bridge,
2826 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002827 if (wpa_s->l2_br == NULL) {
2828 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2829 "connection for the bridge interface '%s'",
2830 wpa_s->bridge_ifname);
2831 return -1;
2832 }
2833 }
2834
2835 wpa_clear_keys(wpa_s, NULL);
2836
2837 /* Make sure that TKIP countermeasures are not left enabled (could
2838 * happen if wpa_supplicant is killed during countermeasures. */
2839 wpa_drv_set_countermeasures(wpa_s, 0);
2840
2841 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2842 wpa_drv_flush_pmkid(wpa_s);
2843
2844 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002845 wpa_s->prev_scan_wildcard = 0;
2846
Dmitry Shmidt04949592012-07-19 12:16:46 -07002847 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002848 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2849 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2850 interface_count = 0;
2851 }
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002852 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07002853 wpa_supplicant_delayed_sched_scan(wpa_s,
2854 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002855 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07002856 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002857 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002858 interface_count++;
2859 } else
2860 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2861
2862 return 0;
2863}
2864
2865
2866static int wpa_supplicant_daemon(const char *pid_file)
2867{
2868 wpa_printf(MSG_DEBUG, "Daemonize..");
2869 return os_daemonize(pid_file);
2870}
2871
2872
2873static struct wpa_supplicant * wpa_supplicant_alloc(void)
2874{
2875 struct wpa_supplicant *wpa_s;
2876
2877 wpa_s = os_zalloc(sizeof(*wpa_s));
2878 if (wpa_s == NULL)
2879 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002880 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002881 wpa_s->scan_interval = 5;
2882 wpa_s->new_connection = 1;
2883 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002884 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885
2886 return wpa_s;
2887}
2888
2889
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002890#ifdef CONFIG_HT_OVERRIDES
2891
2892static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2893 struct ieee80211_ht_capabilities *htcaps,
2894 struct ieee80211_ht_capabilities *htcaps_mask,
2895 const char *ht_mcs)
2896{
2897 /* parse ht_mcs into hex array */
2898 int i;
2899 const char *tmp = ht_mcs;
2900 char *end = NULL;
2901
2902 /* If ht_mcs is null, do not set anything */
2903 if (!ht_mcs)
2904 return 0;
2905
2906 /* This is what we are setting in the kernel */
2907 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2908
2909 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2910
2911 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2912 errno = 0;
2913 long v = strtol(tmp, &end, 16);
2914 if (errno == 0) {
2915 wpa_msg(wpa_s, MSG_DEBUG,
2916 "htcap value[%i]: %ld end: %p tmp: %p",
2917 i, v, end, tmp);
2918 if (end == tmp)
2919 break;
2920
2921 htcaps->supported_mcs_set[i] = v;
2922 tmp = end;
2923 } else {
2924 wpa_msg(wpa_s, MSG_ERROR,
2925 "Failed to parse ht-mcs: %s, error: %s\n",
2926 ht_mcs, strerror(errno));
2927 return -1;
2928 }
2929 }
2930
2931 /*
2932 * If we were able to parse any values, then set mask for the MCS set.
2933 */
2934 if (i) {
2935 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2936 IEEE80211_HT_MCS_MASK_LEN - 1);
2937 /* skip the 3 reserved bits */
2938 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2939 0x1f;
2940 }
2941
2942 return 0;
2943}
2944
2945
2946static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2947 struct ieee80211_ht_capabilities *htcaps,
2948 struct ieee80211_ht_capabilities *htcaps_mask,
2949 int disabled)
2950{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002951 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002952
2953 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2954
2955 if (disabled == -1)
2956 return 0;
2957
2958 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2959 htcaps_mask->ht_capabilities_info |= msk;
2960 if (disabled)
2961 htcaps->ht_capabilities_info &= msk;
2962 else
2963 htcaps->ht_capabilities_info |= msk;
2964
2965 return 0;
2966}
2967
2968
2969static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2970 struct ieee80211_ht_capabilities *htcaps,
2971 struct ieee80211_ht_capabilities *htcaps_mask,
2972 int factor)
2973{
2974 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2975
2976 if (factor == -1)
2977 return 0;
2978
2979 if (factor < 0 || factor > 3) {
2980 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2981 "Must be 0-3 or -1", factor);
2982 return -EINVAL;
2983 }
2984
2985 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2986 htcaps->a_mpdu_params &= ~0x3;
2987 htcaps->a_mpdu_params |= factor & 0x3;
2988
2989 return 0;
2990}
2991
2992
2993static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2994 struct ieee80211_ht_capabilities *htcaps,
2995 struct ieee80211_ht_capabilities *htcaps_mask,
2996 int density)
2997{
2998 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2999
3000 if (density == -1)
3001 return 0;
3002
3003 if (density < 0 || density > 7) {
3004 wpa_msg(wpa_s, MSG_ERROR,
3005 "ampdu_density: %d out of range. Must be 0-7 or -1.",
3006 density);
3007 return -EINVAL;
3008 }
3009
3010 htcaps_mask->a_mpdu_params |= 0x1C;
3011 htcaps->a_mpdu_params &= ~(0x1C);
3012 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3013
3014 return 0;
3015}
3016
3017
3018static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3019 struct ieee80211_ht_capabilities *htcaps,
3020 struct ieee80211_ht_capabilities *htcaps_mask,
3021 int disabled)
3022{
3023 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003024 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3025 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003026
3027 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3028
3029 if (disabled)
3030 htcaps->ht_capabilities_info &= ~msk;
3031 else
3032 htcaps->ht_capabilities_info |= msk;
3033
3034 htcaps_mask->ht_capabilities_info |= msk;
3035
3036 return 0;
3037}
3038
3039
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003040static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3041 struct ieee80211_ht_capabilities *htcaps,
3042 struct ieee80211_ht_capabilities *htcaps_mask,
3043 int disabled)
3044{
3045 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003046 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3047 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003048
3049 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3050
3051 if (disabled)
3052 htcaps->ht_capabilities_info &= ~msk;
3053 else
3054 htcaps->ht_capabilities_info |= msk;
3055
3056 htcaps_mask->ht_capabilities_info |= msk;
3057
3058 return 0;
3059}
3060
3061
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003062static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3063 struct ieee80211_ht_capabilities *htcaps,
3064 struct ieee80211_ht_capabilities *htcaps_mask,
3065 int disabled)
3066{
3067 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003068 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003069
3070 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3071
3072 if (disabled)
3073 htcaps->ht_capabilities_info &= ~msk;
3074 else
3075 htcaps->ht_capabilities_info |= msk;
3076
3077 htcaps_mask->ht_capabilities_info |= msk;
3078
3079 return 0;
3080}
3081
3082
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003083void wpa_supplicant_apply_ht_overrides(
3084 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3085 struct wpa_driver_associate_params *params)
3086{
3087 struct ieee80211_ht_capabilities *htcaps;
3088 struct ieee80211_ht_capabilities *htcaps_mask;
3089
3090 if (!ssid)
3091 return;
3092
3093 params->disable_ht = ssid->disable_ht;
3094 if (!params->htcaps || !params->htcaps_mask)
3095 return;
3096
3097 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3098 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3099 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3100 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3101 ssid->disable_max_amsdu);
3102 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3103 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3104 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003105 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003106 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003107
3108 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003109 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003110 htcaps->ht_capabilities_info |= bit;
3111 htcaps_mask->ht_capabilities_info |= bit;
3112 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003113}
3114
3115#endif /* CONFIG_HT_OVERRIDES */
3116
3117
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003118#ifdef CONFIG_VHT_OVERRIDES
3119void wpa_supplicant_apply_vht_overrides(
3120 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3121 struct wpa_driver_associate_params *params)
3122{
3123 struct ieee80211_vht_capabilities *vhtcaps;
3124 struct ieee80211_vht_capabilities *vhtcaps_mask;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003125#ifdef CONFIG_HT_OVERRIDES
3126 int max_ampdu;
3127 const u32 max_ampdu_mask = VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
3128#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003129
3130 if (!ssid)
3131 return;
3132
3133 params->disable_vht = ssid->disable_vht;
3134
3135 vhtcaps = (void *) params->vhtcaps;
3136 vhtcaps_mask = (void *) params->vhtcaps_mask;
3137
3138 if (!vhtcaps || !vhtcaps_mask)
3139 return;
3140
3141 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3142 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3143
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003144#ifdef CONFIG_HT_OVERRIDES
3145 /* if max ampdu is <= 3, we have to make the HT cap the same */
3146 if (ssid->vht_capa_mask & max_ampdu_mask) {
3147 max_ampdu = (ssid->vht_capa & max_ampdu_mask) >>
3148 find_first_bit(max_ampdu_mask);
3149
3150 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3151 wpa_set_ampdu_factor(wpa_s,
3152 (void *) params->htcaps,
3153 (void *) params->htcaps_mask,
3154 max_ampdu);
3155 }
3156#endif /* CONFIG_HT_OVERRIDES */
3157
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003158#define OVERRIDE_MCS(i) \
3159 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3160 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3161 3 << 2 * (i - 1); \
3162 vhtcaps->vht_supported_mcs_set.tx_map |= \
3163 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3164 } \
3165 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3166 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3167 3 << 2 * (i - 1); \
3168 vhtcaps->vht_supported_mcs_set.rx_map |= \
3169 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3170 }
3171
3172 OVERRIDE_MCS(1);
3173 OVERRIDE_MCS(2);
3174 OVERRIDE_MCS(3);
3175 OVERRIDE_MCS(4);
3176 OVERRIDE_MCS(5);
3177 OVERRIDE_MCS(6);
3178 OVERRIDE_MCS(7);
3179 OVERRIDE_MCS(8);
3180}
3181#endif /* CONFIG_VHT_OVERRIDES */
3182
3183
Dmitry Shmidt04949592012-07-19 12:16:46 -07003184static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3185{
3186#ifdef PCSC_FUNCS
3187 size_t len;
3188
3189 if (!wpa_s->conf->pcsc_reader)
3190 return 0;
3191
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003192 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003193 if (!wpa_s->scard)
3194 return 1;
3195
3196 if (wpa_s->conf->pcsc_pin &&
3197 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3198 scard_deinit(wpa_s->scard);
3199 wpa_s->scard = NULL;
3200 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3201 return -1;
3202 }
3203
3204 len = sizeof(wpa_s->imsi) - 1;
3205 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3206 scard_deinit(wpa_s->scard);
3207 wpa_s->scard = NULL;
3208 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3209 return -1;
3210 }
3211 wpa_s->imsi[len] = '\0';
3212
3213 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3214
3215 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3216 wpa_s->imsi, wpa_s->mnc_len);
3217
3218 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3219 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3220#endif /* PCSC_FUNCS */
3221
3222 return 0;
3223}
3224
3225
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003226int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3227{
3228 char *val, *pos;
3229
3230 ext_password_deinit(wpa_s->ext_pw);
3231 wpa_s->ext_pw = NULL;
3232 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3233
3234 if (!wpa_s->conf->ext_password_backend)
3235 return 0;
3236
3237 val = os_strdup(wpa_s->conf->ext_password_backend);
3238 if (val == NULL)
3239 return -1;
3240 pos = os_strchr(val, ':');
3241 if (pos)
3242 *pos++ = '\0';
3243
3244 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3245
3246 wpa_s->ext_pw = ext_password_init(val, pos);
3247 os_free(val);
3248 if (wpa_s->ext_pw == NULL) {
3249 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3250 return -1;
3251 }
3252 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3253
3254 return 0;
3255}
3256
3257
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003258static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
3259 struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003260{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003261 struct wowlan_triggers *triggers;
3262 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003263
3264 if (!wpa_s->conf->wowlan_triggers)
3265 return 0;
3266
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003267 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3268 if (triggers) {
3269 ret = wpa_drv_wowlan(wpa_s, triggers);
3270 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003271 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003272 return ret;
3273}
3274
3275
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003276static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3277 const char *rn)
3278{
3279 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3280 struct wpa_radio *radio;
3281
3282 while (rn && iface) {
3283 radio = iface->radio;
3284 if (radio && os_strcmp(rn, radio->name) == 0) {
3285 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3286 wpa_s->ifname, rn);
3287 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3288 return radio;
3289 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003290
3291 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003292 }
3293
3294 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3295 wpa_s->ifname, rn ? rn : "N/A");
3296 radio = os_zalloc(sizeof(*radio));
3297 if (radio == NULL)
3298 return NULL;
3299
3300 if (rn)
3301 os_strlcpy(radio->name, rn, sizeof(radio->name));
3302 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003303 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003304 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3305
3306 return radio;
3307}
3308
3309
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003310static void radio_work_free(struct wpa_radio_work *work)
3311{
3312 if (work->wpa_s->scan_work == work) {
3313 /* This should not really happen. */
3314 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3315 work->type, work, work->started);
3316 work->wpa_s->scan_work = NULL;
3317 }
3318
3319#ifdef CONFIG_P2P
3320 if (work->wpa_s->p2p_scan_work == work) {
3321 /* This should not really happen. */
3322 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3323 work->type, work, work->started);
3324 work->wpa_s->p2p_scan_work = NULL;
3325 }
3326#endif /* CONFIG_P2P */
3327
3328 dl_list_del(&work->list);
3329 os_free(work);
3330}
3331
3332
3333static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3334{
3335 struct wpa_radio *radio = eloop_ctx;
3336 struct wpa_radio_work *work;
3337 struct os_reltime now, diff;
3338 struct wpa_supplicant *wpa_s;
3339
3340 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3341 if (work == NULL)
3342 return;
3343
3344 if (work->started)
3345 return; /* already started and still in progress */
3346
3347 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3348 radio_list);
3349 if (wpa_s && wpa_s->external_scan_running) {
3350 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3351 return;
3352 }
3353
3354 os_get_reltime(&now);
3355 os_reltime_sub(&now, &work->time, &diff);
3356 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3357 work->type, work, diff.sec, diff.usec);
3358 work->started = 1;
3359 work->time = now;
3360 work->cb(work, 0);
3361}
3362
3363
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003364/*
3365 * This function removes both started and pending radio works running on
3366 * the provided interface's radio.
3367 * Prior to the removal of the radio work, its callback (cb) is called with
3368 * deinit set to be 1. Each work's callback is responsible for clearing its
3369 * internal data and restoring to a correct state.
3370 * @wpa_s: wpa_supplicant data
3371 * @type: type of works to be removed
3372 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3373 * this interface's works.
3374 */
3375void radio_remove_works(struct wpa_supplicant *wpa_s,
3376 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003377{
3378 struct wpa_radio_work *work, *tmp;
3379 struct wpa_radio *radio = wpa_s->radio;
3380
3381 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3382 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003383 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003384 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003385
3386 /* skip other ifaces' works */
3387 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003388 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003389
3390 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3391 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003392 work->cb(work, 1);
3393 radio_work_free(work);
3394 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003395
3396 /* in case we removed the started work */
3397 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003398}
3399
3400
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003401static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3402{
3403 struct wpa_radio *radio = wpa_s->radio;
3404
3405 if (!radio)
3406 return;
3407
3408 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3409 wpa_s->ifname, radio->name);
3410 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003411 radio_remove_works(wpa_s, NULL, 0);
3412 wpa_s->radio = NULL;
3413 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003414 return; /* Interfaces remain for this radio */
3415
3416 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003417 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003418 os_free(radio);
3419}
3420
3421
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003422void radio_work_check_next(struct wpa_supplicant *wpa_s)
3423{
3424 struct wpa_radio *radio = wpa_s->radio;
3425
3426 if (dl_list_empty(&radio->work))
3427 return;
3428 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3429 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3430}
3431
3432
3433/**
3434 * radio_add_work - Add a radio work item
3435 * @wpa_s: Pointer to wpa_supplicant data
3436 * @freq: Frequency of the offchannel operation in MHz or 0
3437 * @type: Unique identifier for each type of work
3438 * @next: Force as the next work to be executed
3439 * @cb: Callback function for indicating when radio is available
3440 * @ctx: Context pointer for the work (work->ctx in cb())
3441 * Returns: 0 on success, -1 on failure
3442 *
3443 * This function is used to request time for an operation that requires
3444 * exclusive radio control. Once the radio is available, the registered callback
3445 * function will be called. radio_work_done() must be called once the exclusive
3446 * radio operation has been completed, so that the radio is freed for other
3447 * operations. The special case of deinit=1 is used to free the context data
3448 * during interface removal. That does not allow the callback function to start
3449 * the radio operation, i.e., it must free any resources allocated for the radio
3450 * work and return.
3451 *
3452 * The @freq parameter can be used to indicate a single channel on which the
3453 * offchannel operation will occur. This may allow multiple radio work
3454 * operations to be performed in parallel if they apply for the same channel.
3455 * Setting this to 0 indicates that the work item may use multiple channels or
3456 * requires exclusive control of the radio.
3457 */
3458int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3459 const char *type, int next,
3460 void (*cb)(struct wpa_radio_work *work, int deinit),
3461 void *ctx)
3462{
3463 struct wpa_radio_work *work;
3464 int was_empty;
3465
3466 work = os_zalloc(sizeof(*work));
3467 if (work == NULL)
3468 return -1;
3469 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3470 os_get_reltime(&work->time);
3471 work->freq = freq;
3472 work->type = type;
3473 work->wpa_s = wpa_s;
3474 work->cb = cb;
3475 work->ctx = ctx;
3476
3477 was_empty = dl_list_empty(&wpa_s->radio->work);
3478 if (next)
3479 dl_list_add(&wpa_s->radio->work, &work->list);
3480 else
3481 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3482 if (was_empty) {
3483 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3484 radio_work_check_next(wpa_s);
3485 }
3486
3487 return 0;
3488}
3489
3490
3491/**
3492 * radio_work_done - Indicate that a radio work item has been completed
3493 * @work: Completed work
3494 *
3495 * This function is called once the callback function registered with
3496 * radio_add_work() has completed its work.
3497 */
3498void radio_work_done(struct wpa_radio_work *work)
3499{
3500 struct wpa_supplicant *wpa_s = work->wpa_s;
3501 struct os_reltime now, diff;
3502 unsigned int started = work->started;
3503
3504 os_get_reltime(&now);
3505 os_reltime_sub(&now, &work->time, &diff);
3506 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3507 work->type, work, started ? "done" : "canceled",
3508 diff.sec, diff.usec);
3509 radio_work_free(work);
3510 if (started)
3511 radio_work_check_next(wpa_s);
3512}
3513
3514
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003515int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
3516{
3517 struct wpa_radio_work *work;
3518 struct wpa_radio *radio = wpa_s->radio;
3519
3520 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3521 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
3522 return 1;
3523 }
3524
3525 return 0;
3526}
3527
3528
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003529static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3530 struct wpa_interface *iface)
3531{
3532 const char *ifname, *driver, *rn;
3533
3534 driver = iface->driver;
3535next_driver:
3536 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3537 return -1;
3538
3539 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3540 if (wpa_s->drv_priv == NULL) {
3541 const char *pos;
3542 pos = driver ? os_strchr(driver, ',') : NULL;
3543 if (pos) {
3544 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3545 "driver interface - try next driver wrapper");
3546 driver = pos + 1;
3547 goto next_driver;
3548 }
3549 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3550 "interface");
3551 return -1;
3552 }
3553 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3554 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3555 "driver_param '%s'", wpa_s->conf->driver_param);
3556 return -1;
3557 }
3558
3559 ifname = wpa_drv_get_ifname(wpa_s);
3560 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3561 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3562 "interface name with '%s'", ifname);
3563 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3564 }
3565
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003566 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003567 if (rn && rn[0] == '\0')
3568 rn = NULL;
3569
3570 wpa_s->radio = radio_add_interface(wpa_s, rn);
3571 if (wpa_s->radio == NULL)
3572 return -1;
3573
3574 return 0;
3575}
3576
3577
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003578static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3579 struct wpa_interface *iface)
3580{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003581 struct wpa_driver_capa capa;
3582
3583 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3584 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3585 iface->confname ? iface->confname : "N/A",
3586 iface->driver ? iface->driver : "default",
3587 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3588 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3589
3590 if (iface->confname) {
3591#ifdef CONFIG_BACKEND_FILE
3592 wpa_s->confname = os_rel2abs_path(iface->confname);
3593 if (wpa_s->confname == NULL) {
3594 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3595 "for configuration file '%s'.",
3596 iface->confname);
3597 return -1;
3598 }
3599 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3600 iface->confname, wpa_s->confname);
3601#else /* CONFIG_BACKEND_FILE */
3602 wpa_s->confname = os_strdup(iface->confname);
3603#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003604 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003605 if (wpa_s->conf == NULL) {
3606 wpa_printf(MSG_ERROR, "Failed to read or parse "
3607 "configuration '%s'.", wpa_s->confname);
3608 return -1;
3609 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003610 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3611 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003612
3613 /*
3614 * Override ctrl_interface and driver_param if set on command
3615 * line.
3616 */
3617 if (iface->ctrl_interface) {
3618 os_free(wpa_s->conf->ctrl_interface);
3619 wpa_s->conf->ctrl_interface =
3620 os_strdup(iface->ctrl_interface);
3621 }
3622
3623 if (iface->driver_param) {
3624 os_free(wpa_s->conf->driver_param);
3625 wpa_s->conf->driver_param =
3626 os_strdup(iface->driver_param);
3627 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003628
3629 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3630 os_free(wpa_s->conf->ctrl_interface);
3631 wpa_s->conf->ctrl_interface = NULL;
3632 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003633 } else
3634 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3635 iface->driver_param);
3636
3637 if (wpa_s->conf == NULL) {
3638 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3639 return -1;
3640 }
3641
3642 if (iface->ifname == NULL) {
3643 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3644 return -1;
3645 }
3646 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3647 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3648 iface->ifname);
3649 return -1;
3650 }
3651 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3652
3653 if (iface->bridge_ifname) {
3654 if (os_strlen(iface->bridge_ifname) >=
3655 sizeof(wpa_s->bridge_ifname)) {
3656 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3657 "name '%s'.", iface->bridge_ifname);
3658 return -1;
3659 }
3660 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3661 sizeof(wpa_s->bridge_ifname));
3662 }
3663
3664 /* RSNA Supplicant Key Management - INITIALIZE */
3665 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3666 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3667
3668 /* Initialize driver interface and register driver event handler before
3669 * L2 receive handler so that association events are processed before
3670 * EAPOL-Key packets if both become available for the same select()
3671 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003672 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003673 return -1;
3674
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3676 return -1;
3677
3678 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3679 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3680 NULL);
3681 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3682
3683 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3684 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3685 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3686 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3687 "dot11RSNAConfigPMKLifetime");
3688 return -1;
3689 }
3690
3691 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3692 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3693 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3694 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3695 "dot11RSNAConfigPMKReauthThreshold");
3696 return -1;
3697 }
3698
3699 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3700 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3701 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3702 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3703 "dot11RSNAConfigSATimeout");
3704 return -1;
3705 }
3706
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003707 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3708 &wpa_s->hw.num_modes,
3709 &wpa_s->hw.flags);
3710
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003711 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003712 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003713 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003714 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003715 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003716 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003717 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3718 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3719 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003720 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3721 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003722 wpa_s->extended_capa = capa.extended_capa;
3723 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3724 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003725 wpa_s->num_multichan_concurrent =
3726 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003727 }
3728 if (wpa_s->max_remain_on_chan == 0)
3729 wpa_s->max_remain_on_chan = 1000;
3730
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003731 /*
3732 * Only take p2p_mgmt parameters when P2P Device is supported.
3733 * Doing it here as it determines whether l2_packet_init() will be done
3734 * during wpa_supplicant_driver_init().
3735 */
3736 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3737 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3738 else
3739 iface->p2p_mgmt = 1;
3740
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003741 if (wpa_s->num_multichan_concurrent == 0)
3742 wpa_s->num_multichan_concurrent = 1;
3743
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003744 if (wpa_supplicant_driver_init(wpa_s) < 0)
3745 return -1;
3746
3747#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003748 if ((!iface->p2p_mgmt ||
3749 !(wpa_s->drv_flags &
3750 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3751 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003752 return -1;
3753#endif /* CONFIG_TDLS */
3754
3755 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3756 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3757 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3758 return -1;
3759 }
3760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003761 if (wpas_wps_init(wpa_s))
3762 return -1;
3763
3764 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3765 return -1;
3766 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3767
3768 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3769 if (wpa_s->ctrl_iface == NULL) {
3770 wpa_printf(MSG_ERROR,
3771 "Failed to initialize control interface '%s'.\n"
3772 "You may have another wpa_supplicant process "
3773 "already running or the file was\n"
3774 "left by an unclean termination of wpa_supplicant "
3775 "in which case you will need\n"
3776 "to manually remove this file before starting "
3777 "wpa_supplicant again.\n",
3778 wpa_s->conf->ctrl_interface);
3779 return -1;
3780 }
3781
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003782 wpa_s->gas = gas_query_init(wpa_s);
3783 if (wpa_s->gas == NULL) {
3784 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3785 return -1;
3786 }
3787
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003788 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003789 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3790 return -1;
3791 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003792
3793 if (wpa_bss_init(wpa_s) < 0)
3794 return -1;
3795
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003796 /*
3797 * Set Wake-on-WLAN triggers, if configured.
3798 * Note: We don't restore/remove the triggers on shutdown (it doesn't
3799 * have effect anyway when the interface is down).
3800 */
3801 if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
3802 return -1;
3803
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003804#ifdef CONFIG_EAP_PROXY
3805{
3806 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003807 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3808 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003809 if (wpa_s->mnc_len > 0) {
3810 wpa_s->imsi[len] = '\0';
3811 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3812 wpa_s->imsi, wpa_s->mnc_len);
3813 } else {
3814 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3815 }
3816}
3817#endif /* CONFIG_EAP_PROXY */
3818
Dmitry Shmidt04949592012-07-19 12:16:46 -07003819 if (pcsc_reader_init(wpa_s) < 0)
3820 return -1;
3821
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003822 if (wpas_init_ext_pw(wpa_s) < 0)
3823 return -1;
3824
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 return 0;
3826}
3827
3828
3829static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003830 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003831{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003832 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003833 if (wpa_s->drv_priv) {
3834 wpa_supplicant_deauthenticate(wpa_s,
3835 WLAN_REASON_DEAUTH_LEAVING);
3836
3837 wpa_drv_set_countermeasures(wpa_s, 0);
3838 wpa_clear_keys(wpa_s, NULL);
3839 }
3840
3841 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003842 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003843
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003844 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003845 radio_remove_interface(wpa_s);
3846
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003847 if (wpa_s->drv_priv)
3848 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003849
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003850 if (notify)
3851 wpas_notify_iface_removed(wpa_s);
3852
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003853 if (terminate)
3854 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003855
3856 if (wpa_s->ctrl_iface) {
3857 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3858 wpa_s->ctrl_iface = NULL;
3859 }
3860
3861 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003862 wpa_config_free(wpa_s->conf);
3863 wpa_s->conf = NULL;
3864 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003865
3866 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003867}
3868
3869
3870/**
3871 * wpa_supplicant_add_iface - Add a new network interface
3872 * @global: Pointer to global data from wpa_supplicant_init()
3873 * @iface: Interface configuration options
3874 * Returns: Pointer to the created interface or %NULL on failure
3875 *
3876 * This function is used to add new network interfaces for %wpa_supplicant.
3877 * This can be called before wpa_supplicant_run() to add interfaces before the
3878 * main event loop has been started. In addition, new interfaces can be added
3879 * dynamically while %wpa_supplicant is already running. This could happen,
3880 * e.g., when a hotplug network adapter is inserted.
3881 */
3882struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3883 struct wpa_interface *iface)
3884{
3885 struct wpa_supplicant *wpa_s;
3886 struct wpa_interface t_iface;
3887 struct wpa_ssid *ssid;
3888
3889 if (global == NULL || iface == NULL)
3890 return NULL;
3891
3892 wpa_s = wpa_supplicant_alloc();
3893 if (wpa_s == NULL)
3894 return NULL;
3895
3896 wpa_s->global = global;
3897
3898 t_iface = *iface;
3899 if (global->params.override_driver) {
3900 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3901 "('%s' -> '%s')",
3902 iface->driver, global->params.override_driver);
3903 t_iface.driver = global->params.override_driver;
3904 }
3905 if (global->params.override_ctrl_interface) {
3906 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3907 "ctrl_interface ('%s' -> '%s')",
3908 iface->ctrl_interface,
3909 global->params.override_ctrl_interface);
3910 t_iface.ctrl_interface =
3911 global->params.override_ctrl_interface;
3912 }
3913 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3914 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3915 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003916 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003917 return NULL;
3918 }
3919
3920 /* Notify the control interfaces about new iface */
3921 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003922 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 return NULL;
3924 }
3925
3926 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3927 wpas_notify_network_added(wpa_s, ssid);
3928
3929 wpa_s->next = global->ifaces;
3930 global->ifaces = wpa_s;
3931
3932 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003933 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003934
3935 return wpa_s;
3936}
3937
3938
3939/**
3940 * wpa_supplicant_remove_iface - Remove a network interface
3941 * @global: Pointer to global data from wpa_supplicant_init()
3942 * @wpa_s: Pointer to the network interface to be removed
3943 * Returns: 0 if interface was removed, -1 if interface was not found
3944 *
3945 * This function can be used to dynamically remove network interfaces from
3946 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3947 * addition, this function is used to remove all remaining interfaces when
3948 * %wpa_supplicant is terminated.
3949 */
3950int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003951 struct wpa_supplicant *wpa_s,
3952 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003953{
3954 struct wpa_supplicant *prev;
3955
3956 /* Remove interface from the global list of interfaces */
3957 prev = global->ifaces;
3958 if (prev == wpa_s) {
3959 global->ifaces = wpa_s->next;
3960 } else {
3961 while (prev && prev->next != wpa_s)
3962 prev = prev->next;
3963 if (prev == NULL)
3964 return -1;
3965 prev->next = wpa_s->next;
3966 }
3967
3968 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3969
3970 if (global->p2p_group_formation == wpa_s)
3971 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003972 if (global->p2p_invite_group == wpa_s)
3973 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003974 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003975
3976 return 0;
3977}
3978
3979
3980/**
3981 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3982 * @wpa_s: Pointer to the network interface
3983 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3984 */
3985const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3986{
3987 const char *eapol_method;
3988
3989 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3990 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3991 return "NO-EAP";
3992 }
3993
3994 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3995 if (eapol_method == NULL)
3996 return "UNKNOWN-EAP";
3997
3998 return eapol_method;
3999}
4000
4001
4002/**
4003 * wpa_supplicant_get_iface - Get a new network interface
4004 * @global: Pointer to global data from wpa_supplicant_init()
4005 * @ifname: Interface name
4006 * Returns: Pointer to the interface or %NULL if not found
4007 */
4008struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4009 const char *ifname)
4010{
4011 struct wpa_supplicant *wpa_s;
4012
4013 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4014 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4015 return wpa_s;
4016 }
4017 return NULL;
4018}
4019
4020
4021#ifndef CONFIG_NO_WPA_MSG
4022static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4023{
4024 struct wpa_supplicant *wpa_s = ctx;
4025 if (wpa_s == NULL)
4026 return NULL;
4027 return wpa_s->ifname;
4028}
4029#endif /* CONFIG_NO_WPA_MSG */
4030
4031
4032/**
4033 * wpa_supplicant_init - Initialize %wpa_supplicant
4034 * @params: Parameters for %wpa_supplicant
4035 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4036 *
4037 * This function is used to initialize %wpa_supplicant. After successful
4038 * initialization, the returned data pointer can be used to add and remove
4039 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4040 */
4041struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4042{
4043 struct wpa_global *global;
4044 int ret, i;
4045
4046 if (params == NULL)
4047 return NULL;
4048
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004049#ifdef CONFIG_DRIVER_NDIS
4050 {
4051 void driver_ndis_init_ops(void);
4052 driver_ndis_init_ops();
4053 }
4054#endif /* CONFIG_DRIVER_NDIS */
4055
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004056#ifndef CONFIG_NO_WPA_MSG
4057 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4058#endif /* CONFIG_NO_WPA_MSG */
4059
4060 wpa_debug_open_file(params->wpa_debug_file_path);
4061 if (params->wpa_debug_syslog)
4062 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004063 if (params->wpa_debug_tracing) {
4064 ret = wpa_debug_open_linux_tracing();
4065 if (ret) {
4066 wpa_printf(MSG_ERROR,
4067 "Failed to enable trace logging");
4068 return NULL;
4069 }
4070 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004071
4072 ret = eap_register_methods();
4073 if (ret) {
4074 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4075 if (ret == -2)
4076 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4077 "the same EAP type.");
4078 return NULL;
4079 }
4080
4081 global = os_zalloc(sizeof(*global));
4082 if (global == NULL)
4083 return NULL;
4084 dl_list_init(&global->p2p_srv_bonjour);
4085 dl_list_init(&global->p2p_srv_upnp);
4086 global->params.daemonize = params->daemonize;
4087 global->params.wait_for_monitor = params->wait_for_monitor;
4088 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4089 if (params->pid_file)
4090 global->params.pid_file = os_strdup(params->pid_file);
4091 if (params->ctrl_interface)
4092 global->params.ctrl_interface =
4093 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004094 if (params->ctrl_interface_group)
4095 global->params.ctrl_interface_group =
4096 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004097 if (params->override_driver)
4098 global->params.override_driver =
4099 os_strdup(params->override_driver);
4100 if (params->override_ctrl_interface)
4101 global->params.override_ctrl_interface =
4102 os_strdup(params->override_ctrl_interface);
4103 wpa_debug_level = global->params.wpa_debug_level =
4104 params->wpa_debug_level;
4105 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4106 params->wpa_debug_show_keys;
4107 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4108 params->wpa_debug_timestamp;
4109
4110 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4111
4112 if (eloop_init()) {
4113 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4114 wpa_supplicant_deinit(global);
4115 return NULL;
4116 }
4117
Jouni Malinen75ecf522011-06-27 15:19:46 -07004118 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004119
4120 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4121 if (global->ctrl_iface == NULL) {
4122 wpa_supplicant_deinit(global);
4123 return NULL;
4124 }
4125
4126 if (wpas_notify_supplicant_initialized(global)) {
4127 wpa_supplicant_deinit(global);
4128 return NULL;
4129 }
4130
4131 for (i = 0; wpa_drivers[i]; i++)
4132 global->drv_count++;
4133 if (global->drv_count == 0) {
4134 wpa_printf(MSG_ERROR, "No drivers enabled");
4135 wpa_supplicant_deinit(global);
4136 return NULL;
4137 }
4138 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
4139 if (global->drv_priv == NULL) {
4140 wpa_supplicant_deinit(global);
4141 return NULL;
4142 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004143
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004144#ifdef CONFIG_WIFI_DISPLAY
4145 if (wifi_display_init(global) < 0) {
4146 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4147 wpa_supplicant_deinit(global);
4148 return NULL;
4149 }
4150#endif /* CONFIG_WIFI_DISPLAY */
4151
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004152 return global;
4153}
4154
4155
4156/**
4157 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4158 * @global: Pointer to global data from wpa_supplicant_init()
4159 * Returns: 0 after successful event loop run, -1 on failure
4160 *
4161 * This function starts the main event loop and continues running as long as
4162 * there are any remaining events. In most cases, this function is running as
4163 * long as the %wpa_supplicant process in still in use.
4164 */
4165int wpa_supplicant_run(struct wpa_global *global)
4166{
4167 struct wpa_supplicant *wpa_s;
4168
4169 if (global->params.daemonize &&
4170 wpa_supplicant_daemon(global->params.pid_file))
4171 return -1;
4172
4173 if (global->params.wait_for_monitor) {
4174 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4175 if (wpa_s->ctrl_iface)
4176 wpa_supplicant_ctrl_iface_wait(
4177 wpa_s->ctrl_iface);
4178 }
4179
4180 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4181 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4182
4183 eloop_run();
4184
4185 return 0;
4186}
4187
4188
4189/**
4190 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4191 * @global: Pointer to global data from wpa_supplicant_init()
4192 *
4193 * This function is called to deinitialize %wpa_supplicant and to free all
4194 * allocated resources. Remaining network interfaces will also be removed.
4195 */
4196void wpa_supplicant_deinit(struct wpa_global *global)
4197{
4198 int i;
4199
4200 if (global == NULL)
4201 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004202
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004203#ifdef CONFIG_WIFI_DISPLAY
4204 wifi_display_deinit(global);
4205#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004206
4207 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004208 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004209
4210 if (global->ctrl_iface)
4211 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4212
4213 wpas_notify_supplicant_deinitialized(global);
4214
4215 eap_peer_unregister_methods();
4216#ifdef CONFIG_AP
4217 eap_server_unregister_methods();
4218#endif /* CONFIG_AP */
4219
4220 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4221 if (!global->drv_priv[i])
4222 continue;
4223 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4224 }
4225 os_free(global->drv_priv);
4226
4227 random_deinit();
4228
4229 eloop_destroy();
4230
4231 if (global->params.pid_file) {
4232 os_daemonize_terminate(global->params.pid_file);
4233 os_free(global->params.pid_file);
4234 }
4235 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004236 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004237 os_free(global->params.override_driver);
4238 os_free(global->params.override_ctrl_interface);
4239
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004240 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004241 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004242 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004243
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004244 os_free(global);
4245 wpa_debug_close_syslog();
4246 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004247 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004248}
4249
4250
4251void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4252{
4253 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4254 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4255 char country[3];
4256 country[0] = wpa_s->conf->country[0];
4257 country[1] = wpa_s->conf->country[1];
4258 country[2] = '\0';
4259 if (wpa_drv_set_country(wpa_s, country) < 0) {
4260 wpa_printf(MSG_ERROR, "Failed to set country code "
4261 "'%s'", country);
4262 }
4263 }
4264
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004265 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4266 wpas_init_ext_pw(wpa_s);
4267
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004268#ifdef CONFIG_WPS
4269 wpas_wps_update_config(wpa_s);
4270#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004271 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004272 wpa_s->conf->changed_parameters = 0;
4273}
4274
4275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004276static void add_freq(int *freqs, int *num_freqs, int freq)
4277{
4278 int i;
4279
4280 for (i = 0; i < *num_freqs; i++) {
4281 if (freqs[i] == freq)
4282 return;
4283 }
4284
4285 freqs[*num_freqs] = freq;
4286 (*num_freqs)++;
4287}
4288
4289
4290static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4291{
4292 struct wpa_bss *bss, *cbss;
4293 const int max_freqs = 10;
4294 int *freqs;
4295 int num_freqs = 0;
4296
4297 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
4298 if (freqs == NULL)
4299 return NULL;
4300
4301 cbss = wpa_s->current_bss;
4302
4303 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4304 if (bss == cbss)
4305 continue;
4306 if (bss->ssid_len == cbss->ssid_len &&
4307 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4308 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4309 add_freq(freqs, &num_freqs, bss->freq);
4310 if (num_freqs == max_freqs)
4311 break;
4312 }
4313 }
4314
4315 if (num_freqs == 0) {
4316 os_free(freqs);
4317 freqs = NULL;
4318 }
4319
4320 return freqs;
4321}
4322
4323
4324void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4325{
4326 int timeout;
4327 int count;
4328 int *freqs = NULL;
4329
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004330 wpas_connect_work_done(wpa_s);
4331
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004332 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004333 * Remove possible authentication timeout since the connection failed.
4334 */
4335 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4336
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004337 if (wpa_s->disconnected) {
4338 /*
4339 * There is no point in blacklisting the AP if this event is
4340 * generated based on local request to disconnect.
4341 */
4342 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4343 "indication since interface has been put into "
4344 "disconnected state");
4345 return;
4346 }
4347
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004348 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349 * Add the failed BSSID into the blacklist and speed up next scan
4350 * attempt if there could be other APs that could accept association.
4351 * The current blacklist count indicates how many times we have tried
4352 * connecting to this AP and multiple attempts mean that other APs are
4353 * either not available or has already been tried, so that we can start
4354 * increasing the delay here to avoid constant scanning.
4355 */
4356 count = wpa_blacklist_add(wpa_s, bssid);
4357 if (count == 1 && wpa_s->current_bss) {
4358 /*
4359 * This BSS was not in the blacklist before. If there is
4360 * another BSS available for the same ESS, we should try that
4361 * next. Otherwise, we may as well try this one once more
4362 * before allowing other, likely worse, ESSes to be considered.
4363 */
4364 freqs = get_bss_freqs_in_ess(wpa_s);
4365 if (freqs) {
4366 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4367 "has been seen; try it next");
4368 wpa_blacklist_add(wpa_s, bssid);
4369 /*
4370 * On the next scan, go through only the known channels
4371 * used in this ESS based on previous scans to speed up
4372 * common load balancing use case.
4373 */
4374 os_free(wpa_s->next_scan_freqs);
4375 wpa_s->next_scan_freqs = freqs;
4376 }
4377 }
4378
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004379 /*
4380 * Add previous failure count in case the temporary blacklist was
4381 * cleared due to no other BSSes being available.
4382 */
4383 count += wpa_s->extra_blacklist_count;
4384
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004385 if (count > 3 && wpa_s->current_ssid) {
4386 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4387 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004388 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004389 }
4390
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004391 switch (count) {
4392 case 1:
4393 timeout = 100;
4394 break;
4395 case 2:
4396 timeout = 500;
4397 break;
4398 case 3:
4399 timeout = 1000;
4400 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004401 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004402 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004403 break;
4404 default:
4405 timeout = 10000;
4406 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004407 }
4408
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004409 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4410 "ms", count, timeout);
4411
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004412 /*
4413 * TODO: if more than one possible AP is available in scan results,
4414 * could try the other ones before requesting a new scan.
4415 */
4416 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4417 1000 * (timeout % 1000));
4418}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004419
4420
4421int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4422{
4423 return wpa_s->conf->ap_scan == 2 ||
4424 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4425}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004426
Dmitry Shmidt04949592012-07-19 12:16:46 -07004427
4428#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4429int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4430 struct wpa_ssid *ssid,
4431 const char *field,
4432 const char *value)
4433{
4434#ifdef IEEE8021X_EAPOL
4435 struct eap_peer_config *eap = &ssid->eap;
4436
4437 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4438 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4439 (const u8 *) value, os_strlen(value));
4440
4441 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4442 case WPA_CTRL_REQ_EAP_IDENTITY:
4443 os_free(eap->identity);
4444 eap->identity = (u8 *) os_strdup(value);
4445 eap->identity_len = os_strlen(value);
4446 eap->pending_req_identity = 0;
4447 if (ssid == wpa_s->current_ssid)
4448 wpa_s->reassociate = 1;
4449 break;
4450 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004451 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004452 eap->password = (u8 *) os_strdup(value);
4453 eap->password_len = os_strlen(value);
4454 eap->pending_req_password = 0;
4455 if (ssid == wpa_s->current_ssid)
4456 wpa_s->reassociate = 1;
4457 break;
4458 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004459 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004460 eap->new_password = (u8 *) os_strdup(value);
4461 eap->new_password_len = os_strlen(value);
4462 eap->pending_req_new_password = 0;
4463 if (ssid == wpa_s->current_ssid)
4464 wpa_s->reassociate = 1;
4465 break;
4466 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004467 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004468 eap->pin = os_strdup(value);
4469 eap->pending_req_pin = 0;
4470 if (ssid == wpa_s->current_ssid)
4471 wpa_s->reassociate = 1;
4472 break;
4473 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004474 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004475 eap->otp = (u8 *) os_strdup(value);
4476 eap->otp_len = os_strlen(value);
4477 os_free(eap->pending_req_otp);
4478 eap->pending_req_otp = NULL;
4479 eap->pending_req_otp_len = 0;
4480 break;
4481 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004482 str_clear_free(eap->private_key_passwd);
4483 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004484 eap->pending_req_passphrase = 0;
4485 if (ssid == wpa_s->current_ssid)
4486 wpa_s->reassociate = 1;
4487 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004488 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004489 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004490 eap->external_sim_resp = os_strdup(value);
4491 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004492 default:
4493 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4494 return -1;
4495 }
4496
4497 return 0;
4498#else /* IEEE8021X_EAPOL */
4499 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4500 return -1;
4501#endif /* IEEE8021X_EAPOL */
4502}
4503#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4504
4505
4506int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4507{
4508 int i;
4509 unsigned int drv_enc;
4510
4511 if (ssid == NULL)
4512 return 1;
4513
4514 if (ssid->disabled)
4515 return 1;
4516
4517 if (wpa_s && wpa_s->drv_capa_known)
4518 drv_enc = wpa_s->drv_enc;
4519 else
4520 drv_enc = (unsigned int) -1;
4521
4522 for (i = 0; i < NUM_WEP_KEYS; i++) {
4523 size_t len = ssid->wep_key_len[i];
4524 if (len == 0)
4525 continue;
4526 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4527 continue;
4528 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4529 continue;
4530 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4531 continue;
4532 return 1; /* invalid WEP key */
4533 }
4534
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004535 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07004536 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004537 return 1;
4538
Dmitry Shmidt04949592012-07-19 12:16:46 -07004539 return 0;
4540}
4541
4542
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004543int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004544{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004545 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004546 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004547 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004548 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004549 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004550}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004551
4552
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004553void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004554{
4555 struct wpa_ssid *ssid = wpa_s->current_ssid;
4556 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004557 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004558
4559 if (ssid == NULL) {
4560 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4561 "SSID block");
4562 return;
4563 }
4564
4565 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4566 return;
4567
4568 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004569
4570#ifdef CONFIG_P2P
4571 if (ssid->p2p_group &&
4572 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4573 /*
4574 * Skip the wait time since there is a short timeout on the
4575 * connection to a P2P group.
4576 */
4577 return;
4578 }
4579#endif /* CONFIG_P2P */
4580
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004581 if (ssid->auth_failures > 50)
4582 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004583 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004584 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004585 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004586 dur = 90;
4587 else if (ssid->auth_failures > 3)
4588 dur = 60;
4589 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004590 dur = 30;
4591 else if (ssid->auth_failures > 1)
4592 dur = 20;
4593 else
4594 dur = 10;
4595
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004596 if (ssid->auth_failures > 1 &&
4597 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
4598 dur += os_random() % (ssid->auth_failures * 10);
4599
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004600 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004601 if (now.sec + dur <= ssid->disabled_until.sec)
4602 return;
4603
4604 ssid->disabled_until.sec = now.sec + dur;
4605
4606 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004607 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004608 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004609 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004610}
4611
4612
4613void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4614 struct wpa_ssid *ssid, int clear_failures)
4615{
4616 if (ssid == NULL)
4617 return;
4618
4619 if (ssid->disabled_until.sec) {
4620 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4621 "id=%d ssid=\"%s\"",
4622 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4623 }
4624 ssid->disabled_until.sec = 0;
4625 ssid->disabled_until.usec = 0;
4626 if (clear_failures)
4627 ssid->auth_failures = 0;
4628}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004629
4630
4631int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4632{
4633 size_t i;
4634
4635 if (wpa_s->disallow_aps_bssid == NULL)
4636 return 0;
4637
4638 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4639 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4640 bssid, ETH_ALEN) == 0)
4641 return 1;
4642 }
4643
4644 return 0;
4645}
4646
4647
4648int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4649 size_t ssid_len)
4650{
4651 size_t i;
4652
4653 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4654 return 0;
4655
4656 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4657 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4658 if (ssid_len == s->ssid_len &&
4659 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4660 return 1;
4661 }
4662
4663 return 0;
4664}
4665
4666
4667/**
4668 * wpas_request_connection - Request a new connection
4669 * @wpa_s: Pointer to the network interface
4670 *
4671 * This function is used to request a new connection to be found. It will mark
4672 * the interface to allow reassociation and request a new scan to find a
4673 * suitable network to connect to.
4674 */
4675void wpas_request_connection(struct wpa_supplicant *wpa_s)
4676{
4677 wpa_s->normal_scans = 0;
4678 wpa_supplicant_reinit_autoscan(wpa_s);
4679 wpa_s->extra_blacklist_count = 0;
4680 wpa_s->disconnected = 0;
4681 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004682
4683 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4684 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004685}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004686
4687
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004688void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
4689 struct wpa_used_freq_data *freqs_data,
4690 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004691{
4692 unsigned int i;
4693
4694 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4695 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004696 for (i = 0; i < len; i++) {
4697 struct wpa_used_freq_data *cur = &freqs_data[i];
4698 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
4699 i, cur->freq, cur->flags);
4700 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004701}
4702
4703
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004704/*
4705 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004706 * are using the same radio as the current interface, and in addition, get
4707 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004708 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004709int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
4710 struct wpa_used_freq_data *freqs_data,
4711 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004712{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004713 struct wpa_supplicant *ifs;
4714 u8 bssid[ETH_ALEN];
4715 int freq;
4716 unsigned int idx = 0, i;
4717
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004718 wpa_dbg(wpa_s, MSG_DEBUG,
4719 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004720 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004721
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004722 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4723 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004724 if (idx == len)
4725 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004726
4727 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4728 continue;
4729
4730 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4731 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4732 freq = ifs->current_ssid->frequency;
4733 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4734 freq = ifs->assoc_freq;
4735 else
4736 continue;
4737
4738 /* Hold only distinct freqs */
4739 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004740 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004741 break;
4742
4743 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004744 freqs_data[idx++].freq = freq;
4745
4746 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
4747 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
4748 WPA_FREQ_USED_BY_P2P_CLIENT :
4749 WPA_FREQ_USED_BY_INFRA_STATION;
4750 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004751 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004752
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004753 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004754 return idx;
4755}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004756
4757
4758/*
4759 * Find the operating frequencies of any of the virtual interfaces that
4760 * are using the same radio as the current interface.
4761 */
4762int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4763 int *freq_array, unsigned int len)
4764{
4765 struct wpa_used_freq_data *freqs_data;
4766 int num, i;
4767
4768 os_memset(freq_array, 0, sizeof(int) * len);
4769
4770 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
4771 if (!freqs_data)
4772 return -1;
4773
4774 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
4775 for (i = 0; i < num; i++)
4776 freq_array[i] = freqs_data[i].freq;
4777
4778 os_free(freqs_data);
4779
4780 return num;
4781}