blob: 9414e8f3276f6711e17d55d4eb939fb78be8dbf2 [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{
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700378 int i;
379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700380 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700381 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700382 scard_deinit(wpa_s->scard);
383 wpa_s->scard = NULL;
384 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
385 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
386 l2_packet_deinit(wpa_s->l2);
387 wpa_s->l2 = NULL;
388 if (wpa_s->l2_br) {
389 l2_packet_deinit(wpa_s->l2_br);
390 wpa_s->l2_br = NULL;
391 }
392
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700393 if (wpa_s->conf != NULL) {
394 struct wpa_ssid *ssid;
395 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
396 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700397 }
398
399 os_free(wpa_s->confname);
400 wpa_s->confname = NULL;
401
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700402 os_free(wpa_s->confanother);
403 wpa_s->confanother = NULL;
404
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -0800405#ifdef CONFIG_P2P
406 os_free(wpa_s->conf_p2p_dev);
407 wpa_s->conf_p2p_dev = NULL;
408#endif /* CONFIG_P2P */
409
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700410 wpa_sm_set_eapol(wpa_s->wpa, NULL);
411 eapol_sm_deinit(wpa_s->eapol);
412 wpa_s->eapol = NULL;
413
414 rsn_preauth_deinit(wpa_s->wpa);
415
416#ifdef CONFIG_TDLS
417 wpa_tdls_deinit(wpa_s->wpa);
418#endif /* CONFIG_TDLS */
419
420 pmksa_candidate_free(wpa_s->wpa);
421 wpa_sm_deinit(wpa_s->wpa);
422 wpa_s->wpa = NULL;
423 wpa_blacklist_clear(wpa_s);
424
425 wpa_bss_deinit(wpa_s);
426
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700427 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700428 wpa_supplicant_cancel_scan(wpa_s);
429 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800430 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
431#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
432 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
433 wpa_s, NULL);
434#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700435
436 wpas_wps_deinit(wpa_s);
437
438 wpabuf_free(wpa_s->pending_eapol_rx);
439 wpa_s->pending_eapol_rx = NULL;
440
441#ifdef CONFIG_IBSS_RSN
442 ibss_rsn_deinit(wpa_s->ibss_rsn);
443 wpa_s->ibss_rsn = NULL;
444#endif /* CONFIG_IBSS_RSN */
445
446 sme_deinit(wpa_s);
447
448#ifdef CONFIG_AP
449 wpa_supplicant_ap_deinit(wpa_s);
450#endif /* CONFIG_AP */
451
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700452 wpas_p2p_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700453
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800454#ifdef CONFIG_OFFCHANNEL
455 offchannel_deinit(wpa_s);
456#endif /* CONFIG_OFFCHANNEL */
457
458 wpa_supplicant_cancel_sched_scan(wpa_s);
459
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700460 os_free(wpa_s->next_scan_freqs);
461 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800462
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800463 os_free(wpa_s->manual_scan_freqs);
464 wpa_s->manual_scan_freqs = NULL;
465
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700466 os_free(wpa_s->manual_sched_scan_freqs);
467 wpa_s->manual_sched_scan_freqs = NULL;
468
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800469 gas_query_deinit(wpa_s->gas);
470 wpa_s->gas = NULL;
471
472 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700473
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700474 ieee802_1x_dealloc_kay_sm(wpa_s);
475
Dmitry Shmidt04949592012-07-19 12:16:46 -0700476 os_free(wpa_s->bssid_filter);
477 wpa_s->bssid_filter = NULL;
478
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800479 os_free(wpa_s->disallow_aps_bssid);
480 wpa_s->disallow_aps_bssid = NULL;
481 os_free(wpa_s->disallow_aps_ssid);
482 wpa_s->disallow_aps_ssid = NULL;
483
Dmitry Shmidt04949592012-07-19 12:16:46 -0700484 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700485#ifdef CONFIG_WNM
486 wnm_deallocate_memory(wpa_s);
487#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700488
489 ext_password_deinit(wpa_s->ext_pw);
490 wpa_s->ext_pw = NULL;
491
492 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800493 wpa_s->last_gas_resp = NULL;
494 wpabuf_free(wpa_s->prev_gas_resp);
495 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700496
497 os_free(wpa_s->last_scan_res);
498 wpa_s->last_scan_res = NULL;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800499
500#ifdef CONFIG_HS20
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700501 hs20_deinit(wpa_s);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800502#endif /* CONFIG_HS20 */
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700503
504 for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
505 wpabuf_free(wpa_s->vendor_elem[i]);
506 wpa_s->vendor_elem[i] = NULL;
507 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700508}
509
510
511/**
512 * wpa_clear_keys - Clear keys configured for the driver
513 * @wpa_s: Pointer to wpa_supplicant data
514 * @addr: Previously used BSSID or %NULL if not available
515 *
516 * This function clears the encryption keys that has been previously configured
517 * for the driver.
518 */
519void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
520{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800521 int i, max;
522
523#ifdef CONFIG_IEEE80211W
524 max = 6;
525#else /* CONFIG_IEEE80211W */
526 max = 4;
527#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700528
529 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800530 for (i = 0; i < max; i++) {
531 if (wpa_s->keys_cleared & BIT(i))
532 continue;
533 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
534 NULL, 0);
535 }
536 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
537 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700538 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
539 0);
540 /* MLME-SETPROTECTION.request(None) */
541 wpa_drv_mlme_setprotection(
542 wpa_s, addr,
543 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
544 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
545 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800546 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700547}
548
549
550/**
551 * wpa_supplicant_state_txt - Get the connection state name as a text string
552 * @state: State (wpa_state; WPA_*)
553 * Returns: The state name as a printable text string
554 */
555const char * wpa_supplicant_state_txt(enum wpa_states state)
556{
557 switch (state) {
558 case WPA_DISCONNECTED:
559 return "DISCONNECTED";
560 case WPA_INACTIVE:
561 return "INACTIVE";
562 case WPA_INTERFACE_DISABLED:
563 return "INTERFACE_DISABLED";
564 case WPA_SCANNING:
565 return "SCANNING";
566 case WPA_AUTHENTICATING:
567 return "AUTHENTICATING";
568 case WPA_ASSOCIATING:
569 return "ASSOCIATING";
570 case WPA_ASSOCIATED:
571 return "ASSOCIATED";
572 case WPA_4WAY_HANDSHAKE:
573 return "4WAY_HANDSHAKE";
574 case WPA_GROUP_HANDSHAKE:
575 return "GROUP_HANDSHAKE";
576 case WPA_COMPLETED:
577 return "COMPLETED";
578 default:
579 return "UNKNOWN";
580 }
581}
582
583
584#ifdef CONFIG_BGSCAN
585
586static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
587{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800588 const char *name;
589
590 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
591 name = wpa_s->current_ssid->bgscan;
592 else
593 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800594 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800595 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800596 if (wpas_driver_bss_selection(wpa_s))
597 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
599 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800600#ifdef CONFIG_P2P
601 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
602 return;
603#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700604
605 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800606 if (wpa_s->current_ssid) {
607 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700608 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
609 "bgscan");
610 /*
611 * Live without bgscan; it is only used as a roaming
612 * optimization, so the initial connection is not
613 * affected.
614 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700615 } else {
616 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700617 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700618 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
619 0);
620 if (scan_res) {
621 bgscan_notify_scan(wpa_s, scan_res);
622 wpa_scan_results_free(scan_res);
623 }
624 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700625 } else
626 wpa_s->bgscan_ssid = NULL;
627}
628
629
630static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
631{
632 if (wpa_s->bgscan_ssid != NULL) {
633 bgscan_deinit(wpa_s);
634 wpa_s->bgscan_ssid = NULL;
635 }
636}
637
638#endif /* CONFIG_BGSCAN */
639
640
Dmitry Shmidt04949592012-07-19 12:16:46 -0700641static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
642{
643 if (autoscan_init(wpa_s, 0))
644 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
645}
646
647
648static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
649{
650 autoscan_deinit(wpa_s);
651}
652
653
654void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
655{
656 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
657 wpa_s->wpa_state == WPA_SCANNING) {
658 autoscan_deinit(wpa_s);
659 wpa_supplicant_start_autoscan(wpa_s);
660 }
661}
662
663
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700664/**
665 * wpa_supplicant_set_state - Set current connection state
666 * @wpa_s: Pointer to wpa_supplicant data
667 * @state: The new connection state
668 *
669 * This function is called whenever the connection state changes, e.g.,
670 * association is completed for WPA/WPA2 4-Way Handshake is started.
671 */
672void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
673 enum wpa_states state)
674{
675 enum wpa_states old_state = wpa_s->wpa_state;
676
677 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
678 wpa_supplicant_state_txt(wpa_s->wpa_state),
679 wpa_supplicant_state_txt(state));
680
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800681 if (state == WPA_INTERFACE_DISABLED) {
682 /* Assure normal scan when interface is restored */
683 wpa_s->normal_scans = 0;
684 }
685
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700686 if (state == WPA_COMPLETED) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800687 wpas_connect_work_done(wpa_s);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700688 /* Reinitialize normal_scan counter */
689 wpa_s->normal_scans = 0;
690 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800691
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692 if (state != WPA_SCANNING)
693 wpa_supplicant_notify_scanning(wpa_s, 0);
694
695 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700696 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700697#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700698 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800699 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800700 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700701 ssid ? ssid->id : -1,
702 ssid && ssid->id_str ? ssid->id_str : "");
703#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700704 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800705 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700706 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707 wpa_drv_set_operstate(wpa_s, 1);
708#ifndef IEEE8021X_EAPOL
709 wpa_drv_set_supp_port(wpa_s, 1);
710#endif /* IEEE8021X_EAPOL */
711 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700712 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700713 wpas_p2p_completed(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700714
715 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
717 state == WPA_ASSOCIATED) {
718 wpa_s->new_connection = 1;
719 wpa_drv_set_operstate(wpa_s, 0);
720#ifndef IEEE8021X_EAPOL
721 wpa_drv_set_supp_port(wpa_s, 0);
722#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700723 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700724 }
725 wpa_s->wpa_state = state;
726
727#ifdef CONFIG_BGSCAN
728 if (state == WPA_COMPLETED)
729 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800730 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700731 wpa_supplicant_stop_bgscan(wpa_s);
732#endif /* CONFIG_BGSCAN */
733
Dmitry Shmidt04949592012-07-19 12:16:46 -0700734 if (state == WPA_AUTHENTICATING)
735 wpa_supplicant_stop_autoscan(wpa_s);
736
737 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
738 wpa_supplicant_start_autoscan(wpa_s);
739
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740 if (wpa_s->wpa_state != old_state) {
741 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
742
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700743 /*
744 * Notify the P2P Device interface about a state change in one
745 * of the interfaces.
746 */
747 wpas_p2p_indicate_state_change(wpa_s);
748
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749 if (wpa_s->wpa_state == WPA_COMPLETED ||
750 old_state == WPA_COMPLETED)
751 wpas_notify_auth_changed(wpa_s);
752 }
753}
754
755
756void wpa_supplicant_terminate_proc(struct wpa_global *global)
757{
758 int pending = 0;
759#ifdef CONFIG_WPS
760 struct wpa_supplicant *wpa_s = global->ifaces;
761 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800762 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700763 if (wpas_wps_terminate_pending(wpa_s) == 1)
764 pending = 1;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700765#ifdef CONFIG_P2P
766 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
767 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
768 wpas_p2p_disconnect(wpa_s);
769#endif /* CONFIG_P2P */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800770 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700771 }
772#endif /* CONFIG_WPS */
773 if (pending)
774 return;
775 eloop_terminate();
776}
777
778
779static void wpa_supplicant_terminate(int sig, void *signal_ctx)
780{
781 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700782 wpa_supplicant_terminate_proc(global);
783}
784
785
786void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
787{
788 enum wpa_states old_state = wpa_s->wpa_state;
789
790 wpa_s->pairwise_cipher = 0;
791 wpa_s->group_cipher = 0;
792 wpa_s->mgmt_group_cipher = 0;
793 wpa_s->key_mgmt = 0;
794 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700795 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796
797 if (wpa_s->wpa_state != old_state)
798 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
799}
800
801
802/**
803 * wpa_supplicant_reload_configuration - Reload configuration data
804 * @wpa_s: Pointer to wpa_supplicant data
805 * Returns: 0 on success or -1 if configuration parsing failed
806 *
807 * This function can be used to request that the configuration data is reloaded
808 * (e.g., after configuration file change). This function is reloading
809 * configuration only for one interface, so this may need to be called multiple
810 * times if %wpa_supplicant is controlling multiple interfaces and all
811 * interfaces need reconfiguration.
812 */
813int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
814{
815 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700816 int reconf_ctrl;
817 int old_ap_scan;
818
819 if (wpa_s->confname == NULL)
820 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700821 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700822 if (conf == NULL) {
823 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
824 "file '%s' - exiting", wpa_s->confname);
825 return -1;
826 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700827 wpa_config_read(wpa_s->confanother, conf);
828
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700829 conf->changed_parameters = (unsigned int) -1;
830
831 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
832 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
833 os_strcmp(conf->ctrl_interface,
834 wpa_s->conf->ctrl_interface) != 0);
835
836 if (reconf_ctrl && wpa_s->ctrl_iface) {
837 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
838 wpa_s->ctrl_iface = NULL;
839 }
840
841 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800842 if (wpa_s->current_ssid) {
843 wpa_supplicant_deauthenticate(wpa_s,
844 WLAN_REASON_DEAUTH_LEAVING);
845 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700846
847 /*
848 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
849 * pkcs11_engine_path, pkcs11_module_path.
850 */
851 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
852 /*
853 * Clear forced success to clear EAP state for next
854 * authentication.
855 */
856 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
857 }
858 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
859 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800860 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700861 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
862 rsn_preauth_deinit(wpa_s->wpa);
863
864 old_ap_scan = wpa_s->conf->ap_scan;
865 wpa_config_free(wpa_s->conf);
866 wpa_s->conf = conf;
867 if (old_ap_scan != wpa_s->conf->ap_scan)
868 wpas_notify_ap_scan_changed(wpa_s);
869
870 if (reconf_ctrl)
871 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
872
873 wpa_supplicant_update_config(wpa_s);
874
875 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700876 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700877 wpa_s->reassociate = 1;
878 wpa_supplicant_req_scan(wpa_s, 0, 0);
879 }
880 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
881 return 0;
882}
883
884
885static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
886{
887 struct wpa_global *global = signal_ctx;
888 struct wpa_supplicant *wpa_s;
889 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
890 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
891 sig);
892 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
893 wpa_supplicant_terminate_proc(global);
894 }
895 }
896}
897
898
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700899static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
900 struct wpa_ssid *ssid,
901 struct wpa_ie_data *ie)
902{
903 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
904 if (ret) {
905 if (ret == -2) {
906 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
907 "from association info");
908 }
909 return -1;
910 }
911
912 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
913 "cipher suites");
914 if (!(ie->group_cipher & ssid->group_cipher)) {
915 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
916 "cipher 0x%x (mask 0x%x) - reject",
917 ie->group_cipher, ssid->group_cipher);
918 return -1;
919 }
920 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
921 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
922 "cipher 0x%x (mask 0x%x) - reject",
923 ie->pairwise_cipher, ssid->pairwise_cipher);
924 return -1;
925 }
926 if (!(ie->key_mgmt & ssid->key_mgmt)) {
927 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
928 "management 0x%x (mask 0x%x) - reject",
929 ie->key_mgmt, ssid->key_mgmt);
930 return -1;
931 }
932
933#ifdef CONFIG_IEEE80211W
934 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800935 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
936 wpa_s->conf->pmf : ssid->ieee80211w) ==
937 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700938 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
939 "that does not support management frame protection - "
940 "reject");
941 return -1;
942 }
943#endif /* CONFIG_IEEE80211W */
944
945 return 0;
946}
947
948
949/**
950 * wpa_supplicant_set_suites - Set authentication and encryption parameters
951 * @wpa_s: Pointer to wpa_supplicant data
952 * @bss: Scan results for the selected BSS, or %NULL if not available
953 * @ssid: Configuration data for the selected network
954 * @wpa_ie: Buffer for the WPA/RSN IE
955 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
956 * used buffer length in case the functions returns success.
957 * Returns: 0 on success or -1 on failure
958 *
959 * This function is used to configure authentication and encryption parameters
960 * based on the network configuration and scan result for the selected BSS (if
961 * available).
962 */
963int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
964 struct wpa_bss *bss, struct wpa_ssid *ssid,
965 u8 *wpa_ie, size_t *wpa_ie_len)
966{
967 struct wpa_ie_data ie;
968 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800969 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700970
971 if (bss) {
972 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
973 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800974 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700975 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800976 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700977
978 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
979 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[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, "RSN: using IEEE 802.11i/D9.0");
984 proto = WPA_PROTO_RSN;
985 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
986 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
987 (ie.group_cipher & ssid->group_cipher) &&
988 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
989 (ie.key_mgmt & ssid->key_mgmt)) {
990 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
991 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800992#ifdef CONFIG_HS20
993 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
994 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
995 /* TODO: parse OSEN element */
Dmitry Shmidt623d63a2014-06-13 11:05:14 -0700996 os_memset(&ie, 0, sizeof(ie));
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800997 ie.group_cipher = WPA_CIPHER_CCMP;
998 ie.pairwise_cipher = WPA_CIPHER_CCMP;
999 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
1000 proto = WPA_PROTO_OSEN;
1001#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002 } else if (bss) {
1003 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
1004 return -1;
1005 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001006 if (ssid->proto & WPA_PROTO_OSEN)
1007 proto = WPA_PROTO_OSEN;
1008 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009 proto = WPA_PROTO_RSN;
1010 else
1011 proto = WPA_PROTO_WPA;
1012 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
1013 os_memset(&ie, 0, sizeof(ie));
1014 ie.group_cipher = ssid->group_cipher;
1015 ie.pairwise_cipher = ssid->pairwise_cipher;
1016 ie.key_mgmt = ssid->key_mgmt;
1017#ifdef CONFIG_IEEE80211W
1018 ie.mgmt_group_cipher =
1019 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1020 WPA_CIPHER_AES_128_CMAC : 0;
1021#endif /* CONFIG_IEEE80211W */
1022 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1023 "based on configuration");
1024 } else
1025 proto = ie.proto;
1026 }
1027
1028 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1029 "pairwise %d key_mgmt %d proto %d",
1030 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1031#ifdef CONFIG_IEEE80211W
1032 if (ssid->ieee80211w) {
1033 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1034 ie.mgmt_group_cipher);
1035 }
1036#endif /* CONFIG_IEEE80211W */
1037
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001038 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1040 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001041 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042
1043 if (bss || !wpa_s->ap_ies_from_associnfo) {
1044 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1045 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1046 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1047 bss_rsn ? 2 + bss_rsn[1] : 0))
1048 return -1;
1049 }
1050
1051 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001052 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1053 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001054 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1055 "cipher");
1056 return -1;
1057 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001058 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1059 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001060
1061 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001062 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1063 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001064 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1065 "cipher");
1066 return -1;
1067 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001068 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1069 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070
1071 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001072#ifdef CONFIG_SAE
1073 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1074 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1075#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001076 if (0) {
1077#ifdef CONFIG_IEEE80211R
1078 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1079 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1080 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1081 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1082 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1083 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1084#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001085#ifdef CONFIG_SAE
1086 } else if (sel & WPA_KEY_MGMT_SAE) {
1087 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1088 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1089 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1090 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1091 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1092#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001093#ifdef CONFIG_IEEE80211W
1094 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1095 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1096 wpa_dbg(wpa_s, MSG_DEBUG,
1097 "WPA: using KEY_MGMT 802.1X with SHA256");
1098 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1099 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1100 wpa_dbg(wpa_s, MSG_DEBUG,
1101 "WPA: using KEY_MGMT PSK with SHA256");
1102#endif /* CONFIG_IEEE80211W */
1103 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1104 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1105 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1106 } else if (sel & WPA_KEY_MGMT_PSK) {
1107 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1108 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1109 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1110 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1111 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001112#ifdef CONFIG_HS20
1113 } else if (sel & WPA_KEY_MGMT_OSEN) {
1114 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1115 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1116#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117 } else {
1118 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1119 "authenticated key management type");
1120 return -1;
1121 }
1122
1123 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1124 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1125 wpa_s->pairwise_cipher);
1126 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1127
1128#ifdef CONFIG_IEEE80211W
1129 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001130 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1131 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1133 sel = 0;
1134 if (sel & WPA_CIPHER_AES_128_CMAC) {
1135 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1136 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1137 "AES-128-CMAC");
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001138 } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
1139 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
1140 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1141 "BIP-GMAC-128");
1142 } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
1143 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
1144 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1145 "BIP-GMAC-256");
1146 } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
1147 wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
1148 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1149 "BIP-CMAC-256");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001150 } else {
1151 wpa_s->mgmt_group_cipher = 0;
1152 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1153 }
1154 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1155 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001156 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1157 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1158 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001159#endif /* CONFIG_IEEE80211W */
1160
1161 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1162 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1163 return -1;
1164 }
1165
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001166 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001167 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001168#ifndef CONFIG_NO_PBKDF2
1169 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1170 ssid->passphrase) {
1171 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001172 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1173 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001174 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1175 psk, PMK_LEN);
1176 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1177 }
1178#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001179#ifdef CONFIG_EXT_PASSWORD
1180 if (ssid->ext_psk) {
1181 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1182 ssid->ext_psk);
1183 char pw_str[64 + 1];
1184 u8 psk[PMK_LEN];
1185
1186 if (pw == NULL) {
1187 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1188 "found from external storage");
1189 return -1;
1190 }
1191
1192 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1193 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1194 "PSK length %d in external storage",
1195 (int) wpabuf_len(pw));
1196 ext_password_free(pw);
1197 return -1;
1198 }
1199
1200 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1201 pw_str[wpabuf_len(pw)] = '\0';
1202
1203#ifndef CONFIG_NO_PBKDF2
1204 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1205 {
1206 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1207 4096, psk, PMK_LEN);
1208 os_memset(pw_str, 0, sizeof(pw_str));
1209 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1210 "external passphrase)",
1211 psk, PMK_LEN);
1212 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1213 } else
1214#endif /* CONFIG_NO_PBKDF2 */
1215 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1216 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1217 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1218 "Invalid PSK hex string");
1219 os_memset(pw_str, 0, sizeof(pw_str));
1220 ext_password_free(pw);
1221 return -1;
1222 }
1223 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1224 } else {
1225 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1226 "PSK available");
1227 os_memset(pw_str, 0, sizeof(pw_str));
1228 ext_password_free(pw);
1229 return -1;
1230 }
1231
1232 os_memset(pw_str, 0, sizeof(pw_str));
1233 ext_password_free(pw);
1234 }
1235#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001236 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001237 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1238
1239 return 0;
1240}
1241
1242
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001243static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1244{
1245 *pos = 0x00;
1246
1247 switch (idx) {
1248 case 0: /* Bits 0-7 */
1249 break;
1250 case 1: /* Bits 8-15 */
1251 break;
1252 case 2: /* Bits 16-23 */
1253#ifdef CONFIG_WNM
1254 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1255 *pos |= 0x08; /* Bit 19 - BSS Transition */
1256#endif /* CONFIG_WNM */
1257 break;
1258 case 3: /* Bits 24-31 */
1259#ifdef CONFIG_WNM
1260 *pos |= 0x02; /* Bit 25 - SSID List */
1261#endif /* CONFIG_WNM */
1262#ifdef CONFIG_INTERWORKING
1263 if (wpa_s->conf->interworking)
1264 *pos |= 0x80; /* Bit 31 - Interworking */
1265#endif /* CONFIG_INTERWORKING */
1266 break;
1267 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001268#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001269 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1270 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001271#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001272 break;
1273 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001274#ifdef CONFIG_HS20
1275 if (wpa_s->conf->hs20)
1276 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1277#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001278 break;
1279 case 6: /* Bits 48-55 */
1280 break;
1281 }
1282}
1283
1284
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001285int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001286{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001287 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001288 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001289
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001290 if (len < wpa_s->extended_capa_len)
1291 len = wpa_s->extended_capa_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001292 if (buflen < (size_t) len + 2) {
1293 wpa_printf(MSG_INFO,
1294 "Not enough room for building extended capabilities element");
1295 return -1;
1296 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001297
1298 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001299 *pos++ = len;
1300 for (i = 0; i < len; i++, pos++) {
1301 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001302
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001303 if (i < wpa_s->extended_capa_len) {
1304 *pos &= ~wpa_s->extended_capa_mask[i];
1305 *pos |= wpa_s->extended_capa[i];
1306 }
1307 }
1308
1309 while (len > 0 && buf[1 + len] == 0) {
1310 len--;
1311 buf[1] = len;
1312 }
1313 if (len == 0)
1314 return 0;
1315
1316 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001317}
1318
1319
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001320static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1321 struct wpa_bss *test_bss)
1322{
1323 struct wpa_bss *bss;
1324
1325 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1326 if (bss == test_bss)
1327 return 1;
1328 }
1329
1330 return 0;
1331}
1332
1333
1334static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1335 struct wpa_ssid *test_ssid)
1336{
1337 struct wpa_ssid *ssid;
1338
1339 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1340 if (ssid == test_ssid)
1341 return 1;
1342 }
1343
1344 return 0;
1345}
1346
1347
1348int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1349 struct wpa_ssid *test_ssid)
1350{
1351 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1352 return 0;
1353
1354 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1355}
1356
1357
1358void wpas_connect_work_free(struct wpa_connect_work *cwork)
1359{
1360 if (cwork == NULL)
1361 return;
1362 os_free(cwork);
1363}
1364
1365
1366void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1367{
1368 struct wpa_connect_work *cwork;
1369 struct wpa_radio_work *work = wpa_s->connect_work;
1370
1371 if (!work)
1372 return;
1373
1374 wpa_s->connect_work = NULL;
1375 cwork = work->ctx;
1376 work->ctx = NULL;
1377 wpas_connect_work_free(cwork);
1378 radio_work_done(work);
1379}
1380
1381
1382static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001384/**
1385 * wpa_supplicant_associate - Request association
1386 * @wpa_s: Pointer to wpa_supplicant data
1387 * @bss: Scan results for the selected BSS, or %NULL if not available
1388 * @ssid: Configuration data for the selected network
1389 *
1390 * This function is used to request %wpa_supplicant to associate with a BSS.
1391 */
1392void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1393 struct wpa_bss *bss, struct wpa_ssid *ssid)
1394{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001395 struct wpa_connect_work *cwork;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001396
1397#ifdef CONFIG_IBSS_RSN
1398 ibss_rsn_deinit(wpa_s->ibss_rsn);
1399 wpa_s->ibss_rsn = NULL;
1400#endif /* CONFIG_IBSS_RSN */
1401
1402 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1403 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1404#ifdef CONFIG_AP
1405 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1406 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1407 "mode");
1408 return;
1409 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001410 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1411 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001412 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1413 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001414 return;
1415 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416 wpa_s->current_bss = bss;
1417#else /* CONFIG_AP */
1418 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1419 "the build");
1420#endif /* CONFIG_AP */
1421 return;
1422 }
1423
1424#ifdef CONFIG_TDLS
1425 if (bss)
1426 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1427 bss->ie_len);
1428#endif /* CONFIG_TDLS */
1429
1430 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1431 ssid->mode == IEEE80211_MODE_INFRA) {
1432 sme_authenticate(wpa_s, bss, ssid);
1433 return;
1434 }
1435
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001436 if (wpa_s->connect_work) {
1437 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1438 return;
1439 }
1440
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001441 if (radio_work_pending(wpa_s, "connect")) {
1442 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1443 return;
1444 }
1445
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001446 cwork = os_zalloc(sizeof(*cwork));
1447 if (cwork == NULL)
1448 return;
1449
1450 cwork->bss = bss;
1451 cwork->ssid = ssid;
1452
1453 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1454 wpas_start_assoc_cb, cwork) < 0) {
1455 os_free(cwork);
1456 }
1457}
1458
1459
1460static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1461{
1462 struct wpa_connect_work *cwork = work->ctx;
1463 struct wpa_bss *bss = cwork->bss;
1464 struct wpa_ssid *ssid = cwork->ssid;
1465 struct wpa_supplicant *wpa_s = work->wpa_s;
1466 u8 wpa_ie[200];
1467 size_t wpa_ie_len;
1468 int use_crypt, ret, i, bssid_changed;
1469 int algs = WPA_AUTH_ALG_OPEN;
1470 unsigned int cipher_pairwise, cipher_group;
1471 struct wpa_driver_associate_params params;
1472 int wep_keys_set = 0;
1473 int assoc_failed = 0;
1474 struct wpa_ssid *old_ssid;
1475#ifdef CONFIG_HT_OVERRIDES
1476 struct ieee80211_ht_capabilities htcaps;
1477 struct ieee80211_ht_capabilities htcaps_mask;
1478#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001479#ifdef CONFIG_VHT_OVERRIDES
1480 struct ieee80211_vht_capabilities vhtcaps;
1481 struct ieee80211_vht_capabilities vhtcaps_mask;
1482#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001483
1484 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001485 if (work->started) {
1486 wpa_s->connect_work = NULL;
1487
1488 /* cancel possible auth. timeout */
1489 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1490 NULL);
1491 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001492 wpas_connect_work_free(cwork);
1493 return;
1494 }
1495
1496 wpa_s->connect_work = work;
1497
1498 if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
1499 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1500 wpas_connect_work_done(wpa_s);
1501 return;
1502 }
1503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001504 os_memset(&params, 0, sizeof(params));
1505 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001506 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001507 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508#ifdef CONFIG_IEEE80211R
1509 const u8 *ie, *md = NULL;
1510#endif /* CONFIG_IEEE80211R */
1511 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1512 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1513 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1514 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1515 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1516 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1517 if (bssid_changed)
1518 wpas_notify_bssid_changed(wpa_s);
1519#ifdef CONFIG_IEEE80211R
1520 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1521 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1522 md = ie + 2;
1523 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1524 if (md) {
1525 /* Prepare for the next transition */
1526 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1527 }
1528#endif /* CONFIG_IEEE80211R */
1529#ifdef CONFIG_WPS
1530 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1531 wpa_s->conf->ap_scan == 2 &&
1532 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1533 /* Use ap_scan==1 style network selection to find the network
1534 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001535 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001536 wpa_s->reassociate = 1;
1537 wpa_supplicant_req_scan(wpa_s, 0, 0);
1538 return;
1539#endif /* CONFIG_WPS */
1540 } else {
1541 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1542 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1543 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1544 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001545 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001546 wpa_supplicant_cancel_scan(wpa_s);
1547
1548 /* Starting new association, so clear the possibly used WPA IE from the
1549 * previous association. */
1550 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1551
1552#ifdef IEEE8021X_EAPOL
1553 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1554 if (ssid->leap) {
1555 if (ssid->non_leap == 0)
1556 algs = WPA_AUTH_ALG_LEAP;
1557 else
1558 algs |= WPA_AUTH_ALG_LEAP;
1559 }
1560 }
1561#endif /* IEEE8021X_EAPOL */
1562 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1563 if (ssid->auth_alg) {
1564 algs = ssid->auth_alg;
1565 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1566 "0x%x", algs);
1567 }
1568
1569 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1570 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001571 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001572 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001573 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1574 wpa_s->conf->okc :
1575 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001576 (ssid->proto & WPA_PROTO_RSN);
1577 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001578 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001579 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1580 wpa_ie_len = sizeof(wpa_ie);
1581 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1582 wpa_ie, &wpa_ie_len)) {
1583 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1584 "key management and encryption suites");
1585 return;
1586 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001587 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1588 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1589 /*
1590 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1591 * use non-WPA since the scan results did not indicate that the
1592 * AP is using WPA or WPA2.
1593 */
1594 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1595 wpa_ie_len = 0;
1596 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001597 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001598 wpa_ie_len = sizeof(wpa_ie);
1599 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1600 wpa_ie, &wpa_ie_len)) {
1601 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1602 "key management and encryption suites (no "
1603 "scan results)");
1604 return;
1605 }
1606#ifdef CONFIG_WPS
1607 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1608 struct wpabuf *wps_ie;
1609 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1610 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1611 wpa_ie_len = wpabuf_len(wps_ie);
1612 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1613 } else
1614 wpa_ie_len = 0;
1615 wpabuf_free(wps_ie);
1616 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1617 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1618 params.wps = WPS_MODE_PRIVACY;
1619 else
1620 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001621 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622#endif /* CONFIG_WPS */
1623 } else {
1624 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1625 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001626 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001627 }
1628
1629#ifdef CONFIG_P2P
1630 if (wpa_s->global->p2p) {
1631 u8 *pos;
1632 size_t len;
1633 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001634 pos = wpa_ie + wpa_ie_len;
1635 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001636 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1637 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001638 if (res >= 0)
1639 wpa_ie_len += res;
1640 }
1641
1642 wpa_s->cross_connect_disallowed = 0;
1643 if (bss) {
1644 struct wpabuf *p2p;
1645 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1646 if (p2p) {
1647 wpa_s->cross_connect_disallowed =
1648 p2p_get_cross_connect_disallowed(p2p);
1649 wpabuf_free(p2p);
1650 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1651 "connection",
1652 wpa_s->cross_connect_disallowed ?
1653 "disallows" : "allows");
1654 }
1655 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001656
1657 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001658#endif /* CONFIG_P2P */
1659
Dmitry Shmidt04949592012-07-19 12:16:46 -07001660#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001661 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001662 struct wpabuf *hs20;
1663 hs20 = wpabuf_alloc(20);
1664 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001665 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001666 size_t len;
1667
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001668 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001669 len = sizeof(wpa_ie) - wpa_ie_len;
1670 if (wpabuf_len(hs20) <= len) {
1671 os_memcpy(wpa_ie + wpa_ie_len,
1672 wpabuf_head(hs20), wpabuf_len(hs20));
1673 wpa_ie_len += wpabuf_len(hs20);
1674 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001675 wpabuf_free(hs20);
1676 }
1677 }
1678#endif /* CONFIG_HS20 */
1679
Dmitry Shmidt56052862013-10-04 10:23:25 -07001680 /*
1681 * Workaround: Add Extended Capabilities element only if the AP
1682 * included this element in Beacon/Probe Response frames. Some older
1683 * APs seem to have interoperability issues if this element is
1684 * included, so while the standard may require us to include the
1685 * element in all cases, it is justifiable to skip it to avoid
1686 * interoperability issues.
1687 */
1688 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001689 u8 ext_capab[18];
Dmitry Shmidt56052862013-10-04 10:23:25 -07001690 int ext_capab_len;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07001691 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
1692 sizeof(ext_capab));
Dmitry Shmidt56052862013-10-04 10:23:25 -07001693 if (ext_capab_len > 0) {
1694 u8 *pos = wpa_ie;
1695 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1696 pos += 2 + pos[1];
1697 os_memmove(pos + ext_capab_len, pos,
1698 wpa_ie_len - (pos - wpa_ie));
1699 wpa_ie_len += ext_capab_len;
1700 os_memcpy(pos, ext_capab, ext_capab_len);
1701 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001702 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001703
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001704 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1705 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001706 cipher_pairwise = wpa_s->pairwise_cipher;
1707 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001708 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1709 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1710 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1711 use_crypt = 0;
1712 if (wpa_set_wep_keys(wpa_s, ssid)) {
1713 use_crypt = 1;
1714 wep_keys_set = 1;
1715 }
1716 }
1717 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1718 use_crypt = 0;
1719
1720#ifdef IEEE8021X_EAPOL
1721 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1722 if ((ssid->eapol_flags &
1723 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1724 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1725 !wep_keys_set) {
1726 use_crypt = 0;
1727 } else {
1728 /* Assume that dynamic WEP-104 keys will be used and
1729 * set cipher suites in order for drivers to expect
1730 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001731 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732 }
1733 }
1734#endif /* IEEE8021X_EAPOL */
1735
1736 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1737 /* Set the key before (and later after) association */
1738 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1739 }
1740
1741 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1742 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001743 params.ssid = bss->ssid;
1744 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001745 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1746 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1747 MACSTR " freq=%u MHz based on scan results "
1748 "(bssid_set=%d)",
1749 MAC2STR(bss->bssid), bss->freq,
1750 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001751 params.bssid = bss->bssid;
1752 params.freq = bss->freq;
1753 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001754 params.bssid_hint = bss->bssid;
1755 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001756 } else {
1757 params.ssid = ssid->ssid;
1758 params.ssid_len = ssid->ssid_len;
1759 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001760
1761 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1762 wpa_s->conf->ap_scan == 2) {
1763 params.bssid = ssid->bssid;
1764 params.fixed_bssid = 1;
1765 }
1766
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001767 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1768 params.freq == 0)
1769 params.freq = ssid->frequency; /* Initial channel for IBSS */
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08001770
1771 if (ssid->mode == WPAS_MODE_IBSS) {
1772 if (ssid->beacon_int)
1773 params.beacon_int = ssid->beacon_int;
1774 else
1775 params.beacon_int = wpa_s->conf->beacon_int;
1776 }
1777
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001778 params.wpa_ie = wpa_ie;
1779 params.wpa_ie_len = wpa_ie_len;
1780 params.pairwise_suite = cipher_pairwise;
1781 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001782 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001783 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001784 params.auth_alg = algs;
1785 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001786 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787 for (i = 0; i < NUM_WEP_KEYS; i++) {
1788 if (ssid->wep_key_len[i])
1789 params.wep_key[i] = ssid->wep_key[i];
1790 params.wep_key_len[i] = ssid->wep_key_len[i];
1791 }
1792 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1793
1794 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001795 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1796 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 params.passphrase = ssid->passphrase;
1798 if (ssid->psk_set)
1799 params.psk = ssid->psk;
1800 }
1801
1802 params.drop_unencrypted = use_crypt;
1803
1804#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001805 params.mgmt_frame_protection =
1806 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1807 wpa_s->conf->pmf : ssid->ieee80211w;
1808 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001809 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1810 struct wpa_ie_data ie;
1811 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1812 ie.capabilities &
1813 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1814 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1815 "MFP: require MFP");
1816 params.mgmt_frame_protection =
1817 MGMT_FRAME_PROTECTION_REQUIRED;
1818 }
1819 }
1820#endif /* CONFIG_IEEE80211W */
1821
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001822 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823
1824 if (wpa_s->parent->set_sta_uapsd)
1825 params.uapsd = wpa_s->parent->sta_uapsd;
1826 else
1827 params.uapsd = -1;
1828
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001829#ifdef CONFIG_HT_OVERRIDES
1830 os_memset(&htcaps, 0, sizeof(htcaps));
1831 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1832 params.htcaps = (u8 *) &htcaps;
1833 params.htcaps_mask = (u8 *) &htcaps_mask;
1834 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1835#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001836#ifdef CONFIG_VHT_OVERRIDES
1837 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
1838 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
1839 params.vhtcaps = &vhtcaps;
1840 params.vhtcaps_mask = &vhtcaps_mask;
1841 wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
1842#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001843
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001844#ifdef CONFIG_P2P
1845 /*
1846 * If multi-channel concurrency is not supported, check for any
1847 * frequency conflict. In case of any frequency conflict, remove the
1848 * least prioritized connection.
1849 */
1850 if (wpa_s->num_multichan_concurrent < 2) {
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001851 int freq, num;
1852 num = get_shared_radio_freqs(wpa_s, &freq, 1);
1853 if (num > 0 && freq > 0 && freq != params.freq) {
1854 wpa_printf(MSG_DEBUG,
1855 "Assoc conflicting freq found (%d != %d)",
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001856 freq, params.freq);
1857 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1858 params.freq,
1859 ssid) < 0)
1860 return;
1861 }
1862 }
1863#endif /* CONFIG_P2P */
1864
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001865 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866 if (ret < 0) {
1867 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1868 "failed");
1869 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1870 /*
1871 * The driver is known to mean what is saying, so we
1872 * can stop right here; the association will not
1873 * succeed.
1874 */
1875 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001876 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1878 return;
1879 }
1880 /* try to continue anyway; new association will be tried again
1881 * after timeout */
1882 assoc_failed = 1;
1883 }
1884
1885 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1886 /* Set the key after the association just in case association
1887 * cleared the previously configured key. */
1888 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1889 /* No need to timeout authentication since there is no key
1890 * management. */
1891 wpa_supplicant_cancel_auth_timeout(wpa_s);
1892 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1893#ifdef CONFIG_IBSS_RSN
1894 } else if (ssid->mode == WPAS_MODE_IBSS &&
1895 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1896 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1897 /*
1898 * RSN IBSS authentication is per-STA and we can disable the
1899 * per-BSSID authentication.
1900 */
1901 wpa_supplicant_cancel_auth_timeout(wpa_s);
1902#endif /* CONFIG_IBSS_RSN */
1903 } else {
1904 /* Timeout for IEEE 802.11 authentication and association */
1905 int timeout = 60;
1906
1907 if (assoc_failed) {
1908 /* give IBSS a bit more time */
1909 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1910 } else if (wpa_s->conf->ap_scan == 1) {
1911 /* give IBSS a bit more time */
1912 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1913 }
1914 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1915 }
1916
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001917 if (wep_keys_set &&
1918 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001919 /* Set static WEP keys again */
1920 wpa_set_wep_keys(wpa_s, ssid);
1921 }
1922
1923 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1924 /*
1925 * Do not allow EAP session resumption between different
1926 * network configurations.
1927 */
1928 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1929 }
1930 old_ssid = wpa_s->current_ssid;
1931 wpa_s->current_ssid = ssid;
1932 wpa_s->current_bss = bss;
1933 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1934 wpa_supplicant_initiate_eapol(wpa_s);
1935 if (old_ssid != wpa_s->current_ssid)
1936 wpas_notify_network_changed(wpa_s);
1937}
1938
1939
1940static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1941 const u8 *addr)
1942{
1943 struct wpa_ssid *old_ssid;
1944
1945 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001946 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001947 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001948 wpa_sm_set_config(wpa_s->wpa, NULL);
1949 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1950 if (old_ssid != wpa_s->current_ssid)
1951 wpas_notify_network_changed(wpa_s);
1952 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1953}
1954
1955
1956/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001957 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1958 * @wpa_s: Pointer to wpa_supplicant data
1959 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1960 *
1961 * This function is used to request %wpa_supplicant to deauthenticate from the
1962 * current AP.
1963 */
1964void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1965 int reason_code)
1966{
1967 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001968 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001969 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001970
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001971 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1972 " pending_bssid=" MACSTR " reason=%d state=%s",
1973 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1974 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1975
1976 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001977 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001978 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1979 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1980 wpa_s->wpa_state == WPA_ASSOCIATING))
1981 addr = wpa_s->pending_bssid;
1982 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1983 /*
1984 * When using driver-based BSS selection, we may not know the
1985 * BSSID with which we are currently trying to associate. We
1986 * need to notify the driver of this disconnection even in such
1987 * a case, so use the all zeros address here.
1988 */
1989 addr = wpa_s->bssid;
1990 zero_addr = 1;
1991 }
1992
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001993#ifdef CONFIG_TDLS
1994 wpa_tdls_teardown_peers(wpa_s->wpa);
1995#endif /* CONFIG_TDLS */
1996
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001997 if (addr) {
1998 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001999 os_memset(&event, 0, sizeof(event));
2000 event.deauth_info.reason_code = (u16) reason_code;
2001 event.deauth_info.locally_generated = 1;
2002 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002003 if (zero_addr)
2004 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002005 }
2006
2007 wpa_supplicant_clear_connection(wpa_s, addr);
2008}
2009
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002010static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
2011 struct wpa_ssid *ssid)
2012{
2013 if (!ssid || !ssid->disabled || ssid->disabled == 2)
2014 return;
2015
2016 ssid->disabled = 0;
2017 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2018 wpas_notify_network_enabled_changed(wpa_s, ssid);
2019
2020 /*
2021 * Try to reassociate since there is no current configuration and a new
2022 * network was made available.
2023 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002024 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002025 wpa_s->reassociate = 1;
2026}
2027
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002028
2029/**
2030 * wpa_supplicant_enable_network - Mark a configured network as enabled
2031 * @wpa_s: wpa_supplicant structure for a network interface
2032 * @ssid: wpa_ssid structure for a configured network or %NULL
2033 *
2034 * Enables the specified network or all networks if no network specified.
2035 */
2036void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
2037 struct wpa_ssid *ssid)
2038{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002039 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002040 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
2041 wpa_supplicant_enable_one_network(wpa_s, ssid);
2042 } else
2043 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002044
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07002045 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002046 if (wpa_s->sched_scanning) {
2047 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
2048 "new network to scan filters");
2049 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050 }
2051
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002052 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2053 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054 }
2055}
2056
2057
2058/**
2059 * wpa_supplicant_disable_network - Mark a configured network as disabled
2060 * @wpa_s: wpa_supplicant structure for a network interface
2061 * @ssid: wpa_ssid structure for a configured network or %NULL
2062 *
2063 * Disables the specified network or all networks if no network specified.
2064 */
2065void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
2066 struct wpa_ssid *ssid)
2067{
2068 struct wpa_ssid *other_ssid;
2069 int was_disabled;
2070
2071 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002072 if (wpa_s->sched_scanning)
2073 wpa_supplicant_cancel_sched_scan(wpa_s);
2074
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2076 other_ssid = other_ssid->next) {
2077 was_disabled = other_ssid->disabled;
2078 if (was_disabled == 2)
2079 continue; /* do not change persistent P2P group
2080 * data */
2081
2082 other_ssid->disabled = 1;
2083
2084 if (was_disabled != other_ssid->disabled)
2085 wpas_notify_network_enabled_changed(
2086 wpa_s, other_ssid);
2087 }
2088 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002089 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002090 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2091 } else if (ssid->disabled != 2) {
2092 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002093 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002094 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2095
2096 was_disabled = ssid->disabled;
2097
2098 ssid->disabled = 1;
2099
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002100 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002101 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002102 if (wpa_s->sched_scanning) {
2103 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2104 "to remove network from filters");
2105 wpa_supplicant_cancel_sched_scan(wpa_s);
2106 wpa_supplicant_req_scan(wpa_s, 0, 0);
2107 }
2108 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002109 }
2110}
2111
2112
2113/**
2114 * wpa_supplicant_select_network - Attempt association with a network
2115 * @wpa_s: wpa_supplicant structure for a network interface
2116 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2117 */
2118void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2119 struct wpa_ssid *ssid)
2120{
2121
2122 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002123 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002124
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002125 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002126 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002128 disconnected = 1;
2129 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002130
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002131 if (ssid)
2132 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2133
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002134 /*
2135 * Mark all other networks disabled or mark all networks enabled if no
2136 * network specified.
2137 */
2138 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2139 other_ssid = other_ssid->next) {
2140 int was_disabled = other_ssid->disabled;
2141 if (was_disabled == 2)
2142 continue; /* do not change persistent P2P group data */
2143
2144 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002145 if (was_disabled && !other_ssid->disabled)
2146 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002147
2148 if (was_disabled != other_ssid->disabled)
2149 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2150 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002151
2152 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2153 /* We are already associated with the selected network */
2154 wpa_printf(MSG_DEBUG, "Already associated with the "
2155 "selected network - do nothing");
2156 return;
2157 }
2158
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002159 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002160 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002161 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2162 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002163 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002164 wpa_s->disconnected = 0;
2165 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002166
2167 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2168 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169
2170 if (ssid)
2171 wpas_notify_network_selected(wpa_s, ssid);
2172}
2173
2174
2175/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002176 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2177 * @wpa_s: wpa_supplicant structure for a network interface
2178 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2179 * @pkcs11_module_path: PKCS #11 module path or NULL
2180 * Returns: 0 on success; -1 on failure
2181 *
2182 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2183 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2184 * module path fails the paths will be reset to the default value (NULL).
2185 */
2186int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2187 const char *pkcs11_engine_path,
2188 const char *pkcs11_module_path)
2189{
2190 char *pkcs11_engine_path_copy = NULL;
2191 char *pkcs11_module_path_copy = NULL;
2192
2193 if (pkcs11_engine_path != NULL) {
2194 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2195 if (pkcs11_engine_path_copy == NULL)
2196 return -1;
2197 }
2198 if (pkcs11_module_path != NULL) {
2199 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002200 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002201 os_free(pkcs11_engine_path_copy);
2202 return -1;
2203 }
2204 }
2205
2206 os_free(wpa_s->conf->pkcs11_engine_path);
2207 os_free(wpa_s->conf->pkcs11_module_path);
2208 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2209 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2210
2211 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2212 eapol_sm_deinit(wpa_s->eapol);
2213 wpa_s->eapol = NULL;
2214 if (wpa_supplicant_init_eapol(wpa_s)) {
2215 /* Error -> Reset paths to the default value (NULL) once. */
2216 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2217 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2218 NULL);
2219
2220 return -1;
2221 }
2222 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2223
2224 return 0;
2225}
2226
2227
2228/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002229 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2230 * @wpa_s: wpa_supplicant structure for a network interface
2231 * @ap_scan: AP scan mode
2232 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2233 *
2234 */
2235int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2236{
2237
2238 int old_ap_scan;
2239
2240 if (ap_scan < 0 || ap_scan > 2)
2241 return -1;
2242
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002243#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002244 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2245 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2246 wpa_s->wpa_state < WPA_COMPLETED) {
2247 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2248 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002249 return 0;
2250 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002251#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002252
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002253 old_ap_scan = wpa_s->conf->ap_scan;
2254 wpa_s->conf->ap_scan = ap_scan;
2255
2256 if (old_ap_scan != wpa_s->conf->ap_scan)
2257 wpas_notify_ap_scan_changed(wpa_s);
2258
2259 return 0;
2260}
2261
2262
2263/**
2264 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2265 * @wpa_s: wpa_supplicant structure for a network interface
2266 * @expire_age: Expiration age in seconds
2267 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2268 *
2269 */
2270int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2271 unsigned int bss_expire_age)
2272{
2273 if (bss_expire_age < 10) {
2274 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2275 bss_expire_age);
2276 return -1;
2277 }
2278 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2279 bss_expire_age);
2280 wpa_s->conf->bss_expiration_age = bss_expire_age;
2281
2282 return 0;
2283}
2284
2285
2286/**
2287 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2288 * @wpa_s: wpa_supplicant structure for a network interface
2289 * @expire_count: number of scans after which an unseen BSS is reclaimed
2290 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2291 *
2292 */
2293int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2294 unsigned int bss_expire_count)
2295{
2296 if (bss_expire_count < 1) {
2297 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2298 bss_expire_count);
2299 return -1;
2300 }
2301 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2302 bss_expire_count);
2303 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2304
2305 return 0;
2306}
2307
2308
2309/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002310 * wpa_supplicant_set_scan_interval - Set scan interval
2311 * @wpa_s: wpa_supplicant structure for a network interface
2312 * @scan_interval: scan interval in seconds
2313 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2314 *
2315 */
2316int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2317 int scan_interval)
2318{
2319 if (scan_interval < 0) {
2320 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2321 scan_interval);
2322 return -1;
2323 }
2324 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2325 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002326 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002327
2328 return 0;
2329}
2330
2331
2332/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333 * wpa_supplicant_set_debug_params - Set global debug params
2334 * @global: wpa_global structure
2335 * @debug_level: debug level
2336 * @debug_timestamp: determines if show timestamp in debug data
2337 * @debug_show_keys: determines if show keys in debug data
2338 * Returns: 0 if succeed or -1 if debug_level has wrong value
2339 */
2340int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2341 int debug_timestamp, int debug_show_keys)
2342{
2343
2344 int old_level, old_timestamp, old_show_keys;
2345
2346 /* check for allowed debuglevels */
2347 if (debug_level != MSG_EXCESSIVE &&
2348 debug_level != MSG_MSGDUMP &&
2349 debug_level != MSG_DEBUG &&
2350 debug_level != MSG_INFO &&
2351 debug_level != MSG_WARNING &&
2352 debug_level != MSG_ERROR)
2353 return -1;
2354
2355 old_level = wpa_debug_level;
2356 old_timestamp = wpa_debug_timestamp;
2357 old_show_keys = wpa_debug_show_keys;
2358
2359 wpa_debug_level = debug_level;
2360 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2361 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2362
2363 if (wpa_debug_level != old_level)
2364 wpas_notify_debug_level_changed(global);
2365 if (wpa_debug_timestamp != old_timestamp)
2366 wpas_notify_debug_timestamp_changed(global);
2367 if (wpa_debug_show_keys != old_show_keys)
2368 wpas_notify_debug_show_keys_changed(global);
2369
2370 return 0;
2371}
2372
2373
2374/**
2375 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2376 * @wpa_s: Pointer to wpa_supplicant data
2377 * Returns: A pointer to the current network structure or %NULL on failure
2378 */
2379struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2380{
2381 struct wpa_ssid *entry;
2382 u8 ssid[MAX_SSID_LEN];
2383 int res;
2384 size_t ssid_len;
2385 u8 bssid[ETH_ALEN];
2386 int wired;
2387
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002388 res = wpa_drv_get_ssid(wpa_s, ssid);
2389 if (res < 0) {
2390 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2391 "driver");
2392 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002393 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002394 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002395
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002396 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002397 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2398 "driver");
2399 return NULL;
2400 }
2401
2402 wired = wpa_s->conf->ap_scan == 0 &&
2403 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2404
2405 entry = wpa_s->conf->ssid;
2406 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002407 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002408 ((ssid_len == entry->ssid_len &&
2409 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2410 (!entry->bssid_set ||
2411 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2412 return entry;
2413#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002414 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002415 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2416 (entry->ssid == NULL || entry->ssid_len == 0) &&
2417 (!entry->bssid_set ||
2418 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2419 return entry;
2420#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002421
Dmitry Shmidt04949592012-07-19 12:16:46 -07002422 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002423 entry->ssid_len == 0 &&
2424 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2425 return entry;
2426
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 entry = entry->next;
2428 }
2429
2430 return NULL;
2431}
2432
2433
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002434static int select_driver(struct wpa_supplicant *wpa_s, int i)
2435{
2436 struct wpa_global *global = wpa_s->global;
2437
2438 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2439 global->drv_priv[i] = wpa_drivers[i]->global_init();
2440 if (global->drv_priv[i] == NULL) {
2441 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2442 "'%s'", wpa_drivers[i]->name);
2443 return -1;
2444 }
2445 }
2446
2447 wpa_s->driver = wpa_drivers[i];
2448 wpa_s->global_drv_priv = global->drv_priv[i];
2449
2450 return 0;
2451}
2452
2453
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002454static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2455 const char *name)
2456{
2457 int i;
2458 size_t len;
2459 const char *pos, *driver = name;
2460
2461 if (wpa_s == NULL)
2462 return -1;
2463
2464 if (wpa_drivers[0] == NULL) {
2465 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2466 "wpa_supplicant");
2467 return -1;
2468 }
2469
2470 if (name == NULL) {
2471 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002472 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002473 }
2474
2475 do {
2476 pos = os_strchr(driver, ',');
2477 if (pos)
2478 len = pos - driver;
2479 else
2480 len = os_strlen(driver);
2481
2482 for (i = 0; wpa_drivers[i]; i++) {
2483 if (os_strlen(wpa_drivers[i]->name) == len &&
2484 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002485 0) {
2486 /* First driver that succeeds wins */
2487 if (select_driver(wpa_s, i) == 0)
2488 return 0;
2489 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002490 }
2491
2492 driver = pos + 1;
2493 } while (pos);
2494
2495 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2496 return -1;
2497}
2498
2499
2500/**
2501 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2502 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2503 * with struct wpa_driver_ops::init()
2504 * @src_addr: Source address of the EAPOL frame
2505 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2506 * @len: Length of the EAPOL data
2507 *
2508 * This function is called for each received EAPOL frame. Most driver
2509 * interfaces rely on more generic OS mechanism for receiving frames through
2510 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2511 * take care of received EAPOL frames and deliver them to the core supplicant
2512 * code by calling this function.
2513 */
2514void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2515 const u8 *buf, size_t len)
2516{
2517 struct wpa_supplicant *wpa_s = ctx;
2518
2519 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2520 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2521
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002522#ifdef CONFIG_PEERKEY
2523 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2524 wpa_s->current_ssid->peerkey &&
2525 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2526 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2527 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2528 return;
2529 }
2530#endif /* CONFIG_PEERKEY */
2531
Jouni Malinena05074c2012-12-21 21:35:35 +02002532 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2533 (wpa_s->last_eapol_matches_bssid &&
2534#ifdef CONFIG_AP
2535 !wpa_s->ap_iface &&
2536#endif /* CONFIG_AP */
2537 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 /*
2539 * There is possible race condition between receiving the
2540 * association event and the EAPOL frame since they are coming
2541 * through different paths from the driver. In order to avoid
2542 * issues in trying to process the EAPOL frame before receiving
2543 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002544 * the association event is received. This may also be needed in
2545 * driver-based roaming case, so also use src_addr != BSSID as a
2546 * trigger if we have previously confirmed that the
2547 * Authenticator uses BSSID as the src_addr (which is not the
2548 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002549 */
2550 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002551 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2552 wpa_supplicant_state_txt(wpa_s->wpa_state),
2553 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554 wpabuf_free(wpa_s->pending_eapol_rx);
2555 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2556 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002557 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2559 ETH_ALEN);
2560 }
2561 return;
2562 }
2563
Jouni Malinena05074c2012-12-21 21:35:35 +02002564 wpa_s->last_eapol_matches_bssid =
2565 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2566
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567#ifdef CONFIG_AP
2568 if (wpa_s->ap_iface) {
2569 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2570 return;
2571 }
2572#endif /* CONFIG_AP */
2573
2574 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2575 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2576 "no key management is configured");
2577 return;
2578 }
2579
2580 if (wpa_s->eapol_received == 0 &&
2581 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2582 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2583 wpa_s->wpa_state != WPA_COMPLETED) &&
2584 (wpa_s->current_ssid == NULL ||
2585 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2586 /* Timeout for completing IEEE 802.1X and WPA authentication */
2587 wpa_supplicant_req_auth_timeout(
2588 wpa_s,
2589 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2590 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2591 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2592 70 : 10, 0);
2593 }
2594 wpa_s->eapol_received++;
2595
2596 if (wpa_s->countermeasures) {
2597 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2598 "EAPOL packet");
2599 return;
2600 }
2601
2602#ifdef CONFIG_IBSS_RSN
2603 if (wpa_s->current_ssid &&
2604 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2605 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2606 return;
2607 }
2608#endif /* CONFIG_IBSS_RSN */
2609
2610 /* Source address of the incoming EAPOL frame could be compared to the
2611 * current BSSID. However, it is possible that a centralized
2612 * Authenticator could be using another MAC address than the BSSID of
2613 * an AP, so just allow any address to be used for now. The replies are
2614 * still sent to the current BSSID (if available), though. */
2615
2616 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2617 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2618 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2619 return;
2620 wpa_drv_poll(wpa_s);
2621 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2622 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2623 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2624 /*
2625 * Set portValid = TRUE here since we are going to skip 4-way
2626 * handshake processing which would normally set portValid. We
2627 * need this to allow the EAPOL state machines to be completed
2628 * without going through EAPOL-Key handshake.
2629 */
2630 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2631 }
2632}
2633
2634
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002635int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002636{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002637 if (wpa_s->driver->send_eapol) {
2638 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2639 if (addr)
2640 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002641 } else if ((!wpa_s->p2p_mgmt ||
2642 !(wpa_s->drv_flags &
2643 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2644 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002646 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002647 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2648 wpa_drv_get_mac_addr(wpa_s),
2649 ETH_P_EAPOL,
2650 wpa_supplicant_rx_eapol, wpa_s, 0);
2651 if (wpa_s->l2 == NULL)
2652 return -1;
2653 } else {
2654 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2655 if (addr)
2656 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2657 }
2658
2659 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2660 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2661 return -1;
2662 }
2663
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002664 return 0;
2665}
2666
2667
Dmitry Shmidt04949592012-07-19 12:16:46 -07002668static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2669 const u8 *buf, size_t len)
2670{
2671 struct wpa_supplicant *wpa_s = ctx;
2672 const struct l2_ethhdr *eth;
2673
2674 if (len < sizeof(*eth))
2675 return;
2676 eth = (const struct l2_ethhdr *) buf;
2677
2678 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2679 !(eth->h_dest[0] & 0x01)) {
2680 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2681 " (bridge - not for this interface - ignore)",
2682 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2683 return;
2684 }
2685
2686 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2687 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2688 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2689 len - sizeof(*eth));
2690}
2691
2692
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002693/**
2694 * wpa_supplicant_driver_init - Initialize driver interface parameters
2695 * @wpa_s: Pointer to wpa_supplicant data
2696 * Returns: 0 on success, -1 on failure
2697 *
2698 * This function is called to initialize driver interface parameters.
2699 * wpa_drv_init() must have been called before this function to initialize the
2700 * driver interface.
2701 */
2702int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2703{
2704 static int interface_count = 0;
2705
2706 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2707 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002708
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002709 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2710 MAC2STR(wpa_s->own_addr));
2711 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2712
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 if (wpa_s->bridge_ifname[0]) {
2714 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2715 "interface '%s'", wpa_s->bridge_ifname);
2716 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2717 wpa_s->own_addr,
2718 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002719 wpa_supplicant_rx_eapol_bridge,
2720 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002721 if (wpa_s->l2_br == NULL) {
2722 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2723 "connection for the bridge interface '%s'",
2724 wpa_s->bridge_ifname);
2725 return -1;
2726 }
2727 }
2728
2729 wpa_clear_keys(wpa_s, NULL);
2730
2731 /* Make sure that TKIP countermeasures are not left enabled (could
2732 * happen if wpa_supplicant is killed during countermeasures. */
2733 wpa_drv_set_countermeasures(wpa_s, 0);
2734
2735 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2736 wpa_drv_flush_pmkid(wpa_s);
2737
2738 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002739 wpa_s->prev_scan_wildcard = 0;
2740
Dmitry Shmidt04949592012-07-19 12:16:46 -07002741 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002742 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2743 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2744 interface_count = 0;
2745 }
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002746 if (!wpa_s->p2p_mgmt &&
Dmitry Shmidt98660862014-03-11 17:26:21 -07002747 wpa_supplicant_delayed_sched_scan(wpa_s,
2748 interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002749 100000))
Dmitry Shmidt98660862014-03-11 17:26:21 -07002750 wpa_supplicant_req_scan(wpa_s, interface_count % 3,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002751 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002752 interface_count++;
2753 } else
2754 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2755
2756 return 0;
2757}
2758
2759
2760static int wpa_supplicant_daemon(const char *pid_file)
2761{
2762 wpa_printf(MSG_DEBUG, "Daemonize..");
2763 return os_daemonize(pid_file);
2764}
2765
2766
2767static struct wpa_supplicant * wpa_supplicant_alloc(void)
2768{
2769 struct wpa_supplicant *wpa_s;
2770
2771 wpa_s = os_zalloc(sizeof(*wpa_s));
2772 if (wpa_s == NULL)
2773 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002774 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002775 wpa_s->scan_interval = 5;
2776 wpa_s->new_connection = 1;
2777 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002778 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002779
2780 return wpa_s;
2781}
2782
2783
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002784#ifdef CONFIG_HT_OVERRIDES
2785
2786static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2787 struct ieee80211_ht_capabilities *htcaps,
2788 struct ieee80211_ht_capabilities *htcaps_mask,
2789 const char *ht_mcs)
2790{
2791 /* parse ht_mcs into hex array */
2792 int i;
2793 const char *tmp = ht_mcs;
2794 char *end = NULL;
2795
2796 /* If ht_mcs is null, do not set anything */
2797 if (!ht_mcs)
2798 return 0;
2799
2800 /* This is what we are setting in the kernel */
2801 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2802
2803 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2804
2805 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2806 errno = 0;
2807 long v = strtol(tmp, &end, 16);
2808 if (errno == 0) {
2809 wpa_msg(wpa_s, MSG_DEBUG,
2810 "htcap value[%i]: %ld end: %p tmp: %p",
2811 i, v, end, tmp);
2812 if (end == tmp)
2813 break;
2814
2815 htcaps->supported_mcs_set[i] = v;
2816 tmp = end;
2817 } else {
2818 wpa_msg(wpa_s, MSG_ERROR,
2819 "Failed to parse ht-mcs: %s, error: %s\n",
2820 ht_mcs, strerror(errno));
2821 return -1;
2822 }
2823 }
2824
2825 /*
2826 * If we were able to parse any values, then set mask for the MCS set.
2827 */
2828 if (i) {
2829 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2830 IEEE80211_HT_MCS_MASK_LEN - 1);
2831 /* skip the 3 reserved bits */
2832 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2833 0x1f;
2834 }
2835
2836 return 0;
2837}
2838
2839
2840static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2841 struct ieee80211_ht_capabilities *htcaps,
2842 struct ieee80211_ht_capabilities *htcaps_mask,
2843 int disabled)
2844{
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002845 le16 msk;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002846
2847 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2848
2849 if (disabled == -1)
2850 return 0;
2851
2852 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2853 htcaps_mask->ht_capabilities_info |= msk;
2854 if (disabled)
2855 htcaps->ht_capabilities_info &= msk;
2856 else
2857 htcaps->ht_capabilities_info |= msk;
2858
2859 return 0;
2860}
2861
2862
2863static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2864 struct ieee80211_ht_capabilities *htcaps,
2865 struct ieee80211_ht_capabilities *htcaps_mask,
2866 int factor)
2867{
2868 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2869
2870 if (factor == -1)
2871 return 0;
2872
2873 if (factor < 0 || factor > 3) {
2874 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2875 "Must be 0-3 or -1", factor);
2876 return -EINVAL;
2877 }
2878
2879 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2880 htcaps->a_mpdu_params &= ~0x3;
2881 htcaps->a_mpdu_params |= factor & 0x3;
2882
2883 return 0;
2884}
2885
2886
2887static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2888 struct ieee80211_ht_capabilities *htcaps,
2889 struct ieee80211_ht_capabilities *htcaps_mask,
2890 int density)
2891{
2892 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2893
2894 if (density == -1)
2895 return 0;
2896
2897 if (density < 0 || density > 7) {
2898 wpa_msg(wpa_s, MSG_ERROR,
2899 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2900 density);
2901 return -EINVAL;
2902 }
2903
2904 htcaps_mask->a_mpdu_params |= 0x1C;
2905 htcaps->a_mpdu_params &= ~(0x1C);
2906 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2907
2908 return 0;
2909}
2910
2911
2912static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2913 struct ieee80211_ht_capabilities *htcaps,
2914 struct ieee80211_ht_capabilities *htcaps_mask,
2915 int disabled)
2916{
2917 /* Masking these out disables HT40 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002918 le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2919 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002920
2921 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2922
2923 if (disabled)
2924 htcaps->ht_capabilities_info &= ~msk;
2925 else
2926 htcaps->ht_capabilities_info |= msk;
2927
2928 htcaps_mask->ht_capabilities_info |= msk;
2929
2930 return 0;
2931}
2932
2933
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002934static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2935 struct ieee80211_ht_capabilities *htcaps,
2936 struct ieee80211_ht_capabilities *htcaps_mask,
2937 int disabled)
2938{
2939 /* Masking these out disables SGI */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002940 le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2941 HT_CAP_INFO_SHORT_GI40MHZ);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002942
2943 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2944
2945 if (disabled)
2946 htcaps->ht_capabilities_info &= ~msk;
2947 else
2948 htcaps->ht_capabilities_info |= msk;
2949
2950 htcaps_mask->ht_capabilities_info |= msk;
2951
2952 return 0;
2953}
2954
2955
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07002956static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
2957 struct ieee80211_ht_capabilities *htcaps,
2958 struct ieee80211_ht_capabilities *htcaps_mask,
2959 int disabled)
2960{
2961 /* Masking these out disables LDPC */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002962 le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07002963
2964 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
2965
2966 if (disabled)
2967 htcaps->ht_capabilities_info &= ~msk;
2968 else
2969 htcaps->ht_capabilities_info |= msk;
2970
2971 htcaps_mask->ht_capabilities_info |= msk;
2972
2973 return 0;
2974}
2975
2976
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002977void wpa_supplicant_apply_ht_overrides(
2978 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2979 struct wpa_driver_associate_params *params)
2980{
2981 struct ieee80211_ht_capabilities *htcaps;
2982 struct ieee80211_ht_capabilities *htcaps_mask;
2983
2984 if (!ssid)
2985 return;
2986
2987 params->disable_ht = ssid->disable_ht;
2988 if (!params->htcaps || !params->htcaps_mask)
2989 return;
2990
2991 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2992 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2993 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2994 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2995 ssid->disable_max_amsdu);
2996 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2997 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2998 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002999 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003000 wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003001
3002 if (ssid->ht40_intolerant) {
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003003 le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003004 htcaps->ht_capabilities_info |= bit;
3005 htcaps_mask->ht_capabilities_info |= bit;
3006 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003007}
3008
3009#endif /* CONFIG_HT_OVERRIDES */
3010
3011
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003012#ifdef CONFIG_VHT_OVERRIDES
3013void wpa_supplicant_apply_vht_overrides(
3014 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3015 struct wpa_driver_associate_params *params)
3016{
3017 struct ieee80211_vht_capabilities *vhtcaps;
3018 struct ieee80211_vht_capabilities *vhtcaps_mask;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003019#ifdef CONFIG_HT_OVERRIDES
3020 int max_ampdu;
3021 const u32 max_ampdu_mask = VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
3022#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003023
3024 if (!ssid)
3025 return;
3026
3027 params->disable_vht = ssid->disable_vht;
3028
3029 vhtcaps = (void *) params->vhtcaps;
3030 vhtcaps_mask = (void *) params->vhtcaps_mask;
3031
3032 if (!vhtcaps || !vhtcaps_mask)
3033 return;
3034
3035 vhtcaps->vht_capabilities_info = ssid->vht_capa;
3036 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
3037
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003038#ifdef CONFIG_HT_OVERRIDES
3039 /* if max ampdu is <= 3, we have to make the HT cap the same */
3040 if (ssid->vht_capa_mask & max_ampdu_mask) {
3041 max_ampdu = (ssid->vht_capa & max_ampdu_mask) >>
3042 find_first_bit(max_ampdu_mask);
3043
3044 max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
3045 wpa_set_ampdu_factor(wpa_s,
3046 (void *) params->htcaps,
3047 (void *) params->htcaps_mask,
3048 max_ampdu);
3049 }
3050#endif /* CONFIG_HT_OVERRIDES */
3051
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003052#define OVERRIDE_MCS(i) \
3053 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
3054 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
3055 3 << 2 * (i - 1); \
3056 vhtcaps->vht_supported_mcs_set.tx_map |= \
3057 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
3058 } \
3059 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
3060 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
3061 3 << 2 * (i - 1); \
3062 vhtcaps->vht_supported_mcs_set.rx_map |= \
3063 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
3064 }
3065
3066 OVERRIDE_MCS(1);
3067 OVERRIDE_MCS(2);
3068 OVERRIDE_MCS(3);
3069 OVERRIDE_MCS(4);
3070 OVERRIDE_MCS(5);
3071 OVERRIDE_MCS(6);
3072 OVERRIDE_MCS(7);
3073 OVERRIDE_MCS(8);
3074}
3075#endif /* CONFIG_VHT_OVERRIDES */
3076
3077
Dmitry Shmidt04949592012-07-19 12:16:46 -07003078static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
3079{
3080#ifdef PCSC_FUNCS
3081 size_t len;
3082
3083 if (!wpa_s->conf->pcsc_reader)
3084 return 0;
3085
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003086 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003087 if (!wpa_s->scard)
3088 return 1;
3089
3090 if (wpa_s->conf->pcsc_pin &&
3091 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
3092 scard_deinit(wpa_s->scard);
3093 wpa_s->scard = NULL;
3094 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
3095 return -1;
3096 }
3097
3098 len = sizeof(wpa_s->imsi) - 1;
3099 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
3100 scard_deinit(wpa_s->scard);
3101 wpa_s->scard = NULL;
3102 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
3103 return -1;
3104 }
3105 wpa_s->imsi[len] = '\0';
3106
3107 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
3108
3109 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
3110 wpa_s->imsi, wpa_s->mnc_len);
3111
3112 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3113 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3114#endif /* PCSC_FUNCS */
3115
3116 return 0;
3117}
3118
3119
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003120int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3121{
3122 char *val, *pos;
3123
3124 ext_password_deinit(wpa_s->ext_pw);
3125 wpa_s->ext_pw = NULL;
3126 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3127
3128 if (!wpa_s->conf->ext_password_backend)
3129 return 0;
3130
3131 val = os_strdup(wpa_s->conf->ext_password_backend);
3132 if (val == NULL)
3133 return -1;
3134 pos = os_strchr(val, ':');
3135 if (pos)
3136 *pos++ = '\0';
3137
3138 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3139
3140 wpa_s->ext_pw = ext_password_init(val, pos);
3141 os_free(val);
3142 if (wpa_s->ext_pw == NULL) {
3143 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3144 return -1;
3145 }
3146 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3147
3148 return 0;
3149}
3150
3151
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003152static int wpas_check_wowlan_trigger(const char *start, const char *trigger,
3153 int capa_trigger, u8 *param_trigger)
3154{
3155 if (os_strcmp(start, trigger) != 0)
3156 return 0;
3157 if (!capa_trigger)
3158 return 0;
3159
3160 *param_trigger = 1;
3161 return 1;
3162}
3163
3164
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003165static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
3166 struct wpa_driver_capa *capa)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003167{
3168 struct wowlan_triggers triggers;
3169 char *start, *end, *buf;
3170 int last, ret;
3171
3172 if (!wpa_s->conf->wowlan_triggers)
3173 return 0;
3174
3175 buf = os_strdup(wpa_s->conf->wowlan_triggers);
3176 if (buf == NULL)
3177 return -1;
3178
3179 os_memset(&triggers, 0, sizeof(triggers));
3180
3181#define CHECK_TRIGGER(trigger) \
3182 wpas_check_wowlan_trigger(start, #trigger, \
3183 capa->wowlan_triggers.trigger, \
3184 &triggers.trigger)
3185
3186 start = buf;
3187 while (*start != '\0') {
3188 while (isblank(*start))
3189 start++;
3190 if (*start == '\0')
3191 break;
3192 end = start;
3193 while (!isblank(*end) && *end != '\0')
3194 end++;
3195 last = *end == '\0';
3196 *end = '\0';
3197
3198 if (!CHECK_TRIGGER(any) &&
3199 !CHECK_TRIGGER(disconnect) &&
3200 !CHECK_TRIGGER(magic_pkt) &&
3201 !CHECK_TRIGGER(gtk_rekey_failure) &&
3202 !CHECK_TRIGGER(eap_identity_req) &&
3203 !CHECK_TRIGGER(four_way_handshake) &&
3204 !CHECK_TRIGGER(rfkill_release)) {
3205 wpa_printf(MSG_DEBUG,
3206 "Unknown/unsupported wowlan trigger '%s'",
3207 start);
3208 ret = -1;
3209 goto out;
3210 }
3211
3212 if (last)
3213 break;
3214 start = end + 1;
3215 }
3216#undef CHECK_TRIGGER
3217
3218 ret = wpa_drv_wowlan(wpa_s, &triggers);
3219out:
3220 os_free(buf);
3221 return ret;
3222}
3223
3224
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003225static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3226 const char *rn)
3227{
3228 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3229 struct wpa_radio *radio;
3230
3231 while (rn && iface) {
3232 radio = iface->radio;
3233 if (radio && os_strcmp(rn, radio->name) == 0) {
3234 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3235 wpa_s->ifname, rn);
3236 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3237 return radio;
3238 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003239
3240 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003241 }
3242
3243 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3244 wpa_s->ifname, rn ? rn : "N/A");
3245 radio = os_zalloc(sizeof(*radio));
3246 if (radio == NULL)
3247 return NULL;
3248
3249 if (rn)
3250 os_strlcpy(radio->name, rn, sizeof(radio->name));
3251 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003252 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003253 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3254
3255 return radio;
3256}
3257
3258
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003259static void radio_work_free(struct wpa_radio_work *work)
3260{
3261 if (work->wpa_s->scan_work == work) {
3262 /* This should not really happen. */
3263 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3264 work->type, work, work->started);
3265 work->wpa_s->scan_work = NULL;
3266 }
3267
3268#ifdef CONFIG_P2P
3269 if (work->wpa_s->p2p_scan_work == work) {
3270 /* This should not really happen. */
3271 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3272 work->type, work, work->started);
3273 work->wpa_s->p2p_scan_work = NULL;
3274 }
3275#endif /* CONFIG_P2P */
3276
3277 dl_list_del(&work->list);
3278 os_free(work);
3279}
3280
3281
3282static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3283{
3284 struct wpa_radio *radio = eloop_ctx;
3285 struct wpa_radio_work *work;
3286 struct os_reltime now, diff;
3287 struct wpa_supplicant *wpa_s;
3288
3289 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3290 if (work == NULL)
3291 return;
3292
3293 if (work->started)
3294 return; /* already started and still in progress */
3295
3296 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3297 radio_list);
3298 if (wpa_s && wpa_s->external_scan_running) {
3299 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3300 return;
3301 }
3302
3303 os_get_reltime(&now);
3304 os_reltime_sub(&now, &work->time, &diff);
3305 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3306 work->type, work, diff.sec, diff.usec);
3307 work->started = 1;
3308 work->time = now;
3309 work->cb(work, 0);
3310}
3311
3312
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003313/*
3314 * This function removes both started and pending radio works running on
3315 * the provided interface's radio.
3316 * Prior to the removal of the radio work, its callback (cb) is called with
3317 * deinit set to be 1. Each work's callback is responsible for clearing its
3318 * internal data and restoring to a correct state.
3319 * @wpa_s: wpa_supplicant data
3320 * @type: type of works to be removed
3321 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3322 * this interface's works.
3323 */
3324void radio_remove_works(struct wpa_supplicant *wpa_s,
3325 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003326{
3327 struct wpa_radio_work *work, *tmp;
3328 struct wpa_radio *radio = wpa_s->radio;
3329
3330 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3331 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003332 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003333 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003334
3335 /* skip other ifaces' works */
3336 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003337 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003338
3339 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3340 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003341 work->cb(work, 1);
3342 radio_work_free(work);
3343 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003344
3345 /* in case we removed the started work */
3346 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003347}
3348
3349
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003350static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3351{
3352 struct wpa_radio *radio = wpa_s->radio;
3353
3354 if (!radio)
3355 return;
3356
3357 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3358 wpa_s->ifname, radio->name);
3359 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003360 radio_remove_works(wpa_s, NULL, 0);
3361 wpa_s->radio = NULL;
3362 if (!dl_list_empty(&radio->ifaces))
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003363 return; /* Interfaces remain for this radio */
3364
3365 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003366 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003367 os_free(radio);
3368}
3369
3370
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003371void radio_work_check_next(struct wpa_supplicant *wpa_s)
3372{
3373 struct wpa_radio *radio = wpa_s->radio;
3374
3375 if (dl_list_empty(&radio->work))
3376 return;
3377 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3378 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3379}
3380
3381
3382/**
3383 * radio_add_work - Add a radio work item
3384 * @wpa_s: Pointer to wpa_supplicant data
3385 * @freq: Frequency of the offchannel operation in MHz or 0
3386 * @type: Unique identifier for each type of work
3387 * @next: Force as the next work to be executed
3388 * @cb: Callback function for indicating when radio is available
3389 * @ctx: Context pointer for the work (work->ctx in cb())
3390 * Returns: 0 on success, -1 on failure
3391 *
3392 * This function is used to request time for an operation that requires
3393 * exclusive radio control. Once the radio is available, the registered callback
3394 * function will be called. radio_work_done() must be called once the exclusive
3395 * radio operation has been completed, so that the radio is freed for other
3396 * operations. The special case of deinit=1 is used to free the context data
3397 * during interface removal. That does not allow the callback function to start
3398 * the radio operation, i.e., it must free any resources allocated for the radio
3399 * work and return.
3400 *
3401 * The @freq parameter can be used to indicate a single channel on which the
3402 * offchannel operation will occur. This may allow multiple radio work
3403 * operations to be performed in parallel if they apply for the same channel.
3404 * Setting this to 0 indicates that the work item may use multiple channels or
3405 * requires exclusive control of the radio.
3406 */
3407int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3408 const char *type, int next,
3409 void (*cb)(struct wpa_radio_work *work, int deinit),
3410 void *ctx)
3411{
3412 struct wpa_radio_work *work;
3413 int was_empty;
3414
3415 work = os_zalloc(sizeof(*work));
3416 if (work == NULL)
3417 return -1;
3418 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3419 os_get_reltime(&work->time);
3420 work->freq = freq;
3421 work->type = type;
3422 work->wpa_s = wpa_s;
3423 work->cb = cb;
3424 work->ctx = ctx;
3425
3426 was_empty = dl_list_empty(&wpa_s->radio->work);
3427 if (next)
3428 dl_list_add(&wpa_s->radio->work, &work->list);
3429 else
3430 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3431 if (was_empty) {
3432 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3433 radio_work_check_next(wpa_s);
3434 }
3435
3436 return 0;
3437}
3438
3439
3440/**
3441 * radio_work_done - Indicate that a radio work item has been completed
3442 * @work: Completed work
3443 *
3444 * This function is called once the callback function registered with
3445 * radio_add_work() has completed its work.
3446 */
3447void radio_work_done(struct wpa_radio_work *work)
3448{
3449 struct wpa_supplicant *wpa_s = work->wpa_s;
3450 struct os_reltime now, diff;
3451 unsigned int started = work->started;
3452
3453 os_get_reltime(&now);
3454 os_reltime_sub(&now, &work->time, &diff);
3455 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3456 work->type, work, started ? "done" : "canceled",
3457 diff.sec, diff.usec);
3458 radio_work_free(work);
3459 if (started)
3460 radio_work_check_next(wpa_s);
3461}
3462
3463
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003464int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
3465{
3466 struct wpa_radio_work *work;
3467 struct wpa_radio *radio = wpa_s->radio;
3468
3469 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3470 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
3471 return 1;
3472 }
3473
3474 return 0;
3475}
3476
3477
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003478static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3479 struct wpa_interface *iface)
3480{
3481 const char *ifname, *driver, *rn;
3482
3483 driver = iface->driver;
3484next_driver:
3485 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3486 return -1;
3487
3488 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3489 if (wpa_s->drv_priv == NULL) {
3490 const char *pos;
3491 pos = driver ? os_strchr(driver, ',') : NULL;
3492 if (pos) {
3493 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3494 "driver interface - try next driver wrapper");
3495 driver = pos + 1;
3496 goto next_driver;
3497 }
3498 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3499 "interface");
3500 return -1;
3501 }
3502 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3503 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3504 "driver_param '%s'", wpa_s->conf->driver_param);
3505 return -1;
3506 }
3507
3508 ifname = wpa_drv_get_ifname(wpa_s);
3509 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3510 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3511 "interface name with '%s'", ifname);
3512 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3513 }
3514
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003515 rn = wpa_driver_get_radio_name(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003516 if (rn && rn[0] == '\0')
3517 rn = NULL;
3518
3519 wpa_s->radio = radio_add_interface(wpa_s, rn);
3520 if (wpa_s->radio == NULL)
3521 return -1;
3522
3523 return 0;
3524}
3525
3526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3528 struct wpa_interface *iface)
3529{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003530 struct wpa_driver_capa capa;
3531
3532 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3533 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3534 iface->confname ? iface->confname : "N/A",
3535 iface->driver ? iface->driver : "default",
3536 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3537 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3538
3539 if (iface->confname) {
3540#ifdef CONFIG_BACKEND_FILE
3541 wpa_s->confname = os_rel2abs_path(iface->confname);
3542 if (wpa_s->confname == NULL) {
3543 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3544 "for configuration file '%s'.",
3545 iface->confname);
3546 return -1;
3547 }
3548 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3549 iface->confname, wpa_s->confname);
3550#else /* CONFIG_BACKEND_FILE */
3551 wpa_s->confname = os_strdup(iface->confname);
3552#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003553 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554 if (wpa_s->conf == NULL) {
3555 wpa_printf(MSG_ERROR, "Failed to read or parse "
3556 "configuration '%s'.", wpa_s->confname);
3557 return -1;
3558 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003559 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3560 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003561
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08003562#ifdef CONFIG_P2P
3563 wpa_s->conf_p2p_dev = os_rel2abs_path(iface->conf_p2p_dev);
3564 wpa_config_read(wpa_s->conf_p2p_dev, wpa_s->conf);
3565#endif /* CONFIG_P2P */
3566
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003567 /*
3568 * Override ctrl_interface and driver_param if set on command
3569 * line.
3570 */
3571 if (iface->ctrl_interface) {
3572 os_free(wpa_s->conf->ctrl_interface);
3573 wpa_s->conf->ctrl_interface =
3574 os_strdup(iface->ctrl_interface);
3575 }
3576
3577 if (iface->driver_param) {
3578 os_free(wpa_s->conf->driver_param);
3579 wpa_s->conf->driver_param =
3580 os_strdup(iface->driver_param);
3581 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003582
3583 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3584 os_free(wpa_s->conf->ctrl_interface);
3585 wpa_s->conf->ctrl_interface = NULL;
3586 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003587 } else
3588 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3589 iface->driver_param);
3590
3591 if (wpa_s->conf == NULL) {
3592 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3593 return -1;
3594 }
3595
3596 if (iface->ifname == NULL) {
3597 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3598 return -1;
3599 }
3600 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3601 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3602 iface->ifname);
3603 return -1;
3604 }
3605 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3606
3607 if (iface->bridge_ifname) {
3608 if (os_strlen(iface->bridge_ifname) >=
3609 sizeof(wpa_s->bridge_ifname)) {
3610 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3611 "name '%s'.", iface->bridge_ifname);
3612 return -1;
3613 }
3614 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3615 sizeof(wpa_s->bridge_ifname));
3616 }
3617
3618 /* RSNA Supplicant Key Management - INITIALIZE */
3619 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3620 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3621
3622 /* Initialize driver interface and register driver event handler before
3623 * L2 receive handler so that association events are processed before
3624 * EAPOL-Key packets if both become available for the same select()
3625 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003626 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003627 return -1;
3628
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3630 return -1;
3631
3632 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3633 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3634 NULL);
3635 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3636
3637 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3638 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3639 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3640 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3641 "dot11RSNAConfigPMKLifetime");
3642 return -1;
3643 }
3644
3645 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3646 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3647 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3648 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3649 "dot11RSNAConfigPMKReauthThreshold");
3650 return -1;
3651 }
3652
3653 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3654 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3655 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3656 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3657 "dot11RSNAConfigSATimeout");
3658 return -1;
3659 }
3660
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003661 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3662 &wpa_s->hw.num_modes,
3663 &wpa_s->hw.flags);
3664
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003665 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003666 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003667 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003668 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003669 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003670 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003671 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3672 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3673 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003674 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3675 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003676 wpa_s->extended_capa = capa.extended_capa;
3677 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3678 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003679 wpa_s->num_multichan_concurrent =
3680 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003681 }
3682 if (wpa_s->max_remain_on_chan == 0)
3683 wpa_s->max_remain_on_chan = 1000;
3684
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003685 /*
3686 * Only take p2p_mgmt parameters when P2P Device is supported.
3687 * Doing it here as it determines whether l2_packet_init() will be done
3688 * during wpa_supplicant_driver_init().
3689 */
3690 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3691 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3692 else
3693 iface->p2p_mgmt = 1;
3694
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003695 if (wpa_s->num_multichan_concurrent == 0)
3696 wpa_s->num_multichan_concurrent = 1;
3697
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003698 if (wpa_supplicant_driver_init(wpa_s) < 0)
3699 return -1;
3700
3701#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003702 if ((!iface->p2p_mgmt ||
3703 !(wpa_s->drv_flags &
3704 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3705 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706 return -1;
3707#endif /* CONFIG_TDLS */
3708
3709 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3710 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3711 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3712 return -1;
3713 }
3714
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003715 if (wpas_wps_init(wpa_s))
3716 return -1;
3717
3718 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3719 return -1;
3720 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3721
3722 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3723 if (wpa_s->ctrl_iface == NULL) {
3724 wpa_printf(MSG_ERROR,
3725 "Failed to initialize control interface '%s'.\n"
3726 "You may have another wpa_supplicant process "
3727 "already running or the file was\n"
3728 "left by an unclean termination of wpa_supplicant "
3729 "in which case you will need\n"
3730 "to manually remove this file before starting "
3731 "wpa_supplicant again.\n",
3732 wpa_s->conf->ctrl_interface);
3733 return -1;
3734 }
3735
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003736 wpa_s->gas = gas_query_init(wpa_s);
3737 if (wpa_s->gas == NULL) {
3738 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3739 return -1;
3740 }
3741
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003742 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3744 return -1;
3745 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003746
3747 if (wpa_bss_init(wpa_s) < 0)
3748 return -1;
3749
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003750 /*
3751 * Set Wake-on-WLAN triggers, if configured.
3752 * Note: We don't restore/remove the triggers on shutdown (it doesn't
3753 * have effect anyway when the interface is down).
3754 */
3755 if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
3756 return -1;
3757
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003758#ifdef CONFIG_EAP_PROXY
3759{
3760 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003761 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3762 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003763 if (wpa_s->mnc_len > 0) {
3764 wpa_s->imsi[len] = '\0';
3765 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3766 wpa_s->imsi, wpa_s->mnc_len);
3767 } else {
3768 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3769 }
3770}
3771#endif /* CONFIG_EAP_PROXY */
3772
Dmitry Shmidt04949592012-07-19 12:16:46 -07003773 if (pcsc_reader_init(wpa_s) < 0)
3774 return -1;
3775
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003776 if (wpas_init_ext_pw(wpa_s) < 0)
3777 return -1;
3778
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003779 return 0;
3780}
3781
3782
3783static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003784 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003785{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003786 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003787 if (wpa_s->drv_priv) {
3788 wpa_supplicant_deauthenticate(wpa_s,
3789 WLAN_REASON_DEAUTH_LEAVING);
3790
3791 wpa_drv_set_countermeasures(wpa_s, 0);
3792 wpa_clear_keys(wpa_s, NULL);
3793 }
3794
3795 wpa_supplicant_cleanup(wpa_s);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003796 wpas_p2p_deinit_iface(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003797
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003798 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003799 radio_remove_interface(wpa_s);
3800
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003801 if (wpa_s->drv_priv)
3802 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003803
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003804 if (notify)
3805 wpas_notify_iface_removed(wpa_s);
3806
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003807 if (terminate)
3808 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003809
3810 if (wpa_s->ctrl_iface) {
3811 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3812 wpa_s->ctrl_iface = NULL;
3813 }
3814
3815 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003816 wpa_config_free(wpa_s->conf);
3817 wpa_s->conf = NULL;
3818 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003819
3820 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003821}
3822
3823
3824/**
3825 * wpa_supplicant_add_iface - Add a new network interface
3826 * @global: Pointer to global data from wpa_supplicant_init()
3827 * @iface: Interface configuration options
3828 * Returns: Pointer to the created interface or %NULL on failure
3829 *
3830 * This function is used to add new network interfaces for %wpa_supplicant.
3831 * This can be called before wpa_supplicant_run() to add interfaces before the
3832 * main event loop has been started. In addition, new interfaces can be added
3833 * dynamically while %wpa_supplicant is already running. This could happen,
3834 * e.g., when a hotplug network adapter is inserted.
3835 */
3836struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3837 struct wpa_interface *iface)
3838{
3839 struct wpa_supplicant *wpa_s;
3840 struct wpa_interface t_iface;
3841 struct wpa_ssid *ssid;
3842
3843 if (global == NULL || iface == NULL)
3844 return NULL;
3845
3846 wpa_s = wpa_supplicant_alloc();
3847 if (wpa_s == NULL)
3848 return NULL;
3849
3850 wpa_s->global = global;
3851
3852 t_iface = *iface;
3853 if (global->params.override_driver) {
3854 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3855 "('%s' -> '%s')",
3856 iface->driver, global->params.override_driver);
3857 t_iface.driver = global->params.override_driver;
3858 }
3859 if (global->params.override_ctrl_interface) {
3860 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3861 "ctrl_interface ('%s' -> '%s')",
3862 iface->ctrl_interface,
3863 global->params.override_ctrl_interface);
3864 t_iface.ctrl_interface =
3865 global->params.override_ctrl_interface;
3866 }
3867 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3868 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3869 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003870 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003871 return NULL;
3872 }
3873
3874 /* Notify the control interfaces about new iface */
3875 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003876 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003877 return NULL;
3878 }
3879
3880 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3881 wpas_notify_network_added(wpa_s, ssid);
3882
3883 wpa_s->next = global->ifaces;
3884 global->ifaces = wpa_s;
3885
3886 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003887 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003888
3889 return wpa_s;
3890}
3891
3892
3893/**
3894 * wpa_supplicant_remove_iface - Remove a network interface
3895 * @global: Pointer to global data from wpa_supplicant_init()
3896 * @wpa_s: Pointer to the network interface to be removed
3897 * Returns: 0 if interface was removed, -1 if interface was not found
3898 *
3899 * This function can be used to dynamically remove network interfaces from
3900 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3901 * addition, this function is used to remove all remaining interfaces when
3902 * %wpa_supplicant is terminated.
3903 */
3904int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003905 struct wpa_supplicant *wpa_s,
3906 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003907{
3908 struct wpa_supplicant *prev;
3909
3910 /* Remove interface from the global list of interfaces */
3911 prev = global->ifaces;
3912 if (prev == wpa_s) {
3913 global->ifaces = wpa_s->next;
3914 } else {
3915 while (prev && prev->next != wpa_s)
3916 prev = prev->next;
3917 if (prev == NULL)
3918 return -1;
3919 prev->next = wpa_s->next;
3920 }
3921
3922 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3923
3924 if (global->p2p_group_formation == wpa_s)
3925 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003926 if (global->p2p_invite_group == wpa_s)
3927 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003928 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929
3930 return 0;
3931}
3932
3933
3934/**
3935 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3936 * @wpa_s: Pointer to the network interface
3937 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3938 */
3939const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3940{
3941 const char *eapol_method;
3942
3943 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3944 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3945 return "NO-EAP";
3946 }
3947
3948 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3949 if (eapol_method == NULL)
3950 return "UNKNOWN-EAP";
3951
3952 return eapol_method;
3953}
3954
3955
3956/**
3957 * wpa_supplicant_get_iface - Get a new network interface
3958 * @global: Pointer to global data from wpa_supplicant_init()
3959 * @ifname: Interface name
3960 * Returns: Pointer to the interface or %NULL if not found
3961 */
3962struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3963 const char *ifname)
3964{
3965 struct wpa_supplicant *wpa_s;
3966
3967 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3968 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3969 return wpa_s;
3970 }
3971 return NULL;
3972}
3973
3974
3975#ifndef CONFIG_NO_WPA_MSG
3976static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3977{
3978 struct wpa_supplicant *wpa_s = ctx;
3979 if (wpa_s == NULL)
3980 return NULL;
3981 return wpa_s->ifname;
3982}
3983#endif /* CONFIG_NO_WPA_MSG */
3984
3985
3986/**
3987 * wpa_supplicant_init - Initialize %wpa_supplicant
3988 * @params: Parameters for %wpa_supplicant
3989 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3990 *
3991 * This function is used to initialize %wpa_supplicant. After successful
3992 * initialization, the returned data pointer can be used to add and remove
3993 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3994 */
3995struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3996{
3997 struct wpa_global *global;
3998 int ret, i;
3999
4000 if (params == NULL)
4001 return NULL;
4002
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004003#ifdef CONFIG_DRIVER_NDIS
4004 {
4005 void driver_ndis_init_ops(void);
4006 driver_ndis_init_ops();
4007 }
4008#endif /* CONFIG_DRIVER_NDIS */
4009
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004010#ifndef CONFIG_NO_WPA_MSG
4011 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
4012#endif /* CONFIG_NO_WPA_MSG */
4013
4014 wpa_debug_open_file(params->wpa_debug_file_path);
4015 if (params->wpa_debug_syslog)
4016 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004017 if (params->wpa_debug_tracing) {
4018 ret = wpa_debug_open_linux_tracing();
4019 if (ret) {
4020 wpa_printf(MSG_ERROR,
4021 "Failed to enable trace logging");
4022 return NULL;
4023 }
4024 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004025
4026 ret = eap_register_methods();
4027 if (ret) {
4028 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
4029 if (ret == -2)
4030 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
4031 "the same EAP type.");
4032 return NULL;
4033 }
4034
4035 global = os_zalloc(sizeof(*global));
4036 if (global == NULL)
4037 return NULL;
4038 dl_list_init(&global->p2p_srv_bonjour);
4039 dl_list_init(&global->p2p_srv_upnp);
4040 global->params.daemonize = params->daemonize;
4041 global->params.wait_for_monitor = params->wait_for_monitor;
4042 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
4043 if (params->pid_file)
4044 global->params.pid_file = os_strdup(params->pid_file);
4045 if (params->ctrl_interface)
4046 global->params.ctrl_interface =
4047 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004048 if (params->ctrl_interface_group)
4049 global->params.ctrl_interface_group =
4050 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004051 if (params->override_driver)
4052 global->params.override_driver =
4053 os_strdup(params->override_driver);
4054 if (params->override_ctrl_interface)
4055 global->params.override_ctrl_interface =
4056 os_strdup(params->override_ctrl_interface);
4057 wpa_debug_level = global->params.wpa_debug_level =
4058 params->wpa_debug_level;
4059 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
4060 params->wpa_debug_show_keys;
4061 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
4062 params->wpa_debug_timestamp;
4063
4064 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
4065
4066 if (eloop_init()) {
4067 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
4068 wpa_supplicant_deinit(global);
4069 return NULL;
4070 }
4071
Jouni Malinen75ecf522011-06-27 15:19:46 -07004072 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004073
4074 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
4075 if (global->ctrl_iface == NULL) {
4076 wpa_supplicant_deinit(global);
4077 return NULL;
4078 }
4079
4080 if (wpas_notify_supplicant_initialized(global)) {
4081 wpa_supplicant_deinit(global);
4082 return NULL;
4083 }
4084
4085 for (i = 0; wpa_drivers[i]; i++)
4086 global->drv_count++;
4087 if (global->drv_count == 0) {
4088 wpa_printf(MSG_ERROR, "No drivers enabled");
4089 wpa_supplicant_deinit(global);
4090 return NULL;
4091 }
4092 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
4093 if (global->drv_priv == NULL) {
4094 wpa_supplicant_deinit(global);
4095 return NULL;
4096 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004097
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004098#ifdef CONFIG_WIFI_DISPLAY
4099 if (wifi_display_init(global) < 0) {
4100 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
4101 wpa_supplicant_deinit(global);
4102 return NULL;
4103 }
4104#endif /* CONFIG_WIFI_DISPLAY */
4105
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004106 return global;
4107}
4108
4109
4110/**
4111 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
4112 * @global: Pointer to global data from wpa_supplicant_init()
4113 * Returns: 0 after successful event loop run, -1 on failure
4114 *
4115 * This function starts the main event loop and continues running as long as
4116 * there are any remaining events. In most cases, this function is running as
4117 * long as the %wpa_supplicant process in still in use.
4118 */
4119int wpa_supplicant_run(struct wpa_global *global)
4120{
4121 struct wpa_supplicant *wpa_s;
4122
4123 if (global->params.daemonize &&
4124 wpa_supplicant_daemon(global->params.pid_file))
4125 return -1;
4126
4127 if (global->params.wait_for_monitor) {
4128 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
4129 if (wpa_s->ctrl_iface)
4130 wpa_supplicant_ctrl_iface_wait(
4131 wpa_s->ctrl_iface);
4132 }
4133
4134 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
4135 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
4136
4137 eloop_run();
4138
4139 return 0;
4140}
4141
4142
4143/**
4144 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
4145 * @global: Pointer to global data from wpa_supplicant_init()
4146 *
4147 * This function is called to deinitialize %wpa_supplicant and to free all
4148 * allocated resources. Remaining network interfaces will also be removed.
4149 */
4150void wpa_supplicant_deinit(struct wpa_global *global)
4151{
4152 int i;
4153
4154 if (global == NULL)
4155 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004156
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004157#ifdef CONFIG_WIFI_DISPLAY
4158 wifi_display_deinit(global);
4159#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160
4161 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07004162 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004163
4164 if (global->ctrl_iface)
4165 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
4166
4167 wpas_notify_supplicant_deinitialized(global);
4168
4169 eap_peer_unregister_methods();
4170#ifdef CONFIG_AP
4171 eap_server_unregister_methods();
4172#endif /* CONFIG_AP */
4173
4174 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
4175 if (!global->drv_priv[i])
4176 continue;
4177 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
4178 }
4179 os_free(global->drv_priv);
4180
4181 random_deinit();
4182
4183 eloop_destroy();
4184
4185 if (global->params.pid_file) {
4186 os_daemonize_terminate(global->params.pid_file);
4187 os_free(global->params.pid_file);
4188 }
4189 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004190 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004191 os_free(global->params.override_driver);
4192 os_free(global->params.override_ctrl_interface);
4193
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004194 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004195 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004196 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004197
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004198 os_free(global);
4199 wpa_debug_close_syslog();
4200 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004201 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004202}
4203
4204
4205void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4206{
4207 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4208 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4209 char country[3];
4210 country[0] = wpa_s->conf->country[0];
4211 country[1] = wpa_s->conf->country[1];
4212 country[2] = '\0';
4213 if (wpa_drv_set_country(wpa_s, country) < 0) {
4214 wpa_printf(MSG_ERROR, "Failed to set country code "
4215 "'%s'", country);
4216 }
4217 }
4218
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004219 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4220 wpas_init_ext_pw(wpa_s);
4221
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004222#ifdef CONFIG_WPS
4223 wpas_wps_update_config(wpa_s);
4224#endif /* CONFIG_WPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004225 wpas_p2p_update_config(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004226 wpa_s->conf->changed_parameters = 0;
4227}
4228
4229
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004230static void add_freq(int *freqs, int *num_freqs, int freq)
4231{
4232 int i;
4233
4234 for (i = 0; i < *num_freqs; i++) {
4235 if (freqs[i] == freq)
4236 return;
4237 }
4238
4239 freqs[*num_freqs] = freq;
4240 (*num_freqs)++;
4241}
4242
4243
4244static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4245{
4246 struct wpa_bss *bss, *cbss;
4247 const int max_freqs = 10;
4248 int *freqs;
4249 int num_freqs = 0;
4250
4251 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
4252 if (freqs == NULL)
4253 return NULL;
4254
4255 cbss = wpa_s->current_bss;
4256
4257 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4258 if (bss == cbss)
4259 continue;
4260 if (bss->ssid_len == cbss->ssid_len &&
4261 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4262 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4263 add_freq(freqs, &num_freqs, bss->freq);
4264 if (num_freqs == max_freqs)
4265 break;
4266 }
4267 }
4268
4269 if (num_freqs == 0) {
4270 os_free(freqs);
4271 freqs = NULL;
4272 }
4273
4274 return freqs;
4275}
4276
4277
4278void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4279{
4280 int timeout;
4281 int count;
4282 int *freqs = NULL;
4283
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004284 wpas_connect_work_done(wpa_s);
4285
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004286 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004287 * Remove possible authentication timeout since the connection failed.
4288 */
4289 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4290
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004291 if (wpa_s->disconnected) {
4292 /*
4293 * There is no point in blacklisting the AP if this event is
4294 * generated based on local request to disconnect.
4295 */
4296 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4297 "indication since interface has been put into "
4298 "disconnected state");
4299 return;
4300 }
4301
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004302 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004303 * Add the failed BSSID into the blacklist and speed up next scan
4304 * attempt if there could be other APs that could accept association.
4305 * The current blacklist count indicates how many times we have tried
4306 * connecting to this AP and multiple attempts mean that other APs are
4307 * either not available or has already been tried, so that we can start
4308 * increasing the delay here to avoid constant scanning.
4309 */
4310 count = wpa_blacklist_add(wpa_s, bssid);
4311 if (count == 1 && wpa_s->current_bss) {
4312 /*
4313 * This BSS was not in the blacklist before. If there is
4314 * another BSS available for the same ESS, we should try that
4315 * next. Otherwise, we may as well try this one once more
4316 * before allowing other, likely worse, ESSes to be considered.
4317 */
4318 freqs = get_bss_freqs_in_ess(wpa_s);
4319 if (freqs) {
4320 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4321 "has been seen; try it next");
4322 wpa_blacklist_add(wpa_s, bssid);
4323 /*
4324 * On the next scan, go through only the known channels
4325 * used in this ESS based on previous scans to speed up
4326 * common load balancing use case.
4327 */
4328 os_free(wpa_s->next_scan_freqs);
4329 wpa_s->next_scan_freqs = freqs;
4330 }
4331 }
4332
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004333 /*
4334 * Add previous failure count in case the temporary blacklist was
4335 * cleared due to no other BSSes being available.
4336 */
4337 count += wpa_s->extra_blacklist_count;
4338
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004339 if (count > 3 && wpa_s->current_ssid) {
4340 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4341 "consider temporary network disabling");
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004342 wpas_auth_failed(wpa_s, "CONN_FAILED");
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004343 }
4344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004345 switch (count) {
4346 case 1:
4347 timeout = 100;
4348 break;
4349 case 2:
4350 timeout = 500;
4351 break;
4352 case 3:
4353 timeout = 1000;
4354 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004355 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004356 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004357 break;
4358 default:
4359 timeout = 10000;
4360 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004361 }
4362
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004363 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4364 "ms", count, timeout);
4365
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004366 /*
4367 * TODO: if more than one possible AP is available in scan results,
4368 * could try the other ones before requesting a new scan.
4369 */
4370 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4371 1000 * (timeout % 1000));
4372}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004373
4374
4375int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4376{
4377 return wpa_s->conf->ap_scan == 2 ||
4378 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4379}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004380
Dmitry Shmidt04949592012-07-19 12:16:46 -07004381
4382#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4383int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4384 struct wpa_ssid *ssid,
4385 const char *field,
4386 const char *value)
4387{
4388#ifdef IEEE8021X_EAPOL
4389 struct eap_peer_config *eap = &ssid->eap;
4390
4391 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4392 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4393 (const u8 *) value, os_strlen(value));
4394
4395 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4396 case WPA_CTRL_REQ_EAP_IDENTITY:
4397 os_free(eap->identity);
4398 eap->identity = (u8 *) os_strdup(value);
4399 eap->identity_len = os_strlen(value);
4400 eap->pending_req_identity = 0;
4401 if (ssid == wpa_s->current_ssid)
4402 wpa_s->reassociate = 1;
4403 break;
4404 case WPA_CTRL_REQ_EAP_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004405 bin_clear_free(eap->password, eap->password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004406 eap->password = (u8 *) os_strdup(value);
4407 eap->password_len = os_strlen(value);
4408 eap->pending_req_password = 0;
4409 if (ssid == wpa_s->current_ssid)
4410 wpa_s->reassociate = 1;
4411 break;
4412 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004413 bin_clear_free(eap->new_password, eap->new_password_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004414 eap->new_password = (u8 *) os_strdup(value);
4415 eap->new_password_len = os_strlen(value);
4416 eap->pending_req_new_password = 0;
4417 if (ssid == wpa_s->current_ssid)
4418 wpa_s->reassociate = 1;
4419 break;
4420 case WPA_CTRL_REQ_EAP_PIN:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004421 str_clear_free(eap->pin);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004422 eap->pin = os_strdup(value);
4423 eap->pending_req_pin = 0;
4424 if (ssid == wpa_s->current_ssid)
4425 wpa_s->reassociate = 1;
4426 break;
4427 case WPA_CTRL_REQ_EAP_OTP:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004428 bin_clear_free(eap->otp, eap->otp_len);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004429 eap->otp = (u8 *) os_strdup(value);
4430 eap->otp_len = os_strlen(value);
4431 os_free(eap->pending_req_otp);
4432 eap->pending_req_otp = NULL;
4433 eap->pending_req_otp_len = 0;
4434 break;
4435 case WPA_CTRL_REQ_EAP_PASSPHRASE:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004436 str_clear_free(eap->private_key_passwd);
4437 eap->private_key_passwd = os_strdup(value);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004438 eap->pending_req_passphrase = 0;
4439 if (ssid == wpa_s->current_ssid)
4440 wpa_s->reassociate = 1;
4441 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004442 case WPA_CTRL_REQ_SIM:
Dmitry Shmidtc2817022014-07-02 10:32:10 -07004443 str_clear_free(eap->external_sim_resp);
Dmitry Shmidt051af732013-10-22 13:52:46 -07004444 eap->external_sim_resp = os_strdup(value);
4445 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004446 default:
4447 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4448 return -1;
4449 }
4450
4451 return 0;
4452#else /* IEEE8021X_EAPOL */
4453 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4454 return -1;
4455#endif /* IEEE8021X_EAPOL */
4456}
4457#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4458
4459
4460int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4461{
4462 int i;
4463 unsigned int drv_enc;
4464
4465 if (ssid == NULL)
4466 return 1;
4467
4468 if (ssid->disabled)
4469 return 1;
4470
4471 if (wpa_s && wpa_s->drv_capa_known)
4472 drv_enc = wpa_s->drv_enc;
4473 else
4474 drv_enc = (unsigned int) -1;
4475
4476 for (i = 0; i < NUM_WEP_KEYS; i++) {
4477 size_t len = ssid->wep_key_len[i];
4478 if (len == 0)
4479 continue;
4480 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4481 continue;
4482 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4483 continue;
4484 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4485 continue;
4486 return 1; /* invalid WEP key */
4487 }
4488
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004489 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07004490 (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004491 return 1;
4492
Dmitry Shmidt04949592012-07-19 12:16:46 -07004493 return 0;
4494}
4495
4496
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004497int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004498{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004499 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004500 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004501 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004502 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004503 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004504}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004505
4506
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004507void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004508{
4509 struct wpa_ssid *ssid = wpa_s->current_ssid;
4510 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004511 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004512
4513 if (ssid == NULL) {
4514 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4515 "SSID block");
4516 return;
4517 }
4518
4519 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4520 return;
4521
4522 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004523
4524#ifdef CONFIG_P2P
4525 if (ssid->p2p_group &&
4526 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4527 /*
4528 * Skip the wait time since there is a short timeout on the
4529 * connection to a P2P group.
4530 */
4531 return;
4532 }
4533#endif /* CONFIG_P2P */
4534
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004535 if (ssid->auth_failures > 50)
4536 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004537 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004538 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004539 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004540 dur = 90;
4541 else if (ssid->auth_failures > 3)
4542 dur = 60;
4543 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004544 dur = 30;
4545 else if (ssid->auth_failures > 1)
4546 dur = 20;
4547 else
4548 dur = 10;
4549
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004550 if (ssid->auth_failures > 1 &&
4551 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
4552 dur += os_random() % (ssid->auth_failures * 10);
4553
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004554 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004555 if (now.sec + dur <= ssid->disabled_until.sec)
4556 return;
4557
4558 ssid->disabled_until.sec = now.sec + dur;
4559
4560 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004561 "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004562 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07004563 ssid->auth_failures, dur, reason);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004564}
4565
4566
4567void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4568 struct wpa_ssid *ssid, int clear_failures)
4569{
4570 if (ssid == NULL)
4571 return;
4572
4573 if (ssid->disabled_until.sec) {
4574 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4575 "id=%d ssid=\"%s\"",
4576 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4577 }
4578 ssid->disabled_until.sec = 0;
4579 ssid->disabled_until.usec = 0;
4580 if (clear_failures)
4581 ssid->auth_failures = 0;
4582}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004583
4584
4585int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4586{
4587 size_t i;
4588
4589 if (wpa_s->disallow_aps_bssid == NULL)
4590 return 0;
4591
4592 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4593 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4594 bssid, ETH_ALEN) == 0)
4595 return 1;
4596 }
4597
4598 return 0;
4599}
4600
4601
4602int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4603 size_t ssid_len)
4604{
4605 size_t i;
4606
4607 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4608 return 0;
4609
4610 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4611 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4612 if (ssid_len == s->ssid_len &&
4613 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4614 return 1;
4615 }
4616
4617 return 0;
4618}
4619
4620
4621/**
4622 * wpas_request_connection - Request a new connection
4623 * @wpa_s: Pointer to the network interface
4624 *
4625 * This function is used to request a new connection to be found. It will mark
4626 * the interface to allow reassociation and request a new scan to find a
4627 * suitable network to connect to.
4628 */
4629void wpas_request_connection(struct wpa_supplicant *wpa_s)
4630{
4631 wpa_s->normal_scans = 0;
4632 wpa_supplicant_reinit_autoscan(wpa_s);
4633 wpa_s->extra_blacklist_count = 0;
4634 wpa_s->disconnected = 0;
4635 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004636
4637 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4638 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004639}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004640
4641
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004642void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
4643 struct wpa_used_freq_data *freqs_data,
4644 unsigned int len)
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004645{
4646 unsigned int i;
4647
4648 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4649 len, title);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004650 for (i = 0; i < len; i++) {
4651 struct wpa_used_freq_data *cur = &freqs_data[i];
4652 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d, flags=0x%X",
4653 i, cur->freq, cur->flags);
4654 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004655}
4656
4657
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004658/*
4659 * Find the operating frequencies of any of the virtual interfaces that
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004660 * are using the same radio as the current interface, and in addition, get
4661 * information about the interface types that are using the frequency.
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004662 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004663int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
4664 struct wpa_used_freq_data *freqs_data,
4665 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004666{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004667 struct wpa_supplicant *ifs;
4668 u8 bssid[ETH_ALEN];
4669 int freq;
4670 unsigned int idx = 0, i;
4671
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004672 wpa_dbg(wpa_s, MSG_DEBUG,
4673 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004674 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004675
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004676 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4677 radio_list) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004678 if (idx == len)
4679 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004680
4681 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4682 continue;
4683
4684 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4685 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4686 freq = ifs->current_ssid->frequency;
4687 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4688 freq = ifs->assoc_freq;
4689 else
4690 continue;
4691
4692 /* Hold only distinct freqs */
4693 for (i = 0; i < idx; i++)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004694 if (freqs_data[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004695 break;
4696
4697 if (i == idx)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004698 freqs_data[idx++].freq = freq;
4699
4700 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
4701 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
4702 WPA_FREQ_USED_BY_P2P_CLIENT :
4703 WPA_FREQ_USED_BY_INFRA_STATION;
4704 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004705 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004706
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004707 dump_freq_data(wpa_s, "completed iteration", freqs_data, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004708 return idx;
4709}
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004710
4711
4712/*
4713 * Find the operating frequencies of any of the virtual interfaces that
4714 * are using the same radio as the current interface.
4715 */
4716int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4717 int *freq_array, unsigned int len)
4718{
4719 struct wpa_used_freq_data *freqs_data;
4720 int num, i;
4721
4722 os_memset(freq_array, 0, sizeof(int) * len);
4723
4724 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
4725 if (!freqs_data)
4726 return -1;
4727
4728 num = get_shared_radio_freqs_data(wpa_s, freqs_data, len);
4729 for (i = 0; i < num; i++)
4730 freq_array[i] = freqs_data[i].freq;
4731
4732 os_free(freqs_data);
4733
4734 return num;
4735}