blob: d1289928ea5fb4ab07b62e30b3365e9ed3daa7ec [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 Shmidt2ac5f602014-03-07 10:08:21 -0800409#ifdef CONFIG_P2P
410 os_free(wpa_s->conf_p2p_dev);
411 wpa_s->conf_p2p_dev = NULL;
412#endif /* CONFIG_P2P */
413
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700414 wpa_sm_set_eapol(wpa_s->wpa, NULL);
415 eapol_sm_deinit(wpa_s->eapol);
416 wpa_s->eapol = NULL;
417
418 rsn_preauth_deinit(wpa_s->wpa);
419
420#ifdef CONFIG_TDLS
421 wpa_tdls_deinit(wpa_s->wpa);
422#endif /* CONFIG_TDLS */
423
424 pmksa_candidate_free(wpa_s->wpa);
425 wpa_sm_deinit(wpa_s->wpa);
426 wpa_s->wpa = NULL;
427 wpa_blacklist_clear(wpa_s);
428
429 wpa_bss_deinit(wpa_s);
430
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700431 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432 wpa_supplicant_cancel_scan(wpa_s);
433 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800434 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
435#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
436 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
437 wpa_s, NULL);
438#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700439
440 wpas_wps_deinit(wpa_s);
441
442 wpabuf_free(wpa_s->pending_eapol_rx);
443 wpa_s->pending_eapol_rx = NULL;
444
445#ifdef CONFIG_IBSS_RSN
446 ibss_rsn_deinit(wpa_s->ibss_rsn);
447 wpa_s->ibss_rsn = NULL;
448#endif /* CONFIG_IBSS_RSN */
449
450 sme_deinit(wpa_s);
451
452#ifdef CONFIG_AP
453 wpa_supplicant_ap_deinit(wpa_s);
454#endif /* CONFIG_AP */
455
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700456 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800458#ifdef CONFIG_OFFCHANNEL
459 offchannel_deinit(wpa_s);
460#endif /* CONFIG_OFFCHANNEL */
461
462 wpa_supplicant_cancel_sched_scan(wpa_s);
463
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700464 os_free(wpa_s->next_scan_freqs);
465 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800466
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800467 os_free(wpa_s->manual_scan_freqs);
468 wpa_s->manual_scan_freqs = NULL;
469
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700470 os_free(wpa_s->manual_sched_scan_freqs);
471 wpa_s->manual_sched_scan_freqs = NULL;
472
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800473 gas_query_deinit(wpa_s->gas);
474 wpa_s->gas = NULL;
475
476 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700477
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700478 ieee802_1x_dealloc_kay_sm(wpa_s);
479
Dmitry Shmidt04949592012-07-19 12:16:46 -0700480 os_free(wpa_s->bssid_filter);
481 wpa_s->bssid_filter = NULL;
482
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800483 os_free(wpa_s->disallow_aps_bssid);
484 wpa_s->disallow_aps_bssid = NULL;
485 os_free(wpa_s->disallow_aps_ssid);
486 wpa_s->disallow_aps_ssid = NULL;
487
Dmitry Shmidt04949592012-07-19 12:16:46 -0700488 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700489#ifdef CONFIG_WNM
490 wnm_deallocate_memory(wpa_s);
491#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700492
493 ext_password_deinit(wpa_s->ext_pw);
494 wpa_s->ext_pw = NULL;
495
496 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800497 wpa_s->last_gas_resp = NULL;
498 wpabuf_free(wpa_s->prev_gas_resp);
499 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700500
501 os_free(wpa_s->last_scan_res);
502 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800503
504#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700505 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800506#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700507
508 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
509 wpabuf_free(wpa_s->vendor_elem[i]);
510 wpa_s->vendor_elem[i] = NULL;
511 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700512}
513
514
515/**
516 * wpa_clear_keys - Clear keys configured for the driver
517 * @wpa_s: Pointer to wpa_supplicant data
518 * @addr: Previously used BSSID or %NULL if not available
519 *
520 * This function clears the encryption keys that has been previously configured
521 * for the driver.
522 */
523void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
524{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800525 int i, max;
526
527#ifdef CONFIG_IEEE80211W
528 max = 6;
529#else /* CONFIG_IEEE80211W */
530 max = 4;
531#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700532
533 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800534 for (i = 0; i < max; i++) {
535 if (wpa_s->keys_cleared & BIT(i))
536 continue;
537 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
538 NULL, 0);
539 }
540 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
541 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700542 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
543 0);
544 /* MLME-SETPROTECTION.request(None) */
545 wpa_drv_mlme_setprotection(
546 wpa_s, addr,
547 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
548 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
549 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800550 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700551}
552
553
554/**
555 * wpa_supplicant_state_txt - Get the connection state name as a text string
556 * @state: State (wpa_state; WPA_*)
557 * Returns: The state name as a printable text string
558 */
559const char * wpa_supplicant_state_txt(enum wpa_states state)
560{
561 switch (state) {
562 case WPA_DISCONNECTED:
563 return "DISCONNECTED";
564 case WPA_INACTIVE:
565 return "INACTIVE";
566 case WPA_INTERFACE_DISABLED:
567 return "INTERFACE_DISABLED";
568 case WPA_SCANNING:
569 return "SCANNING";
570 case WPA_AUTHENTICATING:
571 return "AUTHENTICATING";
572 case WPA_ASSOCIATING:
573 return "ASSOCIATING";
574 case WPA_ASSOCIATED:
575 return "ASSOCIATED";
576 case WPA_4WAY_HANDSHAKE:
577 return "4WAY_HANDSHAKE";
578 case WPA_GROUP_HANDSHAKE:
579 return "GROUP_HANDSHAKE";
580 case WPA_COMPLETED:
581 return "COMPLETED";
582 default:
583 return "UNKNOWN";
584 }
585}
586
587
588#ifdef CONFIG_BGSCAN
589
590static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
591{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800592 const char *name;
593
594 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
595 name = wpa_s->current_ssid->bgscan;
596 else
597 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800598 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800599 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800600 if (wpas_driver_bss_selection(wpa_s))
601 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
603 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800604#ifdef CONFIG_P2P
605 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
606 return;
607#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700608
609 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800610 if (wpa_s->current_ssid) {
611 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700612 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
613 "bgscan");
614 /*
615 * Live without bgscan; it is only used as a roaming
616 * optimization, so the initial connection is not
617 * affected.
618 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700619 } else {
620 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700621 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700622 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
623 0);
624 if (scan_res) {
625 bgscan_notify_scan(wpa_s, scan_res);
626 wpa_scan_results_free(scan_res);
627 }
628 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700629 } else
630 wpa_s->bgscan_ssid = NULL;
631}
632
633
634static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
635{
636 if (wpa_s->bgscan_ssid != NULL) {
637 bgscan_deinit(wpa_s);
638 wpa_s->bgscan_ssid = NULL;
639 }
640}
641
642#endif /* CONFIG_BGSCAN */
643
644
Dmitry Shmidt04949592012-07-19 12:16:46 -0700645static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
646{
647 if (autoscan_init(wpa_s, 0))
648 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
649}
650
651
652static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
653{
654 autoscan_deinit(wpa_s);
655}
656
657
658void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
659{
660 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
661 wpa_s->wpa_state == WPA_SCANNING) {
662 autoscan_deinit(wpa_s);
663 wpa_supplicant_start_autoscan(wpa_s);
664 }
665}
666
667
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700668/**
669 * wpa_supplicant_set_state - Set current connection state
670 * @wpa_s: Pointer to wpa_supplicant data
671 * @state: The new connection state
672 *
673 * This function is called whenever the connection state changes, e.g.,
674 * association is completed for WPA/WPA2 4-Way Handshake is started.
675 */
676void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
677 enum wpa_states state)
678{
679 enum wpa_states old_state = wpa_s->wpa_state;
680
681 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
682 wpa_supplicant_state_txt(wpa_s->wpa_state),
683 wpa_supplicant_state_txt(state));
684
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800685 if (state == WPA_INTERFACE_DISABLED) {
686 /* Assure normal scan when interface is restored */
687 wpa_s->normal_scans = 0;
688 }
689
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700690 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800691 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700692 /* Reinitialize normal_scan counter */
693 wpa_s->normal_scans = 0;
694 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800695
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700696 if (state != WPA_SCANNING)
697 wpa_supplicant_notify_scanning(wpa_s, 0);
698
699 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700700 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700701#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800703 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800704 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705 ssid ? ssid->id : -1,
706 ssid && ssid->id_str ? ssid->id_str : "");
707#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700708 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800709 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700710 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700711 wpa_drv_set_operstate(wpa_s, 1);
712#ifndef IEEE8021X_EAPOL
713 wpa_drv_set_supp_port(wpa_s, 1);
714#endif /* IEEE8021X_EAPOL */
715 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700716 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700717 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700718
719 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700720 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
721 state == WPA_ASSOCIATED) {
722 wpa_s->new_connection = 1;
723 wpa_drv_set_operstate(wpa_s, 0);
724#ifndef IEEE8021X_EAPOL
725 wpa_drv_set_supp_port(wpa_s, 0);
726#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700727 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700728 }
729 wpa_s->wpa_state = state;
730
731#ifdef CONFIG_BGSCAN
732 if (state == WPA_COMPLETED)
733 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800734 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700735 wpa_supplicant_stop_bgscan(wpa_s);
736#endif /* CONFIG_BGSCAN */
737
Dmitry Shmidt04949592012-07-19 12:16:46 -0700738 if (state == WPA_AUTHENTICATING)
739 wpa_supplicant_stop_autoscan(wpa_s);
740
741 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
742 wpa_supplicant_start_autoscan(wpa_s);
743
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744 if (wpa_s->wpa_state != old_state) {
745 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
746
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700747 /*
748 * Notify the P2P Device interface about a state change in one
749 * of the interfaces.
750 */
751 wpas_p2p_indicate_state_change(wpa_s);
752
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700753 if (wpa_s->wpa_state == WPA_COMPLETED ||
754 old_state == WPA_COMPLETED)
755 wpas_notify_auth_changed(wpa_s);
756 }
757}
758
759
760void wpa_supplicant_terminate_proc(struct wpa_global *global)
761{
762 int pending = 0;
763#ifdef CONFIG_WPS
764 struct wpa_supplicant *wpa_s = global->ifaces;
765 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800766 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700767 if (wpas_wps_terminate_pending(wpa_s) == 1)
768 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700769#ifdef CONFIG_P2P
770 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
771 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
772 wpas_p2p_disconnect(wpa_s);
773#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800774 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700775 }
776#endif /* CONFIG_WPS */
777 if (pending)
778 return;
779 eloop_terminate();
780}
781
782
783static void wpa_supplicant_terminate(int sig, void *signal_ctx)
784{
785 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786 wpa_supplicant_terminate_proc(global);
787}
788
789
790void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
791{
792 enum wpa_states old_state = wpa_s->wpa_state;
793
794 wpa_s->pairwise_cipher = 0;
795 wpa_s->group_cipher = 0;
796 wpa_s->mgmt_group_cipher = 0;
797 wpa_s->key_mgmt = 0;
798 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700799 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700800
801 if (wpa_s->wpa_state != old_state)
802 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
803}
804
805
806/**
807 * wpa_supplicant_reload_configuration - Reload configuration data
808 * @wpa_s: Pointer to wpa_supplicant data
809 * Returns: 0 on success or -1 if configuration parsing failed
810 *
811 * This function can be used to request that the configuration data is reloaded
812 * (e.g., after configuration file change). This function is reloading
813 * configuration only for one interface, so this may need to be called multiple
814 * times if %wpa_supplicant is controlling multiple interfaces and all
815 * interfaces need reconfiguration.
816 */
817int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
818{
819 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700820 int reconf_ctrl;
821 int old_ap_scan;
822
823 if (wpa_s->confname == NULL)
824 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700825 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700826 if (conf == NULL) {
827 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
828 "file '%s' - exiting", wpa_s->confname);
829 return -1;
830 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700831 wpa_config_read(wpa_s->confanother, conf);
832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700833 conf->changed_parameters = (unsigned int) -1;
834
835 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
836 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
837 os_strcmp(conf->ctrl_interface,
838 wpa_s->conf->ctrl_interface) != 0);
839
840 if (reconf_ctrl && wpa_s->ctrl_iface) {
841 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
842 wpa_s->ctrl_iface = NULL;
843 }
844
845 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800846 if (wpa_s->current_ssid) {
847 wpa_supplicant_deauthenticate(wpa_s,
848 WLAN_REASON_DEAUTH_LEAVING);
849 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700850
851 /*
852 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
853 * pkcs11_engine_path, pkcs11_module_path.
854 */
855 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
856 /*
857 * Clear forced success to clear EAP state for next
858 * authentication.
859 */
860 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
861 }
862 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
863 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800864 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700865 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
866 rsn_preauth_deinit(wpa_s->wpa);
867
868 old_ap_scan = wpa_s->conf->ap_scan;
869 wpa_config_free(wpa_s->conf);
870 wpa_s->conf = conf;
871 if (old_ap_scan != wpa_s->conf->ap_scan)
872 wpas_notify_ap_scan_changed(wpa_s);
873
874 if (reconf_ctrl)
875 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
876
877 wpa_supplicant_update_config(wpa_s);
878
879 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700880 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700881 wpa_s->reassociate = 1;
882 wpa_supplicant_req_scan(wpa_s, 0, 0);
883 }
884 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
885 return 0;
886}
887
888
889static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
890{
891 struct wpa_global *global = signal_ctx;
892 struct wpa_supplicant *wpa_s;
893 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
894 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
895 sig);
896 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
897 wpa_supplicant_terminate_proc(global);
898 }
899 }
900}
901
902
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700903static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
904 struct wpa_ssid *ssid,
905 struct wpa_ie_data *ie)
906{
907 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
908 if (ret) {
909 if (ret == -2) {
910 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
911 "from association info");
912 }
913 return -1;
914 }
915
916 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
917 "cipher suites");
918 if (!(ie->group_cipher & ssid->group_cipher)) {
919 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
920 "cipher 0x%x (mask 0x%x) - reject",
921 ie->group_cipher, ssid->group_cipher);
922 return -1;
923 }
924 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
925 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
926 "cipher 0x%x (mask 0x%x) - reject",
927 ie->pairwise_cipher, ssid->pairwise_cipher);
928 return -1;
929 }
930 if (!(ie->key_mgmt & ssid->key_mgmt)) {
931 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
932 "management 0x%x (mask 0x%x) - reject",
933 ie->key_mgmt, ssid->key_mgmt);
934 return -1;
935 }
936
937#ifdef CONFIG_IEEE80211W
938 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800939 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
940 wpa_s->conf->pmf : ssid->ieee80211w) ==
941 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700942 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
943 "that does not support management frame protection - "
944 "reject");
945 return -1;
946 }
947#endif /* CONFIG_IEEE80211W */
948
949 return 0;
950}
951
952
953/**
954 * wpa_supplicant_set_suites - Set authentication and encryption parameters
955 * @wpa_s: Pointer to wpa_supplicant data
956 * @bss: Scan results for the selected BSS, or %NULL if not available
957 * @ssid: Configuration data for the selected network
958 * @wpa_ie: Buffer for the WPA/RSN IE
959 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
960 * used buffer length in case the functions returns success.
961 * Returns: 0 on success or -1 on failure
962 *
963 * This function is used to configure authentication and encryption parameters
964 * based on the network configuration and scan result for the selected BSS (if
965 * available).
966 */
967int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
968 struct wpa_bss *bss, struct wpa_ssid *ssid,
969 u8 *wpa_ie, size_t *wpa_ie_len)
970{
971 struct wpa_ie_data ie;
972 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800973 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974
975 if (bss) {
976 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
977 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800978 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800980 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700981
982 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
983 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
984 (ie.group_cipher & ssid->group_cipher) &&
985 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
986 (ie.key_mgmt & ssid->key_mgmt)) {
987 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
988 proto = WPA_PROTO_RSN;
989 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
990 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
991 (ie.group_cipher & ssid->group_cipher) &&
992 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
993 (ie.key_mgmt & ssid->key_mgmt)) {
994 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
995 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800996#ifdef CONFIG_HS20
997 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
998 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
999 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -07001000 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001001 ie.group_cipher = WPA_CIPHER_CCMP;
1002 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1003 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1004 proto = WPA_PROTO_OSEN;
1005#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006 } else if (bss) {
1007 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
1008 return -1;
1009 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001010 if (ssid->proto & WPA_PROTO_OSEN)
1011 proto = WPA_PROTO_OSEN;
1012 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013 proto = WPA_PROTO_RSN;
1014 else
1015 proto = WPA_PROTO_WPA;
1016 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1017 os_memset(&ie, 0, sizeof(ie));
1018 ie.group_cipher = ssid->group_cipher;
1019 ie.pairwise_cipher = ssid->pairwise_cipher;
1020 ie.key_mgmt = ssid->key_mgmt;
1021#ifdef CONFIG_IEEE80211W
1022 ie.mgmt_group_cipher =
1023 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1024 WPA_CIPHER_AES_128_CMAC : 0;
1025#endif /* CONFIG_IEEE80211W */
1026 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1027 "based on configuration");
1028 } else
1029 proto = ie.proto;
1030 }
1031
1032 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1033 "pairwise %d key_mgmt %d proto %d",
1034 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1035#ifdef CONFIG_IEEE80211W
1036 if (ssid->ieee80211w) {
1037 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1038 ie.mgmt_group_cipher);
1039 }
1040#endif /* CONFIG_IEEE80211W */
1041
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001042 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001043 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1044 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001045 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046
1047 if (bss || !wpa_s->ap_ies_from_associnfo) {
1048 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1049 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1050 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1051 bss_rsn ? 2 + bss_rsn[1] : 0))
1052 return -1;
1053 }
1054
1055 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001056 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1057 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1059 "cipher");
1060 return -1;
1061 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001062 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1063 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001064
1065 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001066 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1067 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001068 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1069 "cipher");
1070 return -1;
1071 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001072 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1073 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001074
1075 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001076#ifdef CONFIG_SAE
1077 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1078 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1079#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001080 if (0) {
1081#ifdef CONFIG_IEEE80211R
1082 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1083 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1084 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1085 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1086 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1087 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1088#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001089#ifdef CONFIG_SAE
1090 } else if (sel & WPA_KEY_MGMT_SAE) {
1091 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1092 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1093 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1094 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1095 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1096#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001097#ifdef CONFIG_IEEE80211W
1098 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1099 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1100 wpa_dbg(wpa_s, MSG_DEBUG,
1101 "WPA: using KEY_MGMT 802.1X with SHA256");
1102 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1103 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1104 wpa_dbg(wpa_s, MSG_DEBUG,
1105 "WPA: using KEY_MGMT PSK with SHA256");
1106#endif /* CONFIG_IEEE80211W */
1107 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1108 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1109 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1110 } else if (sel & WPA_KEY_MGMT_PSK) {
1111 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1112 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1113 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1114 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1115 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001116#ifdef CONFIG_HS20
1117 } else if (sel & WPA_KEY_MGMT_OSEN) {
1118 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1119 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1120#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121 } else {
1122 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1123 "authenticated key management type");
1124 return -1;
1125 }
1126
1127 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1128 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1129 wpa_s->pairwise_cipher);
1130 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1131
1132#ifdef CONFIG_IEEE80211W
1133 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001134 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1135 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001136 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1137 sel = 0;
1138 if (sel & WPA_CIPHER_AES_128_CMAC) {
1139 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1140 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1141 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001142 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1143 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1144 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1145 "BIP-GMAC-128");
1146 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1147 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1148 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1149 "BIP-GMAC-256");
1150 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1151 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1152 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1153 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001154 } else {
1155 wpa_s->mgmt_group_cipher = 0;
1156 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1157 }
1158 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1159 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001160 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1161 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1162 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001163#endif /* CONFIG_IEEE80211W */
1164
1165 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1166 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1167 return -1;
1168 }
1169
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001170 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001171 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001172#ifndef CONFIG_NO_PBKDF2
1173 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1174 ssid->passphrase) {
1175 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001176 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1177 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001178 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1179 psk, PMK_LEN);
1180 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1181 }
1182#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001183#ifdef CONFIG_EXT_PASSWORD
1184 if (ssid->ext_psk) {
1185 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1186 ssid->ext_psk);
1187 char pw_str[64 + 1];
1188 u8 psk[PMK_LEN];
1189
1190 if (pw == NULL) {
1191 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1192 "found from external storage");
1193 return -1;
1194 }
1195
1196 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1197 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1198 "PSK length %d in external storage",
1199 (int) wpabuf_len(pw));
1200 ext_password_free(pw);
1201 return -1;
1202 }
1203
1204 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1205 pw_str[wpabuf_len(pw)] = '\0';
1206
1207#ifndef CONFIG_NO_PBKDF2
1208 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1209 {
1210 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1211 4096, psk, PMK_LEN);
1212 os_memset(pw_str, 0, sizeof(pw_str));
1213 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1214 "external passphrase)",
1215 psk, PMK_LEN);
1216 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1217 } else
1218#endif /* CONFIG_NO_PBKDF2 */
1219 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1220 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1221 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1222 "Invalid PSK hex string");
1223 os_memset(pw_str, 0, sizeof(pw_str));
1224 ext_password_free(pw);
1225 return -1;
1226 }
1227 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1228 } else {
1229 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1230 "PSK available");
1231 os_memset(pw_str, 0, sizeof(pw_str));
1232 ext_password_free(pw);
1233 return -1;
1234 }
1235
1236 os_memset(pw_str, 0, sizeof(pw_str));
1237 ext_password_free(pw);
1238 }
1239#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001240 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001241 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1242
1243 return 0;
1244}
1245
1246
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001247static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1248{
1249 *pos = 0x00;
1250
1251 switch (idx) {
1252 case 0: /* Bits 0-7 */
1253 break;
1254 case 1: /* Bits 8-15 */
1255 break;
1256 case 2: /* Bits 16-23 */
1257#ifdef CONFIG_WNM
1258 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1259 *pos |= 0x08; /* Bit 19 - BSS Transition */
1260#endif /* CONFIG_WNM */
1261 break;
1262 case 3: /* Bits 24-31 */
1263#ifdef CONFIG_WNM
1264 *pos |= 0x02; /* Bit 25 - SSID List */
1265#endif /* CONFIG_WNM */
1266#ifdef CONFIG_INTERWORKING
1267 if (wpa_s->conf->interworking)
1268 *pos |= 0x80; /* Bit 31 - Interworking */
1269#endif /* CONFIG_INTERWORKING */
1270 break;
1271 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001272#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001273 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1274 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001275#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001276 break;
1277 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001278#ifdef CONFIG_HS20
1279 if (wpa_s->conf->hs20)
1280 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1281#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001282 break;
1283 case 6: /* Bits 48-55 */
1284 break;
1285 }
1286}
1287
1288
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001289int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001290{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001291 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001292 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001293
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001294 if (len < wpa_s->extended_capa_len)
1295 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001296 if (buflen < (size_t) len + 2) {
1297 wpa_printf(MSG_INFO,
1298 "Not enough room for building extended capabilities element");
1299 return -1;
1300 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001301
1302 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001303 *pos++ = len;
1304 for (i = 0; i < len; i++, pos++) {
1305 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001306
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001307 if (i < wpa_s->extended_capa_len) {
1308 *pos &= ~wpa_s->extended_capa_mask[i];
1309 *pos |= wpa_s->extended_capa[i];
1310 }
1311 }
1312
1313 while (len > 0 && buf[1 + len] == 0) {
1314 len--;
1315 buf[1] = len;
1316 }
1317 if (len == 0)
1318 return 0;
1319
1320 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001321}
1322
1323
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001324static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1325 struct wpa_bss *test_bss)
1326{
1327 struct wpa_bss *bss;
1328
1329 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1330 if (bss == test_bss)
1331 return 1;
1332 }
1333
1334 return 0;
1335}
1336
1337
1338static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1339 struct wpa_ssid *test_ssid)
1340{
1341 struct wpa_ssid *ssid;
1342
1343 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1344 if (ssid == test_ssid)
1345 return 1;
1346 }
1347
1348 return 0;
1349}
1350
1351
1352int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1353 struct wpa_ssid *test_ssid)
1354{
1355 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1356 return 0;
1357
1358 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1359}
1360
1361
1362void wpas_connect_work_free(struct wpa_connect_work *cwork)
1363{
1364 if (cwork == NULL)
1365 return;
1366 os_free(cwork);
1367}
1368
1369
1370void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1371{
1372 struct wpa_connect_work *cwork;
1373 struct wpa_radio_work *work = wpa_s->connect_work;
1374
1375 if (!work)
1376 return;
1377
1378 wpa_s->connect_work = NULL;
1379 cwork = work->ctx;
1380 work->ctx = NULL;
1381 wpas_connect_work_free(cwork);
1382 radio_work_done(work);
1383}
1384
1385
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001386int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
1387{
1388 struct os_reltime now;
1389 u8 addr[ETH_ALEN];
1390
1391 os_get_reltime(&now);
1392 if (wpa_s->last_mac_addr_style == style &&
1393 wpa_s->last_mac_addr_change.sec != 0 &&
1394 !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
1395 wpa_s->conf->rand_addr_lifetime)) {
1396 wpa_msg(wpa_s, MSG_DEBUG,
1397 "Previously selected random MAC address has not yet expired");
1398 return 0;
1399 }
1400
1401 switch (style) {
1402 case 1:
1403 if (random_mac_addr(addr) < 0)
1404 return -1;
1405 break;
1406 case 2:
1407 os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
1408 if (random_mac_addr_keep_oui(addr) < 0)
1409 return -1;
1410 break;
1411 default:
1412 return -1;
1413 }
1414
1415 if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
1416 wpa_msg(wpa_s, MSG_INFO,
1417 "Failed to set random MAC address");
1418 return -1;
1419 }
1420
1421 os_get_reltime(&wpa_s->last_mac_addr_change);
1422 wpa_s->mac_addr_changed = 1;
1423 wpa_s->last_mac_addr_style = style;
1424
1425 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1426 wpa_msg(wpa_s, MSG_INFO,
1427 "Could not update MAC address information");
1428 return -1;
1429 }
1430
1431 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
1432 MAC2STR(addr));
1433
1434 return 0;
1435}
1436
1437
1438int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
1439{
1440 if (wpa_s->wpa_state >= WPA_AUTHENTICATING ||
1441 !wpa_s->conf->preassoc_mac_addr)
1442 return 0;
1443
1444 return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
1445}
1446
1447
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001448static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1449
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001450/**
1451 * wpa_supplicant_associate - Request association
1452 * @wpa_s: Pointer to wpa_supplicant data
1453 * @bss: Scan results for the selected BSS, or %NULL if not available
1454 * @ssid: Configuration data for the selected network
1455 *
1456 * This function is used to request %wpa_supplicant to associate with a BSS.
1457 */
1458void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1459 struct wpa_bss *bss, struct wpa_ssid *ssid)
1460{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001461 struct wpa_connect_work *cwork;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001462 int rand_style;
1463
1464 if (ssid->mac_addr == -1)
1465 rand_style = wpa_s->conf->mac_addr;
1466 else
1467 rand_style = ssid->mac_addr;
1468
1469 if (wpa_s->last_ssid == ssid) {
1470 wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
1471 } else if (rand_style > 0) {
1472 if (wpas_update_random_addr(wpa_s, rand_style) < 0)
1473 return;
1474 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
1475 } else if (wpa_s->mac_addr_changed) {
1476 if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
1477 wpa_msg(wpa_s, MSG_INFO,
1478 "Could not restore permanent MAC address");
1479 return;
1480 }
1481 wpa_s->mac_addr_changed = 0;
1482 if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
1483 wpa_msg(wpa_s, MSG_INFO,
1484 "Could not update MAC address information");
1485 return;
1486 }
1487 wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
1488 }
1489 wpa_s->last_ssid = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001490
1491#ifdef CONFIG_IBSS_RSN
1492 ibss_rsn_deinit(wpa_s->ibss_rsn);
1493 wpa_s->ibss_rsn = NULL;
1494#endif /* CONFIG_IBSS_RSN */
1495
1496 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1497 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1498#ifdef CONFIG_AP
1499 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1500 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1501 "mode");
1502 return;
1503 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001504 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1505 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001506 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1507 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001508 return;
1509 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001510 wpa_s->current_bss = bss;
1511#else /* CONFIG_AP */
1512 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1513 "the build");
1514#endif /* CONFIG_AP */
1515 return;
1516 }
1517
1518#ifdef CONFIG_TDLS
1519 if (bss)
1520 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1521 bss->ie_len);
1522#endif /* CONFIG_TDLS */
1523
1524 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1525 ssid->mode == IEEE80211_MODE_INFRA) {
1526 sme_authenticate(wpa_s, bss, ssid);
1527 return;
1528 }
1529
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001530 if (wpa_s->connect_work) {
1531 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1532 return;
1533 }
1534
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001535 if (radio_work_pending(wpa_s, "connect")) {
1536 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1537 return;
1538 }
1539
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001540 cwork = os_zalloc(sizeof(*cwork));
1541 if (cwork == NULL)
1542 return;
1543
1544 cwork->bss = bss;
1545 cwork->ssid = ssid;
1546
1547 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1548 wpas_start_assoc_cb, cwork) < 0) {
1549 os_free(cwork);
1550 }
1551}
1552
1553
1554static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1555{
1556 struct wpa_connect_work *cwork = work->ctx;
1557 struct wpa_bss *bss = cwork->bss;
1558 struct wpa_ssid *ssid = cwork->ssid;
1559 struct wpa_supplicant *wpa_s = work->wpa_s;
1560 u8 wpa_ie[200];
1561 size_t wpa_ie_len;
1562 int use_crypt, ret, i, bssid_changed;
1563 int algs = WPA_AUTH_ALG_OPEN;
1564 unsigned int cipher_pairwise, cipher_group;
1565 struct wpa_driver_associate_params params;
1566 int wep_keys_set = 0;
1567 int assoc_failed = 0;
1568 struct wpa_ssid *old_ssid;
1569#ifdef CONFIG_HT_OVERRIDES
1570 struct ieee80211_ht_capabilities htcaps;
1571 struct ieee80211_ht_capabilities htcaps_mask;
1572#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001573#ifdef CONFIG_VHT_OVERRIDES
1574 struct ieee80211_vht_capabilities vhtcaps;
1575 struct ieee80211_vht_capabilities vhtcaps_mask;
1576#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001577
1578 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001579 if (work->started) {
1580 wpa_s->connect_work = NULL;
1581
1582 /* cancel possible auth. timeout */
1583 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1584 NULL);
1585 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001586 wpas_connect_work_free(cwork);
1587 return;
1588 }
1589
1590 wpa_s->connect_work = work;
1591
1592 if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
1593 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1594 wpas_connect_work_done(wpa_s);
1595 return;
1596 }
1597
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001598 os_memset(&params, 0, sizeof(params));
1599 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001600 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001601 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001602#ifdef CONFIG_IEEE80211R
1603 const u8 *ie, *md = NULL;
1604#endif /* CONFIG_IEEE80211R */
1605 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1606 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1607 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1608 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1609 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1610 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1611 if (bssid_changed)
1612 wpas_notify_bssid_changed(wpa_s);
1613#ifdef CONFIG_IEEE80211R
1614 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1615 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1616 md = ie + 2;
1617 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1618 if (md) {
1619 /* Prepare for the next transition */
1620 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1621 }
1622#endif /* CONFIG_IEEE80211R */
1623#ifdef CONFIG_WPS
1624 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1625 wpa_s->conf->ap_scan == 2 &&
1626 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1627 /* Use ap_scan==1 style network selection to find the network
1628 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001629 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001630 wpa_s->reassociate = 1;
1631 wpa_supplicant_req_scan(wpa_s, 0, 0);
1632 return;
1633#endif /* CONFIG_WPS */
1634 } else {
1635 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1636 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1637 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1638 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001639 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001640 wpa_supplicant_cancel_scan(wpa_s);
1641
1642 /* Starting new association, so clear the possibly used WPA IE from the
1643 * previous association. */
1644 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1645
1646#ifdef IEEE8021X_EAPOL
1647 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1648 if (ssid->leap) {
1649 if (ssid->non_leap == 0)
1650 algs = WPA_AUTH_ALG_LEAP;
1651 else
1652 algs |= WPA_AUTH_ALG_LEAP;
1653 }
1654 }
1655#endif /* IEEE8021X_EAPOL */
1656 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1657 if (ssid->auth_alg) {
1658 algs = ssid->auth_alg;
1659 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1660 "0x%x", algs);
1661 }
1662
1663 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1664 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001665 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001666 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001667 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1668 wpa_s->conf->okc :
1669 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001670 (ssid->proto & WPA_PROTO_RSN);
1671 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001672 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001673 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1674 wpa_ie_len = sizeof(wpa_ie);
1675 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1676 wpa_ie, &wpa_ie_len)) {
1677 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1678 "key management and encryption suites");
1679 return;
1680 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001681 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1682 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1683 /*
1684 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1685 * use non-WPA since the scan results did not indicate that the
1686 * AP is using WPA or WPA2.
1687 */
1688 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1689 wpa_ie_len = 0;
1690 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001691 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001692 wpa_ie_len = sizeof(wpa_ie);
1693 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1694 wpa_ie, &wpa_ie_len)) {
1695 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1696 "key management and encryption suites (no "
1697 "scan results)");
1698 return;
1699 }
1700#ifdef CONFIG_WPS
1701 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1702 struct wpabuf *wps_ie;
1703 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1704 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1705 wpa_ie_len = wpabuf_len(wps_ie);
1706 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1707 } else
1708 wpa_ie_len = 0;
1709 wpabuf_free(wps_ie);
1710 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1711 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1712 params.wps = WPS_MODE_PRIVACY;
1713 else
1714 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001715 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716#endif /* CONFIG_WPS */
1717 } else {
1718 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1719 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001720 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721 }
1722
1723#ifdef CONFIG_P2P
1724 if (wpa_s->global->p2p) {
1725 u8 *pos;
1726 size_t len;
1727 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001728 pos = wpa_ie + wpa_ie_len;
1729 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001730 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1731 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732 if (res >= 0)
1733 wpa_ie_len += res;
1734 }
1735
1736 wpa_s->cross_connect_disallowed = 0;
1737 if (bss) {
1738 struct wpabuf *p2p;
1739 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1740 if (p2p) {
1741 wpa_s->cross_connect_disallowed =
1742 p2p_get_cross_connect_disallowed(p2p);
1743 wpabuf_free(p2p);
1744 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1745 "connection",
1746 wpa_s->cross_connect_disallowed ?
1747 "disallows" : "allows");
1748 }
1749 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001750
1751 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001752#endif /* CONFIG_P2P */
1753
Dmitry Shmidt04949592012-07-19 12:16:46 -07001754#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001755 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001756 struct wpabuf *hs20;
1757 hs20 = wpabuf_alloc(20);
1758 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001759 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001760 size_t len;
1761
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001762 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001763 len = sizeof(wpa_ie) - wpa_ie_len;
1764 if (wpabuf_len(hs20) <= len) {
1765 os_memcpy(wpa_ie + wpa_ie_len,
1766 wpabuf_head(hs20), wpabuf_len(hs20));
1767 wpa_ie_len += wpabuf_len(hs20);
1768 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001769 wpabuf_free(hs20);
1770 }
1771 }
1772#endif /* CONFIG_HS20 */
1773
Dmitry Shmidt56052862013-10-04 10:23:25 -07001774 /*
1775 * Workaround: Add Extended Capabilities element only if the AP
1776 * included this element in Beacon/Probe Response frames. Some older
1777 * APs seem to have interoperability issues if this element is
1778 * included, so while the standard may require us to include the
1779 * element in all cases, it is justifiable to skip it to avoid
1780 * interoperability issues.
1781 */
1782 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001783 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07001784 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001785 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
1786 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07001787 if (ext_capab_len > 0) {
1788 u8 *pos = wpa_ie;
1789 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1790 pos += 2 + pos[1];
1791 os_memmove(pos + ext_capab_len, pos,
1792 wpa_ie_len - (pos - wpa_ie));
1793 wpa_ie_len += ext_capab_len;
1794 os_memcpy(pos, ext_capab, ext_capab_len);
1795 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001796 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001797
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001798 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1799 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001800 cipher_pairwise = wpa_s->pairwise_cipher;
1801 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001802 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1803 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1804 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1805 use_crypt = 0;
1806 if (wpa_set_wep_keys(wpa_s, ssid)) {
1807 use_crypt = 1;
1808 wep_keys_set = 1;
1809 }
1810 }
1811 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1812 use_crypt = 0;
1813
1814#ifdef IEEE8021X_EAPOL
1815 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1816 if ((ssid->eapol_flags &
1817 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1818 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1819 !wep_keys_set) {
1820 use_crypt = 0;
1821 } else {
1822 /* Assume that dynamic WEP-104 keys will be used and
1823 * set cipher suites in order for drivers to expect
1824 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001825 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826 }
1827 }
1828#endif /* IEEE8021X_EAPOL */
1829
1830 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1831 /* Set the key before (and later after) association */
1832 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1833 }
1834
1835 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1836 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001837 params.ssid = bss->ssid;
1838 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001839 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1840 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1841 MACSTR " freq=%u MHz based on scan results "
1842 "(bssid_set=%d)",
1843 MAC2STR(bss->bssid), bss->freq,
1844 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001845 params.bssid = bss->bssid;
1846 params.freq = bss->freq;
1847 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001848 params.bssid_hint = bss->bssid;
1849 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001850 } else {
1851 params.ssid = ssid->ssid;
1852 params.ssid_len = ssid->ssid_len;
1853 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001854
1855 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1856 wpa_s->conf->ap_scan == 2) {
1857 params.bssid = ssid->bssid;
1858 params.fixed_bssid = 1;
1859 }
1860
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001861 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1862 params.freq == 0)
1863 params.freq = ssid->frequency; /* Initial channel for IBSS */
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08001864
1865 if (ssid->mode == WPAS_MODE_IBSS) {
1866 if (ssid->beacon_int)
1867 params.beacon_int = ssid->beacon_int;
1868 else
1869 params.beacon_int = wpa_s->conf->beacon_int;
1870 }
1871
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001872 params.wpa_ie = wpa_ie;
1873 params.wpa_ie_len = wpa_ie_len;
1874 params.pairwise_suite = cipher_pairwise;
1875 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001876 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001877 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001878 params.auth_alg = algs;
1879 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001880 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881 for (i = 0; i < NUM_WEP_KEYS; i++) {
1882 if (ssid->wep_key_len[i])
1883 params.wep_key[i] = ssid->wep_key[i];
1884 params.wep_key_len[i] = ssid->wep_key_len[i];
1885 }
1886 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1887
1888 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001889 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1890 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891 params.passphrase = ssid->passphrase;
1892 if (ssid->psk_set)
1893 params.psk = ssid->psk;
1894 }
1895
1896 params.drop_unencrypted = use_crypt;
1897
1898#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001899 params.mgmt_frame_protection =
1900 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1901 wpa_s->conf->pmf : ssid->ieee80211w;
1902 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001903 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1904 struct wpa_ie_data ie;
1905 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1906 ie.capabilities &
1907 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1908 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1909 "MFP: require MFP");
1910 params.mgmt_frame_protection =
1911 MGMT_FRAME_PROTECTION_REQUIRED;
1912 }
1913 }
1914#endif /* CONFIG_IEEE80211W */
1915
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001916 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001917
1918 if (wpa_s->parent->set_sta_uapsd)
1919 params.uapsd = wpa_s->parent->sta_uapsd;
1920 else
1921 params.uapsd = -1;
1922
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001923#ifdef CONFIG_HT_OVERRIDES
1924 os_memset(&htcaps, 0, sizeof(htcaps));
1925 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1926 params.htcaps = (u8 *) &htcaps;
1927 params.htcaps_mask = (u8 *) &htcaps_mask;
1928 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1929#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001930#ifdef CONFIG_VHT_OVERRIDES
1931 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
1932 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
1933 params.vhtcaps = &vhtcaps;
1934 params.vhtcaps_mask = &vhtcaps_mask;
1935 wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
1936#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001937
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001938#ifdef CONFIG_P2P
1939 /*
1940 * If multi-channel concurrency is not supported, check for any
1941 * frequency conflict. In case of any frequency conflict, remove the
1942 * least prioritized connection.
1943 */
1944 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001945 int freq, num;
1946 num = get_shared_radio_freqs(wpa_s, &freq, 1);
1947 if (num > 0 && freq > 0 && freq != params.freq) {
1948 wpa_printf(MSG_DEBUG,
1949 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001950 freq, params.freq);
1951 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1952 params.freq,
1953 ssid) < 0)
1954 return;
1955 }
1956 }
1957#endif /* CONFIG_P2P */
1958
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001959 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001960 if (ret < 0) {
1961 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1962 "failed");
1963 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1964 /*
1965 * The driver is known to mean what is saying, so we
1966 * can stop right here; the association will not
1967 * succeed.
1968 */
1969 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001970 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001971 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1972 return;
1973 }
1974 /* try to continue anyway; new association will be tried again
1975 * after timeout */
1976 assoc_failed = 1;
1977 }
1978
1979 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1980 /* Set the key after the association just in case association
1981 * cleared the previously configured key. */
1982 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1983 /* No need to timeout authentication since there is no key
1984 * management. */
1985 wpa_supplicant_cancel_auth_timeout(wpa_s);
1986 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1987#ifdef CONFIG_IBSS_RSN
1988 } else if (ssid->mode == WPAS_MODE_IBSS &&
1989 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1990 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1991 /*
1992 * RSN IBSS authentication is per-STA and we can disable the
1993 * per-BSSID authentication.
1994 */
1995 wpa_supplicant_cancel_auth_timeout(wpa_s);
1996#endif /* CONFIG_IBSS_RSN */
1997 } else {
1998 /* Timeout for IEEE 802.11 authentication and association */
1999 int timeout = 60;
2000
2001 if (assoc_failed) {
2002 /* give IBSS a bit more time */
2003 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
2004 } else if (wpa_s->conf->ap_scan == 1) {
2005 /* give IBSS a bit more time */
2006 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
2007 }
2008 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
2009 }
2010
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002011 if (wep_keys_set &&
2012 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002013 /* Set static WEP keys again */
2014 wpa_set_wep_keys(wpa_s, ssid);
2015 }
2016
2017 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
2018 /*
2019 * Do not allow EAP session resumption between different
2020 * network configurations.
2021 */
2022 eapol_sm_invalidate_cached_session(wpa_s->eapol);
2023 }
2024 old_ssid = wpa_s->current_ssid;
2025 wpa_s->current_ssid = ssid;
2026 wpa_s->current_bss = bss;
2027 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
2028 wpa_supplicant_initiate_eapol(wpa_s);
2029 if (old_ssid != wpa_s->current_ssid)
2030 wpas_notify_network_changed(wpa_s);
2031}
2032
2033
2034static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
2035 const u8 *addr)
2036{
2037 struct wpa_ssid *old_ssid;
2038
2039 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002040 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002041 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042 wpa_sm_set_config(wpa_s->wpa, NULL);
2043 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2044 if (old_ssid != wpa_s->current_ssid)
2045 wpas_notify_network_changed(wpa_s);
2046 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
2047}
2048
2049
2050/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002051 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
2052 * @wpa_s: Pointer to wpa_supplicant data
2053 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
2054 *
2055 * This function is used to request %wpa_supplicant to deauthenticate from the
2056 * current AP.
2057 */
2058void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
2059 int reason_code)
2060{
2061 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002062 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002063 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002064
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002065 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
2066 " pending_bssid=" MACSTR " reason=%d state=%s",
2067 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
2068 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
2069
2070 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002071 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002072 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
2073 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
2074 wpa_s->wpa_state == WPA_ASSOCIATING))
2075 addr = wpa_s->pending_bssid;
2076 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2077 /*
2078 * When using driver-based BSS selection, we may not know the
2079 * BSSID with which we are currently trying to associate. We
2080 * need to notify the driver of this disconnection even in such
2081 * a case, so use the all zeros address here.
2082 */
2083 addr = wpa_s->bssid;
2084 zero_addr = 1;
2085 }
2086
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002087#ifdef CONFIG_TDLS
2088 wpa_tdls_teardown_peers(wpa_s->wpa);
2089#endif /* CONFIG_TDLS */
2090
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002091 if (addr) {
2092 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002093 os_memset(&event, 0, sizeof(event));
2094 event.deauth_info.reason_code = (u16) reason_code;
2095 event.deauth_info.locally_generated = 1;
2096 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002097 if (zero_addr)
2098 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002099 }
2100
2101 wpa_supplicant_clear_connection(wpa_s, addr);
2102}
2103
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002104static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2105 struct wpa_ssid *ssid)
2106{
2107 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2108 return;
2109
2110 ssid->disabled = 0;
2111 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2112 wpas_notify_network_enabled_changed(wpa_s, ssid);
2113
2114 /*
2115 * Try to reassociate since there is no current configuration and a new
2116 * network was made available.
2117 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002118 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002119 wpa_s->reassociate = 1;
2120}
2121
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002122
2123/**
2124 * wpa_supplicant_enable_network - Mark a configured network as enabled
2125 * @wpa_s: wpa_supplicant structure for a network interface
2126 * @ssid: wpa_ssid structure for a configured network or %NULL
2127 *
2128 * Enables the specified network or all networks if no network specified.
2129 */
2130void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2131 struct wpa_ssid *ssid)
2132{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002133 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002134 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2135 wpa_supplicant_enable_one_network(wpa_s, ssid);
2136 } else
2137 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002138
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002139 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002140 if (wpa_s->sched_scanning) {
2141 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2142 "new network to scan filters");
2143 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002144 }
2145
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002146 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2147 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002148 }
2149}
2150
2151
2152/**
2153 * wpa_supplicant_disable_network - Mark a configured network as disabled
2154 * @wpa_s: wpa_supplicant structure for a network interface
2155 * @ssid: wpa_ssid structure for a configured network or %NULL
2156 *
2157 * Disables the specified network or all networks if no network specified.
2158 */
2159void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2160 struct wpa_ssid *ssid)
2161{
2162 struct wpa_ssid *other_ssid;
2163 int was_disabled;
2164
2165 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002166 if (wpa_s->sched_scanning)
2167 wpa_supplicant_cancel_sched_scan(wpa_s);
2168
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2170 other_ssid = other_ssid->next) {
2171 was_disabled = other_ssid->disabled;
2172 if (was_disabled == 2)
2173 continue; /* do not change persistent P2P group
2174 * data */
2175
2176 other_ssid->disabled = 1;
2177
2178 if (was_disabled != other_ssid->disabled)
2179 wpas_notify_network_enabled_changed(
2180 wpa_s, other_ssid);
2181 }
2182 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002183 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002184 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2185 } else if (ssid->disabled != 2) {
2186 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002187 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002188 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2189
2190 was_disabled = ssid->disabled;
2191
2192 ssid->disabled = 1;
2193
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002194 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002195 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002196 if (wpa_s->sched_scanning) {
2197 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2198 "to remove network from filters");
2199 wpa_supplicant_cancel_sched_scan(wpa_s);
2200 wpa_supplicant_req_scan(wpa_s, 0, 0);
2201 }
2202 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002203 }
2204}
2205
2206
2207/**
2208 * wpa_supplicant_select_network - Attempt association with a network
2209 * @wpa_s: wpa_supplicant structure for a network interface
2210 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2211 */
2212void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2213 struct wpa_ssid *ssid)
2214{
2215
2216 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002217 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002218
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002219 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002220 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002222 disconnected = 1;
2223 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002224
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002225 if (ssid)
2226 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2227
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002228 /*
2229 * Mark all other networks disabled or mark all networks enabled if no
2230 * network specified.
2231 */
2232 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2233 other_ssid = other_ssid->next) {
2234 int was_disabled = other_ssid->disabled;
2235 if (was_disabled == 2)
2236 continue; /* do not change persistent P2P group data */
2237
2238 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002239 if (was_disabled && !other_ssid->disabled)
2240 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241
2242 if (was_disabled != other_ssid->disabled)
2243 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2244 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002245
2246 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2247 /* We are already associated with the selected network */
2248 wpa_printf(MSG_DEBUG, "Already associated with the "
2249 "selected network - do nothing");
2250 return;
2251 }
2252
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002253 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002254 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002255 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2256 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002257 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 wpa_s->disconnected = 0;
2259 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002260
2261 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2262 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002263
2264 if (ssid)
2265 wpas_notify_network_selected(wpa_s, ssid);
2266}
2267
2268
2269/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002270 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2271 * @wpa_s: wpa_supplicant structure for a network interface
2272 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2273 * @pkcs11_module_path: PKCS #11 module path or NULL
2274 * Returns: 0 on success; -1 on failure
2275 *
2276 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2277 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2278 * module path fails the paths will be reset to the default value (NULL).
2279 */
2280int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2281 const char *pkcs11_engine_path,
2282 const char *pkcs11_module_path)
2283{
2284 char *pkcs11_engine_path_copy = NULL;
2285 char *pkcs11_module_path_copy = NULL;
2286
2287 if (pkcs11_engine_path != NULL) {
2288 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2289 if (pkcs11_engine_path_copy == NULL)
2290 return -1;
2291 }
2292 if (pkcs11_module_path != NULL) {
2293 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002294 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002295 os_free(pkcs11_engine_path_copy);
2296 return -1;
2297 }
2298 }
2299
2300 os_free(wpa_s->conf->pkcs11_engine_path);
2301 os_free(wpa_s->conf->pkcs11_module_path);
2302 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2303 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2304
2305 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2306 eapol_sm_deinit(wpa_s->eapol);
2307 wpa_s->eapol = NULL;
2308 if (wpa_supplicant_init_eapol(wpa_s)) {
2309 /* Error -> Reset paths to the default value (NULL) once. */
2310 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2311 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2312 NULL);
2313
2314 return -1;
2315 }
2316 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2317
2318 return 0;
2319}
2320
2321
2322/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002323 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2324 * @wpa_s: wpa_supplicant structure for a network interface
2325 * @ap_scan: AP scan mode
2326 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2327 *
2328 */
2329int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2330{
2331
2332 int old_ap_scan;
2333
2334 if (ap_scan < 0 || ap_scan > 2)
2335 return -1;
2336
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002337#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002338 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2339 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2340 wpa_s->wpa_state < WPA_COMPLETED) {
2341 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2342 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002343 return 0;
2344 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002345#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002346
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347 old_ap_scan = wpa_s->conf->ap_scan;
2348 wpa_s->conf->ap_scan = ap_scan;
2349
2350 if (old_ap_scan != wpa_s->conf->ap_scan)
2351 wpas_notify_ap_scan_changed(wpa_s);
2352
2353 return 0;
2354}
2355
2356
2357/**
2358 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2359 * @wpa_s: wpa_supplicant structure for a network interface
2360 * @expire_age: Expiration age in seconds
2361 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2362 *
2363 */
2364int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2365 unsigned int bss_expire_age)
2366{
2367 if (bss_expire_age < 10) {
2368 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2369 bss_expire_age);
2370 return -1;
2371 }
2372 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2373 bss_expire_age);
2374 wpa_s->conf->bss_expiration_age = bss_expire_age;
2375
2376 return 0;
2377}
2378
2379
2380/**
2381 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2382 * @wpa_s: wpa_supplicant structure for a network interface
2383 * @expire_count: number of scans after which an unseen BSS is reclaimed
2384 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2385 *
2386 */
2387int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2388 unsigned int bss_expire_count)
2389{
2390 if (bss_expire_count < 1) {
2391 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2392 bss_expire_count);
2393 return -1;
2394 }
2395 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2396 bss_expire_count);
2397 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2398
2399 return 0;
2400}
2401
2402
2403/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002404 * wpa_supplicant_set_scan_interval - Set scan interval
2405 * @wpa_s: wpa_supplicant structure for a network interface
2406 * @scan_interval: scan interval in seconds
2407 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2408 *
2409 */
2410int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2411 int scan_interval)
2412{
2413 if (scan_interval < 0) {
2414 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2415 scan_interval);
2416 return -1;
2417 }
2418 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2419 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002420 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002421
2422 return 0;
2423}
2424
2425
2426/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 * wpa_supplicant_set_debug_params - Set global debug params
2428 * @global: wpa_global structure
2429 * @debug_level: debug level
2430 * @debug_timestamp: determines if show timestamp in debug data
2431 * @debug_show_keys: determines if show keys in debug data
2432 * Returns: 0 if succeed or -1 if debug_level has wrong value
2433 */
2434int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2435 int debug_timestamp, int debug_show_keys)
2436{
2437
2438 int old_level, old_timestamp, old_show_keys;
2439
2440 /* check for allowed debuglevels */
2441 if (debug_level != MSG_EXCESSIVE &&
2442 debug_level != MSG_MSGDUMP &&
2443 debug_level != MSG_DEBUG &&
2444 debug_level != MSG_INFO &&
2445 debug_level != MSG_WARNING &&
2446 debug_level != MSG_ERROR)
2447 return -1;
2448
2449 old_level = wpa_debug_level;
2450 old_timestamp = wpa_debug_timestamp;
2451 old_show_keys = wpa_debug_show_keys;
2452
2453 wpa_debug_level = debug_level;
2454 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2455 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2456
2457 if (wpa_debug_level != old_level)
2458 wpas_notify_debug_level_changed(global);
2459 if (wpa_debug_timestamp != old_timestamp)
2460 wpas_notify_debug_timestamp_changed(global);
2461 if (wpa_debug_show_keys != old_show_keys)
2462 wpas_notify_debug_show_keys_changed(global);
2463
2464 return 0;
2465}
2466
2467
2468/**
2469 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2470 * @wpa_s: Pointer to wpa_supplicant data
2471 * Returns: A pointer to the current network structure or %NULL on failure
2472 */
2473struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2474{
2475 struct wpa_ssid *entry;
2476 u8 ssid[MAX_SSID_LEN];
2477 int res;
2478 size_t ssid_len;
2479 u8 bssid[ETH_ALEN];
2480 int wired;
2481
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002482 res = wpa_drv_get_ssid(wpa_s, ssid);
2483 if (res < 0) {
2484 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2485 "driver");
2486 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002487 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002488 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002490 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002491 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2492 "driver");
2493 return NULL;
2494 }
2495
2496 wired = wpa_s->conf->ap_scan == 0 &&
2497 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2498
2499 entry = wpa_s->conf->ssid;
2500 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002501 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 ((ssid_len == entry->ssid_len &&
2503 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2504 (!entry->bssid_set ||
2505 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2506 return entry;
2507#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002508 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2510 (entry->ssid == NULL || entry->ssid_len == 0) &&
2511 (!entry->bssid_set ||
2512 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2513 return entry;
2514#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002515
Dmitry Shmidt04949592012-07-19 12:16:46 -07002516 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002517 entry->ssid_len == 0 &&
2518 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2519 return entry;
2520
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 entry = entry->next;
2522 }
2523
2524 return NULL;
2525}
2526
2527
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002528static int select_driver(struct wpa_supplicant *wpa_s, int i)
2529{
2530 struct wpa_global *global = wpa_s->global;
2531
2532 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2533 global->drv_priv[i] = wpa_drivers[i]->global_init();
2534 if (global->drv_priv[i] == NULL) {
2535 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2536 "'%s'", wpa_drivers[i]->name);
2537 return -1;
2538 }
2539 }
2540
2541 wpa_s->driver = wpa_drivers[i];
2542 wpa_s->global_drv_priv = global->drv_priv[i];
2543
2544 return 0;
2545}
2546
2547
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2549 const char *name)
2550{
2551 int i;
2552 size_t len;
2553 const char *pos, *driver = name;
2554
2555 if (wpa_s == NULL)
2556 return -1;
2557
2558 if (wpa_drivers[0] == NULL) {
2559 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2560 "wpa_supplicant");
2561 return -1;
2562 }
2563
2564 if (name == NULL) {
2565 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002566 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567 }
2568
2569 do {
2570 pos = os_strchr(driver, ',');
2571 if (pos)
2572 len = pos - driver;
2573 else
2574 len = os_strlen(driver);
2575
2576 for (i = 0; wpa_drivers[i]; i++) {
2577 if (os_strlen(wpa_drivers[i]->name) == len &&
2578 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002579 0) {
2580 /* First driver that succeeds wins */
2581 if (select_driver(wpa_s, i) == 0)
2582 return 0;
2583 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002584 }
2585
2586 driver = pos + 1;
2587 } while (pos);
2588
2589 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2590 return -1;
2591}
2592
2593
2594/**
2595 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2596 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2597 * with struct wpa_driver_ops::init()
2598 * @src_addr: Source address of the EAPOL frame
2599 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2600 * @len: Length of the EAPOL data
2601 *
2602 * This function is called for each received EAPOL frame. Most driver
2603 * interfaces rely on more generic OS mechanism for receiving frames through
2604 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2605 * take care of received EAPOL frames and deliver them to the core supplicant
2606 * code by calling this function.
2607 */
2608void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2609 const u8 *buf, size_t len)
2610{
2611 struct wpa_supplicant *wpa_s = ctx;
2612
2613 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2614 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2615
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002616#ifdef CONFIG_PEERKEY
2617 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2618 wpa_s->current_ssid->peerkey &&
2619 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2620 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2621 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2622 return;
2623 }
2624#endif /* CONFIG_PEERKEY */
2625
Jouni Malinena05074c2012-12-21 21:35:35 +02002626 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2627 (wpa_s->last_eapol_matches_bssid &&
2628#ifdef CONFIG_AP
2629 !wpa_s->ap_iface &&
2630#endif /* CONFIG_AP */
2631 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002632 /*
2633 * There is possible race condition between receiving the
2634 * association event and the EAPOL frame since they are coming
2635 * through different paths from the driver. In order to avoid
2636 * issues in trying to process the EAPOL frame before receiving
2637 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002638 * the association event is received. This may also be needed in
2639 * driver-based roaming case, so also use src_addr != BSSID as a
2640 * trigger if we have previously confirmed that the
2641 * Authenticator uses BSSID as the src_addr (which is not the
2642 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 */
2644 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002645 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2646 wpa_supplicant_state_txt(wpa_s->wpa_state),
2647 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 wpabuf_free(wpa_s->pending_eapol_rx);
2649 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2650 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002651 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2653 ETH_ALEN);
2654 }
2655 return;
2656 }
2657
Jouni Malinena05074c2012-12-21 21:35:35 +02002658 wpa_s->last_eapol_matches_bssid =
2659 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2660
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661#ifdef CONFIG_AP
2662 if (wpa_s->ap_iface) {
2663 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2664 return;
2665 }
2666#endif /* CONFIG_AP */
2667
2668 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2669 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2670 "no key management is configured");
2671 return;
2672 }
2673
2674 if (wpa_s->eapol_received == 0 &&
2675 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2676 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2677 wpa_s->wpa_state != WPA_COMPLETED) &&
2678 (wpa_s->current_ssid == NULL ||
2679 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2680 /* Timeout for completing IEEE 802.1X and WPA authentication */
2681 wpa_supplicant_req_auth_timeout(
2682 wpa_s,
2683 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2684 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2685 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2686 70 : 10, 0);
2687 }
2688 wpa_s->eapol_received++;
2689
2690 if (wpa_s->countermeasures) {
2691 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2692 "EAPOL packet");
2693 return;
2694 }
2695
2696#ifdef CONFIG_IBSS_RSN
2697 if (wpa_s->current_ssid &&
2698 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2699 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2700 return;
2701 }
2702#endif /* CONFIG_IBSS_RSN */
2703
2704 /* Source address of the incoming EAPOL frame could be compared to the
2705 * current BSSID. However, it is possible that a centralized
2706 * Authenticator could be using another MAC address than the BSSID of
2707 * an AP, so just allow any address to be used for now. The replies are
2708 * still sent to the current BSSID (if available), though. */
2709
2710 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2711 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2712 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2713 return;
2714 wpa_drv_poll(wpa_s);
2715 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2716 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2717 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2718 /*
2719 * Set portValid = TRUE here since we are going to skip 4-way
2720 * handshake processing which would normally set portValid. We
2721 * need this to allow the EAPOL state machines to be completed
2722 * without going through EAPOL-Key handshake.
2723 */
2724 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2725 }
2726}
2727
2728
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002729int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002730{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 if (wpa_s->driver->send_eapol) {
2732 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2733 if (addr)
2734 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002735 } else if ((!wpa_s->p2p_mgmt ||
2736 !(wpa_s->drv_flags &
2737 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2738 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002739 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002740 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002741 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2742 wpa_drv_get_mac_addr(wpa_s),
2743 ETH_P_EAPOL,
2744 wpa_supplicant_rx_eapol, wpa_s, 0);
2745 if (wpa_s->l2 == NULL)
2746 return -1;
2747 } else {
2748 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2749 if (addr)
2750 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2751 }
2752
2753 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2754 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2755 return -1;
2756 }
2757
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002758 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2759
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002760 return 0;
2761}
2762
2763
Dmitry Shmidt04949592012-07-19 12:16:46 -07002764static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2765 const u8 *buf, size_t len)
2766{
2767 struct wpa_supplicant *wpa_s = ctx;
2768 const struct l2_ethhdr *eth;
2769
2770 if (len < sizeof(*eth))
2771 return;
2772 eth = (const struct l2_ethhdr *) buf;
2773
2774 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2775 !(eth->h_dest[0] & 0x01)) {
2776 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2777 " (bridge - not for this interface - ignore)",
2778 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2779 return;
2780 }
2781
2782 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2783 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2784 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2785 len - sizeof(*eth));
2786}
2787
2788
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002789/**
2790 * wpa_supplicant_driver_init - Initialize driver interface parameters
2791 * @wpa_s: Pointer to wpa_supplicant data
2792 * Returns: 0 on success, -1 on failure
2793 *
2794 * This function is called to initialize driver interface parameters.
2795 * wpa_drv_init() must have been called before this function to initialize the
2796 * driver interface.
2797 */
2798int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2799{
2800 static int interface_count = 0;
2801
2802 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2803 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002804
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002805 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2806 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002807 os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002808 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2809
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002810 if (wpa_s->bridge_ifname[0]) {
2811 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2812 "interface '%s'", wpa_s->bridge_ifname);
2813 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2814 wpa_s->own_addr,
2815 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002816 wpa_supplicant_rx_eapol_bridge,
2817 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002818 if (wpa_s->l2_br == NULL) {
2819 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2820 "connection for the bridge interface '%s'",
2821 wpa_s->bridge_ifname);
2822 return -1;
2823 }
2824 }
2825
2826 wpa_clear_keys(wpa_s, NULL);
2827
2828 /* Make sure that TKIP countermeasures are not left enabled (could
2829 * happen if wpa_supplicant is killed during countermeasures. */
2830 wpa_drv_set_countermeasures(wpa_s, 0);
2831
2832 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2833 wpa_drv_flush_pmkid(wpa_s);
2834
2835 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002836 wpa_s->prev_scan_wildcard = 0;
2837
Dmitry Shmidt04949592012-07-19 12:16:46 -07002838 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002839 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2840 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2841 interface_count = 0;
2842 }
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002843 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07002844 wpa_supplicant_delayed_sched_scan(wpa_s,
2845 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002846 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07002847 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002848 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002849 interface_count++;
2850 } else
2851 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2852
2853 return 0;
2854}
2855
2856
2857static int wpa_supplicant_daemon(const char *pid_file)
2858{
2859 wpa_printf(MSG_DEBUG, "Daemonize..");
2860 return os_daemonize(pid_file);
2861}
2862
2863
2864static struct wpa_supplicant * wpa_supplicant_alloc(void)
2865{
2866 struct wpa_supplicant *wpa_s;
2867
2868 wpa_s = os_zalloc(sizeof(*wpa_s));
2869 if (wpa_s == NULL)
2870 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002871 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002872 wpa_s->scan_interval = 5;
2873 wpa_s->new_connection = 1;
2874 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002875 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002876
2877 return wpa_s;
2878}
2879
2880
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002881#ifdef CONFIG_HT_OVERRIDES
2882
2883static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2884 struct ieee80211_ht_capabilities *htcaps,
2885 struct ieee80211_ht_capabilities *htcaps_mask,
2886 const char *ht_mcs)
2887{
2888 /* parse ht_mcs into hex array */
2889 int i;
2890 const char *tmp = ht_mcs;
2891 char *end = NULL;
2892
2893 /* If ht_mcs is null, do not set anything */
2894 if (!ht_mcs)
2895 return 0;
2896
2897 /* This is what we are setting in the kernel */
2898 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2899
2900 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2901
2902 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2903 errno = 0;
2904 long v = strtol(tmp, &end, 16);
2905 if (errno == 0) {
2906 wpa_msg(wpa_s, MSG_DEBUG,
2907 "htcap value[%i]: %ld end: %p tmp: %p",
2908 i, v, end, tmp);
2909 if (end == tmp)
2910 break;
2911
2912 htcaps->supported_mcs_set[i] = v;
2913 tmp = end;
2914 } else {
2915 wpa_msg(wpa_s, MSG_ERROR,
2916 "Failed to parse ht-mcs: %s, error: %s\n",
2917 ht_mcs, strerror(errno));
2918 return -1;
2919 }
2920 }
2921
2922 /*
2923 * If we were able to parse any values, then set mask for the MCS set.
2924 */
2925 if (i) {
2926 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2927 IEEE80211_HT_MCS_MASK_LEN - 1);
2928 /* skip the 3 reserved bits */
2929 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2930 0x1f;
2931 }
2932
2933 return 0;
2934}
2935
2936
2937static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2938 struct ieee80211_ht_capabilities *htcaps,
2939 struct ieee80211_ht_capabilities *htcaps_mask,
2940 int disabled)
2941{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002942 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002943
2944 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2945
2946 if (disabled == -1)
2947 return 0;
2948
2949 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2950 htcaps_mask->ht_capabilities_info |= msk;
2951 if (disabled)
2952 htcaps->ht_capabilities_info &= msk;
2953 else
2954 htcaps->ht_capabilities_info |= msk;
2955
2956 return 0;
2957}
2958
2959
2960static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2961 struct ieee80211_ht_capabilities *htcaps,
2962 struct ieee80211_ht_capabilities *htcaps_mask,
2963 int factor)
2964{
2965 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2966
2967 if (factor == -1)
2968 return 0;
2969
2970 if (factor < 0 || factor > 3) {
2971 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2972 "Must be 0-3 or -1", factor);
2973 return -EINVAL;
2974 }
2975
2976 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2977 htcaps->a_mpdu_params &= ~0x3;
2978 htcaps->a_mpdu_params |= factor & 0x3;
2979
2980 return 0;
2981}
2982
2983
2984static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2985 struct ieee80211_ht_capabilities *htcaps,
2986 struct ieee80211_ht_capabilities *htcaps_mask,
2987 int density)
2988{
2989 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2990
2991 if (density == -1)
2992 return 0;
2993
2994 if (density < 0 || density > 7) {
2995 wpa_msg(wpa_s, MSG_ERROR,
2996 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2997 density);
2998 return -EINVAL;
2999 }
3000
3001 htcaps_mask->a_mpdu_params |= 0x1C;
3002 htcaps->a_mpdu_params &= ~(0x1C);
3003 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
3004
3005 return 0;
3006}
3007
3008
3009static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
3010 struct ieee80211_ht_capabilities *htcaps,
3011 struct ieee80211_ht_capabilities *htcaps_mask,
3012 int disabled)
3013{
3014 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003015 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
3016 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003017
3018 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
3019
3020 if (disabled)
3021 htcaps->ht_capabilities_info &= ~msk;
3022 else
3023 htcaps->ht_capabilities_info |= msk;
3024
3025 htcaps_mask->ht_capabilities_info |= msk;
3026
3027 return 0;
3028}
3029
3030
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003031static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
3032 struct ieee80211_ht_capabilities *htcaps,
3033 struct ieee80211_ht_capabilities *htcaps_mask,
3034 int disabled)
3035{
3036 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003037 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
3038 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003039
3040 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
3041
3042 if (disabled)
3043 htcaps->ht_capabilities_info &= ~msk;
3044 else
3045 htcaps->ht_capabilities_info |= msk;
3046
3047 htcaps_mask->ht_capabilities_info |= msk;
3048
3049 return 0;
3050}
3051
3052
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003053static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
3054 struct ieee80211_ht_capabilities *htcaps,
3055 struct ieee80211_ht_capabilities *htcaps_mask,
3056 int disabled)
3057{
3058 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003059 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003060
3061 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
3062
3063 if (disabled)
3064 htcaps->ht_capabilities_info &= ~msk;
3065 else
3066 htcaps->ht_capabilities_info |= msk;
3067
3068 htcaps_mask->ht_capabilities_info |= msk;
3069
3070 return 0;
3071}
3072
3073
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003074void wpa_supplicant_apply_ht_overrides(
3075 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3076 struct wpa_driver_associate_params *params)
3077{
3078 struct ieee80211_ht_capabilities *htcaps;
3079 struct ieee80211_ht_capabilities *htcaps_mask;
3080
3081 if (!ssid)
3082 return;
3083
3084 params->disable_ht = ssid->disable_ht;
3085 if (!params->htcaps || !params->htcaps_mask)
3086 return;
3087
3088 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
3089 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
3090 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
3091 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
3092 ssid->disable_max_amsdu);
3093 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3094 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3095 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003096 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003097 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003098
3099 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003100 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003101 htcaps->ht_capabilities_info |= bit;
3102 htcaps_mask->ht_capabilities_info |= bit;
3103 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003104}
3105
3106#endif /* CONFIG_HT_OVERRIDES */
3107
3108
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003109#ifdef CONFIG_VHT_OVERRIDES
3110void wpa_supplicant_apply_vht_overrides(
3111 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3112 struct wpa_driver_associate_params *params)
3113{
3114 struct ieee80211_vht_capabilities *vhtcaps;
3115 struct ieee80211_vht_capabilities *vhtcaps_mask;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003116#ifdef CONFIG_HT_OVERRIDES
3117 int max_ampdu;
3118 const u32 max_ampdu_mask = VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
3119#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003120
3121 if (!ssid)
3122 return;
3123
3124 params->disable_vht = ssid->disable_vht;
3125
3126 vhtcaps = (void *) params->vhtcaps;
3127 vhtcaps_mask = (void *) params->vhtcaps_mask;
3128
3129 if (!vhtcaps || !vhtcaps_mask)
3130 return;
3131
3132 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3133 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3134
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003135#ifdef CONFIG_HT_OVERRIDES
3136 /* if max ampdu is <= 3, we have to make the HT cap the same */
3137 if (ssid->vht_capa_mask & max_ampdu_mask) {
3138 max_ampdu = (ssid->vht_capa & max_ampdu_mask) >>
3139 find_first_bit(max_ampdu_mask);
3140
3141 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3142 wpa_set_ampdu_factor(wpa_s,
3143 (void *) params->htcaps,
3144 (void *) params->htcaps_mask,
3145 max_ampdu);
3146 }
3147#endif /* CONFIG_HT_OVERRIDES */
3148
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003149#define OVERRIDE_MCS(i) \
3150 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3151 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3152 3 << 2 * (i - 1); \
3153 vhtcaps->vht_supported_mcs_set.tx_map |= \
3154 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3155 } \
3156 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3157 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3158 3 << 2 * (i - 1); \
3159 vhtcaps->vht_supported_mcs_set.rx_map |= \
3160 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3161 }
3162
3163 OVERRIDE_MCS(1);
3164 OVERRIDE_MCS(2);
3165 OVERRIDE_MCS(3);
3166 OVERRIDE_MCS(4);
3167 OVERRIDE_MCS(5);
3168 OVERRIDE_MCS(6);
3169 OVERRIDE_MCS(7);
3170 OVERRIDE_MCS(8);
3171}
3172#endif /* CONFIG_VHT_OVERRIDES */
3173
3174
Dmitry Shmidt04949592012-07-19 12:16:46 -07003175static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3176{
3177#ifdef PCSC_FUNCS
3178 size_t len;
3179
3180 if (!wpa_s->conf->pcsc_reader)
3181 return 0;
3182
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003183 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003184 if (!wpa_s->scard)
3185 return 1;
3186
3187 if (wpa_s->conf->pcsc_pin &&
3188 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3189 scard_deinit(wpa_s->scard);
3190 wpa_s->scard = NULL;
3191 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3192 return -1;
3193 }
3194
3195 len = sizeof(wpa_s->imsi) - 1;
3196 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3197 scard_deinit(wpa_s->scard);
3198 wpa_s->scard = NULL;
3199 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3200 return -1;
3201 }
3202 wpa_s->imsi[len] = '\0';
3203
3204 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3205
3206 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3207 wpa_s->imsi, wpa_s->mnc_len);
3208
3209 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3210 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3211#endif /* PCSC_FUNCS */
3212
3213 return 0;
3214}
3215
3216
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003217int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3218{
3219 char *val, *pos;
3220
3221 ext_password_deinit(wpa_s->ext_pw);
3222 wpa_s->ext_pw = NULL;
3223 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3224
3225 if (!wpa_s->conf->ext_password_backend)
3226 return 0;
3227
3228 val = os_strdup(wpa_s->conf->ext_password_backend);
3229 if (val == NULL)
3230 return -1;
3231 pos = os_strchr(val, ':');
3232 if (pos)
3233 *pos++ = '\0';
3234
3235 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3236
3237 wpa_s->ext_pw = ext_password_init(val, pos);
3238 os_free(val);
3239 if (wpa_s->ext_pw == NULL) {
3240 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3241 return -1;
3242 }
3243 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3244
3245 return 0;
3246}
3247
3248
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003249static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
3250 struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003251{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003252 struct wowlan_triggers *triggers;
3253 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003254
3255 if (!wpa_s->conf->wowlan_triggers)
3256 return 0;
3257
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003258 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3259 if (triggers) {
3260 ret = wpa_drv_wowlan(wpa_s, triggers);
3261 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003262 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003263 return ret;
3264}
3265
3266
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003267static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3268 const char *rn)
3269{
3270 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3271 struct wpa_radio *radio;
3272
3273 while (rn && iface) {
3274 radio = iface->radio;
3275 if (radio && os_strcmp(rn, radio->name) == 0) {
3276 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3277 wpa_s->ifname, rn);
3278 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3279 return radio;
3280 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003281
3282 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003283 }
3284
3285 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3286 wpa_s->ifname, rn ? rn : "N/A");
3287 radio = os_zalloc(sizeof(*radio));
3288 if (radio == NULL)
3289 return NULL;
3290
3291 if (rn)
3292 os_strlcpy(radio->name, rn, sizeof(radio->name));
3293 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003294 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003295 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3296
3297 return radio;
3298}
3299
3300
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003301static void radio_work_free(struct wpa_radio_work *work)
3302{
3303 if (work->wpa_s->scan_work == work) {
3304 /* This should not really happen. */
3305 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3306 work->type, work, work->started);
3307 work->wpa_s->scan_work = NULL;
3308 }
3309
3310#ifdef CONFIG_P2P
3311 if (work->wpa_s->p2p_scan_work == work) {
3312 /* This should not really happen. */
3313 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3314 work->type, work, work->started);
3315 work->wpa_s->p2p_scan_work = NULL;
3316 }
3317#endif /* CONFIG_P2P */
3318
3319 dl_list_del(&work->list);
3320 os_free(work);
3321}
3322
3323
3324static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3325{
3326 struct wpa_radio *radio = eloop_ctx;
3327 struct wpa_radio_work *work;
3328 struct os_reltime now, diff;
3329 struct wpa_supplicant *wpa_s;
3330
3331 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3332 if (work == NULL)
3333 return;
3334
3335 if (work->started)
3336 return; /* already started and still in progress */
3337
3338 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3339 radio_list);
3340 if (wpa_s && wpa_s->external_scan_running) {
3341 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3342 return;
3343 }
3344
3345 os_get_reltime(&now);
3346 os_reltime_sub(&now, &work->time, &diff);
3347 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3348 work->type, work, diff.sec, diff.usec);
3349 work->started = 1;
3350 work->time = now;
3351 work->cb(work, 0);
3352}
3353
3354
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003355/*
3356 * This function removes both started and pending radio works running on
3357 * the provided interface's radio.
3358 * Prior to the removal of the radio work, its callback (cb) is called with
3359 * deinit set to be 1. Each work's callback is responsible for clearing its
3360 * internal data and restoring to a correct state.
3361 * @wpa_s: wpa_supplicant data
3362 * @type: type of works to be removed
3363 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3364 * this interface's works.
3365 */
3366void radio_remove_works(struct wpa_supplicant *wpa_s,
3367 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003368{
3369 struct wpa_radio_work *work, *tmp;
3370 struct wpa_radio *radio = wpa_s->radio;
3371
3372 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3373 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003374 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003375 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003376
3377 /* skip other ifaces' works */
3378 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003379 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003380
3381 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3382 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003383 work->cb(work, 1);
3384 radio_work_free(work);
3385 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003386
3387 /* in case we removed the started work */
3388 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003389}
3390
3391
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003392static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3393{
3394 struct wpa_radio *radio = wpa_s->radio;
3395
3396 if (!radio)
3397 return;
3398
3399 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3400 wpa_s->ifname, radio->name);
3401 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003402 radio_remove_works(wpa_s, NULL, 0);
3403 wpa_s->radio = NULL;
3404 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003405 return; /* Interfaces remain for this radio */
3406
3407 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003408 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003409 os_free(radio);
3410}
3411
3412
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003413void radio_work_check_next(struct wpa_supplicant *wpa_s)
3414{
3415 struct wpa_radio *radio = wpa_s->radio;
3416
3417 if (dl_list_empty(&radio->work))
3418 return;
3419 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3420 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3421}
3422
3423
3424/**
3425 * radio_add_work - Add a radio work item
3426 * @wpa_s: Pointer to wpa_supplicant data
3427 * @freq: Frequency of the offchannel operation in MHz or 0
3428 * @type: Unique identifier for each type of work
3429 * @next: Force as the next work to be executed
3430 * @cb: Callback function for indicating when radio is available
3431 * @ctx: Context pointer for the work (work->ctx in cb())
3432 * Returns: 0 on success, -1 on failure
3433 *
3434 * This function is used to request time for an operation that requires
3435 * exclusive radio control. Once the radio is available, the registered callback
3436 * function will be called. radio_work_done() must be called once the exclusive
3437 * radio operation has been completed, so that the radio is freed for other
3438 * operations. The special case of deinit=1 is used to free the context data
3439 * during interface removal. That does not allow the callback function to start
3440 * the radio operation, i.e., it must free any resources allocated for the radio
3441 * work and return.
3442 *
3443 * The @freq parameter can be used to indicate a single channel on which the
3444 * offchannel operation will occur. This may allow multiple radio work
3445 * operations to be performed in parallel if they apply for the same channel.
3446 * Setting this to 0 indicates that the work item may use multiple channels or
3447 * requires exclusive control of the radio.
3448 */
3449int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3450 const char *type, int next,
3451 void (*cb)(struct wpa_radio_work *work, int deinit),
3452 void *ctx)
3453{
3454 struct wpa_radio_work *work;
3455 int was_empty;
3456
3457 work = os_zalloc(sizeof(*work));
3458 if (work == NULL)
3459 return -1;
3460 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3461 os_get_reltime(&work->time);
3462 work->freq = freq;
3463 work->type = type;
3464 work->wpa_s = wpa_s;
3465 work->cb = cb;
3466 work->ctx = ctx;
3467
3468 was_empty = dl_list_empty(&wpa_s->radio->work);
3469 if (next)
3470 dl_list_add(&wpa_s->radio->work, &work->list);
3471 else
3472 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3473 if (was_empty) {
3474 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3475 radio_work_check_next(wpa_s);
3476 }
3477
3478 return 0;
3479}
3480
3481
3482/**
3483 * radio_work_done - Indicate that a radio work item has been completed
3484 * @work: Completed work
3485 *
3486 * This function is called once the callback function registered with
3487 * radio_add_work() has completed its work.
3488 */
3489void radio_work_done(struct wpa_radio_work *work)
3490{
3491 struct wpa_supplicant *wpa_s = work->wpa_s;
3492 struct os_reltime now, diff;
3493 unsigned int started = work->started;
3494
3495 os_get_reltime(&now);
3496 os_reltime_sub(&now, &work->time, &diff);
3497 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3498 work->type, work, started ? "done" : "canceled",
3499 diff.sec, diff.usec);
3500 radio_work_free(work);
3501 if (started)
3502 radio_work_check_next(wpa_s);
3503}
3504
3505
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003506int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
3507{
3508 struct wpa_radio_work *work;
3509 struct wpa_radio *radio = wpa_s->radio;
3510
3511 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3512 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
3513 return 1;
3514 }
3515
3516 return 0;
3517}
3518
3519
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003520static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3521 struct wpa_interface *iface)
3522{
3523 const char *ifname, *driver, *rn;
3524
3525 driver = iface->driver;
3526next_driver:
3527 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3528 return -1;
3529
3530 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3531 if (wpa_s->drv_priv == NULL) {
3532 const char *pos;
3533 pos = driver ? os_strchr(driver, ',') : NULL;
3534 if (pos) {
3535 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3536 "driver interface - try next driver wrapper");
3537 driver = pos + 1;
3538 goto next_driver;
3539 }
3540 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3541 "interface");
3542 return -1;
3543 }
3544 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3545 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3546 "driver_param '%s'", wpa_s->conf->driver_param);
3547 return -1;
3548 }
3549
3550 ifname = wpa_drv_get_ifname(wpa_s);
3551 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3552 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3553 "interface name with '%s'", ifname);
3554 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3555 }
3556
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003557 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003558 if (rn && rn[0] == '\0')
3559 rn = NULL;
3560
3561 wpa_s->radio = radio_add_interface(wpa_s, rn);
3562 if (wpa_s->radio == NULL)
3563 return -1;
3564
3565 return 0;
3566}
3567
3568
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003569static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3570 struct wpa_interface *iface)
3571{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003572 struct wpa_driver_capa capa;
3573
3574 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3575 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3576 iface->confname ? iface->confname : "N/A",
3577 iface->driver ? iface->driver : "default",
3578 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3579 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3580
3581 if (iface->confname) {
3582#ifdef CONFIG_BACKEND_FILE
3583 wpa_s->confname = os_rel2abs_path(iface->confname);
3584 if (wpa_s->confname == NULL) {
3585 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3586 "for configuration file '%s'.",
3587 iface->confname);
3588 return -1;
3589 }
3590 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3591 iface->confname, wpa_s->confname);
3592#else /* CONFIG_BACKEND_FILE */
3593 wpa_s->confname = os_strdup(iface->confname);
3594#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003595 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003596 if (wpa_s->conf == NULL) {
3597 wpa_printf(MSG_ERROR, "Failed to read or parse "
3598 "configuration '%s'.", wpa_s->confname);
3599 return -1;
3600 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003601 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3602 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003603
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003604#ifdef CONFIG_P2P
3605 wpa_s->conf_p2p_dev = os_rel2abs_path(iface->conf_p2p_dev);
Dmitry Shmidt376e1c42014-09-24 10:38:31 -07003606#ifndef ANDROID_P2P
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003607 wpa_config_read(wpa_s->conf_p2p_dev, wpa_s->conf);
Dmitry Shmidt376e1c42014-09-24 10:38:31 -07003608#endif
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003609#endif /* CONFIG_P2P */
3610
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003611 /*
3612 * Override ctrl_interface and driver_param if set on command
3613 * line.
3614 */
3615 if (iface->ctrl_interface) {
3616 os_free(wpa_s->conf->ctrl_interface);
3617 wpa_s->conf->ctrl_interface =
3618 os_strdup(iface->ctrl_interface);
3619 }
3620
3621 if (iface->driver_param) {
3622 os_free(wpa_s->conf->driver_param);
3623 wpa_s->conf->driver_param =
3624 os_strdup(iface->driver_param);
3625 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003626
3627 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3628 os_free(wpa_s->conf->ctrl_interface);
3629 wpa_s->conf->ctrl_interface = NULL;
3630 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003631 } else
3632 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3633 iface->driver_param);
3634
3635 if (wpa_s->conf == NULL) {
3636 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3637 return -1;
3638 }
3639
3640 if (iface->ifname == NULL) {
3641 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3642 return -1;
3643 }
3644 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3645 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3646 iface->ifname);
3647 return -1;
3648 }
3649 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3650
3651 if (iface->bridge_ifname) {
3652 if (os_strlen(iface->bridge_ifname) >=
3653 sizeof(wpa_s->bridge_ifname)) {
3654 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3655 "name '%s'.", iface->bridge_ifname);
3656 return -1;
3657 }
3658 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3659 sizeof(wpa_s->bridge_ifname));
3660 }
3661
3662 /* RSNA Supplicant Key Management - INITIALIZE */
3663 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3664 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3665
3666 /* Initialize driver interface and register driver event handler before
3667 * L2 receive handler so that association events are processed before
3668 * EAPOL-Key packets if both become available for the same select()
3669 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003670 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003671 return -1;
3672
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003673 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3674 return -1;
3675
3676 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3677 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3678 NULL);
3679 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3680
3681 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3682 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3683 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3684 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3685 "dot11RSNAConfigPMKLifetime");
3686 return -1;
3687 }
3688
3689 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3690 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3691 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3692 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3693 "dot11RSNAConfigPMKReauthThreshold");
3694 return -1;
3695 }
3696
3697 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3698 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3699 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3700 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3701 "dot11RSNAConfigSATimeout");
3702 return -1;
3703 }
3704
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003705 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3706 &wpa_s->hw.num_modes,
3707 &wpa_s->hw.flags);
3708
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003709 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003710 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003711 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003712 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003713 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003714 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003715 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3716 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3717 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003718 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3719 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003720 wpa_s->extended_capa = capa.extended_capa;
3721 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3722 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003723 wpa_s->num_multichan_concurrent =
3724 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003725 }
3726 if (wpa_s->max_remain_on_chan == 0)
3727 wpa_s->max_remain_on_chan = 1000;
3728
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003729 /*
3730 * Only take p2p_mgmt parameters when P2P Device is supported.
3731 * Doing it here as it determines whether l2_packet_init() will be done
3732 * during wpa_supplicant_driver_init().
3733 */
3734 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3735 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3736 else
3737 iface->p2p_mgmt = 1;
3738
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003739 if (wpa_s->num_multichan_concurrent == 0)
3740 wpa_s->num_multichan_concurrent = 1;
3741
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003742 if (wpa_supplicant_driver_init(wpa_s) < 0)
3743 return -1;
3744
3745#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003746 if ((!iface->p2p_mgmt ||
3747 !(wpa_s->drv_flags &
3748 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3749 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003750 return -1;
3751#endif /* CONFIG_TDLS */
3752
3753 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3754 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3755 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3756 return -1;
3757 }
3758
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003759 if (wpas_wps_init(wpa_s))
3760 return -1;
3761
3762 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3763 return -1;
3764 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3765
3766 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3767 if (wpa_s->ctrl_iface == NULL) {
3768 wpa_printf(MSG_ERROR,
3769 "Failed to initialize control interface '%s'.\n"
3770 "You may have another wpa_supplicant process "
3771 "already running or the file was\n"
3772 "left by an unclean termination of wpa_supplicant "
3773 "in which case you will need\n"
3774 "to manually remove this file before starting "
3775 "wpa_supplicant again.\n",
3776 wpa_s->conf->ctrl_interface);
3777 return -1;
3778 }
3779
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003780 wpa_s->gas = gas_query_init(wpa_s);
3781 if (wpa_s->gas == NULL) {
3782 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3783 return -1;
3784 }
3785
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003786 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003787 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3788 return -1;
3789 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003790
3791 if (wpa_bss_init(wpa_s) < 0)
3792 return -1;
3793
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003794 /*
3795 * Set Wake-on-WLAN triggers, if configured.
3796 * Note: We don't restore/remove the triggers on shutdown (it doesn't
3797 * have effect anyway when the interface is down).
3798 */
3799 if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
3800 return -1;
3801
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003802#ifdef CONFIG_EAP_PROXY
3803{
3804 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003805 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3806 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003807 if (wpa_s->mnc_len > 0) {
3808 wpa_s->imsi[len] = '\0';
3809 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3810 wpa_s->imsi, wpa_s->mnc_len);
3811 } else {
3812 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3813 }
3814}
3815#endif /* CONFIG_EAP_PROXY */
3816
Dmitry Shmidt04949592012-07-19 12:16:46 -07003817 if (pcsc_reader_init(wpa_s) < 0)
3818 return -1;
3819
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003820 if (wpas_init_ext_pw(wpa_s) < 0)
3821 return -1;
3822
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003823 return 0;
3824}
3825
3826
3827static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003828 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003829{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003830 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003831 if (wpa_s->drv_priv) {
3832 wpa_supplicant_deauthenticate(wpa_s,
3833 WLAN_REASON_DEAUTH_LEAVING);
3834
3835 wpa_drv_set_countermeasures(wpa_s, 0);
3836 wpa_clear_keys(wpa_s, NULL);
3837 }
3838
3839 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003840 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003841
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003842 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003843 radio_remove_interface(wpa_s);
3844
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003845 if (wpa_s->drv_priv)
3846 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003847
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003848 if (notify)
3849 wpas_notify_iface_removed(wpa_s);
3850
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003851 if (terminate)
3852 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003853
3854 if (wpa_s->ctrl_iface) {
3855 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3856 wpa_s->ctrl_iface = NULL;
3857 }
3858
3859 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003860 wpa_config_free(wpa_s->conf);
3861 wpa_s->conf = NULL;
3862 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003863
3864 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003865}
3866
3867
3868/**
3869 * wpa_supplicant_add_iface - Add a new network interface
3870 * @global: Pointer to global data from wpa_supplicant_init()
3871 * @iface: Interface configuration options
3872 * Returns: Pointer to the created interface or %NULL on failure
3873 *
3874 * This function is used to add new network interfaces for %wpa_supplicant.
3875 * This can be called before wpa_supplicant_run() to add interfaces before the
3876 * main event loop has been started. In addition, new interfaces can be added
3877 * dynamically while %wpa_supplicant is already running. This could happen,
3878 * e.g., when a hotplug network adapter is inserted.
3879 */
3880struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3881 struct wpa_interface *iface)
3882{
3883 struct wpa_supplicant *wpa_s;
3884 struct wpa_interface t_iface;
3885 struct wpa_ssid *ssid;
3886
3887 if (global == NULL || iface == NULL)
3888 return NULL;
3889
3890 wpa_s = wpa_supplicant_alloc();
3891 if (wpa_s == NULL)
3892 return NULL;
3893
3894 wpa_s->global = global;
3895
3896 t_iface = *iface;
3897 if (global->params.override_driver) {
3898 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3899 "('%s' -> '%s')",
3900 iface->driver, global->params.override_driver);
3901 t_iface.driver = global->params.override_driver;
3902 }
3903 if (global->params.override_ctrl_interface) {
3904 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3905 "ctrl_interface ('%s' -> '%s')",
3906 iface->ctrl_interface,
3907 global->params.override_ctrl_interface);
3908 t_iface.ctrl_interface =
3909 global->params.override_ctrl_interface;
3910 }
3911 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3912 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3913 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003914 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003915 return NULL;
3916 }
3917
3918 /* Notify the control interfaces about new iface */
3919 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003920 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003921 return NULL;
3922 }
3923
3924 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3925 wpas_notify_network_added(wpa_s, ssid);
3926
3927 wpa_s->next = global->ifaces;
3928 global->ifaces = wpa_s;
3929
3930 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003931 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003932
3933 return wpa_s;
3934}
3935
3936
3937/**
3938 * wpa_supplicant_remove_iface - Remove a network interface
3939 * @global: Pointer to global data from wpa_supplicant_init()
3940 * @wpa_s: Pointer to the network interface to be removed
3941 * Returns: 0 if interface was removed, -1 if interface was not found
3942 *
3943 * This function can be used to dynamically remove network interfaces from
3944 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3945 * addition, this function is used to remove all remaining interfaces when
3946 * %wpa_supplicant is terminated.
3947 */
3948int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003949 struct wpa_supplicant *wpa_s,
3950 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003951{
3952 struct wpa_supplicant *prev;
3953
3954 /* Remove interface from the global list of interfaces */
3955 prev = global->ifaces;
3956 if (prev == wpa_s) {
3957 global->ifaces = wpa_s->next;
3958 } else {
3959 while (prev && prev->next != wpa_s)
3960 prev = prev->next;
3961 if (prev == NULL)
3962 return -1;
3963 prev->next = wpa_s->next;
3964 }
3965
3966 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3967
3968 if (global->p2p_group_formation == wpa_s)
3969 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003970 if (global->p2p_invite_group == wpa_s)
3971 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003972 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003973
3974 return 0;
3975}
3976
3977
3978/**
3979 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3980 * @wpa_s: Pointer to the network interface
3981 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3982 */
3983const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3984{
3985 const char *eapol_method;
3986
3987 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3988 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3989 return "NO-EAP";
3990 }
3991
3992 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3993 if (eapol_method == NULL)
3994 return "UNKNOWN-EAP";
3995
3996 return eapol_method;
3997}
3998
3999
4000/**
4001 * wpa_supplicant_get_iface - Get a new network interface
4002 * @global: Pointer to global data from wpa_supplicant_init()
4003 * @ifname: Interface name
4004 * Returns: Pointer to the interface or %NULL if not found
4005 */
4006struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
4007 const char *ifname)
4008{
4009 struct wpa_supplicant *wpa_s;
4010
4011 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4012 if (os_strcmp(wpa_s->ifname, ifname) == 0)
4013 return wpa_s;
4014 }
4015 return NULL;
4016}
4017
4018
4019#ifndef CONFIG_NO_WPA_MSG
4020static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
4021{
4022 struct wpa_supplicant *wpa_s = ctx;
4023 if (wpa_s == NULL)
4024 return NULL;
4025 return wpa_s->ifname;
4026}
4027#endif /* CONFIG_NO_WPA_MSG */
4028
4029
4030/**
4031 * wpa_supplicant_init - Initialize %wpa_supplicant
4032 * @params: Parameters for %wpa_supplicant
4033 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
4034 *
4035 * This function is used to initialize %wpa_supplicant. After successful
4036 * initialization, the returned data pointer can be used to add and remove
4037 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
4038 */
4039struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
4040{
4041 struct wpa_global *global;
4042 int ret, i;
4043
4044 if (params == NULL)
4045 return NULL;
4046
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004047#ifdef CONFIG_DRIVER_NDIS
4048 {
4049 void driver_ndis_init_ops(void);
4050 driver_ndis_init_ops();
4051 }
4052#endif /* CONFIG_DRIVER_NDIS */
4053
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004054#ifndef CONFIG_NO_WPA_MSG
4055 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4056#endif /* CONFIG_NO_WPA_MSG */
4057
4058 wpa_debug_open_file(params->wpa_debug_file_path);
4059 if (params->wpa_debug_syslog)
4060 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004061 if (params->wpa_debug_tracing) {
4062 ret = wpa_debug_open_linux_tracing();
4063 if (ret) {
4064 wpa_printf(MSG_ERROR,
4065 "Failed to enable trace logging");
4066 return NULL;
4067 }
4068 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004069
4070 ret = eap_register_methods();
4071 if (ret) {
4072 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4073 if (ret == -2)
4074 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4075 "the same EAP type.");
4076 return NULL;
4077 }
4078
4079 global = os_zalloc(sizeof(*global));
4080 if (global == NULL)
4081 return NULL;
4082 dl_list_init(&global->p2p_srv_bonjour);
4083 dl_list_init(&global->p2p_srv_upnp);
4084 global->params.daemonize = params->daemonize;
4085 global->params.wait_for_monitor = params->wait_for_monitor;
4086 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4087 if (params->pid_file)
4088 global->params.pid_file = os_strdup(params->pid_file);
4089 if (params->ctrl_interface)
4090 global->params.ctrl_interface =
4091 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004092 if (params->ctrl_interface_group)
4093 global->params.ctrl_interface_group =
4094 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004095 if (params->override_driver)
4096 global->params.override_driver =
4097 os_strdup(params->override_driver);
4098 if (params->override_ctrl_interface)
4099 global->params.override_ctrl_interface =
4100 os_strdup(params->override_ctrl_interface);
4101 wpa_debug_level = global->params.wpa_debug_level =
4102 params->wpa_debug_level;
4103 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4104 params->wpa_debug_show_keys;
4105 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4106 params->wpa_debug_timestamp;
4107
4108 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4109
4110 if (eloop_init()) {
4111 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4112 wpa_supplicant_deinit(global);
4113 return NULL;
4114 }
4115
Jouni Malinen75ecf522011-06-27 15:19:46 -07004116 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004117
4118 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4119 if (global->ctrl_iface == NULL) {
4120 wpa_supplicant_deinit(global);
4121 return NULL;
4122 }
4123
4124 if (wpas_notify_supplicant_initialized(global)) {
4125 wpa_supplicant_deinit(global);
4126 return NULL;
4127 }
4128
4129 for (i = 0; wpa_drivers[i]; i++)
4130 global->drv_count++;
4131 if (global->drv_count == 0) {
4132 wpa_printf(MSG_ERROR, "No drivers enabled");
4133 wpa_supplicant_deinit(global);
4134 return NULL;
4135 }
4136 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
4137 if (global->drv_priv == NULL) {
4138 wpa_supplicant_deinit(global);
4139 return NULL;
4140 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004141
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004142#ifdef CONFIG_WIFI_DISPLAY
4143 if (wifi_display_init(global) < 0) {
4144 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4145 wpa_supplicant_deinit(global);
4146 return NULL;
4147 }
4148#endif /* CONFIG_WIFI_DISPLAY */
4149
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004150 return global;
4151}
4152
4153
4154/**
4155 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4156 * @global: Pointer to global data from wpa_supplicant_init()
4157 * Returns: 0 after successful event loop run, -1 on failure
4158 *
4159 * This function starts the main event loop and continues running as long as
4160 * there are any remaining events. In most cases, this function is running as
4161 * long as the %wpa_supplicant process in still in use.
4162 */
4163int wpa_supplicant_run(struct wpa_global *global)
4164{
4165 struct wpa_supplicant *wpa_s;
4166
4167 if (global->params.daemonize &&
4168 wpa_supplicant_daemon(global->params.pid_file))
4169 return -1;
4170
4171 if (global->params.wait_for_monitor) {
4172 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4173 if (wpa_s->ctrl_iface)
4174 wpa_supplicant_ctrl_iface_wait(
4175 wpa_s->ctrl_iface);
4176 }
4177
4178 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4179 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4180
4181 eloop_run();
4182
4183 return 0;
4184}
4185
4186
4187/**
4188 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4189 * @global: Pointer to global data from wpa_supplicant_init()
4190 *
4191 * This function is called to deinitialize %wpa_supplicant and to free all
4192 * allocated resources. Remaining network interfaces will also be removed.
4193 */
4194void wpa_supplicant_deinit(struct wpa_global *global)
4195{
4196 int i;
4197
4198 if (global == NULL)
4199 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004200
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004201#ifdef CONFIG_WIFI_DISPLAY
4202 wifi_display_deinit(global);
4203#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004204
4205 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004206 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004207
4208 if (global->ctrl_iface)
4209 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4210
4211 wpas_notify_supplicant_deinitialized(global);
4212
4213 eap_peer_unregister_methods();
4214#ifdef CONFIG_AP
4215 eap_server_unregister_methods();
4216#endif /* CONFIG_AP */
4217
4218 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4219 if (!global->drv_priv[i])
4220 continue;
4221 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4222 }
4223 os_free(global->drv_priv);
4224
4225 random_deinit();
4226
4227 eloop_destroy();
4228
4229 if (global->params.pid_file) {
4230 os_daemonize_terminate(global->params.pid_file);
4231 os_free(global->params.pid_file);
4232 }
4233 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004234 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004235 os_free(global->params.override_driver);
4236 os_free(global->params.override_ctrl_interface);
4237
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004238 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004239 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004240 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004241
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004242 os_free(global);
4243 wpa_debug_close_syslog();
4244 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004245 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004246}
4247
4248
4249void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4250{
4251 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4252 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4253 char country[3];
4254 country[0] = wpa_s->conf->country[0];
4255 country[1] = wpa_s->conf->country[1];
4256 country[2] = '\0';
4257 if (wpa_drv_set_country(wpa_s, country) < 0) {
4258 wpa_printf(MSG_ERROR, "Failed to set country code "
4259 "'%s'", country);
4260 }
4261 }
4262
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004263 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4264 wpas_init_ext_pw(wpa_s);
4265
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004266#ifdef CONFIG_WPS
4267 wpas_wps_update_config(wpa_s);
4268#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004269 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004270 wpa_s->conf->changed_parameters = 0;
4271}
4272
4273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004274static void add_freq(int *freqs, int *num_freqs, int freq)
4275{
4276 int i;
4277
4278 for (i = 0; i < *num_freqs; i++) {
4279 if (freqs[i] == freq)
4280 return;
4281 }
4282
4283 freqs[*num_freqs] = freq;
4284 (*num_freqs)++;
4285}
4286
4287
4288static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4289{
4290 struct wpa_bss *bss, *cbss;
4291 const int max_freqs = 10;
4292 int *freqs;
4293 int num_freqs = 0;
4294
4295 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
4296 if (freqs == NULL)
4297 return NULL;
4298
4299 cbss = wpa_s->current_bss;
4300
4301 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4302 if (bss == cbss)
4303 continue;
4304 if (bss->ssid_len == cbss->ssid_len &&
4305 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4306 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4307 add_freq(freqs, &num_freqs, bss->freq);
4308 if (num_freqs == max_freqs)
4309 break;
4310 }
4311 }
4312
4313 if (num_freqs == 0) {
4314 os_free(freqs);
4315 freqs = NULL;
4316 }
4317
4318 return freqs;
4319}
4320
4321
4322void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4323{
4324 int timeout;
4325 int count;
4326 int *freqs = NULL;
4327
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004328 wpas_connect_work_done(wpa_s);
4329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004330 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004331 * Remove possible authentication timeout since the connection failed.
4332 */
4333 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4334
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004335 if (wpa_s->disconnected) {
4336 /*
4337 * There is no point in blacklisting the AP if this event is
4338 * generated based on local request to disconnect.
4339 */
4340 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4341 "indication since interface has been put into "
4342 "disconnected state");
4343 return;
4344 }
4345
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004346 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347 * Add the failed BSSID into the blacklist and speed up next scan
4348 * attempt if there could be other APs that could accept association.
4349 * The current blacklist count indicates how many times we have tried
4350 * connecting to this AP and multiple attempts mean that other APs are
4351 * either not available or has already been tried, so that we can start
4352 * increasing the delay here to avoid constant scanning.
4353 */
4354 count = wpa_blacklist_add(wpa_s, bssid);
4355 if (count == 1 && wpa_s->current_bss) {
4356 /*
4357 * This BSS was not in the blacklist before. If there is
4358 * another BSS available for the same ESS, we should try that
4359 * next. Otherwise, we may as well try this one once more
4360 * before allowing other, likely worse, ESSes to be considered.
4361 */
4362 freqs = get_bss_freqs_in_ess(wpa_s);
4363 if (freqs) {
4364 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4365 "has been seen; try it next");
4366 wpa_blacklist_add(wpa_s, bssid);
4367 /*
4368 * On the next scan, go through only the known channels
4369 * used in this ESS based on previous scans to speed up
4370 * common load balancing use case.
4371 */
4372 os_free(wpa_s->next_scan_freqs);
4373 wpa_s->next_scan_freqs = freqs;
4374 }
4375 }
4376
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004377 /*
4378 * Add previous failure count in case the temporary blacklist was
4379 * cleared due to no other BSSes being available.
4380 */
4381 count += wpa_s->extra_blacklist_count;
4382
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004383 if (count > 3 && wpa_s->current_ssid) {
4384 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4385 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004386 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004387 }
4388
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004389 switch (count) {
4390 case 1:
4391 timeout = 100;
4392 break;
4393 case 2:
4394 timeout = 500;
4395 break;
4396 case 3:
4397 timeout = 1000;
4398 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004399 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004400 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004401 break;
4402 default:
4403 timeout = 10000;
4404 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004405 }
4406
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004407 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4408 "ms", count, timeout);
4409
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004410 /*
4411 * TODO: if more than one possible AP is available in scan results,
4412 * could try the other ones before requesting a new scan.
4413 */
4414 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4415 1000 * (timeout % 1000));
4416}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004417
4418
4419int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4420{
4421 return wpa_s->conf->ap_scan == 2 ||
4422 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4423}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004424
Dmitry Shmidt04949592012-07-19 12:16:46 -07004425
4426#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4427int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4428 struct wpa_ssid *ssid,
4429 const char *field,
4430 const char *value)
4431{
4432#ifdef IEEE8021X_EAPOL
4433 struct eap_peer_config *eap = &ssid->eap;
4434
4435 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4436 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4437 (const u8 *) value, os_strlen(value));
4438
4439 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4440 case WPA_CTRL_REQ_EAP_IDENTITY:
4441 os_free(eap->identity);
4442 eap->identity = (u8 *) os_strdup(value);
4443 eap->identity_len = os_strlen(value);
4444 eap->pending_req_identity = 0;
4445 if (ssid == wpa_s->current_ssid)
4446 wpa_s->reassociate = 1;
4447 break;
4448 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004449 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004450 eap->password = (u8 *) os_strdup(value);
4451 eap->password_len = os_strlen(value);
4452 eap->pending_req_password = 0;
4453 if (ssid == wpa_s->current_ssid)
4454 wpa_s->reassociate = 1;
4455 break;
4456 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004457 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004458 eap->new_password = (u8 *) os_strdup(value);
4459 eap->new_password_len = os_strlen(value);
4460 eap->pending_req_new_password = 0;
4461 if (ssid == wpa_s->current_ssid)
4462 wpa_s->reassociate = 1;
4463 break;
4464 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004465 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004466 eap->pin = os_strdup(value);
4467 eap->pending_req_pin = 0;
4468 if (ssid == wpa_s->current_ssid)
4469 wpa_s->reassociate = 1;
4470 break;
4471 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004472 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004473 eap->otp = (u8 *) os_strdup(value);
4474 eap->otp_len = os_strlen(value);
4475 os_free(eap->pending_req_otp);
4476 eap->pending_req_otp = NULL;
4477 eap->pending_req_otp_len = 0;
4478 break;
4479 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004480 str_clear_free(eap->private_key_passwd);
4481 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004482 eap->pending_req_passphrase = 0;
4483 if (ssid == wpa_s->current_ssid)
4484 wpa_s->reassociate = 1;
4485 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004486 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004487 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004488 eap->external_sim_resp = os_strdup(value);
4489 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004490 default:
4491 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4492 return -1;
4493 }
4494
4495 return 0;
4496#else /* IEEE8021X_EAPOL */
4497 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4498 return -1;
4499#endif /* IEEE8021X_EAPOL */
4500}
4501#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4502
4503
4504int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4505{
4506 int i;
4507 unsigned int drv_enc;
4508
4509 if (ssid == NULL)
4510 return 1;
4511
4512 if (ssid->disabled)
4513 return 1;
4514
4515 if (wpa_s && wpa_s->drv_capa_known)
4516 drv_enc = wpa_s->drv_enc;
4517 else
4518 drv_enc = (unsigned int) -1;
4519
4520 for (i = 0; i < NUM_WEP_KEYS; i++) {
4521 size_t len = ssid->wep_key_len[i];
4522 if (len == 0)
4523 continue;
4524 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4525 continue;
4526 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4527 continue;
4528 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4529 continue;
4530 return 1; /* invalid WEP key */
4531 }
4532
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004533 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07004534 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004535 return 1;
4536
Dmitry Shmidt04949592012-07-19 12:16:46 -07004537 return 0;
4538}
4539
4540
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004541int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004542{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004543 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004544 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004545 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004546 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004547 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004548}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004549
4550
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004551void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004552{
4553 struct wpa_ssid *ssid = wpa_s->current_ssid;
4554 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004555 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004556
4557 if (ssid == NULL) {
4558 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4559 "SSID block");
4560 return;
4561 }
4562
4563 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4564 return;
4565
4566 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004567
4568#ifdef CONFIG_P2P
4569 if (ssid->p2p_group &&
4570 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4571 /*
4572 * Skip the wait time since there is a short timeout on the
4573 * connection to a P2P group.
4574 */
4575 return;
4576 }
4577#endif /* CONFIG_P2P */
4578
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004579 if (ssid->auth_failures > 50)
4580 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004581 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004582 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004583 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004584 dur = 90;
4585 else if (ssid->auth_failures > 3)
4586 dur = 60;
4587 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004588 dur = 30;
4589 else if (ssid->auth_failures > 1)
4590 dur = 20;
4591 else
4592 dur = 10;
4593
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004594 if (ssid->auth_failures > 1 &&
4595 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
4596 dur += os_random() % (ssid->auth_failures * 10);
4597
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004598 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004599 if (now.sec + dur <= ssid->disabled_until.sec)
4600 return;
4601
4602 ssid->disabled_until.sec = now.sec + dur;
4603
4604 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004605 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004606 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004607 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004608}
4609
4610
4611void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4612 struct wpa_ssid *ssid, int clear_failures)
4613{
4614 if (ssid == NULL)
4615 return;
4616
4617 if (ssid->disabled_until.sec) {
4618 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4619 "id=%d ssid=\"%s\"",
4620 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4621 }
4622 ssid->disabled_until.sec = 0;
4623 ssid->disabled_until.usec = 0;
4624 if (clear_failures)
4625 ssid->auth_failures = 0;
4626}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004627
4628
4629int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4630{
4631 size_t i;
4632
4633 if (wpa_s->disallow_aps_bssid == NULL)
4634 return 0;
4635
4636 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4637 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4638 bssid, ETH_ALEN) == 0)
4639 return 1;
4640 }
4641
4642 return 0;
4643}
4644
4645
4646int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4647 size_t ssid_len)
4648{
4649 size_t i;
4650
4651 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4652 return 0;
4653
4654 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4655 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4656 if (ssid_len == s->ssid_len &&
4657 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4658 return 1;
4659 }
4660
4661 return 0;
4662}
4663
4664
4665/**
4666 * wpas_request_connection - Request a new connection
4667 * @wpa_s: Pointer to the network interface
4668 *
4669 * This function is used to request a new connection to be found. It will mark
4670 * the interface to allow reassociation and request a new scan to find a
4671 * suitable network to connect to.
4672 */
4673void wpas_request_connection(struct wpa_supplicant *wpa_s)
4674{
4675 wpa_s->normal_scans = 0;
4676 wpa_supplicant_reinit_autoscan(wpa_s);
4677 wpa_s->extra_blacklist_count = 0;
4678 wpa_s->disconnected = 0;
4679 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004680
4681 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4682 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004683}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004684
4685
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004686void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
4687 struct wpa_used_freq_data *freqs_data,
4688 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004689{
4690 unsigned int i;
4691
4692 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4693 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004694 for (i = 0; i < len; i++) {
4695 struct wpa_used_freq_data *cur = &freqs_data[i];
4696 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
4697 i, cur->freq, cur->flags);
4698 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004699}
4700
4701
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004702/*
4703 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004704 * are using the same radio as the current interface, and in addition, get
4705 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004706 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004707int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
4708 struct wpa_used_freq_data *freqs_data,
4709 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004710{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004711 struct wpa_supplicant *ifs;
4712 u8 bssid[ETH_ALEN];
4713 int freq;
4714 unsigned int idx = 0, i;
4715
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004716 wpa_dbg(wpa_s, MSG_DEBUG,
4717 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004718 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004719
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004720 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4721 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004722 if (idx == len)
4723 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004724
4725 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4726 continue;
4727
4728 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4729 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4730 freq = ifs->current_ssid->frequency;
4731 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4732 freq = ifs->assoc_freq;
4733 else
4734 continue;
4735
4736 /* Hold only distinct freqs */
4737 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004738 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004739 break;
4740
4741 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004742 freqs_data[idx++].freq = freq;
4743
4744 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
4745 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
4746 WPA_FREQ_USED_BY_P2P_CLIENT :
4747 WPA_FREQ_USED_BY_INFRA_STATION;
4748 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004749 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004750
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004751 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004752 return idx;
4753}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004754
4755
4756/*
4757 * Find the operating frequencies of any of the virtual interfaces that
4758 * are using the same radio as the current interface.
4759 */
4760int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4761 int *freq_array, unsigned int len)
4762{
4763 struct wpa_used_freq_data *freqs_data;
4764 int num, i;
4765
4766 os_memset(freq_array, 0, sizeof(int) * len);
4767
4768 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
4769 if (!freqs_data)
4770 return -1;
4771
4772 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
4773 for (i = 0; i < num; i++)
4774 freq_array[i] = freqs_data[i].freq;
4775
4776 os_free(freqs_data);
4777
4778 return num;
4779}