blob: 55570de6b5b42d1b544084b77a67147a0442dc72 [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);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001659 size_t len;
1660
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001661 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001662 len = sizeof(wpa_ie) - wpa_ie_len;
1663 if (wpabuf_len(hs20) <= len) {
1664 os_memcpy(wpa_ie + wpa_ie_len,
1665 wpabuf_head(hs20), wpabuf_len(hs20));
1666 wpa_ie_len += wpabuf_len(hs20);
1667 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001668 wpabuf_free(hs20);
1669 }
1670 }
1671#endif /* CONFIG_HS20 */
1672
Dmitry Shmidt56052862013-10-04 10:23:25 -07001673 /*
1674 * Workaround: Add Extended Capabilities element only if the AP
1675 * included this element in Beacon/Probe Response frames. Some older
1676 * APs seem to have interoperability issues if this element is
1677 * included, so while the standard may require us to include the
1678 * element in all cases, it is justifiable to skip it to avoid
1679 * interoperability issues.
1680 */
1681 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001682 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07001683 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001684 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
1685 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07001686 if (ext_capab_len > 0) {
1687 u8 *pos = wpa_ie;
1688 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1689 pos += 2 + pos[1];
1690 os_memmove(pos + ext_capab_len, pos,
1691 wpa_ie_len - (pos - wpa_ie));
1692 wpa_ie_len += ext_capab_len;
1693 os_memcpy(pos, ext_capab, ext_capab_len);
1694 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001695 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001696
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001697 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1698 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001699 cipher_pairwise = wpa_s->pairwise_cipher;
1700 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001701 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1702 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1703 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1704 use_crypt = 0;
1705 if (wpa_set_wep_keys(wpa_s, ssid)) {
1706 use_crypt = 1;
1707 wep_keys_set = 1;
1708 }
1709 }
1710 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1711 use_crypt = 0;
1712
1713#ifdef IEEE8021X_EAPOL
1714 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1715 if ((ssid->eapol_flags &
1716 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1717 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1718 !wep_keys_set) {
1719 use_crypt = 0;
1720 } else {
1721 /* Assume that dynamic WEP-104 keys will be used and
1722 * set cipher suites in order for drivers to expect
1723 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001724 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725 }
1726 }
1727#endif /* IEEE8021X_EAPOL */
1728
1729 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1730 /* Set the key before (and later after) association */
1731 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1732 }
1733
1734 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1735 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736 params.ssid = bss->ssid;
1737 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001738 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1739 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1740 MACSTR " freq=%u MHz based on scan results "
1741 "(bssid_set=%d)",
1742 MAC2STR(bss->bssid), bss->freq,
1743 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001744 params.bssid = bss->bssid;
1745 params.freq = bss->freq;
1746 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001747 params.bssid_hint = bss->bssid;
1748 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001749 } else {
1750 params.ssid = ssid->ssid;
1751 params.ssid_len = ssid->ssid_len;
1752 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001753
1754 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1755 wpa_s->conf->ap_scan == 2) {
1756 params.bssid = ssid->bssid;
1757 params.fixed_bssid = 1;
1758 }
1759
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1761 params.freq == 0)
1762 params.freq = ssid->frequency; /* Initial channel for IBSS */
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08001763
1764 if (ssid->mode == WPAS_MODE_IBSS) {
1765 if (ssid->beacon_int)
1766 params.beacon_int = ssid->beacon_int;
1767 else
1768 params.beacon_int = wpa_s->conf->beacon_int;
1769 }
1770
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001771 params.wpa_ie = wpa_ie;
1772 params.wpa_ie_len = wpa_ie_len;
1773 params.pairwise_suite = cipher_pairwise;
1774 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001775 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001776 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001777 params.auth_alg = algs;
1778 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001779 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780 for (i = 0; i < NUM_WEP_KEYS; i++) {
1781 if (ssid->wep_key_len[i])
1782 params.wep_key[i] = ssid->wep_key[i];
1783 params.wep_key_len[i] = ssid->wep_key_len[i];
1784 }
1785 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1786
1787 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001788 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1789 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001790 params.passphrase = ssid->passphrase;
1791 if (ssid->psk_set)
1792 params.psk = ssid->psk;
1793 }
1794
1795 params.drop_unencrypted = use_crypt;
1796
1797#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001798 params.mgmt_frame_protection =
1799 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1800 wpa_s->conf->pmf : ssid->ieee80211w;
1801 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001802 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1803 struct wpa_ie_data ie;
1804 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1805 ie.capabilities &
1806 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1807 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1808 "MFP: require MFP");
1809 params.mgmt_frame_protection =
1810 MGMT_FRAME_PROTECTION_REQUIRED;
1811 }
1812 }
1813#endif /* CONFIG_IEEE80211W */
1814
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001815 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001816
1817 if (wpa_s->parent->set_sta_uapsd)
1818 params.uapsd = wpa_s->parent->sta_uapsd;
1819 else
1820 params.uapsd = -1;
1821
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001822#ifdef CONFIG_HT_OVERRIDES
1823 os_memset(&htcaps, 0, sizeof(htcaps));
1824 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1825 params.htcaps = (u8 *) &htcaps;
1826 params.htcaps_mask = (u8 *) &htcaps_mask;
1827 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1828#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001829#ifdef CONFIG_VHT_OVERRIDES
1830 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
1831 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
1832 params.vhtcaps = &vhtcaps;
1833 params.vhtcaps_mask = &vhtcaps_mask;
1834 wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
1835#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001836
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001837#ifdef CONFIG_P2P
1838 /*
1839 * If multi-channel concurrency is not supported, check for any
1840 * frequency conflict. In case of any frequency conflict, remove the
1841 * least prioritized connection.
1842 */
1843 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001844 int freq, num;
1845 num = get_shared_radio_freqs(wpa_s, &freq, 1);
1846 if (num > 0 && freq > 0 && freq != params.freq) {
1847 wpa_printf(MSG_DEBUG,
1848 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001849 freq, params.freq);
1850 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1851 params.freq,
1852 ssid) < 0)
1853 return;
1854 }
1855 }
1856#endif /* CONFIG_P2P */
1857
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001858 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001859 if (ret < 0) {
1860 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1861 "failed");
1862 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1863 /*
1864 * The driver is known to mean what is saying, so we
1865 * can stop right here; the association will not
1866 * succeed.
1867 */
1868 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001869 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001870 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1871 return;
1872 }
1873 /* try to continue anyway; new association will be tried again
1874 * after timeout */
1875 assoc_failed = 1;
1876 }
1877
1878 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1879 /* Set the key after the association just in case association
1880 * cleared the previously configured key. */
1881 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1882 /* No need to timeout authentication since there is no key
1883 * management. */
1884 wpa_supplicant_cancel_auth_timeout(wpa_s);
1885 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1886#ifdef CONFIG_IBSS_RSN
1887 } else if (ssid->mode == WPAS_MODE_IBSS &&
1888 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1889 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1890 /*
1891 * RSN IBSS authentication is per-STA and we can disable the
1892 * per-BSSID authentication.
1893 */
1894 wpa_supplicant_cancel_auth_timeout(wpa_s);
1895#endif /* CONFIG_IBSS_RSN */
1896 } else {
1897 /* Timeout for IEEE 802.11 authentication and association */
1898 int timeout = 60;
1899
1900 if (assoc_failed) {
1901 /* give IBSS a bit more time */
1902 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1903 } else if (wpa_s->conf->ap_scan == 1) {
1904 /* give IBSS a bit more time */
1905 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1906 }
1907 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1908 }
1909
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001910 if (wep_keys_set &&
1911 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001912 /* Set static WEP keys again */
1913 wpa_set_wep_keys(wpa_s, ssid);
1914 }
1915
1916 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1917 /*
1918 * Do not allow EAP session resumption between different
1919 * network configurations.
1920 */
1921 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1922 }
1923 old_ssid = wpa_s->current_ssid;
1924 wpa_s->current_ssid = ssid;
1925 wpa_s->current_bss = bss;
1926 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1927 wpa_supplicant_initiate_eapol(wpa_s);
1928 if (old_ssid != wpa_s->current_ssid)
1929 wpas_notify_network_changed(wpa_s);
1930}
1931
1932
1933static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1934 const u8 *addr)
1935{
1936 struct wpa_ssid *old_ssid;
1937
1938 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001940 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001941 wpa_sm_set_config(wpa_s->wpa, NULL);
1942 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1943 if (old_ssid != wpa_s->current_ssid)
1944 wpas_notify_network_changed(wpa_s);
1945 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1946}
1947
1948
1949/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001950 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1951 * @wpa_s: Pointer to wpa_supplicant data
1952 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1953 *
1954 * This function is used to request %wpa_supplicant to deauthenticate from the
1955 * current AP.
1956 */
1957void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1958 int reason_code)
1959{
1960 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001961 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001962 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001964 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1965 " pending_bssid=" MACSTR " reason=%d state=%s",
1966 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1967 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1968
1969 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001970 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001971 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1972 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1973 wpa_s->wpa_state == WPA_ASSOCIATING))
1974 addr = wpa_s->pending_bssid;
1975 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1976 /*
1977 * When using driver-based BSS selection, we may not know the
1978 * BSSID with which we are currently trying to associate. We
1979 * need to notify the driver of this disconnection even in such
1980 * a case, so use the all zeros address here.
1981 */
1982 addr = wpa_s->bssid;
1983 zero_addr = 1;
1984 }
1985
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001986#ifdef CONFIG_TDLS
1987 wpa_tdls_teardown_peers(wpa_s->wpa);
1988#endif /* CONFIG_TDLS */
1989
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001990 if (addr) {
1991 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001992 os_memset(&event, 0, sizeof(event));
1993 event.deauth_info.reason_code = (u16) reason_code;
1994 event.deauth_info.locally_generated = 1;
1995 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001996 if (zero_addr)
1997 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998 }
1999
2000 wpa_supplicant_clear_connection(wpa_s, addr);
2001}
2002
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002003static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2004 struct wpa_ssid *ssid)
2005{
2006 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2007 return;
2008
2009 ssid->disabled = 0;
2010 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2011 wpas_notify_network_enabled_changed(wpa_s, ssid);
2012
2013 /*
2014 * Try to reassociate since there is no current configuration and a new
2015 * network was made available.
2016 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002017 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002018 wpa_s->reassociate = 1;
2019}
2020
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002021
2022/**
2023 * wpa_supplicant_enable_network - Mark a configured network as enabled
2024 * @wpa_s: wpa_supplicant structure for a network interface
2025 * @ssid: wpa_ssid structure for a configured network or %NULL
2026 *
2027 * Enables the specified network or all networks if no network specified.
2028 */
2029void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2030 struct wpa_ssid *ssid)
2031{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002032 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002033 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2034 wpa_supplicant_enable_one_network(wpa_s, ssid);
2035 } else
2036 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002037
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002038 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002039 if (wpa_s->sched_scanning) {
2040 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2041 "new network to scan filters");
2042 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002043 }
2044
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002045 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2046 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002047 }
2048}
2049
2050
2051/**
2052 * wpa_supplicant_disable_network - Mark a configured network as disabled
2053 * @wpa_s: wpa_supplicant structure for a network interface
2054 * @ssid: wpa_ssid structure for a configured network or %NULL
2055 *
2056 * Disables the specified network or all networks if no network specified.
2057 */
2058void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2059 struct wpa_ssid *ssid)
2060{
2061 struct wpa_ssid *other_ssid;
2062 int was_disabled;
2063
2064 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002065 if (wpa_s->sched_scanning)
2066 wpa_supplicant_cancel_sched_scan(wpa_s);
2067
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002068 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2069 other_ssid = other_ssid->next) {
2070 was_disabled = other_ssid->disabled;
2071 if (was_disabled == 2)
2072 continue; /* do not change persistent P2P group
2073 * data */
2074
2075 other_ssid->disabled = 1;
2076
2077 if (was_disabled != other_ssid->disabled)
2078 wpas_notify_network_enabled_changed(
2079 wpa_s, other_ssid);
2080 }
2081 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002082 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002083 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2084 } else if (ssid->disabled != 2) {
2085 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002086 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002087 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2088
2089 was_disabled = ssid->disabled;
2090
2091 ssid->disabled = 1;
2092
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002093 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002094 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002095 if (wpa_s->sched_scanning) {
2096 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2097 "to remove network from filters");
2098 wpa_supplicant_cancel_sched_scan(wpa_s);
2099 wpa_supplicant_req_scan(wpa_s, 0, 0);
2100 }
2101 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102 }
2103}
2104
2105
2106/**
2107 * wpa_supplicant_select_network - Attempt association with a network
2108 * @wpa_s: wpa_supplicant structure for a network interface
2109 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2110 */
2111void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2112 struct wpa_ssid *ssid)
2113{
2114
2115 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002116 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002117
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002118 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002119 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002120 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002121 disconnected = 1;
2122 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002123
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002124 if (ssid)
2125 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2126
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127 /*
2128 * Mark all other networks disabled or mark all networks enabled if no
2129 * network specified.
2130 */
2131 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2132 other_ssid = other_ssid->next) {
2133 int was_disabled = other_ssid->disabled;
2134 if (was_disabled == 2)
2135 continue; /* do not change persistent P2P group data */
2136
2137 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002138 if (was_disabled && !other_ssid->disabled)
2139 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002140
2141 if (was_disabled != other_ssid->disabled)
2142 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2143 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002144
2145 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2146 /* We are already associated with the selected network */
2147 wpa_printf(MSG_DEBUG, "Already associated with the "
2148 "selected network - do nothing");
2149 return;
2150 }
2151
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002152 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002153 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002154 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2155 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002156 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002157 wpa_s->disconnected = 0;
2158 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002159
2160 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2161 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002162
2163 if (ssid)
2164 wpas_notify_network_selected(wpa_s, ssid);
2165}
2166
2167
2168/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002169 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2170 * @wpa_s: wpa_supplicant structure for a network interface
2171 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2172 * @pkcs11_module_path: PKCS #11 module path or NULL
2173 * Returns: 0 on success; -1 on failure
2174 *
2175 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2176 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2177 * module path fails the paths will be reset to the default value (NULL).
2178 */
2179int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2180 const char *pkcs11_engine_path,
2181 const char *pkcs11_module_path)
2182{
2183 char *pkcs11_engine_path_copy = NULL;
2184 char *pkcs11_module_path_copy = NULL;
2185
2186 if (pkcs11_engine_path != NULL) {
2187 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2188 if (pkcs11_engine_path_copy == NULL)
2189 return -1;
2190 }
2191 if (pkcs11_module_path != NULL) {
2192 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002193 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002194 os_free(pkcs11_engine_path_copy);
2195 return -1;
2196 }
2197 }
2198
2199 os_free(wpa_s->conf->pkcs11_engine_path);
2200 os_free(wpa_s->conf->pkcs11_module_path);
2201 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2202 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2203
2204 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2205 eapol_sm_deinit(wpa_s->eapol);
2206 wpa_s->eapol = NULL;
2207 if (wpa_supplicant_init_eapol(wpa_s)) {
2208 /* Error -> Reset paths to the default value (NULL) once. */
2209 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2210 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2211 NULL);
2212
2213 return -1;
2214 }
2215 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2216
2217 return 0;
2218}
2219
2220
2221/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002222 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2223 * @wpa_s: wpa_supplicant structure for a network interface
2224 * @ap_scan: AP scan mode
2225 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2226 *
2227 */
2228int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2229{
2230
2231 int old_ap_scan;
2232
2233 if (ap_scan < 0 || ap_scan > 2)
2234 return -1;
2235
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002236#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002237 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2238 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2239 wpa_s->wpa_state < WPA_COMPLETED) {
2240 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2241 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002242 return 0;
2243 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002244#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002246 old_ap_scan = wpa_s->conf->ap_scan;
2247 wpa_s->conf->ap_scan = ap_scan;
2248
2249 if (old_ap_scan != wpa_s->conf->ap_scan)
2250 wpas_notify_ap_scan_changed(wpa_s);
2251
2252 return 0;
2253}
2254
2255
2256/**
2257 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2258 * @wpa_s: wpa_supplicant structure for a network interface
2259 * @expire_age: Expiration age in seconds
2260 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2261 *
2262 */
2263int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2264 unsigned int bss_expire_age)
2265{
2266 if (bss_expire_age < 10) {
2267 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2268 bss_expire_age);
2269 return -1;
2270 }
2271 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2272 bss_expire_age);
2273 wpa_s->conf->bss_expiration_age = bss_expire_age;
2274
2275 return 0;
2276}
2277
2278
2279/**
2280 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2281 * @wpa_s: wpa_supplicant structure for a network interface
2282 * @expire_count: number of scans after which an unseen BSS is reclaimed
2283 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2284 *
2285 */
2286int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2287 unsigned int bss_expire_count)
2288{
2289 if (bss_expire_count < 1) {
2290 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2291 bss_expire_count);
2292 return -1;
2293 }
2294 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2295 bss_expire_count);
2296 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2297
2298 return 0;
2299}
2300
2301
2302/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002303 * wpa_supplicant_set_scan_interval - Set scan interval
2304 * @wpa_s: wpa_supplicant structure for a network interface
2305 * @scan_interval: scan interval in seconds
2306 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2307 *
2308 */
2309int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2310 int scan_interval)
2311{
2312 if (scan_interval < 0) {
2313 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2314 scan_interval);
2315 return -1;
2316 }
2317 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2318 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002319 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002320
2321 return 0;
2322}
2323
2324
2325/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002326 * wpa_supplicant_set_debug_params - Set global debug params
2327 * @global: wpa_global structure
2328 * @debug_level: debug level
2329 * @debug_timestamp: determines if show timestamp in debug data
2330 * @debug_show_keys: determines if show keys in debug data
2331 * Returns: 0 if succeed or -1 if debug_level has wrong value
2332 */
2333int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2334 int debug_timestamp, int debug_show_keys)
2335{
2336
2337 int old_level, old_timestamp, old_show_keys;
2338
2339 /* check for allowed debuglevels */
2340 if (debug_level != MSG_EXCESSIVE &&
2341 debug_level != MSG_MSGDUMP &&
2342 debug_level != MSG_DEBUG &&
2343 debug_level != MSG_INFO &&
2344 debug_level != MSG_WARNING &&
2345 debug_level != MSG_ERROR)
2346 return -1;
2347
2348 old_level = wpa_debug_level;
2349 old_timestamp = wpa_debug_timestamp;
2350 old_show_keys = wpa_debug_show_keys;
2351
2352 wpa_debug_level = debug_level;
2353 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2354 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2355
2356 if (wpa_debug_level != old_level)
2357 wpas_notify_debug_level_changed(global);
2358 if (wpa_debug_timestamp != old_timestamp)
2359 wpas_notify_debug_timestamp_changed(global);
2360 if (wpa_debug_show_keys != old_show_keys)
2361 wpas_notify_debug_show_keys_changed(global);
2362
2363 return 0;
2364}
2365
2366
2367/**
2368 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2369 * @wpa_s: Pointer to wpa_supplicant data
2370 * Returns: A pointer to the current network structure or %NULL on failure
2371 */
2372struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2373{
2374 struct wpa_ssid *entry;
2375 u8 ssid[MAX_SSID_LEN];
2376 int res;
2377 size_t ssid_len;
2378 u8 bssid[ETH_ALEN];
2379 int wired;
2380
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002381 res = wpa_drv_get_ssid(wpa_s, ssid);
2382 if (res < 0) {
2383 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2384 "driver");
2385 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002386 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002387 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002388
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002389 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002390 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2391 "driver");
2392 return NULL;
2393 }
2394
2395 wired = wpa_s->conf->ap_scan == 0 &&
2396 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2397
2398 entry = wpa_s->conf->ssid;
2399 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002400 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002401 ((ssid_len == entry->ssid_len &&
2402 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2403 (!entry->bssid_set ||
2404 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2405 return entry;
2406#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002407 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002408 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2409 (entry->ssid == NULL || entry->ssid_len == 0) &&
2410 (!entry->bssid_set ||
2411 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2412 return entry;
2413#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002414
Dmitry Shmidt04949592012-07-19 12:16:46 -07002415 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002416 entry->ssid_len == 0 &&
2417 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2418 return entry;
2419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002420 entry = entry->next;
2421 }
2422
2423 return NULL;
2424}
2425
2426
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002427static int select_driver(struct wpa_supplicant *wpa_s, int i)
2428{
2429 struct wpa_global *global = wpa_s->global;
2430
2431 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2432 global->drv_priv[i] = wpa_drivers[i]->global_init();
2433 if (global->drv_priv[i] == NULL) {
2434 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2435 "'%s'", wpa_drivers[i]->name);
2436 return -1;
2437 }
2438 }
2439
2440 wpa_s->driver = wpa_drivers[i];
2441 wpa_s->global_drv_priv = global->drv_priv[i];
2442
2443 return 0;
2444}
2445
2446
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002447static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2448 const char *name)
2449{
2450 int i;
2451 size_t len;
2452 const char *pos, *driver = name;
2453
2454 if (wpa_s == NULL)
2455 return -1;
2456
2457 if (wpa_drivers[0] == NULL) {
2458 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2459 "wpa_supplicant");
2460 return -1;
2461 }
2462
2463 if (name == NULL) {
2464 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002465 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002466 }
2467
2468 do {
2469 pos = os_strchr(driver, ',');
2470 if (pos)
2471 len = pos - driver;
2472 else
2473 len = os_strlen(driver);
2474
2475 for (i = 0; wpa_drivers[i]; i++) {
2476 if (os_strlen(wpa_drivers[i]->name) == len &&
2477 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002478 0) {
2479 /* First driver that succeeds wins */
2480 if (select_driver(wpa_s, i) == 0)
2481 return 0;
2482 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002483 }
2484
2485 driver = pos + 1;
2486 } while (pos);
2487
2488 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2489 return -1;
2490}
2491
2492
2493/**
2494 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2495 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2496 * with struct wpa_driver_ops::init()
2497 * @src_addr: Source address of the EAPOL frame
2498 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2499 * @len: Length of the EAPOL data
2500 *
2501 * This function is called for each received EAPOL frame. Most driver
2502 * interfaces rely on more generic OS mechanism for receiving frames through
2503 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2504 * take care of received EAPOL frames and deliver them to the core supplicant
2505 * code by calling this function.
2506 */
2507void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2508 const u8 *buf, size_t len)
2509{
2510 struct wpa_supplicant *wpa_s = ctx;
2511
2512 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2513 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2514
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002515#ifdef CONFIG_PEERKEY
2516 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2517 wpa_s->current_ssid->peerkey &&
2518 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2519 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2520 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2521 return;
2522 }
2523#endif /* CONFIG_PEERKEY */
2524
Jouni Malinena05074c2012-12-21 21:35:35 +02002525 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2526 (wpa_s->last_eapol_matches_bssid &&
2527#ifdef CONFIG_AP
2528 !wpa_s->ap_iface &&
2529#endif /* CONFIG_AP */
2530 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 /*
2532 * There is possible race condition between receiving the
2533 * association event and the EAPOL frame since they are coming
2534 * through different paths from the driver. In order to avoid
2535 * issues in trying to process the EAPOL frame before receiving
2536 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002537 * the association event is received. This may also be needed in
2538 * driver-based roaming case, so also use src_addr != BSSID as a
2539 * trigger if we have previously confirmed that the
2540 * Authenticator uses BSSID as the src_addr (which is not the
2541 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 */
2543 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002544 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2545 wpa_supplicant_state_txt(wpa_s->wpa_state),
2546 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002547 wpabuf_free(wpa_s->pending_eapol_rx);
2548 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2549 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002550 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2552 ETH_ALEN);
2553 }
2554 return;
2555 }
2556
Jouni Malinena05074c2012-12-21 21:35:35 +02002557 wpa_s->last_eapol_matches_bssid =
2558 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560#ifdef CONFIG_AP
2561 if (wpa_s->ap_iface) {
2562 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2563 return;
2564 }
2565#endif /* CONFIG_AP */
2566
2567 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2568 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2569 "no key management is configured");
2570 return;
2571 }
2572
2573 if (wpa_s->eapol_received == 0 &&
2574 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2575 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2576 wpa_s->wpa_state != WPA_COMPLETED) &&
2577 (wpa_s->current_ssid == NULL ||
2578 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2579 /* Timeout for completing IEEE 802.1X and WPA authentication */
2580 wpa_supplicant_req_auth_timeout(
2581 wpa_s,
2582 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2583 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2584 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2585 70 : 10, 0);
2586 }
2587 wpa_s->eapol_received++;
2588
2589 if (wpa_s->countermeasures) {
2590 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2591 "EAPOL packet");
2592 return;
2593 }
2594
2595#ifdef CONFIG_IBSS_RSN
2596 if (wpa_s->current_ssid &&
2597 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2598 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2599 return;
2600 }
2601#endif /* CONFIG_IBSS_RSN */
2602
2603 /* Source address of the incoming EAPOL frame could be compared to the
2604 * current BSSID. However, it is possible that a centralized
2605 * Authenticator could be using another MAC address than the BSSID of
2606 * an AP, so just allow any address to be used for now. The replies are
2607 * still sent to the current BSSID (if available), though. */
2608
2609 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2610 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2611 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2612 return;
2613 wpa_drv_poll(wpa_s);
2614 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2615 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2616 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2617 /*
2618 * Set portValid = TRUE here since we are going to skip 4-way
2619 * handshake processing which would normally set portValid. We
2620 * need this to allow the EAPOL state machines to be completed
2621 * without going through EAPOL-Key handshake.
2622 */
2623 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2624 }
2625}
2626
2627
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002628int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002629{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002630 if (wpa_s->driver->send_eapol) {
2631 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2632 if (addr)
2633 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002634 } else if ((!wpa_s->p2p_mgmt ||
2635 !(wpa_s->drv_flags &
2636 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2637 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002639 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2641 wpa_drv_get_mac_addr(wpa_s),
2642 ETH_P_EAPOL,
2643 wpa_supplicant_rx_eapol, wpa_s, 0);
2644 if (wpa_s->l2 == NULL)
2645 return -1;
2646 } else {
2647 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2648 if (addr)
2649 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2650 }
2651
2652 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2653 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2654 return -1;
2655 }
2656
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002657 return 0;
2658}
2659
2660
Dmitry Shmidt04949592012-07-19 12:16:46 -07002661static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2662 const u8 *buf, size_t len)
2663{
2664 struct wpa_supplicant *wpa_s = ctx;
2665 const struct l2_ethhdr *eth;
2666
2667 if (len < sizeof(*eth))
2668 return;
2669 eth = (const struct l2_ethhdr *) buf;
2670
2671 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2672 !(eth->h_dest[0] & 0x01)) {
2673 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2674 " (bridge - not for this interface - ignore)",
2675 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2676 return;
2677 }
2678
2679 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2680 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2681 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2682 len - sizeof(*eth));
2683}
2684
2685
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002686/**
2687 * wpa_supplicant_driver_init - Initialize driver interface parameters
2688 * @wpa_s: Pointer to wpa_supplicant data
2689 * Returns: 0 on success, -1 on failure
2690 *
2691 * This function is called to initialize driver interface parameters.
2692 * wpa_drv_init() must have been called before this function to initialize the
2693 * driver interface.
2694 */
2695int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2696{
2697 static int interface_count = 0;
2698
2699 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2700 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002702 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2703 MAC2STR(wpa_s->own_addr));
2704 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2705
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002706 if (wpa_s->bridge_ifname[0]) {
2707 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2708 "interface '%s'", wpa_s->bridge_ifname);
2709 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2710 wpa_s->own_addr,
2711 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002712 wpa_supplicant_rx_eapol_bridge,
2713 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 if (wpa_s->l2_br == NULL) {
2715 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2716 "connection for the bridge interface '%s'",
2717 wpa_s->bridge_ifname);
2718 return -1;
2719 }
2720 }
2721
2722 wpa_clear_keys(wpa_s, NULL);
2723
2724 /* Make sure that TKIP countermeasures are not left enabled (could
2725 * happen if wpa_supplicant is killed during countermeasures. */
2726 wpa_drv_set_countermeasures(wpa_s, 0);
2727
2728 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2729 wpa_drv_flush_pmkid(wpa_s);
2730
2731 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002732 wpa_s->prev_scan_wildcard = 0;
2733
Dmitry Shmidt04949592012-07-19 12:16:46 -07002734 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002735 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2736 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2737 interface_count = 0;
2738 }
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002739 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07002740 wpa_supplicant_delayed_sched_scan(wpa_s,
2741 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002742 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07002743 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002744 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002745 interface_count++;
2746 } else
2747 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2748
2749 return 0;
2750}
2751
2752
2753static int wpa_supplicant_daemon(const char *pid_file)
2754{
2755 wpa_printf(MSG_DEBUG, "Daemonize..");
2756 return os_daemonize(pid_file);
2757}
2758
2759
2760static struct wpa_supplicant * wpa_supplicant_alloc(void)
2761{
2762 struct wpa_supplicant *wpa_s;
2763
2764 wpa_s = os_zalloc(sizeof(*wpa_s));
2765 if (wpa_s == NULL)
2766 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002767 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002768 wpa_s->scan_interval = 5;
2769 wpa_s->new_connection = 1;
2770 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002771 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772
2773 return wpa_s;
2774}
2775
2776
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002777#ifdef CONFIG_HT_OVERRIDES
2778
2779static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2780 struct ieee80211_ht_capabilities *htcaps,
2781 struct ieee80211_ht_capabilities *htcaps_mask,
2782 const char *ht_mcs)
2783{
2784 /* parse ht_mcs into hex array */
2785 int i;
2786 const char *tmp = ht_mcs;
2787 char *end = NULL;
2788
2789 /* If ht_mcs is null, do not set anything */
2790 if (!ht_mcs)
2791 return 0;
2792
2793 /* This is what we are setting in the kernel */
2794 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2795
2796 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2797
2798 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2799 errno = 0;
2800 long v = strtol(tmp, &end, 16);
2801 if (errno == 0) {
2802 wpa_msg(wpa_s, MSG_DEBUG,
2803 "htcap value[%i]: %ld end: %p tmp: %p",
2804 i, v, end, tmp);
2805 if (end == tmp)
2806 break;
2807
2808 htcaps->supported_mcs_set[i] = v;
2809 tmp = end;
2810 } else {
2811 wpa_msg(wpa_s, MSG_ERROR,
2812 "Failed to parse ht-mcs: %s, error: %s\n",
2813 ht_mcs, strerror(errno));
2814 return -1;
2815 }
2816 }
2817
2818 /*
2819 * If we were able to parse any values, then set mask for the MCS set.
2820 */
2821 if (i) {
2822 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2823 IEEE80211_HT_MCS_MASK_LEN - 1);
2824 /* skip the 3 reserved bits */
2825 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2826 0x1f;
2827 }
2828
2829 return 0;
2830}
2831
2832
2833static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2834 struct ieee80211_ht_capabilities *htcaps,
2835 struct ieee80211_ht_capabilities *htcaps_mask,
2836 int disabled)
2837{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002838 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002839
2840 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2841
2842 if (disabled == -1)
2843 return 0;
2844
2845 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2846 htcaps_mask->ht_capabilities_info |= msk;
2847 if (disabled)
2848 htcaps->ht_capabilities_info &= msk;
2849 else
2850 htcaps->ht_capabilities_info |= msk;
2851
2852 return 0;
2853}
2854
2855
2856static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2857 struct ieee80211_ht_capabilities *htcaps,
2858 struct ieee80211_ht_capabilities *htcaps_mask,
2859 int factor)
2860{
2861 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2862
2863 if (factor == -1)
2864 return 0;
2865
2866 if (factor < 0 || factor > 3) {
2867 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2868 "Must be 0-3 or -1", factor);
2869 return -EINVAL;
2870 }
2871
2872 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2873 htcaps->a_mpdu_params &= ~0x3;
2874 htcaps->a_mpdu_params |= factor & 0x3;
2875
2876 return 0;
2877}
2878
2879
2880static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2881 struct ieee80211_ht_capabilities *htcaps,
2882 struct ieee80211_ht_capabilities *htcaps_mask,
2883 int density)
2884{
2885 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2886
2887 if (density == -1)
2888 return 0;
2889
2890 if (density < 0 || density > 7) {
2891 wpa_msg(wpa_s, MSG_ERROR,
2892 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2893 density);
2894 return -EINVAL;
2895 }
2896
2897 htcaps_mask->a_mpdu_params |= 0x1C;
2898 htcaps->a_mpdu_params &= ~(0x1C);
2899 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2900
2901 return 0;
2902}
2903
2904
2905static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2906 struct ieee80211_ht_capabilities *htcaps,
2907 struct ieee80211_ht_capabilities *htcaps_mask,
2908 int disabled)
2909{
2910 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002911 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2912 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002913
2914 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2915
2916 if (disabled)
2917 htcaps->ht_capabilities_info &= ~msk;
2918 else
2919 htcaps->ht_capabilities_info |= msk;
2920
2921 htcaps_mask->ht_capabilities_info |= msk;
2922
2923 return 0;
2924}
2925
2926
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002927static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2928 struct ieee80211_ht_capabilities *htcaps,
2929 struct ieee80211_ht_capabilities *htcaps_mask,
2930 int disabled)
2931{
2932 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002933 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2934 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002935
2936 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2937
2938 if (disabled)
2939 htcaps->ht_capabilities_info &= ~msk;
2940 else
2941 htcaps->ht_capabilities_info |= msk;
2942
2943 htcaps_mask->ht_capabilities_info |= msk;
2944
2945 return 0;
2946}
2947
2948
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07002949static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
2950 struct ieee80211_ht_capabilities *htcaps,
2951 struct ieee80211_ht_capabilities *htcaps_mask,
2952 int disabled)
2953{
2954 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002955 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07002956
2957 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
2958
2959 if (disabled)
2960 htcaps->ht_capabilities_info &= ~msk;
2961 else
2962 htcaps->ht_capabilities_info |= msk;
2963
2964 htcaps_mask->ht_capabilities_info |= msk;
2965
2966 return 0;
2967}
2968
2969
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002970void wpa_supplicant_apply_ht_overrides(
2971 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2972 struct wpa_driver_associate_params *params)
2973{
2974 struct ieee80211_ht_capabilities *htcaps;
2975 struct ieee80211_ht_capabilities *htcaps_mask;
2976
2977 if (!ssid)
2978 return;
2979
2980 params->disable_ht = ssid->disable_ht;
2981 if (!params->htcaps || !params->htcaps_mask)
2982 return;
2983
2984 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2985 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2986 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2987 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2988 ssid->disable_max_amsdu);
2989 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2990 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2991 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002992 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07002993 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07002994
2995 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002996 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07002997 htcaps->ht_capabilities_info |= bit;
2998 htcaps_mask->ht_capabilities_info |= bit;
2999 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003000}
3001
3002#endif /* CONFIG_HT_OVERRIDES */
3003
3004
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003005#ifdef CONFIG_VHT_OVERRIDES
3006void wpa_supplicant_apply_vht_overrides(
3007 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3008 struct wpa_driver_associate_params *params)
3009{
3010 struct ieee80211_vht_capabilities *vhtcaps;
3011 struct ieee80211_vht_capabilities *vhtcaps_mask;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003012#ifdef CONFIG_HT_OVERRIDES
3013 int max_ampdu;
3014 const u32 max_ampdu_mask = VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
3015#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003016
3017 if (!ssid)
3018 return;
3019
3020 params->disable_vht = ssid->disable_vht;
3021
3022 vhtcaps = (void *) params->vhtcaps;
3023 vhtcaps_mask = (void *) params->vhtcaps_mask;
3024
3025 if (!vhtcaps || !vhtcaps_mask)
3026 return;
3027
3028 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3029 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3030
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003031#ifdef CONFIG_HT_OVERRIDES
3032 /* if max ampdu is <= 3, we have to make the HT cap the same */
3033 if (ssid->vht_capa_mask & max_ampdu_mask) {
3034 max_ampdu = (ssid->vht_capa & max_ampdu_mask) >>
3035 find_first_bit(max_ampdu_mask);
3036
3037 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3038 wpa_set_ampdu_factor(wpa_s,
3039 (void *) params->htcaps,
3040 (void *) params->htcaps_mask,
3041 max_ampdu);
3042 }
3043#endif /* CONFIG_HT_OVERRIDES */
3044
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003045#define OVERRIDE_MCS(i) \
3046 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3047 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3048 3 << 2 * (i - 1); \
3049 vhtcaps->vht_supported_mcs_set.tx_map |= \
3050 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3051 } \
3052 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3053 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3054 3 << 2 * (i - 1); \
3055 vhtcaps->vht_supported_mcs_set.rx_map |= \
3056 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3057 }
3058
3059 OVERRIDE_MCS(1);
3060 OVERRIDE_MCS(2);
3061 OVERRIDE_MCS(3);
3062 OVERRIDE_MCS(4);
3063 OVERRIDE_MCS(5);
3064 OVERRIDE_MCS(6);
3065 OVERRIDE_MCS(7);
3066 OVERRIDE_MCS(8);
3067}
3068#endif /* CONFIG_VHT_OVERRIDES */
3069
3070
Dmitry Shmidt04949592012-07-19 12:16:46 -07003071static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3072{
3073#ifdef PCSC_FUNCS
3074 size_t len;
3075
3076 if (!wpa_s->conf->pcsc_reader)
3077 return 0;
3078
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003079 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003080 if (!wpa_s->scard)
3081 return 1;
3082
3083 if (wpa_s->conf->pcsc_pin &&
3084 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3085 scard_deinit(wpa_s->scard);
3086 wpa_s->scard = NULL;
3087 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3088 return -1;
3089 }
3090
3091 len = sizeof(wpa_s->imsi) - 1;
3092 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3093 scard_deinit(wpa_s->scard);
3094 wpa_s->scard = NULL;
3095 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3096 return -1;
3097 }
3098 wpa_s->imsi[len] = '\0';
3099
3100 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3101
3102 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3103 wpa_s->imsi, wpa_s->mnc_len);
3104
3105 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3106 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3107#endif /* PCSC_FUNCS */
3108
3109 return 0;
3110}
3111
3112
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003113int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3114{
3115 char *val, *pos;
3116
3117 ext_password_deinit(wpa_s->ext_pw);
3118 wpa_s->ext_pw = NULL;
3119 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3120
3121 if (!wpa_s->conf->ext_password_backend)
3122 return 0;
3123
3124 val = os_strdup(wpa_s->conf->ext_password_backend);
3125 if (val == NULL)
3126 return -1;
3127 pos = os_strchr(val, ':');
3128 if (pos)
3129 *pos++ = '\0';
3130
3131 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3132
3133 wpa_s->ext_pw = ext_password_init(val, pos);
3134 os_free(val);
3135 if (wpa_s->ext_pw == NULL) {
3136 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3137 return -1;
3138 }
3139 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3140
3141 return 0;
3142}
3143
3144
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003145static int wpas_check_wowlan_trigger(const char *start, const char *trigger,
3146 int capa_trigger, u8 *param_trigger)
3147{
3148 if (os_strcmp(start, trigger) != 0)
3149 return 0;
3150 if (!capa_trigger)
3151 return 0;
3152
3153 *param_trigger = 1;
3154 return 1;
3155}
3156
3157
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003158static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
3159 struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003160{
3161 struct wowlan_triggers triggers;
3162 char *start, *end, *buf;
3163 int last, ret;
3164
3165 if (!wpa_s->conf->wowlan_triggers)
3166 return 0;
3167
3168 buf = os_strdup(wpa_s->conf->wowlan_triggers);
3169 if (buf == NULL)
3170 return -1;
3171
3172 os_memset(&triggers, 0, sizeof(triggers));
3173
3174#define CHECK_TRIGGER(trigger) \
3175 wpas_check_wowlan_trigger(start, #trigger, \
3176 capa->wowlan_triggers.trigger, \
3177 &triggers.trigger)
3178
3179 start = buf;
3180 while (*start != '\0') {
3181 while (isblank(*start))
3182 start++;
3183 if (*start == '\0')
3184 break;
3185 end = start;
3186 while (!isblank(*end) && *end != '\0')
3187 end++;
3188 last = *end == '\0';
3189 *end = '\0';
3190
3191 if (!CHECK_TRIGGER(any) &&
3192 !CHECK_TRIGGER(disconnect) &&
3193 !CHECK_TRIGGER(magic_pkt) &&
3194 !CHECK_TRIGGER(gtk_rekey_failure) &&
3195 !CHECK_TRIGGER(eap_identity_req) &&
3196 !CHECK_TRIGGER(four_way_handshake) &&
3197 !CHECK_TRIGGER(rfkill_release)) {
3198 wpa_printf(MSG_DEBUG,
3199 "Unknown/unsupported wowlan trigger '%s'",
3200 start);
3201 ret = -1;
3202 goto out;
3203 }
3204
3205 if (last)
3206 break;
3207 start = end + 1;
3208 }
3209#undef CHECK_TRIGGER
3210
3211 ret = wpa_drv_wowlan(wpa_s, &triggers);
3212out:
3213 os_free(buf);
3214 return ret;
3215}
3216
3217
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003218static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3219 const char *rn)
3220{
3221 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3222 struct wpa_radio *radio;
3223
3224 while (rn && iface) {
3225 radio = iface->radio;
3226 if (radio && os_strcmp(rn, radio->name) == 0) {
3227 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3228 wpa_s->ifname, rn);
3229 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3230 return radio;
3231 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003232
3233 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003234 }
3235
3236 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3237 wpa_s->ifname, rn ? rn : "N/A");
3238 radio = os_zalloc(sizeof(*radio));
3239 if (radio == NULL)
3240 return NULL;
3241
3242 if (rn)
3243 os_strlcpy(radio->name, rn, sizeof(radio->name));
3244 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003245 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003246 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3247
3248 return radio;
3249}
3250
3251
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003252static void radio_work_free(struct wpa_radio_work *work)
3253{
3254 if (work->wpa_s->scan_work == work) {
3255 /* This should not really happen. */
3256 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3257 work->type, work, work->started);
3258 work->wpa_s->scan_work = NULL;
3259 }
3260
3261#ifdef CONFIG_P2P
3262 if (work->wpa_s->p2p_scan_work == work) {
3263 /* This should not really happen. */
3264 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3265 work->type, work, work->started);
3266 work->wpa_s->p2p_scan_work = NULL;
3267 }
3268#endif /* CONFIG_P2P */
3269
3270 dl_list_del(&work->list);
3271 os_free(work);
3272}
3273
3274
3275static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3276{
3277 struct wpa_radio *radio = eloop_ctx;
3278 struct wpa_radio_work *work;
3279 struct os_reltime now, diff;
3280 struct wpa_supplicant *wpa_s;
3281
3282 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3283 if (work == NULL)
3284 return;
3285
3286 if (work->started)
3287 return; /* already started and still in progress */
3288
3289 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3290 radio_list);
3291 if (wpa_s && wpa_s->external_scan_running) {
3292 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3293 return;
3294 }
3295
3296 os_get_reltime(&now);
3297 os_reltime_sub(&now, &work->time, &diff);
3298 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3299 work->type, work, diff.sec, diff.usec);
3300 work->started = 1;
3301 work->time = now;
3302 work->cb(work, 0);
3303}
3304
3305
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003306/*
3307 * This function removes both started and pending radio works running on
3308 * the provided interface's radio.
3309 * Prior to the removal of the radio work, its callback (cb) is called with
3310 * deinit set to be 1. Each work's callback is responsible for clearing its
3311 * internal data and restoring to a correct state.
3312 * @wpa_s: wpa_supplicant data
3313 * @type: type of works to be removed
3314 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3315 * this interface's works.
3316 */
3317void radio_remove_works(struct wpa_supplicant *wpa_s,
3318 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003319{
3320 struct wpa_radio_work *work, *tmp;
3321 struct wpa_radio *radio = wpa_s->radio;
3322
3323 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3324 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003325 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003326 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003327
3328 /* skip other ifaces' works */
3329 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003330 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003331
3332 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3333 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003334 work->cb(work, 1);
3335 radio_work_free(work);
3336 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003337
3338 /* in case we removed the started work */
3339 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003340}
3341
3342
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003343static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3344{
3345 struct wpa_radio *radio = wpa_s->radio;
3346
3347 if (!radio)
3348 return;
3349
3350 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3351 wpa_s->ifname, radio->name);
3352 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003353 radio_remove_works(wpa_s, NULL, 0);
3354 wpa_s->radio = NULL;
3355 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003356 return; /* Interfaces remain for this radio */
3357
3358 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003359 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003360 os_free(radio);
3361}
3362
3363
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003364void radio_work_check_next(struct wpa_supplicant *wpa_s)
3365{
3366 struct wpa_radio *radio = wpa_s->radio;
3367
3368 if (dl_list_empty(&radio->work))
3369 return;
3370 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3371 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3372}
3373
3374
3375/**
3376 * radio_add_work - Add a radio work item
3377 * @wpa_s: Pointer to wpa_supplicant data
3378 * @freq: Frequency of the offchannel operation in MHz or 0
3379 * @type: Unique identifier for each type of work
3380 * @next: Force as the next work to be executed
3381 * @cb: Callback function for indicating when radio is available
3382 * @ctx: Context pointer for the work (work->ctx in cb())
3383 * Returns: 0 on success, -1 on failure
3384 *
3385 * This function is used to request time for an operation that requires
3386 * exclusive radio control. Once the radio is available, the registered callback
3387 * function will be called. radio_work_done() must be called once the exclusive
3388 * radio operation has been completed, so that the radio is freed for other
3389 * operations. The special case of deinit=1 is used to free the context data
3390 * during interface removal. That does not allow the callback function to start
3391 * the radio operation, i.e., it must free any resources allocated for the radio
3392 * work and return.
3393 *
3394 * The @freq parameter can be used to indicate a single channel on which the
3395 * offchannel operation will occur. This may allow multiple radio work
3396 * operations to be performed in parallel if they apply for the same channel.
3397 * Setting this to 0 indicates that the work item may use multiple channels or
3398 * requires exclusive control of the radio.
3399 */
3400int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3401 const char *type, int next,
3402 void (*cb)(struct wpa_radio_work *work, int deinit),
3403 void *ctx)
3404{
3405 struct wpa_radio_work *work;
3406 int was_empty;
3407
3408 work = os_zalloc(sizeof(*work));
3409 if (work == NULL)
3410 return -1;
3411 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3412 os_get_reltime(&work->time);
3413 work->freq = freq;
3414 work->type = type;
3415 work->wpa_s = wpa_s;
3416 work->cb = cb;
3417 work->ctx = ctx;
3418
3419 was_empty = dl_list_empty(&wpa_s->radio->work);
3420 if (next)
3421 dl_list_add(&wpa_s->radio->work, &work->list);
3422 else
3423 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3424 if (was_empty) {
3425 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3426 radio_work_check_next(wpa_s);
3427 }
3428
3429 return 0;
3430}
3431
3432
3433/**
3434 * radio_work_done - Indicate that a radio work item has been completed
3435 * @work: Completed work
3436 *
3437 * This function is called once the callback function registered with
3438 * radio_add_work() has completed its work.
3439 */
3440void radio_work_done(struct wpa_radio_work *work)
3441{
3442 struct wpa_supplicant *wpa_s = work->wpa_s;
3443 struct os_reltime now, diff;
3444 unsigned int started = work->started;
3445
3446 os_get_reltime(&now);
3447 os_reltime_sub(&now, &work->time, &diff);
3448 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3449 work->type, work, started ? "done" : "canceled",
3450 diff.sec, diff.usec);
3451 radio_work_free(work);
3452 if (started)
3453 radio_work_check_next(wpa_s);
3454}
3455
3456
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003457int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
3458{
3459 struct wpa_radio_work *work;
3460 struct wpa_radio *radio = wpa_s->radio;
3461
3462 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3463 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
3464 return 1;
3465 }
3466
3467 return 0;
3468}
3469
3470
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003471static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3472 struct wpa_interface *iface)
3473{
3474 const char *ifname, *driver, *rn;
3475
3476 driver = iface->driver;
3477next_driver:
3478 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3479 return -1;
3480
3481 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3482 if (wpa_s->drv_priv == NULL) {
3483 const char *pos;
3484 pos = driver ? os_strchr(driver, ',') : NULL;
3485 if (pos) {
3486 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3487 "driver interface - try next driver wrapper");
3488 driver = pos + 1;
3489 goto next_driver;
3490 }
3491 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3492 "interface");
3493 return -1;
3494 }
3495 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3496 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3497 "driver_param '%s'", wpa_s->conf->driver_param);
3498 return -1;
3499 }
3500
3501 ifname = wpa_drv_get_ifname(wpa_s);
3502 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3503 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3504 "interface name with '%s'", ifname);
3505 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3506 }
3507
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003508 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003509 if (rn && rn[0] == '\0')
3510 rn = NULL;
3511
3512 wpa_s->radio = radio_add_interface(wpa_s, rn);
3513 if (wpa_s->radio == NULL)
3514 return -1;
3515
3516 return 0;
3517}
3518
3519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003520static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3521 struct wpa_interface *iface)
3522{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003523 struct wpa_driver_capa capa;
3524
3525 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3526 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3527 iface->confname ? iface->confname : "N/A",
3528 iface->driver ? iface->driver : "default",
3529 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3530 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3531
3532 if (iface->confname) {
3533#ifdef CONFIG_BACKEND_FILE
3534 wpa_s->confname = os_rel2abs_path(iface->confname);
3535 if (wpa_s->confname == NULL) {
3536 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3537 "for configuration file '%s'.",
3538 iface->confname);
3539 return -1;
3540 }
3541 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3542 iface->confname, wpa_s->confname);
3543#else /* CONFIG_BACKEND_FILE */
3544 wpa_s->confname = os_strdup(iface->confname);
3545#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003546 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003547 if (wpa_s->conf == NULL) {
3548 wpa_printf(MSG_ERROR, "Failed to read or parse "
3549 "configuration '%s'.", wpa_s->confname);
3550 return -1;
3551 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003552 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3553 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003555#ifdef CONFIG_P2P
3556 wpa_s->conf_p2p_dev = os_rel2abs_path(iface->conf_p2p_dev);
3557 wpa_config_read(wpa_s->conf_p2p_dev, wpa_s->conf);
3558#endif /* CONFIG_P2P */
3559
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003560 /*
3561 * Override ctrl_interface and driver_param if set on command
3562 * line.
3563 */
3564 if (iface->ctrl_interface) {
3565 os_free(wpa_s->conf->ctrl_interface);
3566 wpa_s->conf->ctrl_interface =
3567 os_strdup(iface->ctrl_interface);
3568 }
3569
3570 if (iface->driver_param) {
3571 os_free(wpa_s->conf->driver_param);
3572 wpa_s->conf->driver_param =
3573 os_strdup(iface->driver_param);
3574 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003575
3576 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3577 os_free(wpa_s->conf->ctrl_interface);
3578 wpa_s->conf->ctrl_interface = NULL;
3579 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003580 } else
3581 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3582 iface->driver_param);
3583
3584 if (wpa_s->conf == NULL) {
3585 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3586 return -1;
3587 }
3588
3589 if (iface->ifname == NULL) {
3590 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3591 return -1;
3592 }
3593 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3594 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3595 iface->ifname);
3596 return -1;
3597 }
3598 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3599
3600 if (iface->bridge_ifname) {
3601 if (os_strlen(iface->bridge_ifname) >=
3602 sizeof(wpa_s->bridge_ifname)) {
3603 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3604 "name '%s'.", iface->bridge_ifname);
3605 return -1;
3606 }
3607 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3608 sizeof(wpa_s->bridge_ifname));
3609 }
3610
3611 /* RSNA Supplicant Key Management - INITIALIZE */
3612 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3613 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3614
3615 /* Initialize driver interface and register driver event handler before
3616 * L2 receive handler so that association events are processed before
3617 * EAPOL-Key packets if both become available for the same select()
3618 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003619 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003620 return -1;
3621
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003622 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3623 return -1;
3624
3625 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3626 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3627 NULL);
3628 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3629
3630 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3631 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3632 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3633 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3634 "dot11RSNAConfigPMKLifetime");
3635 return -1;
3636 }
3637
3638 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3639 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3640 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3641 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3642 "dot11RSNAConfigPMKReauthThreshold");
3643 return -1;
3644 }
3645
3646 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3647 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3648 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3649 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3650 "dot11RSNAConfigSATimeout");
3651 return -1;
3652 }
3653
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003654 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3655 &wpa_s->hw.num_modes,
3656 &wpa_s->hw.flags);
3657
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003658 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003659 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003660 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003661 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003662 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003663 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003664 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3665 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3666 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003667 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3668 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003669 wpa_s->extended_capa = capa.extended_capa;
3670 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3671 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003672 wpa_s->num_multichan_concurrent =
3673 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003674 }
3675 if (wpa_s->max_remain_on_chan == 0)
3676 wpa_s->max_remain_on_chan = 1000;
3677
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003678 /*
3679 * Only take p2p_mgmt parameters when P2P Device is supported.
3680 * Doing it here as it determines whether l2_packet_init() will be done
3681 * during wpa_supplicant_driver_init().
3682 */
3683 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3684 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3685 else
3686 iface->p2p_mgmt = 1;
3687
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003688 if (wpa_s->num_multichan_concurrent == 0)
3689 wpa_s->num_multichan_concurrent = 1;
3690
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003691 if (wpa_supplicant_driver_init(wpa_s) < 0)
3692 return -1;
3693
3694#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003695 if ((!iface->p2p_mgmt ||
3696 !(wpa_s->drv_flags &
3697 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3698 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003699 return -1;
3700#endif /* CONFIG_TDLS */
3701
3702 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3703 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3704 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3705 return -1;
3706 }
3707
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708 if (wpas_wps_init(wpa_s))
3709 return -1;
3710
3711 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3712 return -1;
3713 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3714
3715 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3716 if (wpa_s->ctrl_iface == NULL) {
3717 wpa_printf(MSG_ERROR,
3718 "Failed to initialize control interface '%s'.\n"
3719 "You may have another wpa_supplicant process "
3720 "already running or the file was\n"
3721 "left by an unclean termination of wpa_supplicant "
3722 "in which case you will need\n"
3723 "to manually remove this file before starting "
3724 "wpa_supplicant again.\n",
3725 wpa_s->conf->ctrl_interface);
3726 return -1;
3727 }
3728
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003729 wpa_s->gas = gas_query_init(wpa_s);
3730 if (wpa_s->gas == NULL) {
3731 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3732 return -1;
3733 }
3734
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003735 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003736 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3737 return -1;
3738 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003739
3740 if (wpa_bss_init(wpa_s) < 0)
3741 return -1;
3742
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003743 /*
3744 * Set Wake-on-WLAN triggers, if configured.
3745 * Note: We don't restore/remove the triggers on shutdown (it doesn't
3746 * have effect anyway when the interface is down).
3747 */
3748 if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
3749 return -1;
3750
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003751#ifdef CONFIG_EAP_PROXY
3752{
3753 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003754 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3755 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003756 if (wpa_s->mnc_len > 0) {
3757 wpa_s->imsi[len] = '\0';
3758 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3759 wpa_s->imsi, wpa_s->mnc_len);
3760 } else {
3761 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3762 }
3763}
3764#endif /* CONFIG_EAP_PROXY */
3765
Dmitry Shmidt04949592012-07-19 12:16:46 -07003766 if (pcsc_reader_init(wpa_s) < 0)
3767 return -1;
3768
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003769 if (wpas_init_ext_pw(wpa_s) < 0)
3770 return -1;
3771
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003772 return 0;
3773}
3774
3775
3776static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003777 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003778{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003779 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003780 if (wpa_s->drv_priv) {
3781 wpa_supplicant_deauthenticate(wpa_s,
3782 WLAN_REASON_DEAUTH_LEAVING);
3783
3784 wpa_drv_set_countermeasures(wpa_s, 0);
3785 wpa_clear_keys(wpa_s, NULL);
3786 }
3787
3788 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003789 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003790
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003791 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003792 radio_remove_interface(wpa_s);
3793
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003794 if (wpa_s->drv_priv)
3795 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003796
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003797 if (notify)
3798 wpas_notify_iface_removed(wpa_s);
3799
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003800 if (terminate)
3801 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003802
3803 if (wpa_s->ctrl_iface) {
3804 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3805 wpa_s->ctrl_iface = NULL;
3806 }
3807
3808 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003809 wpa_config_free(wpa_s->conf);
3810 wpa_s->conf = NULL;
3811 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003812
3813 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003814}
3815
3816
3817/**
3818 * wpa_supplicant_add_iface - Add a new network interface
3819 * @global: Pointer to global data from wpa_supplicant_init()
3820 * @iface: Interface configuration options
3821 * Returns: Pointer to the created interface or %NULL on failure
3822 *
3823 * This function is used to add new network interfaces for %wpa_supplicant.
3824 * This can be called before wpa_supplicant_run() to add interfaces before the
3825 * main event loop has been started. In addition, new interfaces can be added
3826 * dynamically while %wpa_supplicant is already running. This could happen,
3827 * e.g., when a hotplug network adapter is inserted.
3828 */
3829struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3830 struct wpa_interface *iface)
3831{
3832 struct wpa_supplicant *wpa_s;
3833 struct wpa_interface t_iface;
3834 struct wpa_ssid *ssid;
3835
3836 if (global == NULL || iface == NULL)
3837 return NULL;
3838
3839 wpa_s = wpa_supplicant_alloc();
3840 if (wpa_s == NULL)
3841 return NULL;
3842
3843 wpa_s->global = global;
3844
3845 t_iface = *iface;
3846 if (global->params.override_driver) {
3847 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3848 "('%s' -> '%s')",
3849 iface->driver, global->params.override_driver);
3850 t_iface.driver = global->params.override_driver;
3851 }
3852 if (global->params.override_ctrl_interface) {
3853 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3854 "ctrl_interface ('%s' -> '%s')",
3855 iface->ctrl_interface,
3856 global->params.override_ctrl_interface);
3857 t_iface.ctrl_interface =
3858 global->params.override_ctrl_interface;
3859 }
3860 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3861 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3862 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003863 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003864 return NULL;
3865 }
3866
3867 /* Notify the control interfaces about new iface */
3868 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003869 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003870 return NULL;
3871 }
3872
3873 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3874 wpas_notify_network_added(wpa_s, ssid);
3875
3876 wpa_s->next = global->ifaces;
3877 global->ifaces = wpa_s;
3878
3879 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003880 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003881
3882 return wpa_s;
3883}
3884
3885
3886/**
3887 * wpa_supplicant_remove_iface - Remove a network interface
3888 * @global: Pointer to global data from wpa_supplicant_init()
3889 * @wpa_s: Pointer to the network interface to be removed
3890 * Returns: 0 if interface was removed, -1 if interface was not found
3891 *
3892 * This function can be used to dynamically remove network interfaces from
3893 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3894 * addition, this function is used to remove all remaining interfaces when
3895 * %wpa_supplicant is terminated.
3896 */
3897int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003898 struct wpa_supplicant *wpa_s,
3899 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003900{
3901 struct wpa_supplicant *prev;
3902
3903 /* Remove interface from the global list of interfaces */
3904 prev = global->ifaces;
3905 if (prev == wpa_s) {
3906 global->ifaces = wpa_s->next;
3907 } else {
3908 while (prev && prev->next != wpa_s)
3909 prev = prev->next;
3910 if (prev == NULL)
3911 return -1;
3912 prev->next = wpa_s->next;
3913 }
3914
3915 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3916
3917 if (global->p2p_group_formation == wpa_s)
3918 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003919 if (global->p2p_invite_group == wpa_s)
3920 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003921 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003922
3923 return 0;
3924}
3925
3926
3927/**
3928 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3929 * @wpa_s: Pointer to the network interface
3930 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3931 */
3932const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3933{
3934 const char *eapol_method;
3935
3936 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3937 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3938 return "NO-EAP";
3939 }
3940
3941 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3942 if (eapol_method == NULL)
3943 return "UNKNOWN-EAP";
3944
3945 return eapol_method;
3946}
3947
3948
3949/**
3950 * wpa_supplicant_get_iface - Get a new network interface
3951 * @global: Pointer to global data from wpa_supplicant_init()
3952 * @ifname: Interface name
3953 * Returns: Pointer to the interface or %NULL if not found
3954 */
3955struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3956 const char *ifname)
3957{
3958 struct wpa_supplicant *wpa_s;
3959
3960 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3961 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3962 return wpa_s;
3963 }
3964 return NULL;
3965}
3966
3967
3968#ifndef CONFIG_NO_WPA_MSG
3969static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3970{
3971 struct wpa_supplicant *wpa_s = ctx;
3972 if (wpa_s == NULL)
3973 return NULL;
3974 return wpa_s->ifname;
3975}
3976#endif /* CONFIG_NO_WPA_MSG */
3977
3978
3979/**
3980 * wpa_supplicant_init - Initialize %wpa_supplicant
3981 * @params: Parameters for %wpa_supplicant
3982 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3983 *
3984 * This function is used to initialize %wpa_supplicant. After successful
3985 * initialization, the returned data pointer can be used to add and remove
3986 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3987 */
3988struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3989{
3990 struct wpa_global *global;
3991 int ret, i;
3992
3993 if (params == NULL)
3994 return NULL;
3995
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003996#ifdef CONFIG_DRIVER_NDIS
3997 {
3998 void driver_ndis_init_ops(void);
3999 driver_ndis_init_ops();
4000 }
4001#endif /* CONFIG_DRIVER_NDIS */
4002
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004003#ifndef CONFIG_NO_WPA_MSG
4004 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4005#endif /* CONFIG_NO_WPA_MSG */
4006
4007 wpa_debug_open_file(params->wpa_debug_file_path);
4008 if (params->wpa_debug_syslog)
4009 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004010 if (params->wpa_debug_tracing) {
4011 ret = wpa_debug_open_linux_tracing();
4012 if (ret) {
4013 wpa_printf(MSG_ERROR,
4014 "Failed to enable trace logging");
4015 return NULL;
4016 }
4017 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004018
4019 ret = eap_register_methods();
4020 if (ret) {
4021 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4022 if (ret == -2)
4023 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4024 "the same EAP type.");
4025 return NULL;
4026 }
4027
4028 global = os_zalloc(sizeof(*global));
4029 if (global == NULL)
4030 return NULL;
4031 dl_list_init(&global->p2p_srv_bonjour);
4032 dl_list_init(&global->p2p_srv_upnp);
4033 global->params.daemonize = params->daemonize;
4034 global->params.wait_for_monitor = params->wait_for_monitor;
4035 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4036 if (params->pid_file)
4037 global->params.pid_file = os_strdup(params->pid_file);
4038 if (params->ctrl_interface)
4039 global->params.ctrl_interface =
4040 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004041 if (params->ctrl_interface_group)
4042 global->params.ctrl_interface_group =
4043 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004044 if (params->override_driver)
4045 global->params.override_driver =
4046 os_strdup(params->override_driver);
4047 if (params->override_ctrl_interface)
4048 global->params.override_ctrl_interface =
4049 os_strdup(params->override_ctrl_interface);
4050 wpa_debug_level = global->params.wpa_debug_level =
4051 params->wpa_debug_level;
4052 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4053 params->wpa_debug_show_keys;
4054 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4055 params->wpa_debug_timestamp;
4056
4057 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4058
4059 if (eloop_init()) {
4060 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4061 wpa_supplicant_deinit(global);
4062 return NULL;
4063 }
4064
Jouni Malinen75ecf522011-06-27 15:19:46 -07004065 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004066
4067 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4068 if (global->ctrl_iface == NULL) {
4069 wpa_supplicant_deinit(global);
4070 return NULL;
4071 }
4072
4073 if (wpas_notify_supplicant_initialized(global)) {
4074 wpa_supplicant_deinit(global);
4075 return NULL;
4076 }
4077
4078 for (i = 0; wpa_drivers[i]; i++)
4079 global->drv_count++;
4080 if (global->drv_count == 0) {
4081 wpa_printf(MSG_ERROR, "No drivers enabled");
4082 wpa_supplicant_deinit(global);
4083 return NULL;
4084 }
4085 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
4086 if (global->drv_priv == NULL) {
4087 wpa_supplicant_deinit(global);
4088 return NULL;
4089 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004090
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004091#ifdef CONFIG_WIFI_DISPLAY
4092 if (wifi_display_init(global) < 0) {
4093 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4094 wpa_supplicant_deinit(global);
4095 return NULL;
4096 }
4097#endif /* CONFIG_WIFI_DISPLAY */
4098
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004099 return global;
4100}
4101
4102
4103/**
4104 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4105 * @global: Pointer to global data from wpa_supplicant_init()
4106 * Returns: 0 after successful event loop run, -1 on failure
4107 *
4108 * This function starts the main event loop and continues running as long as
4109 * there are any remaining events. In most cases, this function is running as
4110 * long as the %wpa_supplicant process in still in use.
4111 */
4112int wpa_supplicant_run(struct wpa_global *global)
4113{
4114 struct wpa_supplicant *wpa_s;
4115
4116 if (global->params.daemonize &&
4117 wpa_supplicant_daemon(global->params.pid_file))
4118 return -1;
4119
4120 if (global->params.wait_for_monitor) {
4121 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4122 if (wpa_s->ctrl_iface)
4123 wpa_supplicant_ctrl_iface_wait(
4124 wpa_s->ctrl_iface);
4125 }
4126
4127 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4128 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4129
4130 eloop_run();
4131
4132 return 0;
4133}
4134
4135
4136/**
4137 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4138 * @global: Pointer to global data from wpa_supplicant_init()
4139 *
4140 * This function is called to deinitialize %wpa_supplicant and to free all
4141 * allocated resources. Remaining network interfaces will also be removed.
4142 */
4143void wpa_supplicant_deinit(struct wpa_global *global)
4144{
4145 int i;
4146
4147 if (global == NULL)
4148 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004149
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004150#ifdef CONFIG_WIFI_DISPLAY
4151 wifi_display_deinit(global);
4152#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004153
4154 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004155 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004156
4157 if (global->ctrl_iface)
4158 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4159
4160 wpas_notify_supplicant_deinitialized(global);
4161
4162 eap_peer_unregister_methods();
4163#ifdef CONFIG_AP
4164 eap_server_unregister_methods();
4165#endif /* CONFIG_AP */
4166
4167 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4168 if (!global->drv_priv[i])
4169 continue;
4170 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4171 }
4172 os_free(global->drv_priv);
4173
4174 random_deinit();
4175
4176 eloop_destroy();
4177
4178 if (global->params.pid_file) {
4179 os_daemonize_terminate(global->params.pid_file);
4180 os_free(global->params.pid_file);
4181 }
4182 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004183 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004184 os_free(global->params.override_driver);
4185 os_free(global->params.override_ctrl_interface);
4186
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004187 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004188 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004189 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004190
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004191 os_free(global);
4192 wpa_debug_close_syslog();
4193 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004194 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004195}
4196
4197
4198void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4199{
4200 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4201 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4202 char country[3];
4203 country[0] = wpa_s->conf->country[0];
4204 country[1] = wpa_s->conf->country[1];
4205 country[2] = '\0';
4206 if (wpa_drv_set_country(wpa_s, country) < 0) {
4207 wpa_printf(MSG_ERROR, "Failed to set country code "
4208 "'%s'", country);
4209 }
4210 }
4211
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004212 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4213 wpas_init_ext_pw(wpa_s);
4214
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004215#ifdef CONFIG_WPS
4216 wpas_wps_update_config(wpa_s);
4217#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004218 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004219 wpa_s->conf->changed_parameters = 0;
4220}
4221
4222
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004223static void add_freq(int *freqs, int *num_freqs, int freq)
4224{
4225 int i;
4226
4227 for (i = 0; i < *num_freqs; i++) {
4228 if (freqs[i] == freq)
4229 return;
4230 }
4231
4232 freqs[*num_freqs] = freq;
4233 (*num_freqs)++;
4234}
4235
4236
4237static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4238{
4239 struct wpa_bss *bss, *cbss;
4240 const int max_freqs = 10;
4241 int *freqs;
4242 int num_freqs = 0;
4243
4244 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
4245 if (freqs == NULL)
4246 return NULL;
4247
4248 cbss = wpa_s->current_bss;
4249
4250 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4251 if (bss == cbss)
4252 continue;
4253 if (bss->ssid_len == cbss->ssid_len &&
4254 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4255 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4256 add_freq(freqs, &num_freqs, bss->freq);
4257 if (num_freqs == max_freqs)
4258 break;
4259 }
4260 }
4261
4262 if (num_freqs == 0) {
4263 os_free(freqs);
4264 freqs = NULL;
4265 }
4266
4267 return freqs;
4268}
4269
4270
4271void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4272{
4273 int timeout;
4274 int count;
4275 int *freqs = NULL;
4276
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004277 wpas_connect_work_done(wpa_s);
4278
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004279 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004280 * Remove possible authentication timeout since the connection failed.
4281 */
4282 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4283
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004284 if (wpa_s->disconnected) {
4285 /*
4286 * There is no point in blacklisting the AP if this event is
4287 * generated based on local request to disconnect.
4288 */
4289 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4290 "indication since interface has been put into "
4291 "disconnected state");
4292 return;
4293 }
4294
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004295 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004296 * Add the failed BSSID into the blacklist and speed up next scan
4297 * attempt if there could be other APs that could accept association.
4298 * The current blacklist count indicates how many times we have tried
4299 * connecting to this AP and multiple attempts mean that other APs are
4300 * either not available or has already been tried, so that we can start
4301 * increasing the delay here to avoid constant scanning.
4302 */
4303 count = wpa_blacklist_add(wpa_s, bssid);
4304 if (count == 1 && wpa_s->current_bss) {
4305 /*
4306 * This BSS was not in the blacklist before. If there is
4307 * another BSS available for the same ESS, we should try that
4308 * next. Otherwise, we may as well try this one once more
4309 * before allowing other, likely worse, ESSes to be considered.
4310 */
4311 freqs = get_bss_freqs_in_ess(wpa_s);
4312 if (freqs) {
4313 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4314 "has been seen; try it next");
4315 wpa_blacklist_add(wpa_s, bssid);
4316 /*
4317 * On the next scan, go through only the known channels
4318 * used in this ESS based on previous scans to speed up
4319 * common load balancing use case.
4320 */
4321 os_free(wpa_s->next_scan_freqs);
4322 wpa_s->next_scan_freqs = freqs;
4323 }
4324 }
4325
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004326 /*
4327 * Add previous failure count in case the temporary blacklist was
4328 * cleared due to no other BSSes being available.
4329 */
4330 count += wpa_s->extra_blacklist_count;
4331
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004332 if (count > 3 && wpa_s->current_ssid) {
4333 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4334 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004335 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004336 }
4337
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004338 switch (count) {
4339 case 1:
4340 timeout = 100;
4341 break;
4342 case 2:
4343 timeout = 500;
4344 break;
4345 case 3:
4346 timeout = 1000;
4347 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004348 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004350 break;
4351 default:
4352 timeout = 10000;
4353 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004354 }
4355
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004356 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4357 "ms", count, timeout);
4358
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004359 /*
4360 * TODO: if more than one possible AP is available in scan results,
4361 * could try the other ones before requesting a new scan.
4362 */
4363 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4364 1000 * (timeout % 1000));
4365}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004366
4367
4368int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4369{
4370 return wpa_s->conf->ap_scan == 2 ||
4371 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4372}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004373
Dmitry Shmidt04949592012-07-19 12:16:46 -07004374
4375#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4376int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4377 struct wpa_ssid *ssid,
4378 const char *field,
4379 const char *value)
4380{
4381#ifdef IEEE8021X_EAPOL
4382 struct eap_peer_config *eap = &ssid->eap;
4383
4384 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4385 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4386 (const u8 *) value, os_strlen(value));
4387
4388 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4389 case WPA_CTRL_REQ_EAP_IDENTITY:
4390 os_free(eap->identity);
4391 eap->identity = (u8 *) os_strdup(value);
4392 eap->identity_len = os_strlen(value);
4393 eap->pending_req_identity = 0;
4394 if (ssid == wpa_s->current_ssid)
4395 wpa_s->reassociate = 1;
4396 break;
4397 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004398 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004399 eap->password = (u8 *) os_strdup(value);
4400 eap->password_len = os_strlen(value);
4401 eap->pending_req_password = 0;
4402 if (ssid == wpa_s->current_ssid)
4403 wpa_s->reassociate = 1;
4404 break;
4405 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004406 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004407 eap->new_password = (u8 *) os_strdup(value);
4408 eap->new_password_len = os_strlen(value);
4409 eap->pending_req_new_password = 0;
4410 if (ssid == wpa_s->current_ssid)
4411 wpa_s->reassociate = 1;
4412 break;
4413 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004414 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004415 eap->pin = os_strdup(value);
4416 eap->pending_req_pin = 0;
4417 if (ssid == wpa_s->current_ssid)
4418 wpa_s->reassociate = 1;
4419 break;
4420 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004421 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004422 eap->otp = (u8 *) os_strdup(value);
4423 eap->otp_len = os_strlen(value);
4424 os_free(eap->pending_req_otp);
4425 eap->pending_req_otp = NULL;
4426 eap->pending_req_otp_len = 0;
4427 break;
4428 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004429 str_clear_free(eap->private_key_passwd);
4430 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004431 eap->pending_req_passphrase = 0;
4432 if (ssid == wpa_s->current_ssid)
4433 wpa_s->reassociate = 1;
4434 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004435 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004436 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004437 eap->external_sim_resp = os_strdup(value);
4438 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004439 default:
4440 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4441 return -1;
4442 }
4443
4444 return 0;
4445#else /* IEEE8021X_EAPOL */
4446 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4447 return -1;
4448#endif /* IEEE8021X_EAPOL */
4449}
4450#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4451
4452
4453int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4454{
4455 int i;
4456 unsigned int drv_enc;
4457
4458 if (ssid == NULL)
4459 return 1;
4460
4461 if (ssid->disabled)
4462 return 1;
4463
4464 if (wpa_s && wpa_s->drv_capa_known)
4465 drv_enc = wpa_s->drv_enc;
4466 else
4467 drv_enc = (unsigned int) -1;
4468
4469 for (i = 0; i < NUM_WEP_KEYS; i++) {
4470 size_t len = ssid->wep_key_len[i];
4471 if (len == 0)
4472 continue;
4473 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4474 continue;
4475 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4476 continue;
4477 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4478 continue;
4479 return 1; /* invalid WEP key */
4480 }
4481
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004482 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07004483 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004484 return 1;
4485
Dmitry Shmidt04949592012-07-19 12:16:46 -07004486 return 0;
4487}
4488
4489
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004490int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004491{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004492 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004493 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004494 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004495 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004496 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004497}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004498
4499
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004500void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004501{
4502 struct wpa_ssid *ssid = wpa_s->current_ssid;
4503 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004504 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004505
4506 if (ssid == NULL) {
4507 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4508 "SSID block");
4509 return;
4510 }
4511
4512 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4513 return;
4514
4515 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004516
4517#ifdef CONFIG_P2P
4518 if (ssid->p2p_group &&
4519 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4520 /*
4521 * Skip the wait time since there is a short timeout on the
4522 * connection to a P2P group.
4523 */
4524 return;
4525 }
4526#endif /* CONFIG_P2P */
4527
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004528 if (ssid->auth_failures > 50)
4529 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004530 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004531 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004532 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004533 dur = 90;
4534 else if (ssid->auth_failures > 3)
4535 dur = 60;
4536 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004537 dur = 30;
4538 else if (ssid->auth_failures > 1)
4539 dur = 20;
4540 else
4541 dur = 10;
4542
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004543 if (ssid->auth_failures > 1 &&
4544 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
4545 dur += os_random() % (ssid->auth_failures * 10);
4546
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004547 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004548 if (now.sec + dur <= ssid->disabled_until.sec)
4549 return;
4550
4551 ssid->disabled_until.sec = now.sec + dur;
4552
4553 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004554 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004555 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004556 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004557}
4558
4559
4560void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4561 struct wpa_ssid *ssid, int clear_failures)
4562{
4563 if (ssid == NULL)
4564 return;
4565
4566 if (ssid->disabled_until.sec) {
4567 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4568 "id=%d ssid=\"%s\"",
4569 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4570 }
4571 ssid->disabled_until.sec = 0;
4572 ssid->disabled_until.usec = 0;
4573 if (clear_failures)
4574 ssid->auth_failures = 0;
4575}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004576
4577
4578int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4579{
4580 size_t i;
4581
4582 if (wpa_s->disallow_aps_bssid == NULL)
4583 return 0;
4584
4585 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4586 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4587 bssid, ETH_ALEN) == 0)
4588 return 1;
4589 }
4590
4591 return 0;
4592}
4593
4594
4595int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4596 size_t ssid_len)
4597{
4598 size_t i;
4599
4600 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4601 return 0;
4602
4603 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4604 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4605 if (ssid_len == s->ssid_len &&
4606 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4607 return 1;
4608 }
4609
4610 return 0;
4611}
4612
4613
4614/**
4615 * wpas_request_connection - Request a new connection
4616 * @wpa_s: Pointer to the network interface
4617 *
4618 * This function is used to request a new connection to be found. It will mark
4619 * the interface to allow reassociation and request a new scan to find a
4620 * suitable network to connect to.
4621 */
4622void wpas_request_connection(struct wpa_supplicant *wpa_s)
4623{
4624 wpa_s->normal_scans = 0;
4625 wpa_supplicant_reinit_autoscan(wpa_s);
4626 wpa_s->extra_blacklist_count = 0;
4627 wpa_s->disconnected = 0;
4628 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004629
4630 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4631 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004632}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004633
4634
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004635void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
4636 struct wpa_used_freq_data *freqs_data,
4637 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004638{
4639 unsigned int i;
4640
4641 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4642 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004643 for (i = 0; i < len; i++) {
4644 struct wpa_used_freq_data *cur = &freqs_data[i];
4645 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
4646 i, cur->freq, cur->flags);
4647 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004648}
4649
4650
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004651/*
4652 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004653 * are using the same radio as the current interface, and in addition, get
4654 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004655 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004656int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
4657 struct wpa_used_freq_data *freqs_data,
4658 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004659{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004660 struct wpa_supplicant *ifs;
4661 u8 bssid[ETH_ALEN];
4662 int freq;
4663 unsigned int idx = 0, i;
4664
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004665 wpa_dbg(wpa_s, MSG_DEBUG,
4666 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004667 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004668
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004669 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4670 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004671 if (idx == len)
4672 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004673
4674 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4675 continue;
4676
4677 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4678 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4679 freq = ifs->current_ssid->frequency;
4680 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4681 freq = ifs->assoc_freq;
4682 else
4683 continue;
4684
4685 /* Hold only distinct freqs */
4686 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004687 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004688 break;
4689
4690 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004691 freqs_data[idx++].freq = freq;
4692
4693 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
4694 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
4695 WPA_FREQ_USED_BY_P2P_CLIENT :
4696 WPA_FREQ_USED_BY_INFRA_STATION;
4697 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004698 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004699
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004700 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004701 return idx;
4702}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004703
4704
4705/*
4706 * Find the operating frequencies of any of the virtual interfaces that
4707 * are using the same radio as the current interface.
4708 */
4709int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4710 int *freq_array, unsigned int len)
4711{
4712 struct wpa_used_freq_data *freqs_data;
4713 int num, i;
4714
4715 os_memset(freq_array, 0, sizeof(int) * len);
4716
4717 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
4718 if (!freqs_data)
4719 return -1;
4720
4721 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
4722 for (i = 0; i < num; i++)
4723 freq_array[i] = freqs_data[i].freq;
4724
4725 os_free(freqs_data);
4726
4727 return num;
4728}