blob: 28d763ca0424b6c72535788114ee201eb7c4af22 [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 Shmidt8d520ff2011-05-09 14:06:53 -0700108/* Configure default/group WEP keys for static WEP */
109int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
110{
111 int i, set = 0;
112
113 for (i = 0; i < NUM_WEP_KEYS; i++) {
114 if (ssid->wep_key_len[i] == 0)
115 continue;
116
117 set = 1;
118 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
119 i, i == ssid->wep_tx_keyidx, NULL, 0,
120 ssid->wep_key[i], ssid->wep_key_len[i]);
121 }
122
123 return set;
124}
125
126
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700127int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
128 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700129{
130 u8 key[32];
131 size_t keylen;
132 enum wpa_alg alg;
133 u8 seq[6] = { 0 };
134
135 /* IBSS/WPA-None uses only one key (Group) for both receiving and
136 * sending unicast and multicast packets. */
137
138 if (ssid->mode != WPAS_MODE_IBSS) {
139 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
140 "IBSS/ad-hoc) for WPA-None", ssid->mode);
141 return -1;
142 }
143
144 if (!ssid->psk_set) {
145 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
146 "WPA-None");
147 return -1;
148 }
149
150 switch (wpa_s->group_cipher) {
151 case WPA_CIPHER_CCMP:
152 os_memcpy(key, ssid->psk, 16);
153 keylen = 16;
154 alg = WPA_ALG_CCMP;
155 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700156 case WPA_CIPHER_GCMP:
157 os_memcpy(key, ssid->psk, 16);
158 keylen = 16;
159 alg = WPA_ALG_GCMP;
160 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700161 case WPA_CIPHER_TKIP:
162 /* WPA-None uses the same Michael MIC key for both TX and RX */
163 os_memcpy(key, ssid->psk, 16 + 8);
164 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
165 keylen = 32;
166 alg = WPA_ALG_TKIP;
167 break;
168 default:
169 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
170 "WPA-None", wpa_s->group_cipher);
171 return -1;
172 }
173
174 /* TODO: should actually remember the previously used seq#, both for TX
175 * and RX from each STA.. */
176
177 return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
178}
179
180
181static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
182{
183 struct wpa_supplicant *wpa_s = eloop_ctx;
184 const u8 *bssid = wpa_s->bssid;
185 if (is_zero_ether_addr(bssid))
186 bssid = wpa_s->pending_bssid;
187 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
188 MAC2STR(bssid));
189 wpa_blacklist_add(wpa_s, bssid);
190 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800191 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700192 wpa_s->reassociate = 1;
193
194 /*
195 * If we timed out, the AP or the local radio may be busy.
196 * So, wait a second until scanning again.
197 */
198 wpa_supplicant_req_scan(wpa_s, 1, 0);
199}
200
201
202/**
203 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
204 * @wpa_s: Pointer to wpa_supplicant data
205 * @sec: Number of seconds after which to time out authentication
206 * @usec: Number of microseconds after which to time out authentication
207 *
208 * This function is used to schedule a timeout for the current authentication
209 * attempt.
210 */
211void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
212 int sec, int usec)
213{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700214 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700215 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
216 return;
217
218 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
219 "%d usec", sec, usec);
220 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
221 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
222}
223
224
225/**
226 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
227 * @wpa_s: Pointer to wpa_supplicant data
228 *
229 * This function is used to cancel authentication timeout scheduled with
230 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
231 * been completed.
232 */
233void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
234{
235 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
236 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
237 wpa_blacklist_del(wpa_s, wpa_s->bssid);
238}
239
240
241/**
242 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
243 * @wpa_s: Pointer to wpa_supplicant data
244 *
245 * This function is used to configure EAPOL state machine based on the selected
246 * authentication mode.
247 */
248void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
249{
250#ifdef IEEE8021X_EAPOL
251 struct eapol_config eapol_conf;
252 struct wpa_ssid *ssid = wpa_s->current_ssid;
253
254#ifdef CONFIG_IBSS_RSN
255 if (ssid->mode == WPAS_MODE_IBSS &&
256 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
257 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
258 /*
259 * RSN IBSS authentication is per-STA and we can disable the
260 * per-BSSID EAPOL authentication.
261 */
262 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
263 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
264 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
265 return;
266 }
267#endif /* CONFIG_IBSS_RSN */
268
269 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
270 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
271
272 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
273 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
274 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
275 else
276 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
277
278 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
279 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
280 eapol_conf.accept_802_1x_keys = 1;
281 eapol_conf.required_keys = 0;
282 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
283 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
284 }
285 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
286 eapol_conf.required_keys |=
287 EAPOL_REQUIRE_KEY_BROADCAST;
288 }
289
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700290 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700291 eapol_conf.required_keys = 0;
292 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700293 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700294 eapol_conf.workaround = ssid->eap_workaround;
295 eapol_conf.eap_disabled =
296 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
297 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
298 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700299 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700300 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
301#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700302
303 ieee802_1x_alloc_kay_sm(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700304}
305
306
307/**
308 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
309 * @wpa_s: Pointer to wpa_supplicant data
310 * @ssid: Configuration data for the network
311 *
312 * This function is used to configure WPA state machine and related parameters
313 * to a mode where WPA is not enabled. This is called as part of the
314 * authentication configuration when the selected network does not use WPA.
315 */
316void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
317 struct wpa_ssid *ssid)
318{
319 int i;
320
321 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
322 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
323 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
324 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
325 else
326 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
327 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
328 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
329 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
330 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
331 wpa_s->group_cipher = WPA_CIPHER_NONE;
332 wpa_s->mgmt_group_cipher = 0;
333
334 for (i = 0; i < NUM_WEP_KEYS; i++) {
335 if (ssid->wep_key_len[i] > 5) {
336 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
337 wpa_s->group_cipher = WPA_CIPHER_WEP104;
338 break;
339 } else if (ssid->wep_key_len[i] > 0) {
340 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
341 wpa_s->group_cipher = WPA_CIPHER_WEP40;
342 break;
343 }
344 }
345
346 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
347 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
348 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
349 wpa_s->pairwise_cipher);
350 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
351#ifdef CONFIG_IEEE80211W
352 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
353 wpa_s->mgmt_group_cipher);
354#endif /* CONFIG_IEEE80211W */
355
356 pmksa_cache_clear_current(wpa_s->wpa);
357}
358
359
Dmitry Shmidt04949592012-07-19 12:16:46 -0700360void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800361{
362 int i;
363 if (wpa_s->hw.modes == NULL)
364 return;
365
366 for (i = 0; i < wpa_s->hw.num_modes; i++) {
367 os_free(wpa_s->hw.modes[i].channels);
368 os_free(wpa_s->hw.modes[i].rates);
369 }
370
371 os_free(wpa_s->hw.modes);
372 wpa_s->hw.modes = NULL;
373}
374
375
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700376static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
377{
378 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700379 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700380 scard_deinit(wpa_s->scard);
381 wpa_s->scard = NULL;
382 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
383 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
384 l2_packet_deinit(wpa_s->l2);
385 wpa_s->l2 = NULL;
386 if (wpa_s->l2_br) {
387 l2_packet_deinit(wpa_s->l2_br);
388 wpa_s->l2_br = NULL;
389 }
390
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700391 if (wpa_s->conf != NULL) {
392 struct wpa_ssid *ssid;
393 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
394 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700395 }
396
397 os_free(wpa_s->confname);
398 wpa_s->confname = NULL;
399
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700400 os_free(wpa_s->confanother);
401 wpa_s->confanother = NULL;
402
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -0800403#ifdef CONFIG_P2P
404 os_free(wpa_s->conf_p2p_dev);
405 wpa_s->conf_p2p_dev = NULL;
406#endif /* CONFIG_P2P */
407
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700408 wpa_sm_set_eapol(wpa_s->wpa, NULL);
409 eapol_sm_deinit(wpa_s->eapol);
410 wpa_s->eapol = NULL;
411
412 rsn_preauth_deinit(wpa_s->wpa);
413
414#ifdef CONFIG_TDLS
415 wpa_tdls_deinit(wpa_s->wpa);
416#endif /* CONFIG_TDLS */
417
418 pmksa_candidate_free(wpa_s->wpa);
419 wpa_sm_deinit(wpa_s->wpa);
420 wpa_s->wpa = NULL;
421 wpa_blacklist_clear(wpa_s);
422
423 wpa_bss_deinit(wpa_s);
424
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700425 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700426 wpa_supplicant_cancel_scan(wpa_s);
427 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800428 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
429#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
430 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
431 wpa_s, NULL);
432#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700433
434 wpas_wps_deinit(wpa_s);
435
436 wpabuf_free(wpa_s->pending_eapol_rx);
437 wpa_s->pending_eapol_rx = NULL;
438
439#ifdef CONFIG_IBSS_RSN
440 ibss_rsn_deinit(wpa_s->ibss_rsn);
441 wpa_s->ibss_rsn = NULL;
442#endif /* CONFIG_IBSS_RSN */
443
444 sme_deinit(wpa_s);
445
446#ifdef CONFIG_AP
447 wpa_supplicant_ap_deinit(wpa_s);
448#endif /* CONFIG_AP */
449
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700450 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800452#ifdef CONFIG_OFFCHANNEL
453 offchannel_deinit(wpa_s);
454#endif /* CONFIG_OFFCHANNEL */
455
456 wpa_supplicant_cancel_sched_scan(wpa_s);
457
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700458 os_free(wpa_s->next_scan_freqs);
459 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800460
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800461 os_free(wpa_s->manual_scan_freqs);
462 wpa_s->manual_scan_freqs = NULL;
463
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700464 os_free(wpa_s->manual_sched_scan_freqs);
465 wpa_s->manual_sched_scan_freqs = NULL;
466
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800467 gas_query_deinit(wpa_s->gas);
468 wpa_s->gas = NULL;
469
470 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700471
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700472 ieee802_1x_dealloc_kay_sm(wpa_s);
473
Dmitry Shmidt04949592012-07-19 12:16:46 -0700474 os_free(wpa_s->bssid_filter);
475 wpa_s->bssid_filter = NULL;
476
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800477 os_free(wpa_s->disallow_aps_bssid);
478 wpa_s->disallow_aps_bssid = NULL;
479 os_free(wpa_s->disallow_aps_ssid);
480 wpa_s->disallow_aps_ssid = NULL;
481
Dmitry Shmidt04949592012-07-19 12:16:46 -0700482 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700483#ifdef CONFIG_WNM
484 wnm_deallocate_memory(wpa_s);
485#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700486
487 ext_password_deinit(wpa_s->ext_pw);
488 wpa_s->ext_pw = NULL;
489
490 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800491 wpa_s->last_gas_resp = NULL;
492 wpabuf_free(wpa_s->prev_gas_resp);
493 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700494
495 os_free(wpa_s->last_scan_res);
496 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800497
498#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700499 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800500#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700501}
502
503
504/**
505 * wpa_clear_keys - Clear keys configured for the driver
506 * @wpa_s: Pointer to wpa_supplicant data
507 * @addr: Previously used BSSID or %NULL if not available
508 *
509 * This function clears the encryption keys that has been previously configured
510 * for the driver.
511 */
512void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
513{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800514 int i, max;
515
516#ifdef CONFIG_IEEE80211W
517 max = 6;
518#else /* CONFIG_IEEE80211W */
519 max = 4;
520#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700521
522 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800523 for (i = 0; i < max; i++) {
524 if (wpa_s->keys_cleared & BIT(i))
525 continue;
526 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
527 NULL, 0);
528 }
529 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
530 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700531 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
532 0);
533 /* MLME-SETPROTECTION.request(None) */
534 wpa_drv_mlme_setprotection(
535 wpa_s, addr,
536 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
537 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
538 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800539 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700540}
541
542
543/**
544 * wpa_supplicant_state_txt - Get the connection state name as a text string
545 * @state: State (wpa_state; WPA_*)
546 * Returns: The state name as a printable text string
547 */
548const char * wpa_supplicant_state_txt(enum wpa_states state)
549{
550 switch (state) {
551 case WPA_DISCONNECTED:
552 return "DISCONNECTED";
553 case WPA_INACTIVE:
554 return "INACTIVE";
555 case WPA_INTERFACE_DISABLED:
556 return "INTERFACE_DISABLED";
557 case WPA_SCANNING:
558 return "SCANNING";
559 case WPA_AUTHENTICATING:
560 return "AUTHENTICATING";
561 case WPA_ASSOCIATING:
562 return "ASSOCIATING";
563 case WPA_ASSOCIATED:
564 return "ASSOCIATED";
565 case WPA_4WAY_HANDSHAKE:
566 return "4WAY_HANDSHAKE";
567 case WPA_GROUP_HANDSHAKE:
568 return "GROUP_HANDSHAKE";
569 case WPA_COMPLETED:
570 return "COMPLETED";
571 default:
572 return "UNKNOWN";
573 }
574}
575
576
577#ifdef CONFIG_BGSCAN
578
579static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
580{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800581 const char *name;
582
583 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
584 name = wpa_s->current_ssid->bgscan;
585 else
586 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800587 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800588 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800589 if (wpas_driver_bss_selection(wpa_s))
590 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
592 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800593#ifdef CONFIG_P2P
594 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
595 return;
596#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700597
598 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800599 if (wpa_s->current_ssid) {
600 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
602 "bgscan");
603 /*
604 * Live without bgscan; it is only used as a roaming
605 * optimization, so the initial connection is not
606 * affected.
607 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700608 } else {
609 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700610 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700611 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
612 0);
613 if (scan_res) {
614 bgscan_notify_scan(wpa_s, scan_res);
615 wpa_scan_results_free(scan_res);
616 }
617 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700618 } else
619 wpa_s->bgscan_ssid = NULL;
620}
621
622
623static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
624{
625 if (wpa_s->bgscan_ssid != NULL) {
626 bgscan_deinit(wpa_s);
627 wpa_s->bgscan_ssid = NULL;
628 }
629}
630
631#endif /* CONFIG_BGSCAN */
632
633
Dmitry Shmidt04949592012-07-19 12:16:46 -0700634static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
635{
636 if (autoscan_init(wpa_s, 0))
637 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
638}
639
640
641static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
642{
643 autoscan_deinit(wpa_s);
644}
645
646
647void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
648{
649 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
650 wpa_s->wpa_state == WPA_SCANNING) {
651 autoscan_deinit(wpa_s);
652 wpa_supplicant_start_autoscan(wpa_s);
653 }
654}
655
656
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700657/**
658 * wpa_supplicant_set_state - Set current connection state
659 * @wpa_s: Pointer to wpa_supplicant data
660 * @state: The new connection state
661 *
662 * This function is called whenever the connection state changes, e.g.,
663 * association is completed for WPA/WPA2 4-Way Handshake is started.
664 */
665void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
666 enum wpa_states state)
667{
668 enum wpa_states old_state = wpa_s->wpa_state;
669
670 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
671 wpa_supplicant_state_txt(wpa_s->wpa_state),
672 wpa_supplicant_state_txt(state));
673
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800674 if (state == WPA_INTERFACE_DISABLED) {
675 /* Assure normal scan when interface is restored */
676 wpa_s->normal_scans = 0;
677 }
678
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700679 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800680 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700681 /* Reinitialize normal_scan counter */
682 wpa_s->normal_scans = 0;
683 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800684
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685 if (state != WPA_SCANNING)
686 wpa_supplicant_notify_scanning(wpa_s, 0);
687
688 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700690#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800692 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800693 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700694 ssid ? ssid->id : -1,
695 ssid && ssid->id_str ? ssid->id_str : "");
696#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700697 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800698 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700699 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700700 wpa_drv_set_operstate(wpa_s, 1);
701#ifndef IEEE8021X_EAPOL
702 wpa_drv_set_supp_port(wpa_s, 1);
703#endif /* IEEE8021X_EAPOL */
704 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700705 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700706 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700707
708 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
710 state == WPA_ASSOCIATED) {
711 wpa_s->new_connection = 1;
712 wpa_drv_set_operstate(wpa_s, 0);
713#ifndef IEEE8021X_EAPOL
714 wpa_drv_set_supp_port(wpa_s, 0);
715#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700716 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700717 }
718 wpa_s->wpa_state = state;
719
720#ifdef CONFIG_BGSCAN
721 if (state == WPA_COMPLETED)
722 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800723 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700724 wpa_supplicant_stop_bgscan(wpa_s);
725#endif /* CONFIG_BGSCAN */
726
Dmitry Shmidt04949592012-07-19 12:16:46 -0700727 if (state == WPA_AUTHENTICATING)
728 wpa_supplicant_stop_autoscan(wpa_s);
729
730 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
731 wpa_supplicant_start_autoscan(wpa_s);
732
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700733 if (wpa_s->wpa_state != old_state) {
734 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
735
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700736 /*
737 * Notify the P2P Device interface about a state change in one
738 * of the interfaces.
739 */
740 wpas_p2p_indicate_state_change(wpa_s);
741
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700742 if (wpa_s->wpa_state == WPA_COMPLETED ||
743 old_state == WPA_COMPLETED)
744 wpas_notify_auth_changed(wpa_s);
745 }
746}
747
748
749void wpa_supplicant_terminate_proc(struct wpa_global *global)
750{
751 int pending = 0;
752#ifdef CONFIG_WPS
753 struct wpa_supplicant *wpa_s = global->ifaces;
754 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800755 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700756 if (wpas_wps_terminate_pending(wpa_s) == 1)
757 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700758#ifdef CONFIG_P2P
759 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
760 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
761 wpas_p2p_disconnect(wpa_s);
762#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800763 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700764 }
765#endif /* CONFIG_WPS */
766 if (pending)
767 return;
768 eloop_terminate();
769}
770
771
772static void wpa_supplicant_terminate(int sig, void *signal_ctx)
773{
774 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700775 wpa_supplicant_terminate_proc(global);
776}
777
778
779void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
780{
781 enum wpa_states old_state = wpa_s->wpa_state;
782
783 wpa_s->pairwise_cipher = 0;
784 wpa_s->group_cipher = 0;
785 wpa_s->mgmt_group_cipher = 0;
786 wpa_s->key_mgmt = 0;
787 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700788 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700789
790 if (wpa_s->wpa_state != old_state)
791 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
792}
793
794
795/**
796 * wpa_supplicant_reload_configuration - Reload configuration data
797 * @wpa_s: Pointer to wpa_supplicant data
798 * Returns: 0 on success or -1 if configuration parsing failed
799 *
800 * This function can be used to request that the configuration data is reloaded
801 * (e.g., after configuration file change). This function is reloading
802 * configuration only for one interface, so this may need to be called multiple
803 * times if %wpa_supplicant is controlling multiple interfaces and all
804 * interfaces need reconfiguration.
805 */
806int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
807{
808 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700809 int reconf_ctrl;
810 int old_ap_scan;
811
812 if (wpa_s->confname == NULL)
813 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700814 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700815 if (conf == NULL) {
816 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
817 "file '%s' - exiting", wpa_s->confname);
818 return -1;
819 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700820 wpa_config_read(wpa_s->confanother, conf);
821
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700822 conf->changed_parameters = (unsigned int) -1;
823
824 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
825 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
826 os_strcmp(conf->ctrl_interface,
827 wpa_s->conf->ctrl_interface) != 0);
828
829 if (reconf_ctrl && wpa_s->ctrl_iface) {
830 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
831 wpa_s->ctrl_iface = NULL;
832 }
833
834 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800835 if (wpa_s->current_ssid) {
836 wpa_supplicant_deauthenticate(wpa_s,
837 WLAN_REASON_DEAUTH_LEAVING);
838 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700839
840 /*
841 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
842 * pkcs11_engine_path, pkcs11_module_path.
843 */
844 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
845 /*
846 * Clear forced success to clear EAP state for next
847 * authentication.
848 */
849 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
850 }
851 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
852 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800853 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
855 rsn_preauth_deinit(wpa_s->wpa);
856
857 old_ap_scan = wpa_s->conf->ap_scan;
858 wpa_config_free(wpa_s->conf);
859 wpa_s->conf = conf;
860 if (old_ap_scan != wpa_s->conf->ap_scan)
861 wpas_notify_ap_scan_changed(wpa_s);
862
863 if (reconf_ctrl)
864 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
865
866 wpa_supplicant_update_config(wpa_s);
867
868 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700869 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700870 wpa_s->reassociate = 1;
871 wpa_supplicant_req_scan(wpa_s, 0, 0);
872 }
873 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
874 return 0;
875}
876
877
878static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
879{
880 struct wpa_global *global = signal_ctx;
881 struct wpa_supplicant *wpa_s;
882 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
883 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
884 sig);
885 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
886 wpa_supplicant_terminate_proc(global);
887 }
888 }
889}
890
891
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
893 struct wpa_ssid *ssid,
894 struct wpa_ie_data *ie)
895{
896 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
897 if (ret) {
898 if (ret == -2) {
899 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
900 "from association info");
901 }
902 return -1;
903 }
904
905 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
906 "cipher suites");
907 if (!(ie->group_cipher & ssid->group_cipher)) {
908 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
909 "cipher 0x%x (mask 0x%x) - reject",
910 ie->group_cipher, ssid->group_cipher);
911 return -1;
912 }
913 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
914 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
915 "cipher 0x%x (mask 0x%x) - reject",
916 ie->pairwise_cipher, ssid->pairwise_cipher);
917 return -1;
918 }
919 if (!(ie->key_mgmt & ssid->key_mgmt)) {
920 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
921 "management 0x%x (mask 0x%x) - reject",
922 ie->key_mgmt, ssid->key_mgmt);
923 return -1;
924 }
925
926#ifdef CONFIG_IEEE80211W
927 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800928 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
929 wpa_s->conf->pmf : ssid->ieee80211w) ==
930 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700931 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
932 "that does not support management frame protection - "
933 "reject");
934 return -1;
935 }
936#endif /* CONFIG_IEEE80211W */
937
938 return 0;
939}
940
941
942/**
943 * wpa_supplicant_set_suites - Set authentication and encryption parameters
944 * @wpa_s: Pointer to wpa_supplicant data
945 * @bss: Scan results for the selected BSS, or %NULL if not available
946 * @ssid: Configuration data for the selected network
947 * @wpa_ie: Buffer for the WPA/RSN IE
948 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
949 * used buffer length in case the functions returns success.
950 * Returns: 0 on success or -1 on failure
951 *
952 * This function is used to configure authentication and encryption parameters
953 * based on the network configuration and scan result for the selected BSS (if
954 * available).
955 */
956int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
957 struct wpa_bss *bss, struct wpa_ssid *ssid,
958 u8 *wpa_ie, size_t *wpa_ie_len)
959{
960 struct wpa_ie_data ie;
961 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800962 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700963
964 if (bss) {
965 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
966 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800967 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700968 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800969 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700970
971 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
972 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
973 (ie.group_cipher & ssid->group_cipher) &&
974 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
975 (ie.key_mgmt & ssid->key_mgmt)) {
976 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
977 proto = WPA_PROTO_RSN;
978 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
979 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
980 (ie.group_cipher & ssid->group_cipher) &&
981 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
982 (ie.key_mgmt & ssid->key_mgmt)) {
983 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
984 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800985#ifdef CONFIG_HS20
986 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
987 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
988 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -0700989 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800990 ie.group_cipher = WPA_CIPHER_CCMP;
991 ie.pairwise_cipher = WPA_CIPHER_CCMP;
992 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
993 proto = WPA_PROTO_OSEN;
994#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700995 } else if (bss) {
996 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
997 return -1;
998 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800999 if (ssid->proto & WPA_PROTO_OSEN)
1000 proto = WPA_PROTO_OSEN;
1001 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002 proto = WPA_PROTO_RSN;
1003 else
1004 proto = WPA_PROTO_WPA;
1005 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1006 os_memset(&ie, 0, sizeof(ie));
1007 ie.group_cipher = ssid->group_cipher;
1008 ie.pairwise_cipher = ssid->pairwise_cipher;
1009 ie.key_mgmt = ssid->key_mgmt;
1010#ifdef CONFIG_IEEE80211W
1011 ie.mgmt_group_cipher =
1012 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1013 WPA_CIPHER_AES_128_CMAC : 0;
1014#endif /* CONFIG_IEEE80211W */
1015 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1016 "based on configuration");
1017 } else
1018 proto = ie.proto;
1019 }
1020
1021 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1022 "pairwise %d key_mgmt %d proto %d",
1023 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1024#ifdef CONFIG_IEEE80211W
1025 if (ssid->ieee80211w) {
1026 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1027 ie.mgmt_group_cipher);
1028 }
1029#endif /* CONFIG_IEEE80211W */
1030
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001031 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001032 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1033 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001034 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001035
1036 if (bss || !wpa_s->ap_ies_from_associnfo) {
1037 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1038 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1039 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1040 bss_rsn ? 2 + bss_rsn[1] : 0))
1041 return -1;
1042 }
1043
1044 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001045 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1046 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1048 "cipher");
1049 return -1;
1050 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001051 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1052 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053
1054 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001055 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1056 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001057 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1058 "cipher");
1059 return -1;
1060 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001061 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1062 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001063
1064 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001065#ifdef CONFIG_SAE
1066 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1067 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1068#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069 if (0) {
1070#ifdef CONFIG_IEEE80211R
1071 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1072 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1073 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1074 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1075 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1076 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1077#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001078#ifdef CONFIG_SAE
1079 } else if (sel & WPA_KEY_MGMT_SAE) {
1080 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1081 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1082 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1083 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1084 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1085#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001086#ifdef CONFIG_IEEE80211W
1087 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1088 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1089 wpa_dbg(wpa_s, MSG_DEBUG,
1090 "WPA: using KEY_MGMT 802.1X with SHA256");
1091 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1092 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1093 wpa_dbg(wpa_s, MSG_DEBUG,
1094 "WPA: using KEY_MGMT PSK with SHA256");
1095#endif /* CONFIG_IEEE80211W */
1096 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1097 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1098 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1099 } else if (sel & WPA_KEY_MGMT_PSK) {
1100 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1101 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1102 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1103 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1104 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001105#ifdef CONFIG_HS20
1106 } else if (sel & WPA_KEY_MGMT_OSEN) {
1107 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1108 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1109#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001110 } else {
1111 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1112 "authenticated key management type");
1113 return -1;
1114 }
1115
1116 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1117 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1118 wpa_s->pairwise_cipher);
1119 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1120
1121#ifdef CONFIG_IEEE80211W
1122 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001123 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1124 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1126 sel = 0;
1127 if (sel & WPA_CIPHER_AES_128_CMAC) {
1128 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1129 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1130 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001131 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1132 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1133 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1134 "BIP-GMAC-128");
1135 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1136 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1137 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1138 "BIP-GMAC-256");
1139 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1140 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1141 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1142 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001143 } else {
1144 wpa_s->mgmt_group_cipher = 0;
1145 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1146 }
1147 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1148 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001149 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1150 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1151 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152#endif /* CONFIG_IEEE80211W */
1153
1154 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1155 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1156 return -1;
1157 }
1158
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001159 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001161#ifndef CONFIG_NO_PBKDF2
1162 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1163 ssid->passphrase) {
1164 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001165 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1166 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001167 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1168 psk, PMK_LEN);
1169 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1170 }
1171#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001172#ifdef CONFIG_EXT_PASSWORD
1173 if (ssid->ext_psk) {
1174 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1175 ssid->ext_psk);
1176 char pw_str[64 + 1];
1177 u8 psk[PMK_LEN];
1178
1179 if (pw == NULL) {
1180 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1181 "found from external storage");
1182 return -1;
1183 }
1184
1185 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1186 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1187 "PSK length %d in external storage",
1188 (int) wpabuf_len(pw));
1189 ext_password_free(pw);
1190 return -1;
1191 }
1192
1193 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1194 pw_str[wpabuf_len(pw)] = '\0';
1195
1196#ifndef CONFIG_NO_PBKDF2
1197 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1198 {
1199 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1200 4096, psk, PMK_LEN);
1201 os_memset(pw_str, 0, sizeof(pw_str));
1202 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1203 "external passphrase)",
1204 psk, PMK_LEN);
1205 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1206 } else
1207#endif /* CONFIG_NO_PBKDF2 */
1208 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1209 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1210 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1211 "Invalid PSK hex string");
1212 os_memset(pw_str, 0, sizeof(pw_str));
1213 ext_password_free(pw);
1214 return -1;
1215 }
1216 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1217 } else {
1218 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1219 "PSK available");
1220 os_memset(pw_str, 0, sizeof(pw_str));
1221 ext_password_free(pw);
1222 return -1;
1223 }
1224
1225 os_memset(pw_str, 0, sizeof(pw_str));
1226 ext_password_free(pw);
1227 }
1228#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001229 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001230 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1231
1232 return 0;
1233}
1234
1235
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001236static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1237{
1238 *pos = 0x00;
1239
1240 switch (idx) {
1241 case 0: /* Bits 0-7 */
1242 break;
1243 case 1: /* Bits 8-15 */
1244 break;
1245 case 2: /* Bits 16-23 */
1246#ifdef CONFIG_WNM
1247 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1248 *pos |= 0x08; /* Bit 19 - BSS Transition */
1249#endif /* CONFIG_WNM */
1250 break;
1251 case 3: /* Bits 24-31 */
1252#ifdef CONFIG_WNM
1253 *pos |= 0x02; /* Bit 25 - SSID List */
1254#endif /* CONFIG_WNM */
1255#ifdef CONFIG_INTERWORKING
1256 if (wpa_s->conf->interworking)
1257 *pos |= 0x80; /* Bit 31 - Interworking */
1258#endif /* CONFIG_INTERWORKING */
1259 break;
1260 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001261#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001262 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1263 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001264#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001265 break;
1266 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001267#ifdef CONFIG_HS20
1268 if (wpa_s->conf->hs20)
1269 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1270#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001271 break;
1272 case 6: /* Bits 48-55 */
1273 break;
1274 }
1275}
1276
1277
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001278int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001279{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001280 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001281 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001282
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001283 if (len < wpa_s->extended_capa_len)
1284 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001285 if (buflen < (size_t) len + 2) {
1286 wpa_printf(MSG_INFO,
1287 "Not enough room for building extended capabilities element");
1288 return -1;
1289 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001290
1291 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001292 *pos++ = len;
1293 for (i = 0; i < len; i++, pos++) {
1294 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001295
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001296 if (i < wpa_s->extended_capa_len) {
1297 *pos &= ~wpa_s->extended_capa_mask[i];
1298 *pos |= wpa_s->extended_capa[i];
1299 }
1300 }
1301
1302 while (len > 0 && buf[1 + len] == 0) {
1303 len--;
1304 buf[1] = len;
1305 }
1306 if (len == 0)
1307 return 0;
1308
1309 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001310}
1311
1312
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001313static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1314 struct wpa_bss *test_bss)
1315{
1316 struct wpa_bss *bss;
1317
1318 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1319 if (bss == test_bss)
1320 return 1;
1321 }
1322
1323 return 0;
1324}
1325
1326
1327static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1328 struct wpa_ssid *test_ssid)
1329{
1330 struct wpa_ssid *ssid;
1331
1332 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1333 if (ssid == test_ssid)
1334 return 1;
1335 }
1336
1337 return 0;
1338}
1339
1340
1341int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1342 struct wpa_ssid *test_ssid)
1343{
1344 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1345 return 0;
1346
1347 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1348}
1349
1350
1351void wpas_connect_work_free(struct wpa_connect_work *cwork)
1352{
1353 if (cwork == NULL)
1354 return;
1355 os_free(cwork);
1356}
1357
1358
1359void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1360{
1361 struct wpa_connect_work *cwork;
1362 struct wpa_radio_work *work = wpa_s->connect_work;
1363
1364 if (!work)
1365 return;
1366
1367 wpa_s->connect_work = NULL;
1368 cwork = work->ctx;
1369 work->ctx = NULL;
1370 wpas_connect_work_free(cwork);
1371 radio_work_done(work);
1372}
1373
1374
1375static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1376
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001377/**
1378 * wpa_supplicant_associate - Request association
1379 * @wpa_s: Pointer to wpa_supplicant data
1380 * @bss: Scan results for the selected BSS, or %NULL if not available
1381 * @ssid: Configuration data for the selected network
1382 *
1383 * This function is used to request %wpa_supplicant to associate with a BSS.
1384 */
1385void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1386 struct wpa_bss *bss, struct wpa_ssid *ssid)
1387{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001388 struct wpa_connect_work *cwork;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389
1390#ifdef CONFIG_IBSS_RSN
1391 ibss_rsn_deinit(wpa_s->ibss_rsn);
1392 wpa_s->ibss_rsn = NULL;
1393#endif /* CONFIG_IBSS_RSN */
1394
1395 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1396 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1397#ifdef CONFIG_AP
1398 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1399 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1400 "mode");
1401 return;
1402 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001403 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1404 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001405 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1406 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001407 return;
1408 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001409 wpa_s->current_bss = bss;
1410#else /* CONFIG_AP */
1411 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1412 "the build");
1413#endif /* CONFIG_AP */
1414 return;
1415 }
1416
1417#ifdef CONFIG_TDLS
1418 if (bss)
1419 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1420 bss->ie_len);
1421#endif /* CONFIG_TDLS */
1422
1423 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1424 ssid->mode == IEEE80211_MODE_INFRA) {
1425 sme_authenticate(wpa_s, bss, ssid);
1426 return;
1427 }
1428
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001429 if (wpa_s->connect_work) {
1430 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1431 return;
1432 }
1433
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001434 if (radio_work_pending(wpa_s, "connect")) {
1435 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1436 return;
1437 }
1438
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001439 cwork = os_zalloc(sizeof(*cwork));
1440 if (cwork == NULL)
1441 return;
1442
1443 cwork->bss = bss;
1444 cwork->ssid = ssid;
1445
1446 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1447 wpas_start_assoc_cb, cwork) < 0) {
1448 os_free(cwork);
1449 }
1450}
1451
1452
1453static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1454{
1455 struct wpa_connect_work *cwork = work->ctx;
1456 struct wpa_bss *bss = cwork->bss;
1457 struct wpa_ssid *ssid = cwork->ssid;
1458 struct wpa_supplicant *wpa_s = work->wpa_s;
1459 u8 wpa_ie[200];
1460 size_t wpa_ie_len;
1461 int use_crypt, ret, i, bssid_changed;
1462 int algs = WPA_AUTH_ALG_OPEN;
1463 unsigned int cipher_pairwise, cipher_group;
1464 struct wpa_driver_associate_params params;
1465 int wep_keys_set = 0;
1466 int assoc_failed = 0;
1467 struct wpa_ssid *old_ssid;
1468#ifdef CONFIG_HT_OVERRIDES
1469 struct ieee80211_ht_capabilities htcaps;
1470 struct ieee80211_ht_capabilities htcaps_mask;
1471#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001472#ifdef CONFIG_VHT_OVERRIDES
1473 struct ieee80211_vht_capabilities vhtcaps;
1474 struct ieee80211_vht_capabilities vhtcaps_mask;
1475#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001476
1477 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001478 if (work->started) {
1479 wpa_s->connect_work = NULL;
1480
1481 /* cancel possible auth. timeout */
1482 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1483 NULL);
1484 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001485 wpas_connect_work_free(cwork);
1486 return;
1487 }
1488
1489 wpa_s->connect_work = work;
1490
1491 if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
1492 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1493 wpas_connect_work_done(wpa_s);
1494 return;
1495 }
1496
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001497 os_memset(&params, 0, sizeof(params));
1498 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001499 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001500 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001501#ifdef CONFIG_IEEE80211R
1502 const u8 *ie, *md = NULL;
1503#endif /* CONFIG_IEEE80211R */
1504 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1505 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1506 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1507 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1508 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1509 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1510 if (bssid_changed)
1511 wpas_notify_bssid_changed(wpa_s);
1512#ifdef CONFIG_IEEE80211R
1513 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1514 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1515 md = ie + 2;
1516 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1517 if (md) {
1518 /* Prepare for the next transition */
1519 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1520 }
1521#endif /* CONFIG_IEEE80211R */
1522#ifdef CONFIG_WPS
1523 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1524 wpa_s->conf->ap_scan == 2 &&
1525 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1526 /* Use ap_scan==1 style network selection to find the network
1527 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001528 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529 wpa_s->reassociate = 1;
1530 wpa_supplicant_req_scan(wpa_s, 0, 0);
1531 return;
1532#endif /* CONFIG_WPS */
1533 } else {
1534 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1535 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1536 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1537 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001538 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001539 wpa_supplicant_cancel_scan(wpa_s);
1540
1541 /* Starting new association, so clear the possibly used WPA IE from the
1542 * previous association. */
1543 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1544
1545#ifdef IEEE8021X_EAPOL
1546 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1547 if (ssid->leap) {
1548 if (ssid->non_leap == 0)
1549 algs = WPA_AUTH_ALG_LEAP;
1550 else
1551 algs |= WPA_AUTH_ALG_LEAP;
1552 }
1553 }
1554#endif /* IEEE8021X_EAPOL */
1555 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1556 if (ssid->auth_alg) {
1557 algs = ssid->auth_alg;
1558 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1559 "0x%x", algs);
1560 }
1561
1562 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1563 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001564 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001565 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001566 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1567 wpa_s->conf->okc :
1568 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001569 (ssid->proto & WPA_PROTO_RSN);
1570 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001571 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001572 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1573 wpa_ie_len = sizeof(wpa_ie);
1574 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1575 wpa_ie, &wpa_ie_len)) {
1576 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1577 "key management and encryption suites");
1578 return;
1579 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001580 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1581 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1582 /*
1583 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1584 * use non-WPA since the scan results did not indicate that the
1585 * AP is using WPA or WPA2.
1586 */
1587 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1588 wpa_ie_len = 0;
1589 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001590 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001591 wpa_ie_len = sizeof(wpa_ie);
1592 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1593 wpa_ie, &wpa_ie_len)) {
1594 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1595 "key management and encryption suites (no "
1596 "scan results)");
1597 return;
1598 }
1599#ifdef CONFIG_WPS
1600 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1601 struct wpabuf *wps_ie;
1602 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1603 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1604 wpa_ie_len = wpabuf_len(wps_ie);
1605 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1606 } else
1607 wpa_ie_len = 0;
1608 wpabuf_free(wps_ie);
1609 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1610 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1611 params.wps = WPS_MODE_PRIVACY;
1612 else
1613 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001614 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001615#endif /* CONFIG_WPS */
1616 } else {
1617 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1618 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001619 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001620 }
1621
1622#ifdef CONFIG_P2P
1623 if (wpa_s->global->p2p) {
1624 u8 *pos;
1625 size_t len;
1626 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001627 pos = wpa_ie + wpa_ie_len;
1628 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001629 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1630 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001631 if (res >= 0)
1632 wpa_ie_len += res;
1633 }
1634
1635 wpa_s->cross_connect_disallowed = 0;
1636 if (bss) {
1637 struct wpabuf *p2p;
1638 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1639 if (p2p) {
1640 wpa_s->cross_connect_disallowed =
1641 p2p_get_cross_connect_disallowed(p2p);
1642 wpabuf_free(p2p);
1643 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1644 "connection",
1645 wpa_s->cross_connect_disallowed ?
1646 "disallows" : "allows");
1647 }
1648 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001649
1650 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001651#endif /* CONFIG_P2P */
1652
Dmitry Shmidt04949592012-07-19 12:16:46 -07001653#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001654 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001655 struct wpabuf *hs20;
1656 hs20 = wpabuf_alloc(20);
1657 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001658 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
1659 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001660 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1661 wpabuf_len(hs20));
1662 wpa_ie_len += wpabuf_len(hs20);
1663 wpabuf_free(hs20);
1664 }
1665 }
1666#endif /* CONFIG_HS20 */
1667
Dmitry Shmidt56052862013-10-04 10:23:25 -07001668 /*
1669 * Workaround: Add Extended Capabilities element only if the AP
1670 * included this element in Beacon/Probe Response frames. Some older
1671 * APs seem to have interoperability issues if this element is
1672 * included, so while the standard may require us to include the
1673 * element in all cases, it is justifiable to skip it to avoid
1674 * interoperability issues.
1675 */
1676 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001677 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07001678 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001679 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
1680 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07001681 if (ext_capab_len > 0) {
1682 u8 *pos = wpa_ie;
1683 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1684 pos += 2 + pos[1];
1685 os_memmove(pos + ext_capab_len, pos,
1686 wpa_ie_len - (pos - wpa_ie));
1687 wpa_ie_len += ext_capab_len;
1688 os_memcpy(pos, ext_capab, ext_capab_len);
1689 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001690 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001691
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001692 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1693 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001694 cipher_pairwise = wpa_s->pairwise_cipher;
1695 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001696 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1697 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1698 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1699 use_crypt = 0;
1700 if (wpa_set_wep_keys(wpa_s, ssid)) {
1701 use_crypt = 1;
1702 wep_keys_set = 1;
1703 }
1704 }
1705 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1706 use_crypt = 0;
1707
1708#ifdef IEEE8021X_EAPOL
1709 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1710 if ((ssid->eapol_flags &
1711 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1712 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1713 !wep_keys_set) {
1714 use_crypt = 0;
1715 } else {
1716 /* Assume that dynamic WEP-104 keys will be used and
1717 * set cipher suites in order for drivers to expect
1718 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001719 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720 }
1721 }
1722#endif /* IEEE8021X_EAPOL */
1723
1724 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1725 /* Set the key before (and later after) association */
1726 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1727 }
1728
1729 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1730 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001731 params.ssid = bss->ssid;
1732 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001733 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1734 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1735 MACSTR " freq=%u MHz based on scan results "
1736 "(bssid_set=%d)",
1737 MAC2STR(bss->bssid), bss->freq,
1738 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001739 params.bssid = bss->bssid;
1740 params.freq = bss->freq;
1741 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001742 params.bssid_hint = bss->bssid;
1743 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744 } else {
1745 params.ssid = ssid->ssid;
1746 params.ssid_len = ssid->ssid_len;
1747 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001748
1749 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1750 wpa_s->conf->ap_scan == 2) {
1751 params.bssid = ssid->bssid;
1752 params.fixed_bssid = 1;
1753 }
1754
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001755 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1756 params.freq == 0)
1757 params.freq = ssid->frequency; /* Initial channel for IBSS */
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08001758
1759 if (ssid->mode == WPAS_MODE_IBSS) {
1760 if (ssid->beacon_int)
1761 params.beacon_int = ssid->beacon_int;
1762 else
1763 params.beacon_int = wpa_s->conf->beacon_int;
1764 }
1765
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766 params.wpa_ie = wpa_ie;
1767 params.wpa_ie_len = wpa_ie_len;
1768 params.pairwise_suite = cipher_pairwise;
1769 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001770 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001771 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001772 params.auth_alg = algs;
1773 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001774 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001775 for (i = 0; i < NUM_WEP_KEYS; i++) {
1776 if (ssid->wep_key_len[i])
1777 params.wep_key[i] = ssid->wep_key[i];
1778 params.wep_key_len[i] = ssid->wep_key_len[i];
1779 }
1780 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1781
1782 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001783 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1784 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001785 params.passphrase = ssid->passphrase;
1786 if (ssid->psk_set)
1787 params.psk = ssid->psk;
1788 }
1789
1790 params.drop_unencrypted = use_crypt;
1791
1792#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001793 params.mgmt_frame_protection =
1794 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1795 wpa_s->conf->pmf : ssid->ieee80211w;
1796 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1798 struct wpa_ie_data ie;
1799 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1800 ie.capabilities &
1801 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1802 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1803 "MFP: require MFP");
1804 params.mgmt_frame_protection =
1805 MGMT_FRAME_PROTECTION_REQUIRED;
1806 }
1807 }
1808#endif /* CONFIG_IEEE80211W */
1809
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001810 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001811
1812 if (wpa_s->parent->set_sta_uapsd)
1813 params.uapsd = wpa_s->parent->sta_uapsd;
1814 else
1815 params.uapsd = -1;
1816
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001817#ifdef CONFIG_HT_OVERRIDES
1818 os_memset(&htcaps, 0, sizeof(htcaps));
1819 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1820 params.htcaps = (u8 *) &htcaps;
1821 params.htcaps_mask = (u8 *) &htcaps_mask;
1822 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1823#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001824#ifdef CONFIG_VHT_OVERRIDES
1825 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
1826 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
1827 params.vhtcaps = &vhtcaps;
1828 params.vhtcaps_mask = &vhtcaps_mask;
1829 wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
1830#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001831
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001832#ifdef CONFIG_P2P
1833 /*
1834 * If multi-channel concurrency is not supported, check for any
1835 * frequency conflict. In case of any frequency conflict, remove the
1836 * least prioritized connection.
1837 */
1838 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001839 int freq, num;
1840 num = get_shared_radio_freqs(wpa_s, &freq, 1);
1841 if (num > 0 && freq > 0 && freq != params.freq) {
1842 wpa_printf(MSG_DEBUG,
1843 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001844 freq, params.freq);
1845 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1846 params.freq,
1847 ssid) < 0)
1848 return;
1849 }
1850 }
1851#endif /* CONFIG_P2P */
1852
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001853 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001854 if (ret < 0) {
1855 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1856 "failed");
1857 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1858 /*
1859 * The driver is known to mean what is saying, so we
1860 * can stop right here; the association will not
1861 * succeed.
1862 */
1863 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001864 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001865 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1866 return;
1867 }
1868 /* try to continue anyway; new association will be tried again
1869 * after timeout */
1870 assoc_failed = 1;
1871 }
1872
1873 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1874 /* Set the key after the association just in case association
1875 * cleared the previously configured key. */
1876 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1877 /* No need to timeout authentication since there is no key
1878 * management. */
1879 wpa_supplicant_cancel_auth_timeout(wpa_s);
1880 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1881#ifdef CONFIG_IBSS_RSN
1882 } else if (ssid->mode == WPAS_MODE_IBSS &&
1883 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1884 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1885 /*
1886 * RSN IBSS authentication is per-STA and we can disable the
1887 * per-BSSID authentication.
1888 */
1889 wpa_supplicant_cancel_auth_timeout(wpa_s);
1890#endif /* CONFIG_IBSS_RSN */
1891 } else {
1892 /* Timeout for IEEE 802.11 authentication and association */
1893 int timeout = 60;
1894
1895 if (assoc_failed) {
1896 /* give IBSS a bit more time */
1897 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1898 } else if (wpa_s->conf->ap_scan == 1) {
1899 /* give IBSS a bit more time */
1900 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1901 }
1902 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1903 }
1904
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001905 if (wep_keys_set &&
1906 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001907 /* Set static WEP keys again */
1908 wpa_set_wep_keys(wpa_s, ssid);
1909 }
1910
1911 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1912 /*
1913 * Do not allow EAP session resumption between different
1914 * network configurations.
1915 */
1916 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1917 }
1918 old_ssid = wpa_s->current_ssid;
1919 wpa_s->current_ssid = ssid;
1920 wpa_s->current_bss = bss;
1921 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1922 wpa_supplicant_initiate_eapol(wpa_s);
1923 if (old_ssid != wpa_s->current_ssid)
1924 wpas_notify_network_changed(wpa_s);
1925}
1926
1927
1928static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1929 const u8 *addr)
1930{
1931 struct wpa_ssid *old_ssid;
1932
1933 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001934 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001935 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936 wpa_sm_set_config(wpa_s->wpa, NULL);
1937 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1938 if (old_ssid != wpa_s->current_ssid)
1939 wpas_notify_network_changed(wpa_s);
1940 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1941}
1942
1943
1944/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001945 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1946 * @wpa_s: Pointer to wpa_supplicant data
1947 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1948 *
1949 * This function is used to request %wpa_supplicant to deauthenticate from the
1950 * current AP.
1951 */
1952void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1953 int reason_code)
1954{
1955 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001956 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001957 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001958
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001959 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1960 " pending_bssid=" MACSTR " reason=%d state=%s",
1961 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1962 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1963
1964 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001965 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001966 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1967 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1968 wpa_s->wpa_state == WPA_ASSOCIATING))
1969 addr = wpa_s->pending_bssid;
1970 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1971 /*
1972 * When using driver-based BSS selection, we may not know the
1973 * BSSID with which we are currently trying to associate. We
1974 * need to notify the driver of this disconnection even in such
1975 * a case, so use the all zeros address here.
1976 */
1977 addr = wpa_s->bssid;
1978 zero_addr = 1;
1979 }
1980
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001981#ifdef CONFIG_TDLS
1982 wpa_tdls_teardown_peers(wpa_s->wpa);
1983#endif /* CONFIG_TDLS */
1984
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001985 if (addr) {
1986 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001987 os_memset(&event, 0, sizeof(event));
1988 event.deauth_info.reason_code = (u16) reason_code;
1989 event.deauth_info.locally_generated = 1;
1990 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001991 if (zero_addr)
1992 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993 }
1994
1995 wpa_supplicant_clear_connection(wpa_s, addr);
1996}
1997
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001998static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1999 struct wpa_ssid *ssid)
2000{
2001 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2002 return;
2003
2004 ssid->disabled = 0;
2005 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2006 wpas_notify_network_enabled_changed(wpa_s, ssid);
2007
2008 /*
2009 * Try to reassociate since there is no current configuration and a new
2010 * network was made available.
2011 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002012 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002013 wpa_s->reassociate = 1;
2014}
2015
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002016
2017/**
2018 * wpa_supplicant_enable_network - Mark a configured network as enabled
2019 * @wpa_s: wpa_supplicant structure for a network interface
2020 * @ssid: wpa_ssid structure for a configured network or %NULL
2021 *
2022 * Enables the specified network or all networks if no network specified.
2023 */
2024void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2025 struct wpa_ssid *ssid)
2026{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002027 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002028 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2029 wpa_supplicant_enable_one_network(wpa_s, ssid);
2030 } else
2031 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002032
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002033 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002034 if (wpa_s->sched_scanning) {
2035 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2036 "new network to scan filters");
2037 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002038 }
2039
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002040 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2041 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042 }
2043}
2044
2045
2046/**
2047 * wpa_supplicant_disable_network - Mark a configured network as disabled
2048 * @wpa_s: wpa_supplicant structure for a network interface
2049 * @ssid: wpa_ssid structure for a configured network or %NULL
2050 *
2051 * Disables the specified network or all networks if no network specified.
2052 */
2053void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2054 struct wpa_ssid *ssid)
2055{
2056 struct wpa_ssid *other_ssid;
2057 int was_disabled;
2058
2059 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002060 if (wpa_s->sched_scanning)
2061 wpa_supplicant_cancel_sched_scan(wpa_s);
2062
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002063 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2064 other_ssid = other_ssid->next) {
2065 was_disabled = other_ssid->disabled;
2066 if (was_disabled == 2)
2067 continue; /* do not change persistent P2P group
2068 * data */
2069
2070 other_ssid->disabled = 1;
2071
2072 if (was_disabled != other_ssid->disabled)
2073 wpas_notify_network_enabled_changed(
2074 wpa_s, other_ssid);
2075 }
2076 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002077 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002078 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2079 } else if (ssid->disabled != 2) {
2080 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002081 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002082 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2083
2084 was_disabled = ssid->disabled;
2085
2086 ssid->disabled = 1;
2087
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002088 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002089 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002090 if (wpa_s->sched_scanning) {
2091 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2092 "to remove network from filters");
2093 wpa_supplicant_cancel_sched_scan(wpa_s);
2094 wpa_supplicant_req_scan(wpa_s, 0, 0);
2095 }
2096 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097 }
2098}
2099
2100
2101/**
2102 * wpa_supplicant_select_network - Attempt association with a network
2103 * @wpa_s: wpa_supplicant structure for a network interface
2104 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2105 */
2106void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2107 struct wpa_ssid *ssid)
2108{
2109
2110 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002111 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002112
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002113 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002114 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002115 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002116 disconnected = 1;
2117 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002118
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002119 if (ssid)
2120 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2121
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002122 /*
2123 * Mark all other networks disabled or mark all networks enabled if no
2124 * network specified.
2125 */
2126 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2127 other_ssid = other_ssid->next) {
2128 int was_disabled = other_ssid->disabled;
2129 if (was_disabled == 2)
2130 continue; /* do not change persistent P2P group data */
2131
2132 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002133 if (was_disabled && !other_ssid->disabled)
2134 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002135
2136 if (was_disabled != other_ssid->disabled)
2137 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2138 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002139
2140 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2141 /* We are already associated with the selected network */
2142 wpa_printf(MSG_DEBUG, "Already associated with the "
2143 "selected network - do nothing");
2144 return;
2145 }
2146
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002147 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002148 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002149 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2150 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002151 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152 wpa_s->disconnected = 0;
2153 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002154
2155 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2156 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002157
2158 if (ssid)
2159 wpas_notify_network_selected(wpa_s, ssid);
2160}
2161
2162
2163/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002164 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2165 * @wpa_s: wpa_supplicant structure for a network interface
2166 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2167 * @pkcs11_module_path: PKCS #11 module path or NULL
2168 * Returns: 0 on success; -1 on failure
2169 *
2170 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2171 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2172 * module path fails the paths will be reset to the default value (NULL).
2173 */
2174int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2175 const char *pkcs11_engine_path,
2176 const char *pkcs11_module_path)
2177{
2178 char *pkcs11_engine_path_copy = NULL;
2179 char *pkcs11_module_path_copy = NULL;
2180
2181 if (pkcs11_engine_path != NULL) {
2182 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2183 if (pkcs11_engine_path_copy == NULL)
2184 return -1;
2185 }
2186 if (pkcs11_module_path != NULL) {
2187 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002188 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002189 os_free(pkcs11_engine_path_copy);
2190 return -1;
2191 }
2192 }
2193
2194 os_free(wpa_s->conf->pkcs11_engine_path);
2195 os_free(wpa_s->conf->pkcs11_module_path);
2196 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2197 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2198
2199 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2200 eapol_sm_deinit(wpa_s->eapol);
2201 wpa_s->eapol = NULL;
2202 if (wpa_supplicant_init_eapol(wpa_s)) {
2203 /* Error -> Reset paths to the default value (NULL) once. */
2204 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2205 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2206 NULL);
2207
2208 return -1;
2209 }
2210 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2211
2212 return 0;
2213}
2214
2215
2216/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002217 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2218 * @wpa_s: wpa_supplicant structure for a network interface
2219 * @ap_scan: AP scan mode
2220 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2221 *
2222 */
2223int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2224{
2225
2226 int old_ap_scan;
2227
2228 if (ap_scan < 0 || ap_scan > 2)
2229 return -1;
2230
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002231#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002232 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2233 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2234 wpa_s->wpa_state < WPA_COMPLETED) {
2235 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2236 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002237 return 0;
2238 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002239#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002240
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241 old_ap_scan = wpa_s->conf->ap_scan;
2242 wpa_s->conf->ap_scan = ap_scan;
2243
2244 if (old_ap_scan != wpa_s->conf->ap_scan)
2245 wpas_notify_ap_scan_changed(wpa_s);
2246
2247 return 0;
2248}
2249
2250
2251/**
2252 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2253 * @wpa_s: wpa_supplicant structure for a network interface
2254 * @expire_age: Expiration age in seconds
2255 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2256 *
2257 */
2258int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2259 unsigned int bss_expire_age)
2260{
2261 if (bss_expire_age < 10) {
2262 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2263 bss_expire_age);
2264 return -1;
2265 }
2266 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2267 bss_expire_age);
2268 wpa_s->conf->bss_expiration_age = bss_expire_age;
2269
2270 return 0;
2271}
2272
2273
2274/**
2275 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2276 * @wpa_s: wpa_supplicant structure for a network interface
2277 * @expire_count: number of scans after which an unseen BSS is reclaimed
2278 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2279 *
2280 */
2281int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2282 unsigned int bss_expire_count)
2283{
2284 if (bss_expire_count < 1) {
2285 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2286 bss_expire_count);
2287 return -1;
2288 }
2289 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2290 bss_expire_count);
2291 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2292
2293 return 0;
2294}
2295
2296
2297/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002298 * wpa_supplicant_set_scan_interval - Set scan interval
2299 * @wpa_s: wpa_supplicant structure for a network interface
2300 * @scan_interval: scan interval in seconds
2301 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2302 *
2303 */
2304int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2305 int scan_interval)
2306{
2307 if (scan_interval < 0) {
2308 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2309 scan_interval);
2310 return -1;
2311 }
2312 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2313 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002314 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002315
2316 return 0;
2317}
2318
2319
2320/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002321 * wpa_supplicant_set_debug_params - Set global debug params
2322 * @global: wpa_global structure
2323 * @debug_level: debug level
2324 * @debug_timestamp: determines if show timestamp in debug data
2325 * @debug_show_keys: determines if show keys in debug data
2326 * Returns: 0 if succeed or -1 if debug_level has wrong value
2327 */
2328int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2329 int debug_timestamp, int debug_show_keys)
2330{
2331
2332 int old_level, old_timestamp, old_show_keys;
2333
2334 /* check for allowed debuglevels */
2335 if (debug_level != MSG_EXCESSIVE &&
2336 debug_level != MSG_MSGDUMP &&
2337 debug_level != MSG_DEBUG &&
2338 debug_level != MSG_INFO &&
2339 debug_level != MSG_WARNING &&
2340 debug_level != MSG_ERROR)
2341 return -1;
2342
2343 old_level = wpa_debug_level;
2344 old_timestamp = wpa_debug_timestamp;
2345 old_show_keys = wpa_debug_show_keys;
2346
2347 wpa_debug_level = debug_level;
2348 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2349 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2350
2351 if (wpa_debug_level != old_level)
2352 wpas_notify_debug_level_changed(global);
2353 if (wpa_debug_timestamp != old_timestamp)
2354 wpas_notify_debug_timestamp_changed(global);
2355 if (wpa_debug_show_keys != old_show_keys)
2356 wpas_notify_debug_show_keys_changed(global);
2357
2358 return 0;
2359}
2360
2361
2362/**
2363 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2364 * @wpa_s: Pointer to wpa_supplicant data
2365 * Returns: A pointer to the current network structure or %NULL on failure
2366 */
2367struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2368{
2369 struct wpa_ssid *entry;
2370 u8 ssid[MAX_SSID_LEN];
2371 int res;
2372 size_t ssid_len;
2373 u8 bssid[ETH_ALEN];
2374 int wired;
2375
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002376 res = wpa_drv_get_ssid(wpa_s, ssid);
2377 if (res < 0) {
2378 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2379 "driver");
2380 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002381 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002382 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002383
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002384 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002385 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2386 "driver");
2387 return NULL;
2388 }
2389
2390 wired = wpa_s->conf->ap_scan == 0 &&
2391 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2392
2393 entry = wpa_s->conf->ssid;
2394 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002395 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002396 ((ssid_len == entry->ssid_len &&
2397 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2398 (!entry->bssid_set ||
2399 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2400 return entry;
2401#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002402 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002403 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2404 (entry->ssid == NULL || entry->ssid_len == 0) &&
2405 (!entry->bssid_set ||
2406 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2407 return entry;
2408#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002409
Dmitry Shmidt04949592012-07-19 12:16:46 -07002410 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002411 entry->ssid_len == 0 &&
2412 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2413 return entry;
2414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002415 entry = entry->next;
2416 }
2417
2418 return NULL;
2419}
2420
2421
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002422static int select_driver(struct wpa_supplicant *wpa_s, int i)
2423{
2424 struct wpa_global *global = wpa_s->global;
2425
2426 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2427 global->drv_priv[i] = wpa_drivers[i]->global_init();
2428 if (global->drv_priv[i] == NULL) {
2429 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2430 "'%s'", wpa_drivers[i]->name);
2431 return -1;
2432 }
2433 }
2434
2435 wpa_s->driver = wpa_drivers[i];
2436 wpa_s->global_drv_priv = global->drv_priv[i];
2437
2438 return 0;
2439}
2440
2441
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2443 const char *name)
2444{
2445 int i;
2446 size_t len;
2447 const char *pos, *driver = name;
2448
2449 if (wpa_s == NULL)
2450 return -1;
2451
2452 if (wpa_drivers[0] == NULL) {
2453 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2454 "wpa_supplicant");
2455 return -1;
2456 }
2457
2458 if (name == NULL) {
2459 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002460 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461 }
2462
2463 do {
2464 pos = os_strchr(driver, ',');
2465 if (pos)
2466 len = pos - driver;
2467 else
2468 len = os_strlen(driver);
2469
2470 for (i = 0; wpa_drivers[i]; i++) {
2471 if (os_strlen(wpa_drivers[i]->name) == len &&
2472 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002473 0) {
2474 /* First driver that succeeds wins */
2475 if (select_driver(wpa_s, i) == 0)
2476 return 0;
2477 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478 }
2479
2480 driver = pos + 1;
2481 } while (pos);
2482
2483 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2484 return -1;
2485}
2486
2487
2488/**
2489 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2490 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2491 * with struct wpa_driver_ops::init()
2492 * @src_addr: Source address of the EAPOL frame
2493 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2494 * @len: Length of the EAPOL data
2495 *
2496 * This function is called for each received EAPOL frame. Most driver
2497 * interfaces rely on more generic OS mechanism for receiving frames through
2498 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2499 * take care of received EAPOL frames and deliver them to the core supplicant
2500 * code by calling this function.
2501 */
2502void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2503 const u8 *buf, size_t len)
2504{
2505 struct wpa_supplicant *wpa_s = ctx;
2506
2507 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2508 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2509
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002510#ifdef CONFIG_PEERKEY
2511 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2512 wpa_s->current_ssid->peerkey &&
2513 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2514 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2515 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2516 return;
2517 }
2518#endif /* CONFIG_PEERKEY */
2519
Jouni Malinena05074c2012-12-21 21:35:35 +02002520 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2521 (wpa_s->last_eapol_matches_bssid &&
2522#ifdef CONFIG_AP
2523 !wpa_s->ap_iface &&
2524#endif /* CONFIG_AP */
2525 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 /*
2527 * There is possible race condition between receiving the
2528 * association event and the EAPOL frame since they are coming
2529 * through different paths from the driver. In order to avoid
2530 * issues in trying to process the EAPOL frame before receiving
2531 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002532 * the association event is received. This may also be needed in
2533 * driver-based roaming case, so also use src_addr != BSSID as a
2534 * trigger if we have previously confirmed that the
2535 * Authenticator uses BSSID as the src_addr (which is not the
2536 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537 */
2538 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002539 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2540 wpa_supplicant_state_txt(wpa_s->wpa_state),
2541 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 wpabuf_free(wpa_s->pending_eapol_rx);
2543 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2544 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002545 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002546 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2547 ETH_ALEN);
2548 }
2549 return;
2550 }
2551
Jouni Malinena05074c2012-12-21 21:35:35 +02002552 wpa_s->last_eapol_matches_bssid =
2553 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555#ifdef CONFIG_AP
2556 if (wpa_s->ap_iface) {
2557 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2558 return;
2559 }
2560#endif /* CONFIG_AP */
2561
2562 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2563 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2564 "no key management is configured");
2565 return;
2566 }
2567
2568 if (wpa_s->eapol_received == 0 &&
2569 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2570 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2571 wpa_s->wpa_state != WPA_COMPLETED) &&
2572 (wpa_s->current_ssid == NULL ||
2573 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2574 /* Timeout for completing IEEE 802.1X and WPA authentication */
2575 wpa_supplicant_req_auth_timeout(
2576 wpa_s,
2577 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2578 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2579 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2580 70 : 10, 0);
2581 }
2582 wpa_s->eapol_received++;
2583
2584 if (wpa_s->countermeasures) {
2585 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2586 "EAPOL packet");
2587 return;
2588 }
2589
2590#ifdef CONFIG_IBSS_RSN
2591 if (wpa_s->current_ssid &&
2592 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2593 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2594 return;
2595 }
2596#endif /* CONFIG_IBSS_RSN */
2597
2598 /* Source address of the incoming EAPOL frame could be compared to the
2599 * current BSSID. However, it is possible that a centralized
2600 * Authenticator could be using another MAC address than the BSSID of
2601 * an AP, so just allow any address to be used for now. The replies are
2602 * still sent to the current BSSID (if available), though. */
2603
2604 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2605 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2606 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2607 return;
2608 wpa_drv_poll(wpa_s);
2609 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2610 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2611 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2612 /*
2613 * Set portValid = TRUE here since we are going to skip 4-way
2614 * handshake processing which would normally set portValid. We
2615 * need this to allow the EAPOL state machines to be completed
2616 * without going through EAPOL-Key handshake.
2617 */
2618 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2619 }
2620}
2621
2622
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002623int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002625 if (wpa_s->driver->send_eapol) {
2626 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2627 if (addr)
2628 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002629 } else if ((!wpa_s->p2p_mgmt ||
2630 !(wpa_s->drv_flags &
2631 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2632 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002634 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002635 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2636 wpa_drv_get_mac_addr(wpa_s),
2637 ETH_P_EAPOL,
2638 wpa_supplicant_rx_eapol, wpa_s, 0);
2639 if (wpa_s->l2 == NULL)
2640 return -1;
2641 } else {
2642 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2643 if (addr)
2644 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2645 }
2646
2647 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2648 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2649 return -1;
2650 }
2651
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002652 return 0;
2653}
2654
2655
Dmitry Shmidt04949592012-07-19 12:16:46 -07002656static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2657 const u8 *buf, size_t len)
2658{
2659 struct wpa_supplicant *wpa_s = ctx;
2660 const struct l2_ethhdr *eth;
2661
2662 if (len < sizeof(*eth))
2663 return;
2664 eth = (const struct l2_ethhdr *) buf;
2665
2666 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2667 !(eth->h_dest[0] & 0x01)) {
2668 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2669 " (bridge - not for this interface - ignore)",
2670 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2671 return;
2672 }
2673
2674 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2675 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2676 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2677 len - sizeof(*eth));
2678}
2679
2680
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002681/**
2682 * wpa_supplicant_driver_init - Initialize driver interface parameters
2683 * @wpa_s: Pointer to wpa_supplicant data
2684 * Returns: 0 on success, -1 on failure
2685 *
2686 * This function is called to initialize driver interface parameters.
2687 * wpa_drv_init() must have been called before this function to initialize the
2688 * driver interface.
2689 */
2690int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2691{
2692 static int interface_count = 0;
2693
2694 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2695 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002697 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2698 MAC2STR(wpa_s->own_addr));
2699 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2700
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701 if (wpa_s->bridge_ifname[0]) {
2702 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2703 "interface '%s'", wpa_s->bridge_ifname);
2704 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2705 wpa_s->own_addr,
2706 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002707 wpa_supplicant_rx_eapol_bridge,
2708 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 if (wpa_s->l2_br == NULL) {
2710 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2711 "connection for the bridge interface '%s'",
2712 wpa_s->bridge_ifname);
2713 return -1;
2714 }
2715 }
2716
2717 wpa_clear_keys(wpa_s, NULL);
2718
2719 /* Make sure that TKIP countermeasures are not left enabled (could
2720 * happen if wpa_supplicant is killed during countermeasures. */
2721 wpa_drv_set_countermeasures(wpa_s, 0);
2722
2723 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2724 wpa_drv_flush_pmkid(wpa_s);
2725
2726 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002727 wpa_s->prev_scan_wildcard = 0;
2728
Dmitry Shmidt04949592012-07-19 12:16:46 -07002729 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002730 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2731 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2732 interface_count = 0;
2733 }
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002734 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07002735 wpa_supplicant_delayed_sched_scan(wpa_s,
2736 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002737 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07002738 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002739 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002740 interface_count++;
2741 } else
2742 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2743
2744 return 0;
2745}
2746
2747
2748static int wpa_supplicant_daemon(const char *pid_file)
2749{
2750 wpa_printf(MSG_DEBUG, "Daemonize..");
2751 return os_daemonize(pid_file);
2752}
2753
2754
2755static struct wpa_supplicant * wpa_supplicant_alloc(void)
2756{
2757 struct wpa_supplicant *wpa_s;
2758
2759 wpa_s = os_zalloc(sizeof(*wpa_s));
2760 if (wpa_s == NULL)
2761 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002762 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002763 wpa_s->scan_interval = 5;
2764 wpa_s->new_connection = 1;
2765 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002766 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002767
2768 return wpa_s;
2769}
2770
2771
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002772#ifdef CONFIG_HT_OVERRIDES
2773
2774static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2775 struct ieee80211_ht_capabilities *htcaps,
2776 struct ieee80211_ht_capabilities *htcaps_mask,
2777 const char *ht_mcs)
2778{
2779 /* parse ht_mcs into hex array */
2780 int i;
2781 const char *tmp = ht_mcs;
2782 char *end = NULL;
2783
2784 /* If ht_mcs is null, do not set anything */
2785 if (!ht_mcs)
2786 return 0;
2787
2788 /* This is what we are setting in the kernel */
2789 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2790
2791 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2792
2793 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2794 errno = 0;
2795 long v = strtol(tmp, &end, 16);
2796 if (errno == 0) {
2797 wpa_msg(wpa_s, MSG_DEBUG,
2798 "htcap value[%i]: %ld end: %p tmp: %p",
2799 i, v, end, tmp);
2800 if (end == tmp)
2801 break;
2802
2803 htcaps->supported_mcs_set[i] = v;
2804 tmp = end;
2805 } else {
2806 wpa_msg(wpa_s, MSG_ERROR,
2807 "Failed to parse ht-mcs: %s, error: %s\n",
2808 ht_mcs, strerror(errno));
2809 return -1;
2810 }
2811 }
2812
2813 /*
2814 * If we were able to parse any values, then set mask for the MCS set.
2815 */
2816 if (i) {
2817 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2818 IEEE80211_HT_MCS_MASK_LEN - 1);
2819 /* skip the 3 reserved bits */
2820 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2821 0x1f;
2822 }
2823
2824 return 0;
2825}
2826
2827
2828static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2829 struct ieee80211_ht_capabilities *htcaps,
2830 struct ieee80211_ht_capabilities *htcaps_mask,
2831 int disabled)
2832{
2833 u16 msk;
2834
2835 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2836
2837 if (disabled == -1)
2838 return 0;
2839
2840 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2841 htcaps_mask->ht_capabilities_info |= msk;
2842 if (disabled)
2843 htcaps->ht_capabilities_info &= msk;
2844 else
2845 htcaps->ht_capabilities_info |= msk;
2846
2847 return 0;
2848}
2849
2850
2851static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2852 struct ieee80211_ht_capabilities *htcaps,
2853 struct ieee80211_ht_capabilities *htcaps_mask,
2854 int factor)
2855{
2856 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2857
2858 if (factor == -1)
2859 return 0;
2860
2861 if (factor < 0 || factor > 3) {
2862 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2863 "Must be 0-3 or -1", factor);
2864 return -EINVAL;
2865 }
2866
2867 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2868 htcaps->a_mpdu_params &= ~0x3;
2869 htcaps->a_mpdu_params |= factor & 0x3;
2870
2871 return 0;
2872}
2873
2874
2875static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2876 struct ieee80211_ht_capabilities *htcaps,
2877 struct ieee80211_ht_capabilities *htcaps_mask,
2878 int density)
2879{
2880 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2881
2882 if (density == -1)
2883 return 0;
2884
2885 if (density < 0 || density > 7) {
2886 wpa_msg(wpa_s, MSG_ERROR,
2887 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2888 density);
2889 return -EINVAL;
2890 }
2891
2892 htcaps_mask->a_mpdu_params |= 0x1C;
2893 htcaps->a_mpdu_params &= ~(0x1C);
2894 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2895
2896 return 0;
2897}
2898
2899
2900static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2901 struct ieee80211_ht_capabilities *htcaps,
2902 struct ieee80211_ht_capabilities *htcaps_mask,
2903 int disabled)
2904{
2905 /* Masking these out disables HT40 */
2906 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2907 HT_CAP_INFO_SHORT_GI40MHZ);
2908
2909 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2910
2911 if (disabled)
2912 htcaps->ht_capabilities_info &= ~msk;
2913 else
2914 htcaps->ht_capabilities_info |= msk;
2915
2916 htcaps_mask->ht_capabilities_info |= msk;
2917
2918 return 0;
2919}
2920
2921
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002922static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2923 struct ieee80211_ht_capabilities *htcaps,
2924 struct ieee80211_ht_capabilities *htcaps_mask,
2925 int disabled)
2926{
2927 /* Masking these out disables SGI */
2928 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2929 HT_CAP_INFO_SHORT_GI40MHZ);
2930
2931 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2932
2933 if (disabled)
2934 htcaps->ht_capabilities_info &= ~msk;
2935 else
2936 htcaps->ht_capabilities_info |= msk;
2937
2938 htcaps_mask->ht_capabilities_info |= msk;
2939
2940 return 0;
2941}
2942
2943
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07002944static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
2945 struct ieee80211_ht_capabilities *htcaps,
2946 struct ieee80211_ht_capabilities *htcaps_mask,
2947 int disabled)
2948{
2949 /* Masking these out disables LDPC */
2950 u16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
2951
2952 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
2953
2954 if (disabled)
2955 htcaps->ht_capabilities_info &= ~msk;
2956 else
2957 htcaps->ht_capabilities_info |= msk;
2958
2959 htcaps_mask->ht_capabilities_info |= msk;
2960
2961 return 0;
2962}
2963
2964
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002965void wpa_supplicant_apply_ht_overrides(
2966 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2967 struct wpa_driver_associate_params *params)
2968{
2969 struct ieee80211_ht_capabilities *htcaps;
2970 struct ieee80211_ht_capabilities *htcaps_mask;
2971
2972 if (!ssid)
2973 return;
2974
2975 params->disable_ht = ssid->disable_ht;
2976 if (!params->htcaps || !params->htcaps_mask)
2977 return;
2978
2979 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2980 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2981 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2982 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2983 ssid->disable_max_amsdu);
2984 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2985 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2986 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002987 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07002988 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07002989
2990 if (ssid->ht40_intolerant) {
2991 u16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
2992 htcaps->ht_capabilities_info |= bit;
2993 htcaps_mask->ht_capabilities_info |= bit;
2994 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002995}
2996
2997#endif /* CONFIG_HT_OVERRIDES */
2998
2999
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003000#ifdef CONFIG_VHT_OVERRIDES
3001void wpa_supplicant_apply_vht_overrides(
3002 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3003 struct wpa_driver_associate_params *params)
3004{
3005 struct ieee80211_vht_capabilities *vhtcaps;
3006 struct ieee80211_vht_capabilities *vhtcaps_mask;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003007#ifdef CONFIG_HT_OVERRIDES
3008 int max_ampdu;
3009 const u32 max_ampdu_mask = VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
3010#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003011
3012 if (!ssid)
3013 return;
3014
3015 params->disable_vht = ssid->disable_vht;
3016
3017 vhtcaps = (void *) params->vhtcaps;
3018 vhtcaps_mask = (void *) params->vhtcaps_mask;
3019
3020 if (!vhtcaps || !vhtcaps_mask)
3021 return;
3022
3023 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3024 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3025
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003026#ifdef CONFIG_HT_OVERRIDES
3027 /* if max ampdu is <= 3, we have to make the HT cap the same */
3028 if (ssid->vht_capa_mask & max_ampdu_mask) {
3029 max_ampdu = (ssid->vht_capa & max_ampdu_mask) >>
3030 find_first_bit(max_ampdu_mask);
3031
3032 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3033 wpa_set_ampdu_factor(wpa_s,
3034 (void *) params->htcaps,
3035 (void *) params->htcaps_mask,
3036 max_ampdu);
3037 }
3038#endif /* CONFIG_HT_OVERRIDES */
3039
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003040#define OVERRIDE_MCS(i) \
3041 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3042 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3043 3 << 2 * (i - 1); \
3044 vhtcaps->vht_supported_mcs_set.tx_map |= \
3045 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3046 } \
3047 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3048 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3049 3 << 2 * (i - 1); \
3050 vhtcaps->vht_supported_mcs_set.rx_map |= \
3051 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3052 }
3053
3054 OVERRIDE_MCS(1);
3055 OVERRIDE_MCS(2);
3056 OVERRIDE_MCS(3);
3057 OVERRIDE_MCS(4);
3058 OVERRIDE_MCS(5);
3059 OVERRIDE_MCS(6);
3060 OVERRIDE_MCS(7);
3061 OVERRIDE_MCS(8);
3062}
3063#endif /* CONFIG_VHT_OVERRIDES */
3064
3065
Dmitry Shmidt04949592012-07-19 12:16:46 -07003066static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3067{
3068#ifdef PCSC_FUNCS
3069 size_t len;
3070
3071 if (!wpa_s->conf->pcsc_reader)
3072 return 0;
3073
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003074 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003075 if (!wpa_s->scard)
3076 return 1;
3077
3078 if (wpa_s->conf->pcsc_pin &&
3079 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3080 scard_deinit(wpa_s->scard);
3081 wpa_s->scard = NULL;
3082 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3083 return -1;
3084 }
3085
3086 len = sizeof(wpa_s->imsi) - 1;
3087 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3088 scard_deinit(wpa_s->scard);
3089 wpa_s->scard = NULL;
3090 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3091 return -1;
3092 }
3093 wpa_s->imsi[len] = '\0';
3094
3095 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3096
3097 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3098 wpa_s->imsi, wpa_s->mnc_len);
3099
3100 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3101 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3102#endif /* PCSC_FUNCS */
3103
3104 return 0;
3105}
3106
3107
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003108int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3109{
3110 char *val, *pos;
3111
3112 ext_password_deinit(wpa_s->ext_pw);
3113 wpa_s->ext_pw = NULL;
3114 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3115
3116 if (!wpa_s->conf->ext_password_backend)
3117 return 0;
3118
3119 val = os_strdup(wpa_s->conf->ext_password_backend);
3120 if (val == NULL)
3121 return -1;
3122 pos = os_strchr(val, ':');
3123 if (pos)
3124 *pos++ = '\0';
3125
3126 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3127
3128 wpa_s->ext_pw = ext_password_init(val, pos);
3129 os_free(val);
3130 if (wpa_s->ext_pw == NULL) {
3131 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3132 return -1;
3133 }
3134 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3135
3136 return 0;
3137}
3138
3139
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003140static int wpas_check_wowlan_trigger(const char *start, const char *trigger,
3141 int capa_trigger, u8 *param_trigger)
3142{
3143 if (os_strcmp(start, trigger) != 0)
3144 return 0;
3145 if (!capa_trigger)
3146 return 0;
3147
3148 *param_trigger = 1;
3149 return 1;
3150}
3151
3152
3153int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
3154 struct wpa_driver_capa *capa)
3155{
3156 struct wowlan_triggers triggers;
3157 char *start, *end, *buf;
3158 int last, ret;
3159
3160 if (!wpa_s->conf->wowlan_triggers)
3161 return 0;
3162
3163 buf = os_strdup(wpa_s->conf->wowlan_triggers);
3164 if (buf == NULL)
3165 return -1;
3166
3167 os_memset(&triggers, 0, sizeof(triggers));
3168
3169#define CHECK_TRIGGER(trigger) \
3170 wpas_check_wowlan_trigger(start, #trigger, \
3171 capa->wowlan_triggers.trigger, \
3172 &triggers.trigger)
3173
3174 start = buf;
3175 while (*start != '\0') {
3176 while (isblank(*start))
3177 start++;
3178 if (*start == '\0')
3179 break;
3180 end = start;
3181 while (!isblank(*end) && *end != '\0')
3182 end++;
3183 last = *end == '\0';
3184 *end = '\0';
3185
3186 if (!CHECK_TRIGGER(any) &&
3187 !CHECK_TRIGGER(disconnect) &&
3188 !CHECK_TRIGGER(magic_pkt) &&
3189 !CHECK_TRIGGER(gtk_rekey_failure) &&
3190 !CHECK_TRIGGER(eap_identity_req) &&
3191 !CHECK_TRIGGER(four_way_handshake) &&
3192 !CHECK_TRIGGER(rfkill_release)) {
3193 wpa_printf(MSG_DEBUG,
3194 "Unknown/unsupported wowlan trigger '%s'",
3195 start);
3196 ret = -1;
3197 goto out;
3198 }
3199
3200 if (last)
3201 break;
3202 start = end + 1;
3203 }
3204#undef CHECK_TRIGGER
3205
3206 ret = wpa_drv_wowlan(wpa_s, &triggers);
3207out:
3208 os_free(buf);
3209 return ret;
3210}
3211
3212
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003213static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3214 const char *rn)
3215{
3216 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3217 struct wpa_radio *radio;
3218
3219 while (rn && iface) {
3220 radio = iface->radio;
3221 if (radio && os_strcmp(rn, radio->name) == 0) {
3222 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3223 wpa_s->ifname, rn);
3224 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3225 return radio;
3226 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003227
3228 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003229 }
3230
3231 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3232 wpa_s->ifname, rn ? rn : "N/A");
3233 radio = os_zalloc(sizeof(*radio));
3234 if (radio == NULL)
3235 return NULL;
3236
3237 if (rn)
3238 os_strlcpy(radio->name, rn, sizeof(radio->name));
3239 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003240 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003241 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3242
3243 return radio;
3244}
3245
3246
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003247static void radio_work_free(struct wpa_radio_work *work)
3248{
3249 if (work->wpa_s->scan_work == work) {
3250 /* This should not really happen. */
3251 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3252 work->type, work, work->started);
3253 work->wpa_s->scan_work = NULL;
3254 }
3255
3256#ifdef CONFIG_P2P
3257 if (work->wpa_s->p2p_scan_work == work) {
3258 /* This should not really happen. */
3259 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3260 work->type, work, work->started);
3261 work->wpa_s->p2p_scan_work = NULL;
3262 }
3263#endif /* CONFIG_P2P */
3264
3265 dl_list_del(&work->list);
3266 os_free(work);
3267}
3268
3269
3270static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3271{
3272 struct wpa_radio *radio = eloop_ctx;
3273 struct wpa_radio_work *work;
3274 struct os_reltime now, diff;
3275 struct wpa_supplicant *wpa_s;
3276
3277 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3278 if (work == NULL)
3279 return;
3280
3281 if (work->started)
3282 return; /* already started and still in progress */
3283
3284 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3285 radio_list);
3286 if (wpa_s && wpa_s->external_scan_running) {
3287 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3288 return;
3289 }
3290
3291 os_get_reltime(&now);
3292 os_reltime_sub(&now, &work->time, &diff);
3293 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3294 work->type, work, diff.sec, diff.usec);
3295 work->started = 1;
3296 work->time = now;
3297 work->cb(work, 0);
3298}
3299
3300
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003301/*
3302 * This function removes both started and pending radio works running on
3303 * the provided interface's radio.
3304 * Prior to the removal of the radio work, its callback (cb) is called with
3305 * deinit set to be 1. Each work's callback is responsible for clearing its
3306 * internal data and restoring to a correct state.
3307 * @wpa_s: wpa_supplicant data
3308 * @type: type of works to be removed
3309 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3310 * this interface's works.
3311 */
3312void radio_remove_works(struct wpa_supplicant *wpa_s,
3313 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003314{
3315 struct wpa_radio_work *work, *tmp;
3316 struct wpa_radio *radio = wpa_s->radio;
3317
3318 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3319 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003320 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003321 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003322
3323 /* skip other ifaces' works */
3324 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003325 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003326
3327 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3328 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003329 work->cb(work, 1);
3330 radio_work_free(work);
3331 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003332
3333 /* in case we removed the started work */
3334 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003335}
3336
3337
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003338static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3339{
3340 struct wpa_radio *radio = wpa_s->radio;
3341
3342 if (!radio)
3343 return;
3344
3345 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3346 wpa_s->ifname, radio->name);
3347 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003348 radio_remove_works(wpa_s, NULL, 0);
3349 wpa_s->radio = NULL;
3350 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003351 return; /* Interfaces remain for this radio */
3352
3353 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003354 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003355 os_free(radio);
3356}
3357
3358
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003359void radio_work_check_next(struct wpa_supplicant *wpa_s)
3360{
3361 struct wpa_radio *radio = wpa_s->radio;
3362
3363 if (dl_list_empty(&radio->work))
3364 return;
3365 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3366 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3367}
3368
3369
3370/**
3371 * radio_add_work - Add a radio work item
3372 * @wpa_s: Pointer to wpa_supplicant data
3373 * @freq: Frequency of the offchannel operation in MHz or 0
3374 * @type: Unique identifier for each type of work
3375 * @next: Force as the next work to be executed
3376 * @cb: Callback function for indicating when radio is available
3377 * @ctx: Context pointer for the work (work->ctx in cb())
3378 * Returns: 0 on success, -1 on failure
3379 *
3380 * This function is used to request time for an operation that requires
3381 * exclusive radio control. Once the radio is available, the registered callback
3382 * function will be called. radio_work_done() must be called once the exclusive
3383 * radio operation has been completed, so that the radio is freed for other
3384 * operations. The special case of deinit=1 is used to free the context data
3385 * during interface removal. That does not allow the callback function to start
3386 * the radio operation, i.e., it must free any resources allocated for the radio
3387 * work and return.
3388 *
3389 * The @freq parameter can be used to indicate a single channel on which the
3390 * offchannel operation will occur. This may allow multiple radio work
3391 * operations to be performed in parallel if they apply for the same channel.
3392 * Setting this to 0 indicates that the work item may use multiple channels or
3393 * requires exclusive control of the radio.
3394 */
3395int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3396 const char *type, int next,
3397 void (*cb)(struct wpa_radio_work *work, int deinit),
3398 void *ctx)
3399{
3400 struct wpa_radio_work *work;
3401 int was_empty;
3402
3403 work = os_zalloc(sizeof(*work));
3404 if (work == NULL)
3405 return -1;
3406 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3407 os_get_reltime(&work->time);
3408 work->freq = freq;
3409 work->type = type;
3410 work->wpa_s = wpa_s;
3411 work->cb = cb;
3412 work->ctx = ctx;
3413
3414 was_empty = dl_list_empty(&wpa_s->radio->work);
3415 if (next)
3416 dl_list_add(&wpa_s->radio->work, &work->list);
3417 else
3418 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3419 if (was_empty) {
3420 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3421 radio_work_check_next(wpa_s);
3422 }
3423
3424 return 0;
3425}
3426
3427
3428/**
3429 * radio_work_done - Indicate that a radio work item has been completed
3430 * @work: Completed work
3431 *
3432 * This function is called once the callback function registered with
3433 * radio_add_work() has completed its work.
3434 */
3435void radio_work_done(struct wpa_radio_work *work)
3436{
3437 struct wpa_supplicant *wpa_s = work->wpa_s;
3438 struct os_reltime now, diff;
3439 unsigned int started = work->started;
3440
3441 os_get_reltime(&now);
3442 os_reltime_sub(&now, &work->time, &diff);
3443 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3444 work->type, work, started ? "done" : "canceled",
3445 diff.sec, diff.usec);
3446 radio_work_free(work);
3447 if (started)
3448 radio_work_check_next(wpa_s);
3449}
3450
3451
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003452int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
3453{
3454 struct wpa_radio_work *work;
3455 struct wpa_radio *radio = wpa_s->radio;
3456
3457 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3458 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
3459 return 1;
3460 }
3461
3462 return 0;
3463}
3464
3465
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003466static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3467 struct wpa_interface *iface)
3468{
3469 const char *ifname, *driver, *rn;
3470
3471 driver = iface->driver;
3472next_driver:
3473 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3474 return -1;
3475
3476 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3477 if (wpa_s->drv_priv == NULL) {
3478 const char *pos;
3479 pos = driver ? os_strchr(driver, ',') : NULL;
3480 if (pos) {
3481 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3482 "driver interface - try next driver wrapper");
3483 driver = pos + 1;
3484 goto next_driver;
3485 }
3486 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3487 "interface");
3488 return -1;
3489 }
3490 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3491 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3492 "driver_param '%s'", wpa_s->conf->driver_param);
3493 return -1;
3494 }
3495
3496 ifname = wpa_drv_get_ifname(wpa_s);
3497 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3498 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3499 "interface name with '%s'", ifname);
3500 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3501 }
3502
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003503 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003504 if (rn && rn[0] == '\0')
3505 rn = NULL;
3506
3507 wpa_s->radio = radio_add_interface(wpa_s, rn);
3508 if (wpa_s->radio == NULL)
3509 return -1;
3510
3511 return 0;
3512}
3513
3514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003515static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3516 struct wpa_interface *iface)
3517{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518 struct wpa_driver_capa capa;
3519
3520 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3521 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3522 iface->confname ? iface->confname : "N/A",
3523 iface->driver ? iface->driver : "default",
3524 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3525 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3526
3527 if (iface->confname) {
3528#ifdef CONFIG_BACKEND_FILE
3529 wpa_s->confname = os_rel2abs_path(iface->confname);
3530 if (wpa_s->confname == NULL) {
3531 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3532 "for configuration file '%s'.",
3533 iface->confname);
3534 return -1;
3535 }
3536 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3537 iface->confname, wpa_s->confname);
3538#else /* CONFIG_BACKEND_FILE */
3539 wpa_s->confname = os_strdup(iface->confname);
3540#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003541 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003542 if (wpa_s->conf == NULL) {
3543 wpa_printf(MSG_ERROR, "Failed to read or parse "
3544 "configuration '%s'.", wpa_s->confname);
3545 return -1;
3546 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003547 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3548 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003549
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003550#ifdef CONFIG_P2P
3551 wpa_s->conf_p2p_dev = os_rel2abs_path(iface->conf_p2p_dev);
3552 wpa_config_read(wpa_s->conf_p2p_dev, wpa_s->conf);
3553#endif /* CONFIG_P2P */
3554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003555 /*
3556 * Override ctrl_interface and driver_param if set on command
3557 * line.
3558 */
3559 if (iface->ctrl_interface) {
3560 os_free(wpa_s->conf->ctrl_interface);
3561 wpa_s->conf->ctrl_interface =
3562 os_strdup(iface->ctrl_interface);
3563 }
3564
3565 if (iface->driver_param) {
3566 os_free(wpa_s->conf->driver_param);
3567 wpa_s->conf->driver_param =
3568 os_strdup(iface->driver_param);
3569 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003570
3571 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3572 os_free(wpa_s->conf->ctrl_interface);
3573 wpa_s->conf->ctrl_interface = NULL;
3574 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003575 } else
3576 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3577 iface->driver_param);
3578
3579 if (wpa_s->conf == NULL) {
3580 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3581 return -1;
3582 }
3583
3584 if (iface->ifname == NULL) {
3585 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3586 return -1;
3587 }
3588 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3589 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3590 iface->ifname);
3591 return -1;
3592 }
3593 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3594
3595 if (iface->bridge_ifname) {
3596 if (os_strlen(iface->bridge_ifname) >=
3597 sizeof(wpa_s->bridge_ifname)) {
3598 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3599 "name '%s'.", iface->bridge_ifname);
3600 return -1;
3601 }
3602 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3603 sizeof(wpa_s->bridge_ifname));
3604 }
3605
3606 /* RSNA Supplicant Key Management - INITIALIZE */
3607 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3608 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3609
3610 /* Initialize driver interface and register driver event handler before
3611 * L2 receive handler so that association events are processed before
3612 * EAPOL-Key packets if both become available for the same select()
3613 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003614 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003615 return -1;
3616
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003617 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3618 return -1;
3619
3620 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3621 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3622 NULL);
3623 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3624
3625 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3626 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3627 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3628 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3629 "dot11RSNAConfigPMKLifetime");
3630 return -1;
3631 }
3632
3633 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3634 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3635 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3636 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3637 "dot11RSNAConfigPMKReauthThreshold");
3638 return -1;
3639 }
3640
3641 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3642 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3643 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3644 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3645 "dot11RSNAConfigSATimeout");
3646 return -1;
3647 }
3648
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003649 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3650 &wpa_s->hw.num_modes,
3651 &wpa_s->hw.flags);
3652
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003653 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003654 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003655 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003656 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003657 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003658 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003659 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3660 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3661 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003662 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3663 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003664 wpa_s->extended_capa = capa.extended_capa;
3665 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3666 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003667 wpa_s->num_multichan_concurrent =
3668 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669 }
3670 if (wpa_s->max_remain_on_chan == 0)
3671 wpa_s->max_remain_on_chan = 1000;
3672
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003673 /*
3674 * Only take p2p_mgmt parameters when P2P Device is supported.
3675 * Doing it here as it determines whether l2_packet_init() will be done
3676 * during wpa_supplicant_driver_init().
3677 */
3678 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3679 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3680 else
3681 iface->p2p_mgmt = 1;
3682
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003683 if (wpa_s->num_multichan_concurrent == 0)
3684 wpa_s->num_multichan_concurrent = 1;
3685
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003686 if (wpa_supplicant_driver_init(wpa_s) < 0)
3687 return -1;
3688
3689#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003690 if ((!iface->p2p_mgmt ||
3691 !(wpa_s->drv_flags &
3692 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3693 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003694 return -1;
3695#endif /* CONFIG_TDLS */
3696
3697 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3698 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3699 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3700 return -1;
3701 }
3702
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003703 if (wpas_wps_init(wpa_s))
3704 return -1;
3705
3706 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3707 return -1;
3708 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3709
3710 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3711 if (wpa_s->ctrl_iface == NULL) {
3712 wpa_printf(MSG_ERROR,
3713 "Failed to initialize control interface '%s'.\n"
3714 "You may have another wpa_supplicant process "
3715 "already running or the file was\n"
3716 "left by an unclean termination of wpa_supplicant "
3717 "in which case you will need\n"
3718 "to manually remove this file before starting "
3719 "wpa_supplicant again.\n",
3720 wpa_s->conf->ctrl_interface);
3721 return -1;
3722 }
3723
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003724 wpa_s->gas = gas_query_init(wpa_s);
3725 if (wpa_s->gas == NULL) {
3726 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3727 return -1;
3728 }
3729
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003730 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003731 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3732 return -1;
3733 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003734
3735 if (wpa_bss_init(wpa_s) < 0)
3736 return -1;
3737
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003738 /*
3739 * Set Wake-on-WLAN triggers, if configured.
3740 * Note: We don't restore/remove the triggers on shutdown (it doesn't
3741 * have effect anyway when the interface is down).
3742 */
3743 if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
3744 return -1;
3745
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003746#ifdef CONFIG_EAP_PROXY
3747{
3748 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003749 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3750 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003751 if (wpa_s->mnc_len > 0) {
3752 wpa_s->imsi[len] = '\0';
3753 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3754 wpa_s->imsi, wpa_s->mnc_len);
3755 } else {
3756 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3757 }
3758}
3759#endif /* CONFIG_EAP_PROXY */
3760
Dmitry Shmidt04949592012-07-19 12:16:46 -07003761 if (pcsc_reader_init(wpa_s) < 0)
3762 return -1;
3763
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003764 if (wpas_init_ext_pw(wpa_s) < 0)
3765 return -1;
3766
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767 return 0;
3768}
3769
3770
3771static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003772 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003773{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003774 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003775 if (wpa_s->drv_priv) {
3776 wpa_supplicant_deauthenticate(wpa_s,
3777 WLAN_REASON_DEAUTH_LEAVING);
3778
3779 wpa_drv_set_countermeasures(wpa_s, 0);
3780 wpa_clear_keys(wpa_s, NULL);
3781 }
3782
3783 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003784 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003785
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003786 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003787 radio_remove_interface(wpa_s);
3788
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003789 if (wpa_s->drv_priv)
3790 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003791
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003792 if (notify)
3793 wpas_notify_iface_removed(wpa_s);
3794
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003795 if (terminate)
3796 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003797
3798 if (wpa_s->ctrl_iface) {
3799 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3800 wpa_s->ctrl_iface = NULL;
3801 }
3802
3803 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003804 wpa_config_free(wpa_s->conf);
3805 wpa_s->conf = NULL;
3806 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003807
3808 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003809}
3810
3811
3812/**
3813 * wpa_supplicant_add_iface - Add a new network interface
3814 * @global: Pointer to global data from wpa_supplicant_init()
3815 * @iface: Interface configuration options
3816 * Returns: Pointer to the created interface or %NULL on failure
3817 *
3818 * This function is used to add new network interfaces for %wpa_supplicant.
3819 * This can be called before wpa_supplicant_run() to add interfaces before the
3820 * main event loop has been started. In addition, new interfaces can be added
3821 * dynamically while %wpa_supplicant is already running. This could happen,
3822 * e.g., when a hotplug network adapter is inserted.
3823 */
3824struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3825 struct wpa_interface *iface)
3826{
3827 struct wpa_supplicant *wpa_s;
3828 struct wpa_interface t_iface;
3829 struct wpa_ssid *ssid;
3830
3831 if (global == NULL || iface == NULL)
3832 return NULL;
3833
3834 wpa_s = wpa_supplicant_alloc();
3835 if (wpa_s == NULL)
3836 return NULL;
3837
3838 wpa_s->global = global;
3839
3840 t_iface = *iface;
3841 if (global->params.override_driver) {
3842 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3843 "('%s' -> '%s')",
3844 iface->driver, global->params.override_driver);
3845 t_iface.driver = global->params.override_driver;
3846 }
3847 if (global->params.override_ctrl_interface) {
3848 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3849 "ctrl_interface ('%s' -> '%s')",
3850 iface->ctrl_interface,
3851 global->params.override_ctrl_interface);
3852 t_iface.ctrl_interface =
3853 global->params.override_ctrl_interface;
3854 }
3855 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3856 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3857 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003858 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003859 return NULL;
3860 }
3861
3862 /* Notify the control interfaces about new iface */
3863 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003864 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003865 return NULL;
3866 }
3867
3868 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3869 wpas_notify_network_added(wpa_s, ssid);
3870
3871 wpa_s->next = global->ifaces;
3872 global->ifaces = wpa_s;
3873
3874 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003875 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003876
3877 return wpa_s;
3878}
3879
3880
3881/**
3882 * wpa_supplicant_remove_iface - Remove a network interface
3883 * @global: Pointer to global data from wpa_supplicant_init()
3884 * @wpa_s: Pointer to the network interface to be removed
3885 * Returns: 0 if interface was removed, -1 if interface was not found
3886 *
3887 * This function can be used to dynamically remove network interfaces from
3888 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3889 * addition, this function is used to remove all remaining interfaces when
3890 * %wpa_supplicant is terminated.
3891 */
3892int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003893 struct wpa_supplicant *wpa_s,
3894 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003895{
3896 struct wpa_supplicant *prev;
3897
3898 /* Remove interface from the global list of interfaces */
3899 prev = global->ifaces;
3900 if (prev == wpa_s) {
3901 global->ifaces = wpa_s->next;
3902 } else {
3903 while (prev && prev->next != wpa_s)
3904 prev = prev->next;
3905 if (prev == NULL)
3906 return -1;
3907 prev->next = wpa_s->next;
3908 }
3909
3910 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3911
3912 if (global->p2p_group_formation == wpa_s)
3913 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003914 if (global->p2p_invite_group == wpa_s)
3915 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003916 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003917
3918 return 0;
3919}
3920
3921
3922/**
3923 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3924 * @wpa_s: Pointer to the network interface
3925 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3926 */
3927const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3928{
3929 const char *eapol_method;
3930
3931 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3932 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3933 return "NO-EAP";
3934 }
3935
3936 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3937 if (eapol_method == NULL)
3938 return "UNKNOWN-EAP";
3939
3940 return eapol_method;
3941}
3942
3943
3944/**
3945 * wpa_supplicant_get_iface - Get a new network interface
3946 * @global: Pointer to global data from wpa_supplicant_init()
3947 * @ifname: Interface name
3948 * Returns: Pointer to the interface or %NULL if not found
3949 */
3950struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3951 const char *ifname)
3952{
3953 struct wpa_supplicant *wpa_s;
3954
3955 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3956 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3957 return wpa_s;
3958 }
3959 return NULL;
3960}
3961
3962
3963#ifndef CONFIG_NO_WPA_MSG
3964static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3965{
3966 struct wpa_supplicant *wpa_s = ctx;
3967 if (wpa_s == NULL)
3968 return NULL;
3969 return wpa_s->ifname;
3970}
3971#endif /* CONFIG_NO_WPA_MSG */
3972
3973
3974/**
3975 * wpa_supplicant_init - Initialize %wpa_supplicant
3976 * @params: Parameters for %wpa_supplicant
3977 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3978 *
3979 * This function is used to initialize %wpa_supplicant. After successful
3980 * initialization, the returned data pointer can be used to add and remove
3981 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3982 */
3983struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3984{
3985 struct wpa_global *global;
3986 int ret, i;
3987
3988 if (params == NULL)
3989 return NULL;
3990
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003991#ifdef CONFIG_DRIVER_NDIS
3992 {
3993 void driver_ndis_init_ops(void);
3994 driver_ndis_init_ops();
3995 }
3996#endif /* CONFIG_DRIVER_NDIS */
3997
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003998#ifndef CONFIG_NO_WPA_MSG
3999 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4000#endif /* CONFIG_NO_WPA_MSG */
4001
4002 wpa_debug_open_file(params->wpa_debug_file_path);
4003 if (params->wpa_debug_syslog)
4004 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004005 if (params->wpa_debug_tracing) {
4006 ret = wpa_debug_open_linux_tracing();
4007 if (ret) {
4008 wpa_printf(MSG_ERROR,
4009 "Failed to enable trace logging");
4010 return NULL;
4011 }
4012 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004013
4014 ret = eap_register_methods();
4015 if (ret) {
4016 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4017 if (ret == -2)
4018 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4019 "the same EAP type.");
4020 return NULL;
4021 }
4022
4023 global = os_zalloc(sizeof(*global));
4024 if (global == NULL)
4025 return NULL;
4026 dl_list_init(&global->p2p_srv_bonjour);
4027 dl_list_init(&global->p2p_srv_upnp);
4028 global->params.daemonize = params->daemonize;
4029 global->params.wait_for_monitor = params->wait_for_monitor;
4030 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4031 if (params->pid_file)
4032 global->params.pid_file = os_strdup(params->pid_file);
4033 if (params->ctrl_interface)
4034 global->params.ctrl_interface =
4035 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004036 if (params->ctrl_interface_group)
4037 global->params.ctrl_interface_group =
4038 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004039 if (params->override_driver)
4040 global->params.override_driver =
4041 os_strdup(params->override_driver);
4042 if (params->override_ctrl_interface)
4043 global->params.override_ctrl_interface =
4044 os_strdup(params->override_ctrl_interface);
4045 wpa_debug_level = global->params.wpa_debug_level =
4046 params->wpa_debug_level;
4047 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4048 params->wpa_debug_show_keys;
4049 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4050 params->wpa_debug_timestamp;
4051
4052 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4053
4054 if (eloop_init()) {
4055 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4056 wpa_supplicant_deinit(global);
4057 return NULL;
4058 }
4059
Jouni Malinen75ecf522011-06-27 15:19:46 -07004060 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004061
4062 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4063 if (global->ctrl_iface == NULL) {
4064 wpa_supplicant_deinit(global);
4065 return NULL;
4066 }
4067
4068 if (wpas_notify_supplicant_initialized(global)) {
4069 wpa_supplicant_deinit(global);
4070 return NULL;
4071 }
4072
4073 for (i = 0; wpa_drivers[i]; i++)
4074 global->drv_count++;
4075 if (global->drv_count == 0) {
4076 wpa_printf(MSG_ERROR, "No drivers enabled");
4077 wpa_supplicant_deinit(global);
4078 return NULL;
4079 }
4080 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
4081 if (global->drv_priv == NULL) {
4082 wpa_supplicant_deinit(global);
4083 return NULL;
4084 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004085
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004086#ifdef CONFIG_WIFI_DISPLAY
4087 if (wifi_display_init(global) < 0) {
4088 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4089 wpa_supplicant_deinit(global);
4090 return NULL;
4091 }
4092#endif /* CONFIG_WIFI_DISPLAY */
4093
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004094 return global;
4095}
4096
4097
4098/**
4099 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4100 * @global: Pointer to global data from wpa_supplicant_init()
4101 * Returns: 0 after successful event loop run, -1 on failure
4102 *
4103 * This function starts the main event loop and continues running as long as
4104 * there are any remaining events. In most cases, this function is running as
4105 * long as the %wpa_supplicant process in still in use.
4106 */
4107int wpa_supplicant_run(struct wpa_global *global)
4108{
4109 struct wpa_supplicant *wpa_s;
4110
4111 if (global->params.daemonize &&
4112 wpa_supplicant_daemon(global->params.pid_file))
4113 return -1;
4114
4115 if (global->params.wait_for_monitor) {
4116 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4117 if (wpa_s->ctrl_iface)
4118 wpa_supplicant_ctrl_iface_wait(
4119 wpa_s->ctrl_iface);
4120 }
4121
4122 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4123 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4124
4125 eloop_run();
4126
4127 return 0;
4128}
4129
4130
4131/**
4132 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4133 * @global: Pointer to global data from wpa_supplicant_init()
4134 *
4135 * This function is called to deinitialize %wpa_supplicant and to free all
4136 * allocated resources. Remaining network interfaces will also be removed.
4137 */
4138void wpa_supplicant_deinit(struct wpa_global *global)
4139{
4140 int i;
4141
4142 if (global == NULL)
4143 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004144
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004145#ifdef CONFIG_WIFI_DISPLAY
4146 wifi_display_deinit(global);
4147#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004148
4149 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004150 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004151
4152 if (global->ctrl_iface)
4153 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4154
4155 wpas_notify_supplicant_deinitialized(global);
4156
4157 eap_peer_unregister_methods();
4158#ifdef CONFIG_AP
4159 eap_server_unregister_methods();
4160#endif /* CONFIG_AP */
4161
4162 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4163 if (!global->drv_priv[i])
4164 continue;
4165 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4166 }
4167 os_free(global->drv_priv);
4168
4169 random_deinit();
4170
4171 eloop_destroy();
4172
4173 if (global->params.pid_file) {
4174 os_daemonize_terminate(global->params.pid_file);
4175 os_free(global->params.pid_file);
4176 }
4177 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004178 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004179 os_free(global->params.override_driver);
4180 os_free(global->params.override_ctrl_interface);
4181
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004182 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004183 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004184 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004185
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004186 os_free(global);
4187 wpa_debug_close_syslog();
4188 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004189 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004190}
4191
4192
4193void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4194{
4195 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4196 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4197 char country[3];
4198 country[0] = wpa_s->conf->country[0];
4199 country[1] = wpa_s->conf->country[1];
4200 country[2] = '\0';
4201 if (wpa_drv_set_country(wpa_s, country) < 0) {
4202 wpa_printf(MSG_ERROR, "Failed to set country code "
4203 "'%s'", country);
4204 }
4205 }
4206
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004207 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4208 wpas_init_ext_pw(wpa_s);
4209
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004210#ifdef CONFIG_WPS
4211 wpas_wps_update_config(wpa_s);
4212#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004213 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004214 wpa_s->conf->changed_parameters = 0;
4215}
4216
4217
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004218static void add_freq(int *freqs, int *num_freqs, int freq)
4219{
4220 int i;
4221
4222 for (i = 0; i < *num_freqs; i++) {
4223 if (freqs[i] == freq)
4224 return;
4225 }
4226
4227 freqs[*num_freqs] = freq;
4228 (*num_freqs)++;
4229}
4230
4231
4232static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4233{
4234 struct wpa_bss *bss, *cbss;
4235 const int max_freqs = 10;
4236 int *freqs;
4237 int num_freqs = 0;
4238
4239 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
4240 if (freqs == NULL)
4241 return NULL;
4242
4243 cbss = wpa_s->current_bss;
4244
4245 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4246 if (bss == cbss)
4247 continue;
4248 if (bss->ssid_len == cbss->ssid_len &&
4249 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4250 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4251 add_freq(freqs, &num_freqs, bss->freq);
4252 if (num_freqs == max_freqs)
4253 break;
4254 }
4255 }
4256
4257 if (num_freqs == 0) {
4258 os_free(freqs);
4259 freqs = NULL;
4260 }
4261
4262 return freqs;
4263}
4264
4265
4266void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4267{
4268 int timeout;
4269 int count;
4270 int *freqs = NULL;
4271
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004272 wpas_connect_work_done(wpa_s);
4273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004274 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004275 * Remove possible authentication timeout since the connection failed.
4276 */
4277 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4278
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004279 if (wpa_s->disconnected) {
4280 /*
4281 * There is no point in blacklisting the AP if this event is
4282 * generated based on local request to disconnect.
4283 */
4284 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4285 "indication since interface has been put into "
4286 "disconnected state");
4287 return;
4288 }
4289
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004290 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004291 * Add the failed BSSID into the blacklist and speed up next scan
4292 * attempt if there could be other APs that could accept association.
4293 * The current blacklist count indicates how many times we have tried
4294 * connecting to this AP and multiple attempts mean that other APs are
4295 * either not available or has already been tried, so that we can start
4296 * increasing the delay here to avoid constant scanning.
4297 */
4298 count = wpa_blacklist_add(wpa_s, bssid);
4299 if (count == 1 && wpa_s->current_bss) {
4300 /*
4301 * This BSS was not in the blacklist before. If there is
4302 * another BSS available for the same ESS, we should try that
4303 * next. Otherwise, we may as well try this one once more
4304 * before allowing other, likely worse, ESSes to be considered.
4305 */
4306 freqs = get_bss_freqs_in_ess(wpa_s);
4307 if (freqs) {
4308 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4309 "has been seen; try it next");
4310 wpa_blacklist_add(wpa_s, bssid);
4311 /*
4312 * On the next scan, go through only the known channels
4313 * used in this ESS based on previous scans to speed up
4314 * common load balancing use case.
4315 */
4316 os_free(wpa_s->next_scan_freqs);
4317 wpa_s->next_scan_freqs = freqs;
4318 }
4319 }
4320
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004321 /*
4322 * Add previous failure count in case the temporary blacklist was
4323 * cleared due to no other BSSes being available.
4324 */
4325 count += wpa_s->extra_blacklist_count;
4326
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004327 if (count > 3 && wpa_s->current_ssid) {
4328 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4329 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004330 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004331 }
4332
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004333 switch (count) {
4334 case 1:
4335 timeout = 100;
4336 break;
4337 case 2:
4338 timeout = 500;
4339 break;
4340 case 3:
4341 timeout = 1000;
4342 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004343 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004344 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004345 break;
4346 default:
4347 timeout = 10000;
4348 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349 }
4350
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004351 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4352 "ms", count, timeout);
4353
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004354 /*
4355 * TODO: if more than one possible AP is available in scan results,
4356 * could try the other ones before requesting a new scan.
4357 */
4358 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4359 1000 * (timeout % 1000));
4360}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004361
4362
4363int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4364{
4365 return wpa_s->conf->ap_scan == 2 ||
4366 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4367}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004368
Dmitry Shmidt04949592012-07-19 12:16:46 -07004369
4370#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4371int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4372 struct wpa_ssid *ssid,
4373 const char *field,
4374 const char *value)
4375{
4376#ifdef IEEE8021X_EAPOL
4377 struct eap_peer_config *eap = &ssid->eap;
4378
4379 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4380 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4381 (const u8 *) value, os_strlen(value));
4382
4383 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4384 case WPA_CTRL_REQ_EAP_IDENTITY:
4385 os_free(eap->identity);
4386 eap->identity = (u8 *) os_strdup(value);
4387 eap->identity_len = os_strlen(value);
4388 eap->pending_req_identity = 0;
4389 if (ssid == wpa_s->current_ssid)
4390 wpa_s->reassociate = 1;
4391 break;
4392 case WPA_CTRL_REQ_EAP_PASSWORD:
4393 os_free(eap->password);
4394 eap->password = (u8 *) os_strdup(value);
4395 eap->password_len = os_strlen(value);
4396 eap->pending_req_password = 0;
4397 if (ssid == wpa_s->current_ssid)
4398 wpa_s->reassociate = 1;
4399 break;
4400 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
4401 os_free(eap->new_password);
4402 eap->new_password = (u8 *) os_strdup(value);
4403 eap->new_password_len = os_strlen(value);
4404 eap->pending_req_new_password = 0;
4405 if (ssid == wpa_s->current_ssid)
4406 wpa_s->reassociate = 1;
4407 break;
4408 case WPA_CTRL_REQ_EAP_PIN:
4409 os_free(eap->pin);
4410 eap->pin = os_strdup(value);
4411 eap->pending_req_pin = 0;
4412 if (ssid == wpa_s->current_ssid)
4413 wpa_s->reassociate = 1;
4414 break;
4415 case WPA_CTRL_REQ_EAP_OTP:
4416 os_free(eap->otp);
4417 eap->otp = (u8 *) os_strdup(value);
4418 eap->otp_len = os_strlen(value);
4419 os_free(eap->pending_req_otp);
4420 eap->pending_req_otp = NULL;
4421 eap->pending_req_otp_len = 0;
4422 break;
4423 case WPA_CTRL_REQ_EAP_PASSPHRASE:
4424 os_free(eap->private_key_passwd);
4425 eap->private_key_passwd = (u8 *) os_strdup(value);
4426 eap->pending_req_passphrase = 0;
4427 if (ssid == wpa_s->current_ssid)
4428 wpa_s->reassociate = 1;
4429 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004430 case WPA_CTRL_REQ_SIM:
4431 os_free(eap->external_sim_resp);
4432 eap->external_sim_resp = os_strdup(value);
4433 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004434 default:
4435 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4436 return -1;
4437 }
4438
4439 return 0;
4440#else /* IEEE8021X_EAPOL */
4441 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4442 return -1;
4443#endif /* IEEE8021X_EAPOL */
4444}
4445#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4446
4447
4448int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4449{
4450 int i;
4451 unsigned int drv_enc;
4452
4453 if (ssid == NULL)
4454 return 1;
4455
4456 if (ssid->disabled)
4457 return 1;
4458
4459 if (wpa_s && wpa_s->drv_capa_known)
4460 drv_enc = wpa_s->drv_enc;
4461 else
4462 drv_enc = (unsigned int) -1;
4463
4464 for (i = 0; i < NUM_WEP_KEYS; i++) {
4465 size_t len = ssid->wep_key_len[i];
4466 if (len == 0)
4467 continue;
4468 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4469 continue;
4470 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4471 continue;
4472 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4473 continue;
4474 return 1; /* invalid WEP key */
4475 }
4476
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004477 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07004478 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004479 return 1;
4480
Dmitry Shmidt04949592012-07-19 12:16:46 -07004481 return 0;
4482}
4483
4484
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004485int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004486{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004487 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004488 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004489 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004490 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004491 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004492}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004493
4494
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004495void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004496{
4497 struct wpa_ssid *ssid = wpa_s->current_ssid;
4498 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004499 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004500
4501 if (ssid == NULL) {
4502 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4503 "SSID block");
4504 return;
4505 }
4506
4507 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4508 return;
4509
4510 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004511
4512#ifdef CONFIG_P2P
4513 if (ssid->p2p_group &&
4514 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4515 /*
4516 * Skip the wait time since there is a short timeout on the
4517 * connection to a P2P group.
4518 */
4519 return;
4520 }
4521#endif /* CONFIG_P2P */
4522
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004523 if (ssid->auth_failures > 50)
4524 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004525 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004526 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004527 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004528 dur = 90;
4529 else if (ssid->auth_failures > 3)
4530 dur = 60;
4531 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004532 dur = 30;
4533 else if (ssid->auth_failures > 1)
4534 dur = 20;
4535 else
4536 dur = 10;
4537
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004538 if (ssid->auth_failures > 1 &&
4539 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
4540 dur += os_random() % (ssid->auth_failures * 10);
4541
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004542 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004543 if (now.sec + dur <= ssid->disabled_until.sec)
4544 return;
4545
4546 ssid->disabled_until.sec = now.sec + dur;
4547
4548 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004549 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004550 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004551 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004552}
4553
4554
4555void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4556 struct wpa_ssid *ssid, int clear_failures)
4557{
4558 if (ssid == NULL)
4559 return;
4560
4561 if (ssid->disabled_until.sec) {
4562 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4563 "id=%d ssid=\"%s\"",
4564 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4565 }
4566 ssid->disabled_until.sec = 0;
4567 ssid->disabled_until.usec = 0;
4568 if (clear_failures)
4569 ssid->auth_failures = 0;
4570}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004571
4572
4573int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4574{
4575 size_t i;
4576
4577 if (wpa_s->disallow_aps_bssid == NULL)
4578 return 0;
4579
4580 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4581 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4582 bssid, ETH_ALEN) == 0)
4583 return 1;
4584 }
4585
4586 return 0;
4587}
4588
4589
4590int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4591 size_t ssid_len)
4592{
4593 size_t i;
4594
4595 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4596 return 0;
4597
4598 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4599 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4600 if (ssid_len == s->ssid_len &&
4601 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4602 return 1;
4603 }
4604
4605 return 0;
4606}
4607
4608
4609/**
4610 * wpas_request_connection - Request a new connection
4611 * @wpa_s: Pointer to the network interface
4612 *
4613 * This function is used to request a new connection to be found. It will mark
4614 * the interface to allow reassociation and request a new scan to find a
4615 * suitable network to connect to.
4616 */
4617void wpas_request_connection(struct wpa_supplicant *wpa_s)
4618{
4619 wpa_s->normal_scans = 0;
4620 wpa_supplicant_reinit_autoscan(wpa_s);
4621 wpa_s->extra_blacklist_count = 0;
4622 wpa_s->disconnected = 0;
4623 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004624
4625 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4626 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004627}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004628
4629
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004630void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
4631 struct wpa_used_freq_data *freqs_data,
4632 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004633{
4634 unsigned int i;
4635
4636 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4637 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004638 for (i = 0; i < len; i++) {
4639 struct wpa_used_freq_data *cur = &freqs_data[i];
4640 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
4641 i, cur->freq, cur->flags);
4642 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004643}
4644
4645
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004646/*
4647 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004648 * are using the same radio as the current interface, and in addition, get
4649 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004650 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004651int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
4652 struct wpa_used_freq_data *freqs_data,
4653 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004654{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004655 struct wpa_supplicant *ifs;
4656 u8 bssid[ETH_ALEN];
4657 int freq;
4658 unsigned int idx = 0, i;
4659
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004660 wpa_dbg(wpa_s, MSG_DEBUG,
4661 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004662 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004663
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004664 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4665 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004666 if (idx == len)
4667 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004668
4669 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4670 continue;
4671
4672 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4673 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4674 freq = ifs->current_ssid->frequency;
4675 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4676 freq = ifs->assoc_freq;
4677 else
4678 continue;
4679
4680 /* Hold only distinct freqs */
4681 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004682 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004683 break;
4684
4685 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004686 freqs_data[idx++].freq = freq;
4687
4688 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
4689 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
4690 WPA_FREQ_USED_BY_P2P_CLIENT :
4691 WPA_FREQ_USED_BY_INFRA_STATION;
4692 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004693 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004694
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004695 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004696 return idx;
4697}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004698
4699
4700/*
4701 * Find the operating frequencies of any of the virtual interfaces that
4702 * are using the same radio as the current interface.
4703 */
4704int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4705 int *freq_array, unsigned int len)
4706{
4707 struct wpa_used_freq_data *freqs_data;
4708 int num, i;
4709
4710 os_memset(freq_array, 0, sizeof(int) * len);
4711
4712 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
4713 if (!freqs_data)
4714 return -1;
4715
4716 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
4717 for (i = 0; i < num; i++)
4718 freq_array[i] = freqs_data[i].freq;
4719
4720 os_free(freqs_data);
4721
4722 return num;
4723}