blob: f20bc622f111db850b5197846a99fefa52bcc77b [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 Shmidt8d520ff2011-05-09 14:06:53 -0700303 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
304#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700305
306 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700307}
308
309
310/**
311 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
312 * @wpa_s: Pointer to wpa_supplicant data
313 * @ssid: Configuration data for the network
314 *
315 * This function is used to configure WPA state machine and related parameters
316 * to a mode where WPA is not enabled. This is called as part of the
317 * authentication configuration when the selected network does not use WPA.
318 */
319void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
320 struct wpa_ssid *ssid)
321{
322 int i;
323
324 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
325 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
326 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
327 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
328 else
329 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
330 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
331 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
332 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
333 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
334 wpa_s->group_cipher = WPA_CIPHER_NONE;
335 wpa_s->mgmt_group_cipher = 0;
336
337 for (i = 0; i < NUM_WEP_KEYS; i++) {
338 if (ssid->wep_key_len[i] > 5) {
339 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
340 wpa_s->group_cipher = WPA_CIPHER_WEP104;
341 break;
342 } else if (ssid->wep_key_len[i] > 0) {
343 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
344 wpa_s->group_cipher = WPA_CIPHER_WEP40;
345 break;
346 }
347 }
348
349 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
350 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
351 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
352 wpa_s->pairwise_cipher);
353 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
354#ifdef CONFIG_IEEE80211W
355 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
356 wpa_s->mgmt_group_cipher);
357#endif /* CONFIG_IEEE80211W */
358
359 pmksa_cache_clear_current(wpa_s->wpa);
360}
361
362
Dmitry Shmidt04949592012-07-19 12:16:46 -0700363void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800364{
365 int i;
366 if (wpa_s->hw.modes == NULL)
367 return;
368
369 for (i = 0; i < wpa_s->hw.num_modes; i++) {
370 os_free(wpa_s->hw.modes[i].channels);
371 os_free(wpa_s->hw.modes[i].rates);
372 }
373
374 os_free(wpa_s->hw.modes);
375 wpa_s->hw.modes = NULL;
376}
377
378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700379static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
380{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700381 int i;
382
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700383 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700384 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700385 scard_deinit(wpa_s->scard);
386 wpa_s->scard = NULL;
387 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
388 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
389 l2_packet_deinit(wpa_s->l2);
390 wpa_s->l2 = NULL;
391 if (wpa_s->l2_br) {
392 l2_packet_deinit(wpa_s->l2_br);
393 wpa_s->l2_br = NULL;
394 }
395
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700396 if (wpa_s->conf != NULL) {
397 struct wpa_ssid *ssid;
398 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
399 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700400 }
401
402 os_free(wpa_s->confname);
403 wpa_s->confname = NULL;
404
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700405 os_free(wpa_s->confanother);
406 wpa_s->confanother = NULL;
407
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -0800408#ifdef CONFIG_P2P
409 os_free(wpa_s->conf_p2p_dev);
410 wpa_s->conf_p2p_dev = NULL;
411#endif /* CONFIG_P2P */
412
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700413 wpa_sm_set_eapol(wpa_s->wpa, NULL);
414 eapol_sm_deinit(wpa_s->eapol);
415 wpa_s->eapol = NULL;
416
417 rsn_preauth_deinit(wpa_s->wpa);
418
419#ifdef CONFIG_TDLS
420 wpa_tdls_deinit(wpa_s->wpa);
421#endif /* CONFIG_TDLS */
422
423 pmksa_candidate_free(wpa_s->wpa);
424 wpa_sm_deinit(wpa_s->wpa);
425 wpa_s->wpa = NULL;
426 wpa_blacklist_clear(wpa_s);
427
428 wpa_bss_deinit(wpa_s);
429
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700430 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700431 wpa_supplicant_cancel_scan(wpa_s);
432 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800433 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
434#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
435 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
436 wpa_s, NULL);
437#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700438
439 wpas_wps_deinit(wpa_s);
440
441 wpabuf_free(wpa_s->pending_eapol_rx);
442 wpa_s->pending_eapol_rx = NULL;
443
444#ifdef CONFIG_IBSS_RSN
445 ibss_rsn_deinit(wpa_s->ibss_rsn);
446 wpa_s->ibss_rsn = NULL;
447#endif /* CONFIG_IBSS_RSN */
448
449 sme_deinit(wpa_s);
450
451#ifdef CONFIG_AP
452 wpa_supplicant_ap_deinit(wpa_s);
453#endif /* CONFIG_AP */
454
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700455 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700456
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800457#ifdef CONFIG_OFFCHANNEL
458 offchannel_deinit(wpa_s);
459#endif /* CONFIG_OFFCHANNEL */
460
461 wpa_supplicant_cancel_sched_scan(wpa_s);
462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700463 os_free(wpa_s->next_scan_freqs);
464 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800465
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800466 os_free(wpa_s->manual_scan_freqs);
467 wpa_s->manual_scan_freqs = NULL;
468
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700469 os_free(wpa_s->manual_sched_scan_freqs);
470 wpa_s->manual_sched_scan_freqs = NULL;
471
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800472 gas_query_deinit(wpa_s->gas);
473 wpa_s->gas = NULL;
474
475 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700476
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700477 ieee802_1x_dealloc_kay_sm(wpa_s);
478
Dmitry Shmidt04949592012-07-19 12:16:46 -0700479 os_free(wpa_s->bssid_filter);
480 wpa_s->bssid_filter = NULL;
481
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800482 os_free(wpa_s->disallow_aps_bssid);
483 wpa_s->disallow_aps_bssid = NULL;
484 os_free(wpa_s->disallow_aps_ssid);
485 wpa_s->disallow_aps_ssid = NULL;
486
Dmitry Shmidt04949592012-07-19 12:16:46 -0700487 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700488#ifdef CONFIG_WNM
489 wnm_deallocate_memory(wpa_s);
490#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700491
492 ext_password_deinit(wpa_s->ext_pw);
493 wpa_s->ext_pw = NULL;
494
495 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800496 wpa_s->last_gas_resp = NULL;
497 wpabuf_free(wpa_s->prev_gas_resp);
498 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700499
500 os_free(wpa_s->last_scan_res);
501 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800502
503#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700504 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800505#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700506
507 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
508 wpabuf_free(wpa_s->vendor_elem[i]);
509 wpa_s->vendor_elem[i] = NULL;
510 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700511}
512
513
514/**
515 * wpa_clear_keys - Clear keys configured for the driver
516 * @wpa_s: Pointer to wpa_supplicant data
517 * @addr: Previously used BSSID or %NULL if not available
518 *
519 * This function clears the encryption keys that has been previously configured
520 * for the driver.
521 */
522void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
523{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800524 int i, max;
525
526#ifdef CONFIG_IEEE80211W
527 max = 6;
528#else /* CONFIG_IEEE80211W */
529 max = 4;
530#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700531
532 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800533 for (i = 0; i < max; i++) {
534 if (wpa_s->keys_cleared & BIT(i))
535 continue;
536 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
537 NULL, 0);
538 }
539 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
540 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700541 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
542 0);
543 /* MLME-SETPROTECTION.request(None) */
544 wpa_drv_mlme_setprotection(
545 wpa_s, addr,
546 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
547 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
548 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800549 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700550}
551
552
553/**
554 * wpa_supplicant_state_txt - Get the connection state name as a text string
555 * @state: State (wpa_state; WPA_*)
556 * Returns: The state name as a printable text string
557 */
558const char * wpa_supplicant_state_txt(enum wpa_states state)
559{
560 switch (state) {
561 case WPA_DISCONNECTED:
562 return "DISCONNECTED";
563 case WPA_INACTIVE:
564 return "INACTIVE";
565 case WPA_INTERFACE_DISABLED:
566 return "INTERFACE_DISABLED";
567 case WPA_SCANNING:
568 return "SCANNING";
569 case WPA_AUTHENTICATING:
570 return "AUTHENTICATING";
571 case WPA_ASSOCIATING:
572 return "ASSOCIATING";
573 case WPA_ASSOCIATED:
574 return "ASSOCIATED";
575 case WPA_4WAY_HANDSHAKE:
576 return "4WAY_HANDSHAKE";
577 case WPA_GROUP_HANDSHAKE:
578 return "GROUP_HANDSHAKE";
579 case WPA_COMPLETED:
580 return "COMPLETED";
581 default:
582 return "UNKNOWN";
583 }
584}
585
586
587#ifdef CONFIG_BGSCAN
588
589static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
590{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800591 const char *name;
592
593 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
594 name = wpa_s->current_ssid->bgscan;
595 else
596 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800597 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800598 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800599 if (wpas_driver_bss_selection(wpa_s))
600 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
602 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800603#ifdef CONFIG_P2P
604 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
605 return;
606#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700607
608 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800609 if (wpa_s->current_ssid) {
610 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700611 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
612 "bgscan");
613 /*
614 * Live without bgscan; it is only used as a roaming
615 * optimization, so the initial connection is not
616 * affected.
617 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700618 } else {
619 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700620 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700621 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
622 0);
623 if (scan_res) {
624 bgscan_notify_scan(wpa_s, scan_res);
625 wpa_scan_results_free(scan_res);
626 }
627 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700628 } else
629 wpa_s->bgscan_ssid = NULL;
630}
631
632
633static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
634{
635 if (wpa_s->bgscan_ssid != NULL) {
636 bgscan_deinit(wpa_s);
637 wpa_s->bgscan_ssid = NULL;
638 }
639}
640
641#endif /* CONFIG_BGSCAN */
642
643
Dmitry Shmidt04949592012-07-19 12:16:46 -0700644static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
645{
646 if (autoscan_init(wpa_s, 0))
647 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
648}
649
650
651static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
652{
653 autoscan_deinit(wpa_s);
654}
655
656
657void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
658{
659 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
660 wpa_s->wpa_state == WPA_SCANNING) {
661 autoscan_deinit(wpa_s);
662 wpa_supplicant_start_autoscan(wpa_s);
663 }
664}
665
666
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700667/**
668 * wpa_supplicant_set_state - Set current connection state
669 * @wpa_s: Pointer to wpa_supplicant data
670 * @state: The new connection state
671 *
672 * This function is called whenever the connection state changes, e.g.,
673 * association is completed for WPA/WPA2 4-Way Handshake is started.
674 */
675void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
676 enum wpa_states state)
677{
678 enum wpa_states old_state = wpa_s->wpa_state;
679
680 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
681 wpa_supplicant_state_txt(wpa_s->wpa_state),
682 wpa_supplicant_state_txt(state));
683
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800684 if (state == WPA_INTERFACE_DISABLED) {
685 /* Assure normal scan when interface is restored */
686 wpa_s->normal_scans = 0;
687 }
688
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700689 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800690 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700691 /* Reinitialize normal_scan counter */
692 wpa_s->normal_scans = 0;
693 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800694
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700695 if (state != WPA_SCANNING)
696 wpa_supplicant_notify_scanning(wpa_s, 0);
697
698 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700699 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700700#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700701 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800702 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800703 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700704 ssid ? ssid->id : -1,
705 ssid && ssid->id_str ? ssid->id_str : "");
706#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700707 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800708 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700710 wpa_drv_set_operstate(wpa_s, 1);
711#ifndef IEEE8021X_EAPOL
712 wpa_drv_set_supp_port(wpa_s, 1);
713#endif /* IEEE8021X_EAPOL */
714 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700715 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700717
718 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700719 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
720 state == WPA_ASSOCIATED) {
721 wpa_s->new_connection = 1;
722 wpa_drv_set_operstate(wpa_s, 0);
723#ifndef IEEE8021X_EAPOL
724 wpa_drv_set_supp_port(wpa_s, 0);
725#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700726 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700727 }
728 wpa_s->wpa_state = state;
729
730#ifdef CONFIG_BGSCAN
731 if (state == WPA_COMPLETED)
732 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800733 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734 wpa_supplicant_stop_bgscan(wpa_s);
735#endif /* CONFIG_BGSCAN */
736
Dmitry Shmidt04949592012-07-19 12:16:46 -0700737 if (state == WPA_AUTHENTICATING)
738 wpa_supplicant_stop_autoscan(wpa_s);
739
740 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
741 wpa_supplicant_start_autoscan(wpa_s);
742
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743 if (wpa_s->wpa_state != old_state) {
744 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
745
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700746 /*
747 * Notify the P2P Device interface about a state change in one
748 * of the interfaces.
749 */
750 wpas_p2p_indicate_state_change(wpa_s);
751
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700752 if (wpa_s->wpa_state == WPA_COMPLETED ||
753 old_state == WPA_COMPLETED)
754 wpas_notify_auth_changed(wpa_s);
755 }
756}
757
758
759void wpa_supplicant_terminate_proc(struct wpa_global *global)
760{
761 int pending = 0;
762#ifdef CONFIG_WPS
763 struct wpa_supplicant *wpa_s = global->ifaces;
764 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800765 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700766 if (wpas_wps_terminate_pending(wpa_s) == 1)
767 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700768#ifdef CONFIG_P2P
769 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
770 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
771 wpas_p2p_disconnect(wpa_s);
772#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800773 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700774 }
775#endif /* CONFIG_WPS */
776 if (pending)
777 return;
778 eloop_terminate();
779}
780
781
782static void wpa_supplicant_terminate(int sig, void *signal_ctx)
783{
784 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700785 wpa_supplicant_terminate_proc(global);
786}
787
788
789void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
790{
791 enum wpa_states old_state = wpa_s->wpa_state;
792
793 wpa_s->pairwise_cipher = 0;
794 wpa_s->group_cipher = 0;
795 wpa_s->mgmt_group_cipher = 0;
796 wpa_s->key_mgmt = 0;
797 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700798 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700799
800 if (wpa_s->wpa_state != old_state)
801 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
802}
803
804
805/**
806 * wpa_supplicant_reload_configuration - Reload configuration data
807 * @wpa_s: Pointer to wpa_supplicant data
808 * Returns: 0 on success or -1 if configuration parsing failed
809 *
810 * This function can be used to request that the configuration data is reloaded
811 * (e.g., after configuration file change). This function is reloading
812 * configuration only for one interface, so this may need to be called multiple
813 * times if %wpa_supplicant is controlling multiple interfaces and all
814 * interfaces need reconfiguration.
815 */
816int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
817{
818 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819 int reconf_ctrl;
820 int old_ap_scan;
821
822 if (wpa_s->confname == NULL)
823 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700824 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700825 if (conf == NULL) {
826 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
827 "file '%s' - exiting", wpa_s->confname);
828 return -1;
829 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700830 wpa_config_read(wpa_s->confanother, conf);
831
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700832 conf->changed_parameters = (unsigned int) -1;
833
834 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
835 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
836 os_strcmp(conf->ctrl_interface,
837 wpa_s->conf->ctrl_interface) != 0);
838
839 if (reconf_ctrl && wpa_s->ctrl_iface) {
840 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
841 wpa_s->ctrl_iface = NULL;
842 }
843
844 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800845 if (wpa_s->current_ssid) {
846 wpa_supplicant_deauthenticate(wpa_s,
847 WLAN_REASON_DEAUTH_LEAVING);
848 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849
850 /*
851 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
852 * pkcs11_engine_path, pkcs11_module_path.
853 */
854 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
855 /*
856 * Clear forced success to clear EAP state for next
857 * authentication.
858 */
859 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
860 }
861 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
862 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800863 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700864 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
865 rsn_preauth_deinit(wpa_s->wpa);
866
867 old_ap_scan = wpa_s->conf->ap_scan;
868 wpa_config_free(wpa_s->conf);
869 wpa_s->conf = conf;
870 if (old_ap_scan != wpa_s->conf->ap_scan)
871 wpas_notify_ap_scan_changed(wpa_s);
872
873 if (reconf_ctrl)
874 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
875
876 wpa_supplicant_update_config(wpa_s);
877
878 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700879 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880 wpa_s->reassociate = 1;
881 wpa_supplicant_req_scan(wpa_s, 0, 0);
882 }
883 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
884 return 0;
885}
886
887
888static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
889{
890 struct wpa_global *global = signal_ctx;
891 struct wpa_supplicant *wpa_s;
892 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
893 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
894 sig);
895 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
896 wpa_supplicant_terminate_proc(global);
897 }
898 }
899}
900
901
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
903 struct wpa_ssid *ssid,
904 struct wpa_ie_data *ie)
905{
906 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
907 if (ret) {
908 if (ret == -2) {
909 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
910 "from association info");
911 }
912 return -1;
913 }
914
915 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
916 "cipher suites");
917 if (!(ie->group_cipher & ssid->group_cipher)) {
918 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
919 "cipher 0x%x (mask 0x%x) - reject",
920 ie->group_cipher, ssid->group_cipher);
921 return -1;
922 }
923 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
924 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
925 "cipher 0x%x (mask 0x%x) - reject",
926 ie->pairwise_cipher, ssid->pairwise_cipher);
927 return -1;
928 }
929 if (!(ie->key_mgmt & ssid->key_mgmt)) {
930 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
931 "management 0x%x (mask 0x%x) - reject",
932 ie->key_mgmt, ssid->key_mgmt);
933 return -1;
934 }
935
936#ifdef CONFIG_IEEE80211W
937 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800938 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
939 wpa_s->conf->pmf : ssid->ieee80211w) ==
940 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700941 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
942 "that does not support management frame protection - "
943 "reject");
944 return -1;
945 }
946#endif /* CONFIG_IEEE80211W */
947
948 return 0;
949}
950
951
952/**
953 * wpa_supplicant_set_suites - Set authentication and encryption parameters
954 * @wpa_s: Pointer to wpa_supplicant data
955 * @bss: Scan results for the selected BSS, or %NULL if not available
956 * @ssid: Configuration data for the selected network
957 * @wpa_ie: Buffer for the WPA/RSN IE
958 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
959 * used buffer length in case the functions returns success.
960 * Returns: 0 on success or -1 on failure
961 *
962 * This function is used to configure authentication and encryption parameters
963 * based on the network configuration and scan result for the selected BSS (if
964 * available).
965 */
966int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
967 struct wpa_bss *bss, struct wpa_ssid *ssid,
968 u8 *wpa_ie, size_t *wpa_ie_len)
969{
970 struct wpa_ie_data ie;
971 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800972 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700973
974 if (bss) {
975 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
976 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800977 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700978 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800979 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980
981 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
982 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
983 (ie.group_cipher & ssid->group_cipher) &&
984 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
985 (ie.key_mgmt & ssid->key_mgmt)) {
986 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
987 proto = WPA_PROTO_RSN;
988 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
989 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
990 (ie.group_cipher & ssid->group_cipher) &&
991 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
992 (ie.key_mgmt & ssid->key_mgmt)) {
993 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
994 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800995#ifdef CONFIG_HS20
996 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
997 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
998 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -0700999 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001000 ie.group_cipher = WPA_CIPHER_CCMP;
1001 ie.pairwise_cipher = WPA_CIPHER_CCMP;
1002 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1003 proto = WPA_PROTO_OSEN;
1004#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001005 } else if (bss) {
1006 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
1007 return -1;
1008 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001009 if (ssid->proto & WPA_PROTO_OSEN)
1010 proto = WPA_PROTO_OSEN;
1011 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001012 proto = WPA_PROTO_RSN;
1013 else
1014 proto = WPA_PROTO_WPA;
1015 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1016 os_memset(&ie, 0, sizeof(ie));
1017 ie.group_cipher = ssid->group_cipher;
1018 ie.pairwise_cipher = ssid->pairwise_cipher;
1019 ie.key_mgmt = ssid->key_mgmt;
1020#ifdef CONFIG_IEEE80211W
1021 ie.mgmt_group_cipher =
1022 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1023 WPA_CIPHER_AES_128_CMAC : 0;
1024#endif /* CONFIG_IEEE80211W */
1025 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1026 "based on configuration");
1027 } else
1028 proto = ie.proto;
1029 }
1030
1031 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1032 "pairwise %d key_mgmt %d proto %d",
1033 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1034#ifdef CONFIG_IEEE80211W
1035 if (ssid->ieee80211w) {
1036 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1037 ie.mgmt_group_cipher);
1038 }
1039#endif /* CONFIG_IEEE80211W */
1040
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001041 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1043 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001044 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045
1046 if (bss || !wpa_s->ap_ies_from_associnfo) {
1047 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1048 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1049 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1050 bss_rsn ? 2 + bss_rsn[1] : 0))
1051 return -1;
1052 }
1053
1054 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001055 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1056 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1058 "cipher");
1059 return -1;
1060 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001061 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1062 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001063
1064 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001065 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1066 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001067 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1068 "cipher");
1069 return -1;
1070 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001071 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1072 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001073
1074 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001075#ifdef CONFIG_SAE
1076 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1077 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1078#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001079 if (0) {
1080#ifdef CONFIG_IEEE80211R
1081 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1082 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1083 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1084 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1085 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1086 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1087#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001088#ifdef CONFIG_SAE
1089 } else if (sel & WPA_KEY_MGMT_SAE) {
1090 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1091 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1092 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1093 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1094 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1095#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096#ifdef CONFIG_IEEE80211W
1097 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1098 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1099 wpa_dbg(wpa_s, MSG_DEBUG,
1100 "WPA: using KEY_MGMT 802.1X with SHA256");
1101 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1102 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1103 wpa_dbg(wpa_s, MSG_DEBUG,
1104 "WPA: using KEY_MGMT PSK with SHA256");
1105#endif /* CONFIG_IEEE80211W */
1106 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1107 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1108 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1109 } else if (sel & WPA_KEY_MGMT_PSK) {
1110 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1111 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1112 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1113 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1114 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001115#ifdef CONFIG_HS20
1116 } else if (sel & WPA_KEY_MGMT_OSEN) {
1117 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1118 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1119#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120 } else {
1121 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1122 "authenticated key management type");
1123 return -1;
1124 }
1125
1126 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1127 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1128 wpa_s->pairwise_cipher);
1129 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1130
1131#ifdef CONFIG_IEEE80211W
1132 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001133 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1134 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001135 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1136 sel = 0;
1137 if (sel & WPA_CIPHER_AES_128_CMAC) {
1138 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1139 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1140 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001141 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1142 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1143 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1144 "BIP-GMAC-128");
1145 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1146 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1147 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1148 "BIP-GMAC-256");
1149 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1150 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1151 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1152 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001153 } else {
1154 wpa_s->mgmt_group_cipher = 0;
1155 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1156 }
1157 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1158 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001159 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1160 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1161 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001162#endif /* CONFIG_IEEE80211W */
1163
1164 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1165 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1166 return -1;
1167 }
1168
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001169 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001170 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001171#ifndef CONFIG_NO_PBKDF2
1172 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1173 ssid->passphrase) {
1174 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001175 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1176 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001177 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1178 psk, PMK_LEN);
1179 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1180 }
1181#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001182#ifdef CONFIG_EXT_PASSWORD
1183 if (ssid->ext_psk) {
1184 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1185 ssid->ext_psk);
1186 char pw_str[64 + 1];
1187 u8 psk[PMK_LEN];
1188
1189 if (pw == NULL) {
1190 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1191 "found from external storage");
1192 return -1;
1193 }
1194
1195 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1196 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1197 "PSK length %d in external storage",
1198 (int) wpabuf_len(pw));
1199 ext_password_free(pw);
1200 return -1;
1201 }
1202
1203 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1204 pw_str[wpabuf_len(pw)] = '\0';
1205
1206#ifndef CONFIG_NO_PBKDF2
1207 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1208 {
1209 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1210 4096, psk, PMK_LEN);
1211 os_memset(pw_str, 0, sizeof(pw_str));
1212 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1213 "external passphrase)",
1214 psk, PMK_LEN);
1215 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1216 } else
1217#endif /* CONFIG_NO_PBKDF2 */
1218 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1219 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1220 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1221 "Invalid PSK hex string");
1222 os_memset(pw_str, 0, sizeof(pw_str));
1223 ext_password_free(pw);
1224 return -1;
1225 }
1226 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1227 } else {
1228 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1229 "PSK available");
1230 os_memset(pw_str, 0, sizeof(pw_str));
1231 ext_password_free(pw);
1232 return -1;
1233 }
1234
1235 os_memset(pw_str, 0, sizeof(pw_str));
1236 ext_password_free(pw);
1237 }
1238#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001239 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001240 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1241
1242 return 0;
1243}
1244
1245
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001246static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1247{
1248 *pos = 0x00;
1249
1250 switch (idx) {
1251 case 0: /* Bits 0-7 */
1252 break;
1253 case 1: /* Bits 8-15 */
1254 break;
1255 case 2: /* Bits 16-23 */
1256#ifdef CONFIG_WNM
1257 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1258 *pos |= 0x08; /* Bit 19 - BSS Transition */
1259#endif /* CONFIG_WNM */
1260 break;
1261 case 3: /* Bits 24-31 */
1262#ifdef CONFIG_WNM
1263 *pos |= 0x02; /* Bit 25 - SSID List */
1264#endif /* CONFIG_WNM */
1265#ifdef CONFIG_INTERWORKING
1266 if (wpa_s->conf->interworking)
1267 *pos |= 0x80; /* Bit 31 - Interworking */
1268#endif /* CONFIG_INTERWORKING */
1269 break;
1270 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001271#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001272 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1273 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001274#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001275 break;
1276 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001277#ifdef CONFIG_HS20
1278 if (wpa_s->conf->hs20)
1279 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1280#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001281 break;
1282 case 6: /* Bits 48-55 */
1283 break;
1284 }
1285}
1286
1287
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001288int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001289{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001290 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001291 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001292
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001293 if (len < wpa_s->extended_capa_len)
1294 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001295 if (buflen < (size_t) len + 2) {
1296 wpa_printf(MSG_INFO,
1297 "Not enough room for building extended capabilities element");
1298 return -1;
1299 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001300
1301 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001302 *pos++ = len;
1303 for (i = 0; i < len; i++, pos++) {
1304 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001305
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001306 if (i < wpa_s->extended_capa_len) {
1307 *pos &= ~wpa_s->extended_capa_mask[i];
1308 *pos |= wpa_s->extended_capa[i];
1309 }
1310 }
1311
1312 while (len > 0 && buf[1 + len] == 0) {
1313 len--;
1314 buf[1] = len;
1315 }
1316 if (len == 0)
1317 return 0;
1318
1319 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001320}
1321
1322
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001323static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1324 struct wpa_bss *test_bss)
1325{
1326 struct wpa_bss *bss;
1327
1328 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1329 if (bss == test_bss)
1330 return 1;
1331 }
1332
1333 return 0;
1334}
1335
1336
1337static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1338 struct wpa_ssid *test_ssid)
1339{
1340 struct wpa_ssid *ssid;
1341
1342 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1343 if (ssid == test_ssid)
1344 return 1;
1345 }
1346
1347 return 0;
1348}
1349
1350
1351int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1352 struct wpa_ssid *test_ssid)
1353{
1354 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1355 return 0;
1356
1357 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1358}
1359
1360
1361void wpas_connect_work_free(struct wpa_connect_work *cwork)
1362{
1363 if (cwork == NULL)
1364 return;
1365 os_free(cwork);
1366}
1367
1368
1369void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1370{
1371 struct wpa_connect_work *cwork;
1372 struct wpa_radio_work *work = wpa_s->connect_work;
1373
1374 if (!work)
1375 return;
1376
1377 wpa_s->connect_work = NULL;
1378 cwork = work->ctx;
1379 work->ctx = NULL;
1380 wpas_connect_work_free(cwork);
1381 radio_work_done(work);
1382}
1383
1384
1385static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1386
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001387/**
1388 * wpa_supplicant_associate - Request association
1389 * @wpa_s: Pointer to wpa_supplicant data
1390 * @bss: Scan results for the selected BSS, or %NULL if not available
1391 * @ssid: Configuration data for the selected network
1392 *
1393 * This function is used to request %wpa_supplicant to associate with a BSS.
1394 */
1395void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1396 struct wpa_bss *bss, struct wpa_ssid *ssid)
1397{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001398 struct wpa_connect_work *cwork;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001399
1400#ifdef CONFIG_IBSS_RSN
1401 ibss_rsn_deinit(wpa_s->ibss_rsn);
1402 wpa_s->ibss_rsn = NULL;
1403#endif /* CONFIG_IBSS_RSN */
1404
1405 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1406 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1407#ifdef CONFIG_AP
1408 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1409 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1410 "mode");
1411 return;
1412 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001413 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1414 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001415 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1416 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001417 return;
1418 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001419 wpa_s->current_bss = bss;
1420#else /* CONFIG_AP */
1421 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1422 "the build");
1423#endif /* CONFIG_AP */
1424 return;
1425 }
1426
1427#ifdef CONFIG_TDLS
1428 if (bss)
1429 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1430 bss->ie_len);
1431#endif /* CONFIG_TDLS */
1432
1433 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1434 ssid->mode == IEEE80211_MODE_INFRA) {
1435 sme_authenticate(wpa_s, bss, ssid);
1436 return;
1437 }
1438
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001439 if (wpa_s->connect_work) {
1440 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1441 return;
1442 }
1443
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001444 if (radio_work_pending(wpa_s, "connect")) {
1445 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1446 return;
1447 }
1448
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001449 cwork = os_zalloc(sizeof(*cwork));
1450 if (cwork == NULL)
1451 return;
1452
1453 cwork->bss = bss;
1454 cwork->ssid = ssid;
1455
1456 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1457 wpas_start_assoc_cb, cwork) < 0) {
1458 os_free(cwork);
1459 }
1460}
1461
1462
1463static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1464{
1465 struct wpa_connect_work *cwork = work->ctx;
1466 struct wpa_bss *bss = cwork->bss;
1467 struct wpa_ssid *ssid = cwork->ssid;
1468 struct wpa_supplicant *wpa_s = work->wpa_s;
1469 u8 wpa_ie[200];
1470 size_t wpa_ie_len;
1471 int use_crypt, ret, i, bssid_changed;
1472 int algs = WPA_AUTH_ALG_OPEN;
1473 unsigned int cipher_pairwise, cipher_group;
1474 struct wpa_driver_associate_params params;
1475 int wep_keys_set = 0;
1476 int assoc_failed = 0;
1477 struct wpa_ssid *old_ssid;
1478#ifdef CONFIG_HT_OVERRIDES
1479 struct ieee80211_ht_capabilities htcaps;
1480 struct ieee80211_ht_capabilities htcaps_mask;
1481#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001482#ifdef CONFIG_VHT_OVERRIDES
1483 struct ieee80211_vht_capabilities vhtcaps;
1484 struct ieee80211_vht_capabilities vhtcaps_mask;
1485#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001486
1487 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001488 if (work->started) {
1489 wpa_s->connect_work = NULL;
1490
1491 /* cancel possible auth. timeout */
1492 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1493 NULL);
1494 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001495 wpas_connect_work_free(cwork);
1496 return;
1497 }
1498
1499 wpa_s->connect_work = work;
1500
1501 if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
1502 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1503 wpas_connect_work_done(wpa_s);
1504 return;
1505 }
1506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001507 os_memset(&params, 0, sizeof(params));
1508 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001509 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001510 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001511#ifdef CONFIG_IEEE80211R
1512 const u8 *ie, *md = NULL;
1513#endif /* CONFIG_IEEE80211R */
1514 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1515 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1516 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1517 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1518 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1519 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1520 if (bssid_changed)
1521 wpas_notify_bssid_changed(wpa_s);
1522#ifdef CONFIG_IEEE80211R
1523 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1524 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1525 md = ie + 2;
1526 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1527 if (md) {
1528 /* Prepare for the next transition */
1529 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1530 }
1531#endif /* CONFIG_IEEE80211R */
1532#ifdef CONFIG_WPS
1533 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1534 wpa_s->conf->ap_scan == 2 &&
1535 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1536 /* Use ap_scan==1 style network selection to find the network
1537 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001538 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001539 wpa_s->reassociate = 1;
1540 wpa_supplicant_req_scan(wpa_s, 0, 0);
1541 return;
1542#endif /* CONFIG_WPS */
1543 } else {
1544 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1545 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1546 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1547 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001548 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001549 wpa_supplicant_cancel_scan(wpa_s);
1550
1551 /* Starting new association, so clear the possibly used WPA IE from the
1552 * previous association. */
1553 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1554
1555#ifdef IEEE8021X_EAPOL
1556 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1557 if (ssid->leap) {
1558 if (ssid->non_leap == 0)
1559 algs = WPA_AUTH_ALG_LEAP;
1560 else
1561 algs |= WPA_AUTH_ALG_LEAP;
1562 }
1563 }
1564#endif /* IEEE8021X_EAPOL */
1565 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1566 if (ssid->auth_alg) {
1567 algs = ssid->auth_alg;
1568 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1569 "0x%x", algs);
1570 }
1571
1572 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1573 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001574 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001575 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001576 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1577 wpa_s->conf->okc :
1578 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001579 (ssid->proto & WPA_PROTO_RSN);
1580 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001581 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001582 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1583 wpa_ie_len = sizeof(wpa_ie);
1584 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1585 wpa_ie, &wpa_ie_len)) {
1586 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1587 "key management and encryption suites");
1588 return;
1589 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001590 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1591 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1592 /*
1593 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1594 * use non-WPA since the scan results did not indicate that the
1595 * AP is using WPA or WPA2.
1596 */
1597 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1598 wpa_ie_len = 0;
1599 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001600 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001601 wpa_ie_len = sizeof(wpa_ie);
1602 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1603 wpa_ie, &wpa_ie_len)) {
1604 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1605 "key management and encryption suites (no "
1606 "scan results)");
1607 return;
1608 }
1609#ifdef CONFIG_WPS
1610 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1611 struct wpabuf *wps_ie;
1612 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1613 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1614 wpa_ie_len = wpabuf_len(wps_ie);
1615 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1616 } else
1617 wpa_ie_len = 0;
1618 wpabuf_free(wps_ie);
1619 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1620 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1621 params.wps = WPS_MODE_PRIVACY;
1622 else
1623 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001624 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001625#endif /* CONFIG_WPS */
1626 } else {
1627 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1628 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001629 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001630 }
1631
1632#ifdef CONFIG_P2P
1633 if (wpa_s->global->p2p) {
1634 u8 *pos;
1635 size_t len;
1636 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001637 pos = wpa_ie + wpa_ie_len;
1638 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001639 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1640 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641 if (res >= 0)
1642 wpa_ie_len += res;
1643 }
1644
1645 wpa_s->cross_connect_disallowed = 0;
1646 if (bss) {
1647 struct wpabuf *p2p;
1648 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1649 if (p2p) {
1650 wpa_s->cross_connect_disallowed =
1651 p2p_get_cross_connect_disallowed(p2p);
1652 wpabuf_free(p2p);
1653 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1654 "connection",
1655 wpa_s->cross_connect_disallowed ?
1656 "disallows" : "allows");
1657 }
1658 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001659
1660 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661#endif /* CONFIG_P2P */
1662
Dmitry Shmidt04949592012-07-19 12:16:46 -07001663#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001664 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001665 struct wpabuf *hs20;
1666 hs20 = wpabuf_alloc(20);
1667 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001668 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001669 size_t len;
1670
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001671 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001672 len = sizeof(wpa_ie) - wpa_ie_len;
1673 if (wpabuf_len(hs20) <= len) {
1674 os_memcpy(wpa_ie + wpa_ie_len,
1675 wpabuf_head(hs20), wpabuf_len(hs20));
1676 wpa_ie_len += wpabuf_len(hs20);
1677 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001678 wpabuf_free(hs20);
1679 }
1680 }
1681#endif /* CONFIG_HS20 */
1682
Dmitry Shmidt56052862013-10-04 10:23:25 -07001683 /*
1684 * Workaround: Add Extended Capabilities element only if the AP
1685 * included this element in Beacon/Probe Response frames. Some older
1686 * APs seem to have interoperability issues if this element is
1687 * included, so while the standard may require us to include the
1688 * element in all cases, it is justifiable to skip it to avoid
1689 * interoperability issues.
1690 */
1691 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001692 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07001693 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001694 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
1695 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07001696 if (ext_capab_len > 0) {
1697 u8 *pos = wpa_ie;
1698 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1699 pos += 2 + pos[1];
1700 os_memmove(pos + ext_capab_len, pos,
1701 wpa_ie_len - (pos - wpa_ie));
1702 wpa_ie_len += ext_capab_len;
1703 os_memcpy(pos, ext_capab, ext_capab_len);
1704 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001705 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001706
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001707 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1708 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001709 cipher_pairwise = wpa_s->pairwise_cipher;
1710 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001711 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1712 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1713 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1714 use_crypt = 0;
1715 if (wpa_set_wep_keys(wpa_s, ssid)) {
1716 use_crypt = 1;
1717 wep_keys_set = 1;
1718 }
1719 }
1720 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1721 use_crypt = 0;
1722
1723#ifdef IEEE8021X_EAPOL
1724 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1725 if ((ssid->eapol_flags &
1726 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1727 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1728 !wep_keys_set) {
1729 use_crypt = 0;
1730 } else {
1731 /* Assume that dynamic WEP-104 keys will be used and
1732 * set cipher suites in order for drivers to expect
1733 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001734 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001735 }
1736 }
1737#endif /* IEEE8021X_EAPOL */
1738
1739 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1740 /* Set the key before (and later after) association */
1741 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1742 }
1743
1744 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1745 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746 params.ssid = bss->ssid;
1747 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001748 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1749 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1750 MACSTR " freq=%u MHz based on scan results "
1751 "(bssid_set=%d)",
1752 MAC2STR(bss->bssid), bss->freq,
1753 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001754 params.bssid = bss->bssid;
1755 params.freq = bss->freq;
1756 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001757 params.bssid_hint = bss->bssid;
1758 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001759 } else {
1760 params.ssid = ssid->ssid;
1761 params.ssid_len = ssid->ssid_len;
1762 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001763
1764 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1765 wpa_s->conf->ap_scan == 2) {
1766 params.bssid = ssid->bssid;
1767 params.fixed_bssid = 1;
1768 }
1769
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001770 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1771 params.freq == 0)
1772 params.freq = ssid->frequency; /* Initial channel for IBSS */
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08001773
1774 if (ssid->mode == WPAS_MODE_IBSS) {
1775 if (ssid->beacon_int)
1776 params.beacon_int = ssid->beacon_int;
1777 else
1778 params.beacon_int = wpa_s->conf->beacon_int;
1779 }
1780
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001781 params.wpa_ie = wpa_ie;
1782 params.wpa_ie_len = wpa_ie_len;
1783 params.pairwise_suite = cipher_pairwise;
1784 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001785 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001786 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787 params.auth_alg = algs;
1788 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001789 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001790 for (i = 0; i < NUM_WEP_KEYS; i++) {
1791 if (ssid->wep_key_len[i])
1792 params.wep_key[i] = ssid->wep_key[i];
1793 params.wep_key_len[i] = ssid->wep_key_len[i];
1794 }
1795 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1796
1797 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001798 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1799 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001800 params.passphrase = ssid->passphrase;
1801 if (ssid->psk_set)
1802 params.psk = ssid->psk;
1803 }
1804
1805 params.drop_unencrypted = use_crypt;
1806
1807#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001808 params.mgmt_frame_protection =
1809 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1810 wpa_s->conf->pmf : ssid->ieee80211w;
1811 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001812 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1813 struct wpa_ie_data ie;
1814 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1815 ie.capabilities &
1816 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1817 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1818 "MFP: require MFP");
1819 params.mgmt_frame_protection =
1820 MGMT_FRAME_PROTECTION_REQUIRED;
1821 }
1822 }
1823#endif /* CONFIG_IEEE80211W */
1824
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001825 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826
1827 if (wpa_s->parent->set_sta_uapsd)
1828 params.uapsd = wpa_s->parent->sta_uapsd;
1829 else
1830 params.uapsd = -1;
1831
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001832#ifdef CONFIG_HT_OVERRIDES
1833 os_memset(&htcaps, 0, sizeof(htcaps));
1834 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1835 params.htcaps = (u8 *) &htcaps;
1836 params.htcaps_mask = (u8 *) &htcaps_mask;
1837 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1838#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001839#ifdef CONFIG_VHT_OVERRIDES
1840 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
1841 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
1842 params.vhtcaps = &vhtcaps;
1843 params.vhtcaps_mask = &vhtcaps_mask;
1844 wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
1845#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001846
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001847#ifdef CONFIG_P2P
1848 /*
1849 * If multi-channel concurrency is not supported, check for any
1850 * frequency conflict. In case of any frequency conflict, remove the
1851 * least prioritized connection.
1852 */
1853 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001854 int freq, num;
1855 num = get_shared_radio_freqs(wpa_s, &freq, 1);
1856 if (num > 0 && freq > 0 && freq != params.freq) {
1857 wpa_printf(MSG_DEBUG,
1858 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001859 freq, params.freq);
1860 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1861 params.freq,
1862 ssid) < 0)
1863 return;
1864 }
1865 }
1866#endif /* CONFIG_P2P */
1867
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001868 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001869 if (ret < 0) {
1870 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1871 "failed");
1872 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1873 /*
1874 * The driver is known to mean what is saying, so we
1875 * can stop right here; the association will not
1876 * succeed.
1877 */
1878 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001879 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001880 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1881 return;
1882 }
1883 /* try to continue anyway; new association will be tried again
1884 * after timeout */
1885 assoc_failed = 1;
1886 }
1887
1888 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1889 /* Set the key after the association just in case association
1890 * cleared the previously configured key. */
1891 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1892 /* No need to timeout authentication since there is no key
1893 * management. */
1894 wpa_supplicant_cancel_auth_timeout(wpa_s);
1895 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1896#ifdef CONFIG_IBSS_RSN
1897 } else if (ssid->mode == WPAS_MODE_IBSS &&
1898 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1899 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1900 /*
1901 * RSN IBSS authentication is per-STA and we can disable the
1902 * per-BSSID authentication.
1903 */
1904 wpa_supplicant_cancel_auth_timeout(wpa_s);
1905#endif /* CONFIG_IBSS_RSN */
1906 } else {
1907 /* Timeout for IEEE 802.11 authentication and association */
1908 int timeout = 60;
1909
1910 if (assoc_failed) {
1911 /* give IBSS a bit more time */
1912 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1913 } else if (wpa_s->conf->ap_scan == 1) {
1914 /* give IBSS a bit more time */
1915 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1916 }
1917 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1918 }
1919
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001920 if (wep_keys_set &&
1921 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922 /* Set static WEP keys again */
1923 wpa_set_wep_keys(wpa_s, ssid);
1924 }
1925
1926 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1927 /*
1928 * Do not allow EAP session resumption between different
1929 * network configurations.
1930 */
1931 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1932 }
1933 old_ssid = wpa_s->current_ssid;
1934 wpa_s->current_ssid = ssid;
1935 wpa_s->current_bss = bss;
1936 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1937 wpa_supplicant_initiate_eapol(wpa_s);
1938 if (old_ssid != wpa_s->current_ssid)
1939 wpas_notify_network_changed(wpa_s);
1940}
1941
1942
1943static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1944 const u8 *addr)
1945{
1946 struct wpa_ssid *old_ssid;
1947
1948 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001949 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001950 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001951 wpa_sm_set_config(wpa_s->wpa, NULL);
1952 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1953 if (old_ssid != wpa_s->current_ssid)
1954 wpas_notify_network_changed(wpa_s);
1955 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1956}
1957
1958
1959/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001960 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1961 * @wpa_s: Pointer to wpa_supplicant data
1962 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1963 *
1964 * This function is used to request %wpa_supplicant to deauthenticate from the
1965 * current AP.
1966 */
1967void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1968 int reason_code)
1969{
1970 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001971 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001972 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001973
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001974 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1975 " pending_bssid=" MACSTR " reason=%d state=%s",
1976 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1977 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1978
1979 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001980 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001981 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1982 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1983 wpa_s->wpa_state == WPA_ASSOCIATING))
1984 addr = wpa_s->pending_bssid;
1985 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1986 /*
1987 * When using driver-based BSS selection, we may not know the
1988 * BSSID with which we are currently trying to associate. We
1989 * need to notify the driver of this disconnection even in such
1990 * a case, so use the all zeros address here.
1991 */
1992 addr = wpa_s->bssid;
1993 zero_addr = 1;
1994 }
1995
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001996#ifdef CONFIG_TDLS
1997 wpa_tdls_teardown_peers(wpa_s->wpa);
1998#endif /* CONFIG_TDLS */
1999
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002000 if (addr) {
2001 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002002 os_memset(&event, 0, sizeof(event));
2003 event.deauth_info.reason_code = (u16) reason_code;
2004 event.deauth_info.locally_generated = 1;
2005 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002006 if (zero_addr)
2007 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002008 }
2009
2010 wpa_supplicant_clear_connection(wpa_s, addr);
2011}
2012
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002013static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2014 struct wpa_ssid *ssid)
2015{
2016 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2017 return;
2018
2019 ssid->disabled = 0;
2020 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2021 wpas_notify_network_enabled_changed(wpa_s, ssid);
2022
2023 /*
2024 * Try to reassociate since there is no current configuration and a new
2025 * network was made available.
2026 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002027 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002028 wpa_s->reassociate = 1;
2029}
2030
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002031
2032/**
2033 * wpa_supplicant_enable_network - Mark a configured network as enabled
2034 * @wpa_s: wpa_supplicant structure for a network interface
2035 * @ssid: wpa_ssid structure for a configured network or %NULL
2036 *
2037 * Enables the specified network or all networks if no network specified.
2038 */
2039void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2040 struct wpa_ssid *ssid)
2041{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002043 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2044 wpa_supplicant_enable_one_network(wpa_s, ssid);
2045 } else
2046 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002047
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002048 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002049 if (wpa_s->sched_scanning) {
2050 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2051 "new network to scan filters");
2052 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053 }
2054
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002055 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2056 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057 }
2058}
2059
2060
2061/**
2062 * wpa_supplicant_disable_network - Mark a configured network as disabled
2063 * @wpa_s: wpa_supplicant structure for a network interface
2064 * @ssid: wpa_ssid structure for a configured network or %NULL
2065 *
2066 * Disables the specified network or all networks if no network specified.
2067 */
2068void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2069 struct wpa_ssid *ssid)
2070{
2071 struct wpa_ssid *other_ssid;
2072 int was_disabled;
2073
2074 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002075 if (wpa_s->sched_scanning)
2076 wpa_supplicant_cancel_sched_scan(wpa_s);
2077
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002078 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2079 other_ssid = other_ssid->next) {
2080 was_disabled = other_ssid->disabled;
2081 if (was_disabled == 2)
2082 continue; /* do not change persistent P2P group
2083 * data */
2084
2085 other_ssid->disabled = 1;
2086
2087 if (was_disabled != other_ssid->disabled)
2088 wpas_notify_network_enabled_changed(
2089 wpa_s, other_ssid);
2090 }
2091 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002092 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2094 } else if (ssid->disabled != 2) {
2095 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002096 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2098
2099 was_disabled = ssid->disabled;
2100
2101 ssid->disabled = 1;
2102
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002103 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002104 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002105 if (wpa_s->sched_scanning) {
2106 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2107 "to remove network from filters");
2108 wpa_supplicant_cancel_sched_scan(wpa_s);
2109 wpa_supplicant_req_scan(wpa_s, 0, 0);
2110 }
2111 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002112 }
2113}
2114
2115
2116/**
2117 * wpa_supplicant_select_network - Attempt association with a network
2118 * @wpa_s: wpa_supplicant structure for a network interface
2119 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2120 */
2121void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2122 struct wpa_ssid *ssid)
2123{
2124
2125 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002126 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002128 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002129 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002130 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002131 disconnected = 1;
2132 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002133
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002134 if (ssid)
2135 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2136
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 /*
2138 * Mark all other networks disabled or mark all networks enabled if no
2139 * network specified.
2140 */
2141 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2142 other_ssid = other_ssid->next) {
2143 int was_disabled = other_ssid->disabled;
2144 if (was_disabled == 2)
2145 continue; /* do not change persistent P2P group data */
2146
2147 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002148 if (was_disabled && !other_ssid->disabled)
2149 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002150
2151 if (was_disabled != other_ssid->disabled)
2152 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2153 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002154
2155 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2156 /* We are already associated with the selected network */
2157 wpa_printf(MSG_DEBUG, "Already associated with the "
2158 "selected network - do nothing");
2159 return;
2160 }
2161
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002162 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002163 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002164 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2165 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002166 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002167 wpa_s->disconnected = 0;
2168 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002169
2170 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2171 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002172
2173 if (ssid)
2174 wpas_notify_network_selected(wpa_s, ssid);
2175}
2176
2177
2178/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002179 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2180 * @wpa_s: wpa_supplicant structure for a network interface
2181 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2182 * @pkcs11_module_path: PKCS #11 module path or NULL
2183 * Returns: 0 on success; -1 on failure
2184 *
2185 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2186 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2187 * module path fails the paths will be reset to the default value (NULL).
2188 */
2189int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2190 const char *pkcs11_engine_path,
2191 const char *pkcs11_module_path)
2192{
2193 char *pkcs11_engine_path_copy = NULL;
2194 char *pkcs11_module_path_copy = NULL;
2195
2196 if (pkcs11_engine_path != NULL) {
2197 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2198 if (pkcs11_engine_path_copy == NULL)
2199 return -1;
2200 }
2201 if (pkcs11_module_path != NULL) {
2202 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002203 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002204 os_free(pkcs11_engine_path_copy);
2205 return -1;
2206 }
2207 }
2208
2209 os_free(wpa_s->conf->pkcs11_engine_path);
2210 os_free(wpa_s->conf->pkcs11_module_path);
2211 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2212 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2213
2214 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2215 eapol_sm_deinit(wpa_s->eapol);
2216 wpa_s->eapol = NULL;
2217 if (wpa_supplicant_init_eapol(wpa_s)) {
2218 /* Error -> Reset paths to the default value (NULL) once. */
2219 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2220 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2221 NULL);
2222
2223 return -1;
2224 }
2225 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2226
2227 return 0;
2228}
2229
2230
2231/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002232 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2233 * @wpa_s: wpa_supplicant structure for a network interface
2234 * @ap_scan: AP scan mode
2235 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2236 *
2237 */
2238int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2239{
2240
2241 int old_ap_scan;
2242
2243 if (ap_scan < 0 || ap_scan > 2)
2244 return -1;
2245
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002246#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002247 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2248 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2249 wpa_s->wpa_state < WPA_COMPLETED) {
2250 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2251 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002252 return 0;
2253 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002254#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002255
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002256 old_ap_scan = wpa_s->conf->ap_scan;
2257 wpa_s->conf->ap_scan = ap_scan;
2258
2259 if (old_ap_scan != wpa_s->conf->ap_scan)
2260 wpas_notify_ap_scan_changed(wpa_s);
2261
2262 return 0;
2263}
2264
2265
2266/**
2267 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2268 * @wpa_s: wpa_supplicant structure for a network interface
2269 * @expire_age: Expiration age in seconds
2270 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2271 *
2272 */
2273int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2274 unsigned int bss_expire_age)
2275{
2276 if (bss_expire_age < 10) {
2277 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2278 bss_expire_age);
2279 return -1;
2280 }
2281 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2282 bss_expire_age);
2283 wpa_s->conf->bss_expiration_age = bss_expire_age;
2284
2285 return 0;
2286}
2287
2288
2289/**
2290 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2291 * @wpa_s: wpa_supplicant structure for a network interface
2292 * @expire_count: number of scans after which an unseen BSS is reclaimed
2293 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2294 *
2295 */
2296int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2297 unsigned int bss_expire_count)
2298{
2299 if (bss_expire_count < 1) {
2300 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2301 bss_expire_count);
2302 return -1;
2303 }
2304 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2305 bss_expire_count);
2306 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2307
2308 return 0;
2309}
2310
2311
2312/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002313 * wpa_supplicant_set_scan_interval - Set scan interval
2314 * @wpa_s: wpa_supplicant structure for a network interface
2315 * @scan_interval: scan interval in seconds
2316 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2317 *
2318 */
2319int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2320 int scan_interval)
2321{
2322 if (scan_interval < 0) {
2323 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2324 scan_interval);
2325 return -1;
2326 }
2327 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2328 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002329 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002330
2331 return 0;
2332}
2333
2334
2335/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002336 * wpa_supplicant_set_debug_params - Set global debug params
2337 * @global: wpa_global structure
2338 * @debug_level: debug level
2339 * @debug_timestamp: determines if show timestamp in debug data
2340 * @debug_show_keys: determines if show keys in debug data
2341 * Returns: 0 if succeed or -1 if debug_level has wrong value
2342 */
2343int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2344 int debug_timestamp, int debug_show_keys)
2345{
2346
2347 int old_level, old_timestamp, old_show_keys;
2348
2349 /* check for allowed debuglevels */
2350 if (debug_level != MSG_EXCESSIVE &&
2351 debug_level != MSG_MSGDUMP &&
2352 debug_level != MSG_DEBUG &&
2353 debug_level != MSG_INFO &&
2354 debug_level != MSG_WARNING &&
2355 debug_level != MSG_ERROR)
2356 return -1;
2357
2358 old_level = wpa_debug_level;
2359 old_timestamp = wpa_debug_timestamp;
2360 old_show_keys = wpa_debug_show_keys;
2361
2362 wpa_debug_level = debug_level;
2363 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2364 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2365
2366 if (wpa_debug_level != old_level)
2367 wpas_notify_debug_level_changed(global);
2368 if (wpa_debug_timestamp != old_timestamp)
2369 wpas_notify_debug_timestamp_changed(global);
2370 if (wpa_debug_show_keys != old_show_keys)
2371 wpas_notify_debug_show_keys_changed(global);
2372
2373 return 0;
2374}
2375
2376
2377/**
2378 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2379 * @wpa_s: Pointer to wpa_supplicant data
2380 * Returns: A pointer to the current network structure or %NULL on failure
2381 */
2382struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2383{
2384 struct wpa_ssid *entry;
2385 u8 ssid[MAX_SSID_LEN];
2386 int res;
2387 size_t ssid_len;
2388 u8 bssid[ETH_ALEN];
2389 int wired;
2390
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002391 res = wpa_drv_get_ssid(wpa_s, ssid);
2392 if (res < 0) {
2393 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2394 "driver");
2395 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002396 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002397 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002398
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002399 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2401 "driver");
2402 return NULL;
2403 }
2404
2405 wired = wpa_s->conf->ap_scan == 0 &&
2406 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2407
2408 entry = wpa_s->conf->ssid;
2409 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002410 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002411 ((ssid_len == entry->ssid_len &&
2412 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2413 (!entry->bssid_set ||
2414 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2415 return entry;
2416#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002417 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2419 (entry->ssid == NULL || entry->ssid_len == 0) &&
2420 (!entry->bssid_set ||
2421 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2422 return entry;
2423#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002424
Dmitry Shmidt04949592012-07-19 12:16:46 -07002425 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002426 entry->ssid_len == 0 &&
2427 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2428 return entry;
2429
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002430 entry = entry->next;
2431 }
2432
2433 return NULL;
2434}
2435
2436
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002437static int select_driver(struct wpa_supplicant *wpa_s, int i)
2438{
2439 struct wpa_global *global = wpa_s->global;
2440
2441 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2442 global->drv_priv[i] = wpa_drivers[i]->global_init();
2443 if (global->drv_priv[i] == NULL) {
2444 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2445 "'%s'", wpa_drivers[i]->name);
2446 return -1;
2447 }
2448 }
2449
2450 wpa_s->driver = wpa_drivers[i];
2451 wpa_s->global_drv_priv = global->drv_priv[i];
2452
2453 return 0;
2454}
2455
2456
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2458 const char *name)
2459{
2460 int i;
2461 size_t len;
2462 const char *pos, *driver = name;
2463
2464 if (wpa_s == NULL)
2465 return -1;
2466
2467 if (wpa_drivers[0] == NULL) {
2468 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2469 "wpa_supplicant");
2470 return -1;
2471 }
2472
2473 if (name == NULL) {
2474 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002475 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 }
2477
2478 do {
2479 pos = os_strchr(driver, ',');
2480 if (pos)
2481 len = pos - driver;
2482 else
2483 len = os_strlen(driver);
2484
2485 for (i = 0; wpa_drivers[i]; i++) {
2486 if (os_strlen(wpa_drivers[i]->name) == len &&
2487 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002488 0) {
2489 /* First driver that succeeds wins */
2490 if (select_driver(wpa_s, i) == 0)
2491 return 0;
2492 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 }
2494
2495 driver = pos + 1;
2496 } while (pos);
2497
2498 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2499 return -1;
2500}
2501
2502
2503/**
2504 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2505 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2506 * with struct wpa_driver_ops::init()
2507 * @src_addr: Source address of the EAPOL frame
2508 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2509 * @len: Length of the EAPOL data
2510 *
2511 * This function is called for each received EAPOL frame. Most driver
2512 * interfaces rely on more generic OS mechanism for receiving frames through
2513 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2514 * take care of received EAPOL frames and deliver them to the core supplicant
2515 * code by calling this function.
2516 */
2517void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2518 const u8 *buf, size_t len)
2519{
2520 struct wpa_supplicant *wpa_s = ctx;
2521
2522 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2523 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2524
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002525#ifdef CONFIG_PEERKEY
2526 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2527 wpa_s->current_ssid->peerkey &&
2528 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2529 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2530 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2531 return;
2532 }
2533#endif /* CONFIG_PEERKEY */
2534
Jouni Malinena05074c2012-12-21 21:35:35 +02002535 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2536 (wpa_s->last_eapol_matches_bssid &&
2537#ifdef CONFIG_AP
2538 !wpa_s->ap_iface &&
2539#endif /* CONFIG_AP */
2540 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 /*
2542 * There is possible race condition between receiving the
2543 * association event and the EAPOL frame since they are coming
2544 * through different paths from the driver. In order to avoid
2545 * issues in trying to process the EAPOL frame before receiving
2546 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002547 * the association event is received. This may also be needed in
2548 * driver-based roaming case, so also use src_addr != BSSID as a
2549 * trigger if we have previously confirmed that the
2550 * Authenticator uses BSSID as the src_addr (which is not the
2551 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 */
2553 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002554 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2555 wpa_supplicant_state_txt(wpa_s->wpa_state),
2556 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557 wpabuf_free(wpa_s->pending_eapol_rx);
2558 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2559 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002560 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2562 ETH_ALEN);
2563 }
2564 return;
2565 }
2566
Jouni Malinena05074c2012-12-21 21:35:35 +02002567 wpa_s->last_eapol_matches_bssid =
2568 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2569
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570#ifdef CONFIG_AP
2571 if (wpa_s->ap_iface) {
2572 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2573 return;
2574 }
2575#endif /* CONFIG_AP */
2576
2577 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2578 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2579 "no key management is configured");
2580 return;
2581 }
2582
2583 if (wpa_s->eapol_received == 0 &&
2584 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2585 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2586 wpa_s->wpa_state != WPA_COMPLETED) &&
2587 (wpa_s->current_ssid == NULL ||
2588 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2589 /* Timeout for completing IEEE 802.1X and WPA authentication */
2590 wpa_supplicant_req_auth_timeout(
2591 wpa_s,
2592 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2593 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2594 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2595 70 : 10, 0);
2596 }
2597 wpa_s->eapol_received++;
2598
2599 if (wpa_s->countermeasures) {
2600 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2601 "EAPOL packet");
2602 return;
2603 }
2604
2605#ifdef CONFIG_IBSS_RSN
2606 if (wpa_s->current_ssid &&
2607 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2608 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2609 return;
2610 }
2611#endif /* CONFIG_IBSS_RSN */
2612
2613 /* Source address of the incoming EAPOL frame could be compared to the
2614 * current BSSID. However, it is possible that a centralized
2615 * Authenticator could be using another MAC address than the BSSID of
2616 * an AP, so just allow any address to be used for now. The replies are
2617 * still sent to the current BSSID (if available), though. */
2618
2619 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2620 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2621 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2622 return;
2623 wpa_drv_poll(wpa_s);
2624 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2625 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2626 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2627 /*
2628 * Set portValid = TRUE here since we are going to skip 4-way
2629 * handshake processing which would normally set portValid. We
2630 * need this to allow the EAPOL state machines to be completed
2631 * without going through EAPOL-Key handshake.
2632 */
2633 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2634 }
2635}
2636
2637
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002638int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002639{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640 if (wpa_s->driver->send_eapol) {
2641 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2642 if (addr)
2643 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002644 } else if ((!wpa_s->p2p_mgmt ||
2645 !(wpa_s->drv_flags &
2646 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2647 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002649 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002650 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2651 wpa_drv_get_mac_addr(wpa_s),
2652 ETH_P_EAPOL,
2653 wpa_supplicant_rx_eapol, wpa_s, 0);
2654 if (wpa_s->l2 == NULL)
2655 return -1;
2656 } else {
2657 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2658 if (addr)
2659 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2660 }
2661
2662 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2663 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2664 return -1;
2665 }
2666
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002667 return 0;
2668}
2669
2670
Dmitry Shmidt04949592012-07-19 12:16:46 -07002671static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2672 const u8 *buf, size_t len)
2673{
2674 struct wpa_supplicant *wpa_s = ctx;
2675 const struct l2_ethhdr *eth;
2676
2677 if (len < sizeof(*eth))
2678 return;
2679 eth = (const struct l2_ethhdr *) buf;
2680
2681 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2682 !(eth->h_dest[0] & 0x01)) {
2683 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2684 " (bridge - not for this interface - ignore)",
2685 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2686 return;
2687 }
2688
2689 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2690 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2691 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2692 len - sizeof(*eth));
2693}
2694
2695
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002696/**
2697 * wpa_supplicant_driver_init - Initialize driver interface parameters
2698 * @wpa_s: Pointer to wpa_supplicant data
2699 * Returns: 0 on success, -1 on failure
2700 *
2701 * This function is called to initialize driver interface parameters.
2702 * wpa_drv_init() must have been called before this function to initialize the
2703 * driver interface.
2704 */
2705int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2706{
2707 static int interface_count = 0;
2708
2709 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2710 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002712 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2713 MAC2STR(wpa_s->own_addr));
2714 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2715
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002716 if (wpa_s->bridge_ifname[0]) {
2717 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2718 "interface '%s'", wpa_s->bridge_ifname);
2719 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2720 wpa_s->own_addr,
2721 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002722 wpa_supplicant_rx_eapol_bridge,
2723 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002724 if (wpa_s->l2_br == NULL) {
2725 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2726 "connection for the bridge interface '%s'",
2727 wpa_s->bridge_ifname);
2728 return -1;
2729 }
2730 }
2731
2732 wpa_clear_keys(wpa_s, NULL);
2733
2734 /* Make sure that TKIP countermeasures are not left enabled (could
2735 * happen if wpa_supplicant is killed during countermeasures. */
2736 wpa_drv_set_countermeasures(wpa_s, 0);
2737
2738 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2739 wpa_drv_flush_pmkid(wpa_s);
2740
2741 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002742 wpa_s->prev_scan_wildcard = 0;
2743
Dmitry Shmidt04949592012-07-19 12:16:46 -07002744 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002745 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2746 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2747 interface_count = 0;
2748 }
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002749 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07002750 wpa_supplicant_delayed_sched_scan(wpa_s,
2751 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002752 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07002753 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002754 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 interface_count++;
2756 } else
2757 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2758
2759 return 0;
2760}
2761
2762
2763static int wpa_supplicant_daemon(const char *pid_file)
2764{
2765 wpa_printf(MSG_DEBUG, "Daemonize..");
2766 return os_daemonize(pid_file);
2767}
2768
2769
2770static struct wpa_supplicant * wpa_supplicant_alloc(void)
2771{
2772 struct wpa_supplicant *wpa_s;
2773
2774 wpa_s = os_zalloc(sizeof(*wpa_s));
2775 if (wpa_s == NULL)
2776 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002777 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 wpa_s->scan_interval = 5;
2779 wpa_s->new_connection = 1;
2780 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002781 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002782
2783 return wpa_s;
2784}
2785
2786
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002787#ifdef CONFIG_HT_OVERRIDES
2788
2789static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2790 struct ieee80211_ht_capabilities *htcaps,
2791 struct ieee80211_ht_capabilities *htcaps_mask,
2792 const char *ht_mcs)
2793{
2794 /* parse ht_mcs into hex array */
2795 int i;
2796 const char *tmp = ht_mcs;
2797 char *end = NULL;
2798
2799 /* If ht_mcs is null, do not set anything */
2800 if (!ht_mcs)
2801 return 0;
2802
2803 /* This is what we are setting in the kernel */
2804 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2805
2806 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2807
2808 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2809 errno = 0;
2810 long v = strtol(tmp, &end, 16);
2811 if (errno == 0) {
2812 wpa_msg(wpa_s, MSG_DEBUG,
2813 "htcap value[%i]: %ld end: %p tmp: %p",
2814 i, v, end, tmp);
2815 if (end == tmp)
2816 break;
2817
2818 htcaps->supported_mcs_set[i] = v;
2819 tmp = end;
2820 } else {
2821 wpa_msg(wpa_s, MSG_ERROR,
2822 "Failed to parse ht-mcs: %s, error: %s\n",
2823 ht_mcs, strerror(errno));
2824 return -1;
2825 }
2826 }
2827
2828 /*
2829 * If we were able to parse any values, then set mask for the MCS set.
2830 */
2831 if (i) {
2832 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2833 IEEE80211_HT_MCS_MASK_LEN - 1);
2834 /* skip the 3 reserved bits */
2835 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2836 0x1f;
2837 }
2838
2839 return 0;
2840}
2841
2842
2843static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2844 struct ieee80211_ht_capabilities *htcaps,
2845 struct ieee80211_ht_capabilities *htcaps_mask,
2846 int disabled)
2847{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002848 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002849
2850 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2851
2852 if (disabled == -1)
2853 return 0;
2854
2855 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2856 htcaps_mask->ht_capabilities_info |= msk;
2857 if (disabled)
2858 htcaps->ht_capabilities_info &= msk;
2859 else
2860 htcaps->ht_capabilities_info |= msk;
2861
2862 return 0;
2863}
2864
2865
2866static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2867 struct ieee80211_ht_capabilities *htcaps,
2868 struct ieee80211_ht_capabilities *htcaps_mask,
2869 int factor)
2870{
2871 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2872
2873 if (factor == -1)
2874 return 0;
2875
2876 if (factor < 0 || factor > 3) {
2877 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2878 "Must be 0-3 or -1", factor);
2879 return -EINVAL;
2880 }
2881
2882 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2883 htcaps->a_mpdu_params &= ~0x3;
2884 htcaps->a_mpdu_params |= factor & 0x3;
2885
2886 return 0;
2887}
2888
2889
2890static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2891 struct ieee80211_ht_capabilities *htcaps,
2892 struct ieee80211_ht_capabilities *htcaps_mask,
2893 int density)
2894{
2895 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2896
2897 if (density == -1)
2898 return 0;
2899
2900 if (density < 0 || density > 7) {
2901 wpa_msg(wpa_s, MSG_ERROR,
2902 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2903 density);
2904 return -EINVAL;
2905 }
2906
2907 htcaps_mask->a_mpdu_params |= 0x1C;
2908 htcaps->a_mpdu_params &= ~(0x1C);
2909 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2910
2911 return 0;
2912}
2913
2914
2915static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2916 struct ieee80211_ht_capabilities *htcaps,
2917 struct ieee80211_ht_capabilities *htcaps_mask,
2918 int disabled)
2919{
2920 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002921 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2922 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002923
2924 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2925
2926 if (disabled)
2927 htcaps->ht_capabilities_info &= ~msk;
2928 else
2929 htcaps->ht_capabilities_info |= msk;
2930
2931 htcaps_mask->ht_capabilities_info |= msk;
2932
2933 return 0;
2934}
2935
2936
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002937static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2938 struct ieee80211_ht_capabilities *htcaps,
2939 struct ieee80211_ht_capabilities *htcaps_mask,
2940 int disabled)
2941{
2942 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002943 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2944 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002945
2946 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2947
2948 if (disabled)
2949 htcaps->ht_capabilities_info &= ~msk;
2950 else
2951 htcaps->ht_capabilities_info |= msk;
2952
2953 htcaps_mask->ht_capabilities_info |= msk;
2954
2955 return 0;
2956}
2957
2958
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07002959static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
2960 struct ieee80211_ht_capabilities *htcaps,
2961 struct ieee80211_ht_capabilities *htcaps_mask,
2962 int disabled)
2963{
2964 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002965 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07002966
2967 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
2968
2969 if (disabled)
2970 htcaps->ht_capabilities_info &= ~msk;
2971 else
2972 htcaps->ht_capabilities_info |= msk;
2973
2974 htcaps_mask->ht_capabilities_info |= msk;
2975
2976 return 0;
2977}
2978
2979
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002980void wpa_supplicant_apply_ht_overrides(
2981 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2982 struct wpa_driver_associate_params *params)
2983{
2984 struct ieee80211_ht_capabilities *htcaps;
2985 struct ieee80211_ht_capabilities *htcaps_mask;
2986
2987 if (!ssid)
2988 return;
2989
2990 params->disable_ht = ssid->disable_ht;
2991 if (!params->htcaps || !params->htcaps_mask)
2992 return;
2993
2994 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2995 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2996 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2997 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2998 ssid->disable_max_amsdu);
2999 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
3000 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
3001 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003002 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003003 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003004
3005 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003006 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003007 htcaps->ht_capabilities_info |= bit;
3008 htcaps_mask->ht_capabilities_info |= bit;
3009 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003010}
3011
3012#endif /* CONFIG_HT_OVERRIDES */
3013
3014
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003015#ifdef CONFIG_VHT_OVERRIDES
3016void wpa_supplicant_apply_vht_overrides(
3017 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3018 struct wpa_driver_associate_params *params)
3019{
3020 struct ieee80211_vht_capabilities *vhtcaps;
3021 struct ieee80211_vht_capabilities *vhtcaps_mask;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003022#ifdef CONFIG_HT_OVERRIDES
3023 int max_ampdu;
3024 const u32 max_ampdu_mask = VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
3025#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003026
3027 if (!ssid)
3028 return;
3029
3030 params->disable_vht = ssid->disable_vht;
3031
3032 vhtcaps = (void *) params->vhtcaps;
3033 vhtcaps_mask = (void *) params->vhtcaps_mask;
3034
3035 if (!vhtcaps || !vhtcaps_mask)
3036 return;
3037
3038 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3039 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3040
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003041#ifdef CONFIG_HT_OVERRIDES
3042 /* if max ampdu is <= 3, we have to make the HT cap the same */
3043 if (ssid->vht_capa_mask & max_ampdu_mask) {
3044 max_ampdu = (ssid->vht_capa & max_ampdu_mask) >>
3045 find_first_bit(max_ampdu_mask);
3046
3047 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3048 wpa_set_ampdu_factor(wpa_s,
3049 (void *) params->htcaps,
3050 (void *) params->htcaps_mask,
3051 max_ampdu);
3052 }
3053#endif /* CONFIG_HT_OVERRIDES */
3054
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003055#define OVERRIDE_MCS(i) \
3056 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3057 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3058 3 << 2 * (i - 1); \
3059 vhtcaps->vht_supported_mcs_set.tx_map |= \
3060 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3061 } \
3062 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3063 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3064 3 << 2 * (i - 1); \
3065 vhtcaps->vht_supported_mcs_set.rx_map |= \
3066 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3067 }
3068
3069 OVERRIDE_MCS(1);
3070 OVERRIDE_MCS(2);
3071 OVERRIDE_MCS(3);
3072 OVERRIDE_MCS(4);
3073 OVERRIDE_MCS(5);
3074 OVERRIDE_MCS(6);
3075 OVERRIDE_MCS(7);
3076 OVERRIDE_MCS(8);
3077}
3078#endif /* CONFIG_VHT_OVERRIDES */
3079
3080
Dmitry Shmidt04949592012-07-19 12:16:46 -07003081static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3082{
3083#ifdef PCSC_FUNCS
3084 size_t len;
3085
3086 if (!wpa_s->conf->pcsc_reader)
3087 return 0;
3088
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003089 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003090 if (!wpa_s->scard)
3091 return 1;
3092
3093 if (wpa_s->conf->pcsc_pin &&
3094 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3095 scard_deinit(wpa_s->scard);
3096 wpa_s->scard = NULL;
3097 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3098 return -1;
3099 }
3100
3101 len = sizeof(wpa_s->imsi) - 1;
3102 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3103 scard_deinit(wpa_s->scard);
3104 wpa_s->scard = NULL;
3105 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3106 return -1;
3107 }
3108 wpa_s->imsi[len] = '\0';
3109
3110 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3111
3112 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3113 wpa_s->imsi, wpa_s->mnc_len);
3114
3115 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3116 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3117#endif /* PCSC_FUNCS */
3118
3119 return 0;
3120}
3121
3122
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003123int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3124{
3125 char *val, *pos;
3126
3127 ext_password_deinit(wpa_s->ext_pw);
3128 wpa_s->ext_pw = NULL;
3129 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3130
3131 if (!wpa_s->conf->ext_password_backend)
3132 return 0;
3133
3134 val = os_strdup(wpa_s->conf->ext_password_backend);
3135 if (val == NULL)
3136 return -1;
3137 pos = os_strchr(val, ':');
3138 if (pos)
3139 *pos++ = '\0';
3140
3141 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3142
3143 wpa_s->ext_pw = ext_password_init(val, pos);
3144 os_free(val);
3145 if (wpa_s->ext_pw == NULL) {
3146 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3147 return -1;
3148 }
3149 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3150
3151 return 0;
3152}
3153
3154
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003155static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
3156 struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003157{
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003158 struct wowlan_triggers *triggers;
3159 int ret = 0;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003160
3161 if (!wpa_s->conf->wowlan_triggers)
3162 return 0;
3163
Dmitry Shmidt0207e232014-09-03 14:58:37 -07003164 triggers = wpa_get_wowlan_triggers(wpa_s->conf->wowlan_triggers, capa);
3165 if (triggers) {
3166 ret = wpa_drv_wowlan(wpa_s, triggers);
3167 os_free(triggers);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003168 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003169 return ret;
3170}
3171
3172
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003173static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3174 const char *rn)
3175{
3176 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3177 struct wpa_radio *radio;
3178
3179 while (rn && iface) {
3180 radio = iface->radio;
3181 if (radio && os_strcmp(rn, radio->name) == 0) {
3182 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3183 wpa_s->ifname, rn);
3184 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3185 return radio;
3186 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003187
3188 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003189 }
3190
3191 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3192 wpa_s->ifname, rn ? rn : "N/A");
3193 radio = os_zalloc(sizeof(*radio));
3194 if (radio == NULL)
3195 return NULL;
3196
3197 if (rn)
3198 os_strlcpy(radio->name, rn, sizeof(radio->name));
3199 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003200 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003201 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3202
3203 return radio;
3204}
3205
3206
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003207static void radio_work_free(struct wpa_radio_work *work)
3208{
3209 if (work->wpa_s->scan_work == work) {
3210 /* This should not really happen. */
3211 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3212 work->type, work, work->started);
3213 work->wpa_s->scan_work = NULL;
3214 }
3215
3216#ifdef CONFIG_P2P
3217 if (work->wpa_s->p2p_scan_work == work) {
3218 /* This should not really happen. */
3219 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3220 work->type, work, work->started);
3221 work->wpa_s->p2p_scan_work = NULL;
3222 }
3223#endif /* CONFIG_P2P */
3224
3225 dl_list_del(&work->list);
3226 os_free(work);
3227}
3228
3229
3230static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3231{
3232 struct wpa_radio *radio = eloop_ctx;
3233 struct wpa_radio_work *work;
3234 struct os_reltime now, diff;
3235 struct wpa_supplicant *wpa_s;
3236
3237 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3238 if (work == NULL)
3239 return;
3240
3241 if (work->started)
3242 return; /* already started and still in progress */
3243
3244 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3245 radio_list);
3246 if (wpa_s && wpa_s->external_scan_running) {
3247 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3248 return;
3249 }
3250
3251 os_get_reltime(&now);
3252 os_reltime_sub(&now, &work->time, &diff);
3253 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3254 work->type, work, diff.sec, diff.usec);
3255 work->started = 1;
3256 work->time = now;
3257 work->cb(work, 0);
3258}
3259
3260
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003261/*
3262 * This function removes both started and pending radio works running on
3263 * the provided interface's radio.
3264 * Prior to the removal of the radio work, its callback (cb) is called with
3265 * deinit set to be 1. Each work's callback is responsible for clearing its
3266 * internal data and restoring to a correct state.
3267 * @wpa_s: wpa_supplicant data
3268 * @type: type of works to be removed
3269 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3270 * this interface's works.
3271 */
3272void radio_remove_works(struct wpa_supplicant *wpa_s,
3273 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003274{
3275 struct wpa_radio_work *work, *tmp;
3276 struct wpa_radio *radio = wpa_s->radio;
3277
3278 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3279 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003280 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003281 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003282
3283 /* skip other ifaces' works */
3284 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003285 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003286
3287 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3288 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003289 work->cb(work, 1);
3290 radio_work_free(work);
3291 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003292
3293 /* in case we removed the started work */
3294 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003295}
3296
3297
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003298static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3299{
3300 struct wpa_radio *radio = wpa_s->radio;
3301
3302 if (!radio)
3303 return;
3304
3305 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3306 wpa_s->ifname, radio->name);
3307 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003308 radio_remove_works(wpa_s, NULL, 0);
3309 wpa_s->radio = NULL;
3310 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003311 return; /* Interfaces remain for this radio */
3312
3313 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003314 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003315 os_free(radio);
3316}
3317
3318
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003319void radio_work_check_next(struct wpa_supplicant *wpa_s)
3320{
3321 struct wpa_radio *radio = wpa_s->radio;
3322
3323 if (dl_list_empty(&radio->work))
3324 return;
3325 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3326 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3327}
3328
3329
3330/**
3331 * radio_add_work - Add a radio work item
3332 * @wpa_s: Pointer to wpa_supplicant data
3333 * @freq: Frequency of the offchannel operation in MHz or 0
3334 * @type: Unique identifier for each type of work
3335 * @next: Force as the next work to be executed
3336 * @cb: Callback function for indicating when radio is available
3337 * @ctx: Context pointer for the work (work->ctx in cb())
3338 * Returns: 0 on success, -1 on failure
3339 *
3340 * This function is used to request time for an operation that requires
3341 * exclusive radio control. Once the radio is available, the registered callback
3342 * function will be called. radio_work_done() must be called once the exclusive
3343 * radio operation has been completed, so that the radio is freed for other
3344 * operations. The special case of deinit=1 is used to free the context data
3345 * during interface removal. That does not allow the callback function to start
3346 * the radio operation, i.e., it must free any resources allocated for the radio
3347 * work and return.
3348 *
3349 * The @freq parameter can be used to indicate a single channel on which the
3350 * offchannel operation will occur. This may allow multiple radio work
3351 * operations to be performed in parallel if they apply for the same channel.
3352 * Setting this to 0 indicates that the work item may use multiple channels or
3353 * requires exclusive control of the radio.
3354 */
3355int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3356 const char *type, int next,
3357 void (*cb)(struct wpa_radio_work *work, int deinit),
3358 void *ctx)
3359{
3360 struct wpa_radio_work *work;
3361 int was_empty;
3362
3363 work = os_zalloc(sizeof(*work));
3364 if (work == NULL)
3365 return -1;
3366 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3367 os_get_reltime(&work->time);
3368 work->freq = freq;
3369 work->type = type;
3370 work->wpa_s = wpa_s;
3371 work->cb = cb;
3372 work->ctx = ctx;
3373
3374 was_empty = dl_list_empty(&wpa_s->radio->work);
3375 if (next)
3376 dl_list_add(&wpa_s->radio->work, &work->list);
3377 else
3378 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3379 if (was_empty) {
3380 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3381 radio_work_check_next(wpa_s);
3382 }
3383
3384 return 0;
3385}
3386
3387
3388/**
3389 * radio_work_done - Indicate that a radio work item has been completed
3390 * @work: Completed work
3391 *
3392 * This function is called once the callback function registered with
3393 * radio_add_work() has completed its work.
3394 */
3395void radio_work_done(struct wpa_radio_work *work)
3396{
3397 struct wpa_supplicant *wpa_s = work->wpa_s;
3398 struct os_reltime now, diff;
3399 unsigned int started = work->started;
3400
3401 os_get_reltime(&now);
3402 os_reltime_sub(&now, &work->time, &diff);
3403 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3404 work->type, work, started ? "done" : "canceled",
3405 diff.sec, diff.usec);
3406 radio_work_free(work);
3407 if (started)
3408 radio_work_check_next(wpa_s);
3409}
3410
3411
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003412int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
3413{
3414 struct wpa_radio_work *work;
3415 struct wpa_radio *radio = wpa_s->radio;
3416
3417 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3418 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
3419 return 1;
3420 }
3421
3422 return 0;
3423}
3424
3425
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003426static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3427 struct wpa_interface *iface)
3428{
3429 const char *ifname, *driver, *rn;
3430
3431 driver = iface->driver;
3432next_driver:
3433 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3434 return -1;
3435
3436 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3437 if (wpa_s->drv_priv == NULL) {
3438 const char *pos;
3439 pos = driver ? os_strchr(driver, ',') : NULL;
3440 if (pos) {
3441 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3442 "driver interface - try next driver wrapper");
3443 driver = pos + 1;
3444 goto next_driver;
3445 }
3446 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3447 "interface");
3448 return -1;
3449 }
3450 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3451 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3452 "driver_param '%s'", wpa_s->conf->driver_param);
3453 return -1;
3454 }
3455
3456 ifname = wpa_drv_get_ifname(wpa_s);
3457 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3458 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3459 "interface name with '%s'", ifname);
3460 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3461 }
3462
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003463 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003464 if (rn && rn[0] == '\0')
3465 rn = NULL;
3466
3467 wpa_s->radio = radio_add_interface(wpa_s, rn);
3468 if (wpa_s->radio == NULL)
3469 return -1;
3470
3471 return 0;
3472}
3473
3474
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003475static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3476 struct wpa_interface *iface)
3477{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003478 struct wpa_driver_capa capa;
3479
3480 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3481 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3482 iface->confname ? iface->confname : "N/A",
3483 iface->driver ? iface->driver : "default",
3484 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3485 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3486
3487 if (iface->confname) {
3488#ifdef CONFIG_BACKEND_FILE
3489 wpa_s->confname = os_rel2abs_path(iface->confname);
3490 if (wpa_s->confname == NULL) {
3491 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3492 "for configuration file '%s'.",
3493 iface->confname);
3494 return -1;
3495 }
3496 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3497 iface->confname, wpa_s->confname);
3498#else /* CONFIG_BACKEND_FILE */
3499 wpa_s->confname = os_strdup(iface->confname);
3500#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003501 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003502 if (wpa_s->conf == NULL) {
3503 wpa_printf(MSG_ERROR, "Failed to read or parse "
3504 "configuration '%s'.", wpa_s->confname);
3505 return -1;
3506 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003507 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3508 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003509
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003510#ifdef CONFIG_P2P
3511 wpa_s->conf_p2p_dev = os_rel2abs_path(iface->conf_p2p_dev);
3512 wpa_config_read(wpa_s->conf_p2p_dev, wpa_s->conf);
3513#endif /* CONFIG_P2P */
3514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003515 /*
3516 * Override ctrl_interface and driver_param if set on command
3517 * line.
3518 */
3519 if (iface->ctrl_interface) {
3520 os_free(wpa_s->conf->ctrl_interface);
3521 wpa_s->conf->ctrl_interface =
3522 os_strdup(iface->ctrl_interface);
3523 }
3524
3525 if (iface->driver_param) {
3526 os_free(wpa_s->conf->driver_param);
3527 wpa_s->conf->driver_param =
3528 os_strdup(iface->driver_param);
3529 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003530
3531 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3532 os_free(wpa_s->conf->ctrl_interface);
3533 wpa_s->conf->ctrl_interface = NULL;
3534 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003535 } else
3536 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3537 iface->driver_param);
3538
3539 if (wpa_s->conf == NULL) {
3540 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3541 return -1;
3542 }
3543
3544 if (iface->ifname == NULL) {
3545 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3546 return -1;
3547 }
3548 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3549 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3550 iface->ifname);
3551 return -1;
3552 }
3553 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3554
3555 if (iface->bridge_ifname) {
3556 if (os_strlen(iface->bridge_ifname) >=
3557 sizeof(wpa_s->bridge_ifname)) {
3558 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3559 "name '%s'.", iface->bridge_ifname);
3560 return -1;
3561 }
3562 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3563 sizeof(wpa_s->bridge_ifname));
3564 }
3565
3566 /* RSNA Supplicant Key Management - INITIALIZE */
3567 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3568 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3569
3570 /* Initialize driver interface and register driver event handler before
3571 * L2 receive handler so that association events are processed before
3572 * EAPOL-Key packets if both become available for the same select()
3573 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003574 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003575 return -1;
3576
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003577 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3578 return -1;
3579
3580 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3581 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3582 NULL);
3583 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3584
3585 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3586 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3587 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3588 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3589 "dot11RSNAConfigPMKLifetime");
3590 return -1;
3591 }
3592
3593 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3594 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3595 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3596 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3597 "dot11RSNAConfigPMKReauthThreshold");
3598 return -1;
3599 }
3600
3601 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3602 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3603 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3604 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3605 "dot11RSNAConfigSATimeout");
3606 return -1;
3607 }
3608
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003609 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3610 &wpa_s->hw.num_modes,
3611 &wpa_s->hw.flags);
3612
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003613 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003614 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003615 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003616 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003617 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003618 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003619 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3620 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3621 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003622 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3623 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003624 wpa_s->extended_capa = capa.extended_capa;
3625 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3626 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003627 wpa_s->num_multichan_concurrent =
3628 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629 }
3630 if (wpa_s->max_remain_on_chan == 0)
3631 wpa_s->max_remain_on_chan = 1000;
3632
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003633 /*
3634 * Only take p2p_mgmt parameters when P2P Device is supported.
3635 * Doing it here as it determines whether l2_packet_init() will be done
3636 * during wpa_supplicant_driver_init().
3637 */
3638 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3639 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3640 else
3641 iface->p2p_mgmt = 1;
3642
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003643 if (wpa_s->num_multichan_concurrent == 0)
3644 wpa_s->num_multichan_concurrent = 1;
3645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646 if (wpa_supplicant_driver_init(wpa_s) < 0)
3647 return -1;
3648
3649#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003650 if ((!iface->p2p_mgmt ||
3651 !(wpa_s->drv_flags &
3652 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3653 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003654 return -1;
3655#endif /* CONFIG_TDLS */
3656
3657 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3658 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3659 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3660 return -1;
3661 }
3662
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003663 if (wpas_wps_init(wpa_s))
3664 return -1;
3665
3666 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3667 return -1;
3668 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3669
3670 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3671 if (wpa_s->ctrl_iface == NULL) {
3672 wpa_printf(MSG_ERROR,
3673 "Failed to initialize control interface '%s'.\n"
3674 "You may have another wpa_supplicant process "
3675 "already running or the file was\n"
3676 "left by an unclean termination of wpa_supplicant "
3677 "in which case you will need\n"
3678 "to manually remove this file before starting "
3679 "wpa_supplicant again.\n",
3680 wpa_s->conf->ctrl_interface);
3681 return -1;
3682 }
3683
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003684 wpa_s->gas = gas_query_init(wpa_s);
3685 if (wpa_s->gas == NULL) {
3686 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3687 return -1;
3688 }
3689
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003690 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003691 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3692 return -1;
3693 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003694
3695 if (wpa_bss_init(wpa_s) < 0)
3696 return -1;
3697
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003698 /*
3699 * Set Wake-on-WLAN triggers, if configured.
3700 * Note: We don't restore/remove the triggers on shutdown (it doesn't
3701 * have effect anyway when the interface is down).
3702 */
3703 if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
3704 return -1;
3705
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003706#ifdef CONFIG_EAP_PROXY
3707{
3708 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003709 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3710 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003711 if (wpa_s->mnc_len > 0) {
3712 wpa_s->imsi[len] = '\0';
3713 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3714 wpa_s->imsi, wpa_s->mnc_len);
3715 } else {
3716 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3717 }
3718}
3719#endif /* CONFIG_EAP_PROXY */
3720
Dmitry Shmidt04949592012-07-19 12:16:46 -07003721 if (pcsc_reader_init(wpa_s) < 0)
3722 return -1;
3723
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003724 if (wpas_init_ext_pw(wpa_s) < 0)
3725 return -1;
3726
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003727 return 0;
3728}
3729
3730
3731static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003732 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003733{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003734 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003735 if (wpa_s->drv_priv) {
3736 wpa_supplicant_deauthenticate(wpa_s,
3737 WLAN_REASON_DEAUTH_LEAVING);
3738
3739 wpa_drv_set_countermeasures(wpa_s, 0);
3740 wpa_clear_keys(wpa_s, NULL);
3741 }
3742
3743 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003744 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003745
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003746 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003747 radio_remove_interface(wpa_s);
3748
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003749 if (wpa_s->drv_priv)
3750 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003751
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003752 if (notify)
3753 wpas_notify_iface_removed(wpa_s);
3754
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003755 if (terminate)
3756 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003757
3758 if (wpa_s->ctrl_iface) {
3759 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3760 wpa_s->ctrl_iface = NULL;
3761 }
3762
3763 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003764 wpa_config_free(wpa_s->conf);
3765 wpa_s->conf = NULL;
3766 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003767
3768 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003769}
3770
3771
3772/**
3773 * wpa_supplicant_add_iface - Add a new network interface
3774 * @global: Pointer to global data from wpa_supplicant_init()
3775 * @iface: Interface configuration options
3776 * Returns: Pointer to the created interface or %NULL on failure
3777 *
3778 * This function is used to add new network interfaces for %wpa_supplicant.
3779 * This can be called before wpa_supplicant_run() to add interfaces before the
3780 * main event loop has been started. In addition, new interfaces can be added
3781 * dynamically while %wpa_supplicant is already running. This could happen,
3782 * e.g., when a hotplug network adapter is inserted.
3783 */
3784struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3785 struct wpa_interface *iface)
3786{
3787 struct wpa_supplicant *wpa_s;
3788 struct wpa_interface t_iface;
3789 struct wpa_ssid *ssid;
3790
3791 if (global == NULL || iface == NULL)
3792 return NULL;
3793
3794 wpa_s = wpa_supplicant_alloc();
3795 if (wpa_s == NULL)
3796 return NULL;
3797
3798 wpa_s->global = global;
3799
3800 t_iface = *iface;
3801 if (global->params.override_driver) {
3802 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3803 "('%s' -> '%s')",
3804 iface->driver, global->params.override_driver);
3805 t_iface.driver = global->params.override_driver;
3806 }
3807 if (global->params.override_ctrl_interface) {
3808 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3809 "ctrl_interface ('%s' -> '%s')",
3810 iface->ctrl_interface,
3811 global->params.override_ctrl_interface);
3812 t_iface.ctrl_interface =
3813 global->params.override_ctrl_interface;
3814 }
3815 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3816 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3817 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003818 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003819 return NULL;
3820 }
3821
3822 /* Notify the control interfaces about new iface */
3823 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003824 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 return NULL;
3826 }
3827
3828 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3829 wpas_notify_network_added(wpa_s, ssid);
3830
3831 wpa_s->next = global->ifaces;
3832 global->ifaces = wpa_s;
3833
3834 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003835 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003836
3837 return wpa_s;
3838}
3839
3840
3841/**
3842 * wpa_supplicant_remove_iface - Remove a network interface
3843 * @global: Pointer to global data from wpa_supplicant_init()
3844 * @wpa_s: Pointer to the network interface to be removed
3845 * Returns: 0 if interface was removed, -1 if interface was not found
3846 *
3847 * This function can be used to dynamically remove network interfaces from
3848 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3849 * addition, this function is used to remove all remaining interfaces when
3850 * %wpa_supplicant is terminated.
3851 */
3852int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003853 struct wpa_supplicant *wpa_s,
3854 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003855{
3856 struct wpa_supplicant *prev;
3857
3858 /* Remove interface from the global list of interfaces */
3859 prev = global->ifaces;
3860 if (prev == wpa_s) {
3861 global->ifaces = wpa_s->next;
3862 } else {
3863 while (prev && prev->next != wpa_s)
3864 prev = prev->next;
3865 if (prev == NULL)
3866 return -1;
3867 prev->next = wpa_s->next;
3868 }
3869
3870 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3871
3872 if (global->p2p_group_formation == wpa_s)
3873 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003874 if (global->p2p_invite_group == wpa_s)
3875 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003876 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003877
3878 return 0;
3879}
3880
3881
3882/**
3883 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3884 * @wpa_s: Pointer to the network interface
3885 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3886 */
3887const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3888{
3889 const char *eapol_method;
3890
3891 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3892 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3893 return "NO-EAP";
3894 }
3895
3896 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3897 if (eapol_method == NULL)
3898 return "UNKNOWN-EAP";
3899
3900 return eapol_method;
3901}
3902
3903
3904/**
3905 * wpa_supplicant_get_iface - Get a new network interface
3906 * @global: Pointer to global data from wpa_supplicant_init()
3907 * @ifname: Interface name
3908 * Returns: Pointer to the interface or %NULL if not found
3909 */
3910struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3911 const char *ifname)
3912{
3913 struct wpa_supplicant *wpa_s;
3914
3915 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3916 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3917 return wpa_s;
3918 }
3919 return NULL;
3920}
3921
3922
3923#ifndef CONFIG_NO_WPA_MSG
3924static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3925{
3926 struct wpa_supplicant *wpa_s = ctx;
3927 if (wpa_s == NULL)
3928 return NULL;
3929 return wpa_s->ifname;
3930}
3931#endif /* CONFIG_NO_WPA_MSG */
3932
3933
3934/**
3935 * wpa_supplicant_init - Initialize %wpa_supplicant
3936 * @params: Parameters for %wpa_supplicant
3937 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3938 *
3939 * This function is used to initialize %wpa_supplicant. After successful
3940 * initialization, the returned data pointer can be used to add and remove
3941 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3942 */
3943struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3944{
3945 struct wpa_global *global;
3946 int ret, i;
3947
3948 if (params == NULL)
3949 return NULL;
3950
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003951#ifdef CONFIG_DRIVER_NDIS
3952 {
3953 void driver_ndis_init_ops(void);
3954 driver_ndis_init_ops();
3955 }
3956#endif /* CONFIG_DRIVER_NDIS */
3957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958#ifndef CONFIG_NO_WPA_MSG
3959 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3960#endif /* CONFIG_NO_WPA_MSG */
3961
3962 wpa_debug_open_file(params->wpa_debug_file_path);
3963 if (params->wpa_debug_syslog)
3964 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003965 if (params->wpa_debug_tracing) {
3966 ret = wpa_debug_open_linux_tracing();
3967 if (ret) {
3968 wpa_printf(MSG_ERROR,
3969 "Failed to enable trace logging");
3970 return NULL;
3971 }
3972 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003973
3974 ret = eap_register_methods();
3975 if (ret) {
3976 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3977 if (ret == -2)
3978 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3979 "the same EAP type.");
3980 return NULL;
3981 }
3982
3983 global = os_zalloc(sizeof(*global));
3984 if (global == NULL)
3985 return NULL;
3986 dl_list_init(&global->p2p_srv_bonjour);
3987 dl_list_init(&global->p2p_srv_upnp);
3988 global->params.daemonize = params->daemonize;
3989 global->params.wait_for_monitor = params->wait_for_monitor;
3990 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3991 if (params->pid_file)
3992 global->params.pid_file = os_strdup(params->pid_file);
3993 if (params->ctrl_interface)
3994 global->params.ctrl_interface =
3995 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003996 if (params->ctrl_interface_group)
3997 global->params.ctrl_interface_group =
3998 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003999 if (params->override_driver)
4000 global->params.override_driver =
4001 os_strdup(params->override_driver);
4002 if (params->override_ctrl_interface)
4003 global->params.override_ctrl_interface =
4004 os_strdup(params->override_ctrl_interface);
4005 wpa_debug_level = global->params.wpa_debug_level =
4006 params->wpa_debug_level;
4007 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4008 params->wpa_debug_show_keys;
4009 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4010 params->wpa_debug_timestamp;
4011
4012 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4013
4014 if (eloop_init()) {
4015 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4016 wpa_supplicant_deinit(global);
4017 return NULL;
4018 }
4019
Jouni Malinen75ecf522011-06-27 15:19:46 -07004020 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004021
4022 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4023 if (global->ctrl_iface == NULL) {
4024 wpa_supplicant_deinit(global);
4025 return NULL;
4026 }
4027
4028 if (wpas_notify_supplicant_initialized(global)) {
4029 wpa_supplicant_deinit(global);
4030 return NULL;
4031 }
4032
4033 for (i = 0; wpa_drivers[i]; i++)
4034 global->drv_count++;
4035 if (global->drv_count == 0) {
4036 wpa_printf(MSG_ERROR, "No drivers enabled");
4037 wpa_supplicant_deinit(global);
4038 return NULL;
4039 }
4040 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
4041 if (global->drv_priv == NULL) {
4042 wpa_supplicant_deinit(global);
4043 return NULL;
4044 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004045
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004046#ifdef CONFIG_WIFI_DISPLAY
4047 if (wifi_display_init(global) < 0) {
4048 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4049 wpa_supplicant_deinit(global);
4050 return NULL;
4051 }
4052#endif /* CONFIG_WIFI_DISPLAY */
4053
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004054 return global;
4055}
4056
4057
4058/**
4059 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4060 * @global: Pointer to global data from wpa_supplicant_init()
4061 * Returns: 0 after successful event loop run, -1 on failure
4062 *
4063 * This function starts the main event loop and continues running as long as
4064 * there are any remaining events. In most cases, this function is running as
4065 * long as the %wpa_supplicant process in still in use.
4066 */
4067int wpa_supplicant_run(struct wpa_global *global)
4068{
4069 struct wpa_supplicant *wpa_s;
4070
4071 if (global->params.daemonize &&
4072 wpa_supplicant_daemon(global->params.pid_file))
4073 return -1;
4074
4075 if (global->params.wait_for_monitor) {
4076 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4077 if (wpa_s->ctrl_iface)
4078 wpa_supplicant_ctrl_iface_wait(
4079 wpa_s->ctrl_iface);
4080 }
4081
4082 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4083 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4084
4085 eloop_run();
4086
4087 return 0;
4088}
4089
4090
4091/**
4092 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4093 * @global: Pointer to global data from wpa_supplicant_init()
4094 *
4095 * This function is called to deinitialize %wpa_supplicant and to free all
4096 * allocated resources. Remaining network interfaces will also be removed.
4097 */
4098void wpa_supplicant_deinit(struct wpa_global *global)
4099{
4100 int i;
4101
4102 if (global == NULL)
4103 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004104
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004105#ifdef CONFIG_WIFI_DISPLAY
4106 wifi_display_deinit(global);
4107#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004108
4109 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004110 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004111
4112 if (global->ctrl_iface)
4113 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4114
4115 wpas_notify_supplicant_deinitialized(global);
4116
4117 eap_peer_unregister_methods();
4118#ifdef CONFIG_AP
4119 eap_server_unregister_methods();
4120#endif /* CONFIG_AP */
4121
4122 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4123 if (!global->drv_priv[i])
4124 continue;
4125 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4126 }
4127 os_free(global->drv_priv);
4128
4129 random_deinit();
4130
4131 eloop_destroy();
4132
4133 if (global->params.pid_file) {
4134 os_daemonize_terminate(global->params.pid_file);
4135 os_free(global->params.pid_file);
4136 }
4137 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004138 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004139 os_free(global->params.override_driver);
4140 os_free(global->params.override_ctrl_interface);
4141
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004142 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004143 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004144 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004145
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004146 os_free(global);
4147 wpa_debug_close_syslog();
4148 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004149 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004150}
4151
4152
4153void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4154{
4155 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4156 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4157 char country[3];
4158 country[0] = wpa_s->conf->country[0];
4159 country[1] = wpa_s->conf->country[1];
4160 country[2] = '\0';
4161 if (wpa_drv_set_country(wpa_s, country) < 0) {
4162 wpa_printf(MSG_ERROR, "Failed to set country code "
4163 "'%s'", country);
4164 }
4165 }
4166
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004167 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4168 wpas_init_ext_pw(wpa_s);
4169
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004170#ifdef CONFIG_WPS
4171 wpas_wps_update_config(wpa_s);
4172#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004173 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004174 wpa_s->conf->changed_parameters = 0;
4175}
4176
4177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004178static void add_freq(int *freqs, int *num_freqs, int freq)
4179{
4180 int i;
4181
4182 for (i = 0; i < *num_freqs; i++) {
4183 if (freqs[i] == freq)
4184 return;
4185 }
4186
4187 freqs[*num_freqs] = freq;
4188 (*num_freqs)++;
4189}
4190
4191
4192static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4193{
4194 struct wpa_bss *bss, *cbss;
4195 const int max_freqs = 10;
4196 int *freqs;
4197 int num_freqs = 0;
4198
4199 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
4200 if (freqs == NULL)
4201 return NULL;
4202
4203 cbss = wpa_s->current_bss;
4204
4205 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4206 if (bss == cbss)
4207 continue;
4208 if (bss->ssid_len == cbss->ssid_len &&
4209 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4210 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4211 add_freq(freqs, &num_freqs, bss->freq);
4212 if (num_freqs == max_freqs)
4213 break;
4214 }
4215 }
4216
4217 if (num_freqs == 0) {
4218 os_free(freqs);
4219 freqs = NULL;
4220 }
4221
4222 return freqs;
4223}
4224
4225
4226void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4227{
4228 int timeout;
4229 int count;
4230 int *freqs = NULL;
4231
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004232 wpas_connect_work_done(wpa_s);
4233
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004234 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004235 * Remove possible authentication timeout since the connection failed.
4236 */
4237 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4238
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004239 if (wpa_s->disconnected) {
4240 /*
4241 * There is no point in blacklisting the AP if this event is
4242 * generated based on local request to disconnect.
4243 */
4244 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4245 "indication since interface has been put into "
4246 "disconnected state");
4247 return;
4248 }
4249
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004250 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004251 * Add the failed BSSID into the blacklist and speed up next scan
4252 * attempt if there could be other APs that could accept association.
4253 * The current blacklist count indicates how many times we have tried
4254 * connecting to this AP and multiple attempts mean that other APs are
4255 * either not available or has already been tried, so that we can start
4256 * increasing the delay here to avoid constant scanning.
4257 */
4258 count = wpa_blacklist_add(wpa_s, bssid);
4259 if (count == 1 && wpa_s->current_bss) {
4260 /*
4261 * This BSS was not in the blacklist before. If there is
4262 * another BSS available for the same ESS, we should try that
4263 * next. Otherwise, we may as well try this one once more
4264 * before allowing other, likely worse, ESSes to be considered.
4265 */
4266 freqs = get_bss_freqs_in_ess(wpa_s);
4267 if (freqs) {
4268 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4269 "has been seen; try it next");
4270 wpa_blacklist_add(wpa_s, bssid);
4271 /*
4272 * On the next scan, go through only the known channels
4273 * used in this ESS based on previous scans to speed up
4274 * common load balancing use case.
4275 */
4276 os_free(wpa_s->next_scan_freqs);
4277 wpa_s->next_scan_freqs = freqs;
4278 }
4279 }
4280
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004281 /*
4282 * Add previous failure count in case the temporary blacklist was
4283 * cleared due to no other BSSes being available.
4284 */
4285 count += wpa_s->extra_blacklist_count;
4286
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004287 if (count > 3 && wpa_s->current_ssid) {
4288 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4289 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004290 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004291 }
4292
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004293 switch (count) {
4294 case 1:
4295 timeout = 100;
4296 break;
4297 case 2:
4298 timeout = 500;
4299 break;
4300 case 3:
4301 timeout = 1000;
4302 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004303 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004304 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004305 break;
4306 default:
4307 timeout = 10000;
4308 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004309 }
4310
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004311 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4312 "ms", count, timeout);
4313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004314 /*
4315 * TODO: if more than one possible AP is available in scan results,
4316 * could try the other ones before requesting a new scan.
4317 */
4318 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4319 1000 * (timeout % 1000));
4320}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004321
4322
4323int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4324{
4325 return wpa_s->conf->ap_scan == 2 ||
4326 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4327}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004328
Dmitry Shmidt04949592012-07-19 12:16:46 -07004329
4330#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4331int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4332 struct wpa_ssid *ssid,
4333 const char *field,
4334 const char *value)
4335{
4336#ifdef IEEE8021X_EAPOL
4337 struct eap_peer_config *eap = &ssid->eap;
4338
4339 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4340 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4341 (const u8 *) value, os_strlen(value));
4342
4343 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4344 case WPA_CTRL_REQ_EAP_IDENTITY:
4345 os_free(eap->identity);
4346 eap->identity = (u8 *) os_strdup(value);
4347 eap->identity_len = os_strlen(value);
4348 eap->pending_req_identity = 0;
4349 if (ssid == wpa_s->current_ssid)
4350 wpa_s->reassociate = 1;
4351 break;
4352 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004353 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004354 eap->password = (u8 *) os_strdup(value);
4355 eap->password_len = os_strlen(value);
4356 eap->pending_req_password = 0;
4357 if (ssid == wpa_s->current_ssid)
4358 wpa_s->reassociate = 1;
4359 break;
4360 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004361 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004362 eap->new_password = (u8 *) os_strdup(value);
4363 eap->new_password_len = os_strlen(value);
4364 eap->pending_req_new_password = 0;
4365 if (ssid == wpa_s->current_ssid)
4366 wpa_s->reassociate = 1;
4367 break;
4368 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004369 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004370 eap->pin = os_strdup(value);
4371 eap->pending_req_pin = 0;
4372 if (ssid == wpa_s->current_ssid)
4373 wpa_s->reassociate = 1;
4374 break;
4375 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004376 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004377 eap->otp = (u8 *) os_strdup(value);
4378 eap->otp_len = os_strlen(value);
4379 os_free(eap->pending_req_otp);
4380 eap->pending_req_otp = NULL;
4381 eap->pending_req_otp_len = 0;
4382 break;
4383 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004384 str_clear_free(eap->private_key_passwd);
4385 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004386 eap->pending_req_passphrase = 0;
4387 if (ssid == wpa_s->current_ssid)
4388 wpa_s->reassociate = 1;
4389 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004390 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004391 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004392 eap->external_sim_resp = os_strdup(value);
4393 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004394 default:
4395 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4396 return -1;
4397 }
4398
4399 return 0;
4400#else /* IEEE8021X_EAPOL */
4401 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4402 return -1;
4403#endif /* IEEE8021X_EAPOL */
4404}
4405#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4406
4407
4408int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4409{
4410 int i;
4411 unsigned int drv_enc;
4412
4413 if (ssid == NULL)
4414 return 1;
4415
4416 if (ssid->disabled)
4417 return 1;
4418
4419 if (wpa_s && wpa_s->drv_capa_known)
4420 drv_enc = wpa_s->drv_enc;
4421 else
4422 drv_enc = (unsigned int) -1;
4423
4424 for (i = 0; i < NUM_WEP_KEYS; i++) {
4425 size_t len = ssid->wep_key_len[i];
4426 if (len == 0)
4427 continue;
4428 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4429 continue;
4430 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4431 continue;
4432 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4433 continue;
4434 return 1; /* invalid WEP key */
4435 }
4436
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004437 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07004438 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004439 return 1;
4440
Dmitry Shmidt04949592012-07-19 12:16:46 -07004441 return 0;
4442}
4443
4444
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004445int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004446{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004447 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004448 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004449 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004450 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004451 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004452}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004453
4454
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004455void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004456{
4457 struct wpa_ssid *ssid = wpa_s->current_ssid;
4458 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004459 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004460
4461 if (ssid == NULL) {
4462 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4463 "SSID block");
4464 return;
4465 }
4466
4467 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4468 return;
4469
4470 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004471
4472#ifdef CONFIG_P2P
4473 if (ssid->p2p_group &&
4474 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4475 /*
4476 * Skip the wait time since there is a short timeout on the
4477 * connection to a P2P group.
4478 */
4479 return;
4480 }
4481#endif /* CONFIG_P2P */
4482
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004483 if (ssid->auth_failures > 50)
4484 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004485 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004486 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004487 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004488 dur = 90;
4489 else if (ssid->auth_failures > 3)
4490 dur = 60;
4491 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004492 dur = 30;
4493 else if (ssid->auth_failures > 1)
4494 dur = 20;
4495 else
4496 dur = 10;
4497
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004498 if (ssid->auth_failures > 1 &&
4499 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
4500 dur += os_random() % (ssid->auth_failures * 10);
4501
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004502 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004503 if (now.sec + dur <= ssid->disabled_until.sec)
4504 return;
4505
4506 ssid->disabled_until.sec = now.sec + dur;
4507
4508 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004509 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004510 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004511 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004512}
4513
4514
4515void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4516 struct wpa_ssid *ssid, int clear_failures)
4517{
4518 if (ssid == NULL)
4519 return;
4520
4521 if (ssid->disabled_until.sec) {
4522 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4523 "id=%d ssid=\"%s\"",
4524 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4525 }
4526 ssid->disabled_until.sec = 0;
4527 ssid->disabled_until.usec = 0;
4528 if (clear_failures)
4529 ssid->auth_failures = 0;
4530}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004531
4532
4533int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4534{
4535 size_t i;
4536
4537 if (wpa_s->disallow_aps_bssid == NULL)
4538 return 0;
4539
4540 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4541 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4542 bssid, ETH_ALEN) == 0)
4543 return 1;
4544 }
4545
4546 return 0;
4547}
4548
4549
4550int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4551 size_t ssid_len)
4552{
4553 size_t i;
4554
4555 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4556 return 0;
4557
4558 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4559 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4560 if (ssid_len == s->ssid_len &&
4561 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4562 return 1;
4563 }
4564
4565 return 0;
4566}
4567
4568
4569/**
4570 * wpas_request_connection - Request a new connection
4571 * @wpa_s: Pointer to the network interface
4572 *
4573 * This function is used to request a new connection to be found. It will mark
4574 * the interface to allow reassociation and request a new scan to find a
4575 * suitable network to connect to.
4576 */
4577void wpas_request_connection(struct wpa_supplicant *wpa_s)
4578{
4579 wpa_s->normal_scans = 0;
4580 wpa_supplicant_reinit_autoscan(wpa_s);
4581 wpa_s->extra_blacklist_count = 0;
4582 wpa_s->disconnected = 0;
4583 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004584
4585 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4586 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004587}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004588
4589
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004590void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
4591 struct wpa_used_freq_data *freqs_data,
4592 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004593{
4594 unsigned int i;
4595
4596 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4597 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004598 for (i = 0; i < len; i++) {
4599 struct wpa_used_freq_data *cur = &freqs_data[i];
4600 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
4601 i, cur->freq, cur->flags);
4602 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004603}
4604
4605
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004606/*
4607 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004608 * are using the same radio as the current interface, and in addition, get
4609 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004610 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004611int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
4612 struct wpa_used_freq_data *freqs_data,
4613 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004614{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004615 struct wpa_supplicant *ifs;
4616 u8 bssid[ETH_ALEN];
4617 int freq;
4618 unsigned int idx = 0, i;
4619
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004620 wpa_dbg(wpa_s, MSG_DEBUG,
4621 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004622 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004623
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004624 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4625 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004626 if (idx == len)
4627 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004628
4629 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4630 continue;
4631
4632 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4633 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4634 freq = ifs->current_ssid->frequency;
4635 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4636 freq = ifs->assoc_freq;
4637 else
4638 continue;
4639
4640 /* Hold only distinct freqs */
4641 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004642 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004643 break;
4644
4645 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004646 freqs_data[idx++].freq = freq;
4647
4648 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
4649 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
4650 WPA_FREQ_USED_BY_P2P_CLIENT :
4651 WPA_FREQ_USED_BY_INFRA_STATION;
4652 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004653 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004654
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004655 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004656 return idx;
4657}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004658
4659
4660/*
4661 * Find the operating frequencies of any of the virtual interfaces that
4662 * are using the same radio as the current interface.
4663 */
4664int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4665 int *freq_array, unsigned int len)
4666{
4667 struct wpa_used_freq_data *freqs_data;
4668 int num, i;
4669
4670 os_memset(freq_array, 0, sizeof(int) * len);
4671
4672 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
4673 if (!freqs_data)
4674 return -1;
4675
4676 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
4677 for (i = 0; i < num; i++)
4678 freq_array[i] = freqs_data[i].freq;
4679
4680 os_free(freqs_data);
4681
4682 return num;
4683}