1189251Ssam/*
2189251Ssam * WPA Supplicant
3252726Srpaulo * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
4189251Ssam *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7189251Ssam *
8189251Ssam * This file implements functions for registering and unregistering
9189251Ssam * %wpa_supplicant interfaces. In addition, this file contains number of
10189251Ssam * functions for managing network connections.
11189251Ssam */
12189251Ssam
13189251Ssam#include "includes.h"
14189251Ssam
15189251Ssam#include "common.h"
16252726Srpaulo#include "crypto/random.h"
17252726Srpaulo#include "crypto/sha1.h"
18189251Ssam#include "eapol_supp/eapol_supp_sm.h"
19189251Ssam#include "eap_peer/eap.h"
20214734Srpaulo#include "eap_server/eap_methods.h"
21214734Srpaulo#include "rsn_supp/wpa.h"
22189251Ssam#include "eloop.h"
23189251Ssam#include "config.h"
24252726Srpaulo#include "utils/ext_password.h"
25189251Ssam#include "l2_packet/l2_packet.h"
26189251Ssam#include "wpa_supplicant_i.h"
27214734Srpaulo#include "driver_i.h"
28189251Ssam#include "ctrl_iface.h"
29189251Ssam#include "pcsc_funcs.h"
30214734Srpaulo#include "common/version.h"
31214734Srpaulo#include "rsn_supp/preauth.h"
32214734Srpaulo#include "rsn_supp/pmksa_cache.h"
33214734Srpaulo#include "common/wpa_ctrl.h"
34214734Srpaulo#include "common/ieee802_11_defs.h"
35252726Srpaulo#include "p2p/p2p.h"
36189251Ssam#include "blacklist.h"
37189251Ssam#include "wpas_glue.h"
38189251Ssam#include "wps_supplicant.h"
39214734Srpaulo#include "ibss_rsn.h"
40214734Srpaulo#include "sme.h"
41252726Srpaulo#include "gas_query.h"
42214734Srpaulo#include "ap.h"
43252726Srpaulo#include "p2p_supplicant.h"
44252726Srpaulo#include "wifi_display.h"
45214734Srpaulo#include "notify.h"
46214734Srpaulo#include "bgscan.h"
47252726Srpaulo#include "autoscan.h"
48214734Srpaulo#include "bss.h"
49214734Srpaulo#include "scan.h"
50252726Srpaulo#include "offchannel.h"
51252726Srpaulo#include "hs20_supplicant.h"
52189251Ssam
53189251Ssamconst char *wpa_supplicant_version =
54189251Ssam"wpa_supplicant v" VERSION_STR "\n"
55252726Srpaulo"Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> and contributors";
56189251Ssam
57189251Ssamconst char *wpa_supplicant_license =
58252726Srpaulo"This software may be distributed under the terms of the BSD license.\n"
59252726Srpaulo"See README for more details.\n"
60189251Ssam#ifdef EAP_TLS_OPENSSL
61189251Ssam"\nThis product includes software developed by the OpenSSL Project\n"
62189251Ssam"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
63189251Ssam#endif /* EAP_TLS_OPENSSL */
64189251Ssam;
65189251Ssam
66189251Ssam#ifndef CONFIG_NO_STDOUT_DEBUG
67189251Ssam/* Long text divided into parts in order to fit in C89 strings size limits. */
68189251Ssamconst char *wpa_supplicant_full_license1 =
69252726Srpaulo"";
70189251Ssamconst char *wpa_supplicant_full_license2 =
71252726Srpaulo"This software may be distributed under the terms of the BSD license.\n"
72189251Ssam"\n"
73189251Ssam"Redistribution and use in source and binary forms, with or without\n"
74189251Ssam"modification, are permitted provided that the following conditions are\n"
75189251Ssam"met:\n"
76189251Ssam"\n";
77189251Ssamconst char *wpa_supplicant_full_license3 =
78189251Ssam"1. Redistributions of source code must retain the above copyright\n"
79189251Ssam"   notice, this list of conditions and the following disclaimer.\n"
80189251Ssam"\n"
81189251Ssam"2. Redistributions in binary form must reproduce the above copyright\n"
82189251Ssam"   notice, this list of conditions and the following disclaimer in the\n"
83189251Ssam"   documentation and/or other materials provided with the distribution.\n"
84189251Ssam"\n";
85189251Ssamconst char *wpa_supplicant_full_license4 =
86189251Ssam"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
87189251Ssam"   names of its contributors may be used to endorse or promote products\n"
88189251Ssam"   derived from this software without specific prior written permission.\n"
89189251Ssam"\n"
90189251Ssam"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
91189251Ssam"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
92189251Ssam"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
93189251Ssam"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
94189251Ssamconst char *wpa_supplicant_full_license5 =
95189251Ssam"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
96189251Ssam"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
97189251Ssam"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
98189251Ssam"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
99189251Ssam"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
100189251Ssam"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
101189251Ssam"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
102189251Ssam"\n";
103189251Ssam#endif /* CONFIG_NO_STDOUT_DEBUG */
104189251Ssam
105189251Ssamextern int wpa_debug_level;
106189251Ssamextern int wpa_debug_show_keys;
107189251Ssamextern int wpa_debug_timestamp;
108214734Srpauloextern struct wpa_driver_ops *wpa_drivers[];
109189251Ssam
110189251Ssam/* Configure default/group WEP keys for static WEP */
111214734Srpauloint wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
112189251Ssam{
113189251Ssam	int i, set = 0;
114189251Ssam
115189251Ssam	for (i = 0; i < NUM_WEP_KEYS; i++) {
116189251Ssam		if (ssid->wep_key_len[i] == 0)
117189251Ssam			continue;
118189251Ssam
119189251Ssam		set = 1;
120252726Srpaulo		wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
121252726Srpaulo				i, i == ssid->wep_tx_keyidx, NULL, 0,
122189251Ssam				ssid->wep_key[i], ssid->wep_key_len[i]);
123189251Ssam	}
124189251Ssam
125189251Ssam	return set;
126189251Ssam}
127189251Ssam
128189251Ssam
129189251Ssamstatic int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
130189251Ssam					   struct wpa_ssid *ssid)
131189251Ssam{
132189251Ssam	u8 key[32];
133189251Ssam	size_t keylen;
134214734Srpaulo	enum wpa_alg alg;
135189251Ssam	u8 seq[6] = { 0 };
136189251Ssam
137189251Ssam	/* IBSS/WPA-None uses only one key (Group) for both receiving and
138189251Ssam	 * sending unicast and multicast packets. */
139189251Ssam
140214734Srpaulo	if (ssid->mode != WPAS_MODE_IBSS) {
141252726Srpaulo		wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
142252726Srpaulo			"IBSS/ad-hoc) for WPA-None", ssid->mode);
143189251Ssam		return -1;
144189251Ssam	}
145189251Ssam
146189251Ssam	if (!ssid->psk_set) {
147252726Srpaulo		wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
148252726Srpaulo			"WPA-None");
149189251Ssam		return -1;
150189251Ssam	}
151189251Ssam
152189251Ssam	switch (wpa_s->group_cipher) {
153189251Ssam	case WPA_CIPHER_CCMP:
154189251Ssam		os_memcpy(key, ssid->psk, 16);
155189251Ssam		keylen = 16;
156189251Ssam		alg = WPA_ALG_CCMP;
157189251Ssam		break;
158252726Srpaulo	case WPA_CIPHER_GCMP:
159252726Srpaulo		os_memcpy(key, ssid->psk, 16);
160252726Srpaulo		keylen = 16;
161252726Srpaulo		alg = WPA_ALG_GCMP;
162252726Srpaulo		break;
163189251Ssam	case WPA_CIPHER_TKIP:
164189251Ssam		/* WPA-None uses the same Michael MIC key for both TX and RX */
165189251Ssam		os_memcpy(key, ssid->psk, 16 + 8);
166189251Ssam		os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
167189251Ssam		keylen = 32;
168189251Ssam		alg = WPA_ALG_TKIP;
169189251Ssam		break;
170189251Ssam	default:
171252726Srpaulo		wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
172252726Srpaulo			"WPA-None", wpa_s->group_cipher);
173189251Ssam		return -1;
174189251Ssam	}
175189251Ssam
176189251Ssam	/* TODO: should actually remember the previously used seq#, both for TX
177189251Ssam	 * and RX from each STA.. */
178189251Ssam
179252726Srpaulo	return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
180189251Ssam}
181189251Ssam
182189251Ssam
183189251Ssamstatic void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
184189251Ssam{
185189251Ssam	struct wpa_supplicant *wpa_s = eloop_ctx;
186189251Ssam	const u8 *bssid = wpa_s->bssid;
187189251Ssam	if (is_zero_ether_addr(bssid))
188189251Ssam		bssid = wpa_s->pending_bssid;
189189251Ssam	wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
190189251Ssam		MAC2STR(bssid));
191189251Ssam	wpa_blacklist_add(wpa_s, bssid);
192189251Ssam	wpa_sm_notify_disassoc(wpa_s->wpa);
193252726Srpaulo	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
194189251Ssam	wpa_s->reassociate = 1;
195252726Srpaulo
196252726Srpaulo	/*
197252726Srpaulo	 * If we timed out, the AP or the local radio may be busy.
198252726Srpaulo	 * So, wait a second until scanning again.
199252726Srpaulo	 */
200252726Srpaulo	wpa_supplicant_req_scan(wpa_s, 1, 0);
201252726Srpaulo
202252726Srpaulo#ifdef CONFIG_P2P
203252726Srpaulo	if (wpa_s->global->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled &&
204252726Srpaulo	    wpa_s->global->p2p != NULL) {
205252726Srpaulo		wpa_s->global->p2p_cb_on_scan_complete = 0;
206252726Srpaulo		if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
207252726Srpaulo			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
208252726Srpaulo				"continued after timed out authentication");
209252726Srpaulo		}
210252726Srpaulo	}
211252726Srpaulo#endif /* CONFIG_P2P */
212189251Ssam}
213189251Ssam
214189251Ssam
215189251Ssam/**
216189251Ssam * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
217189251Ssam * @wpa_s: Pointer to wpa_supplicant data
218189251Ssam * @sec: Number of seconds after which to time out authentication
219189251Ssam * @usec: Number of microseconds after which to time out authentication
220189251Ssam *
221189251Ssam * This function is used to schedule a timeout for the current authentication
222189251Ssam * attempt.
223189251Ssam */
224189251Ssamvoid wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
225189251Ssam				     int sec, int usec)
226189251Ssam{
227189251Ssam	if (wpa_s->conf && wpa_s->conf->ap_scan == 0 &&
228214734Srpaulo	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
229189251Ssam		return;
230189251Ssam
231252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
232189251Ssam		"%d usec", sec, usec);
233189251Ssam	eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
234189251Ssam	eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
235189251Ssam}
236189251Ssam
237189251Ssam
238189251Ssam/**
239189251Ssam * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
240189251Ssam * @wpa_s: Pointer to wpa_supplicant data
241189251Ssam *
242189251Ssam * This function is used to cancel authentication timeout scheduled with
243189251Ssam * wpa_supplicant_req_auth_timeout() and it is called when authentication has
244189251Ssam * been completed.
245189251Ssam */
246189251Ssamvoid wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
247189251Ssam{
248252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
249189251Ssam	eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
250189251Ssam	wpa_blacklist_del(wpa_s, wpa_s->bssid);
251189251Ssam}
252189251Ssam
253189251Ssam
254189251Ssam/**
255189251Ssam * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
256189251Ssam * @wpa_s: Pointer to wpa_supplicant data
257189251Ssam *
258189251Ssam * This function is used to configure EAPOL state machine based on the selected
259189251Ssam * authentication mode.
260189251Ssam */
261189251Ssamvoid wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
262189251Ssam{
263189251Ssam#ifdef IEEE8021X_EAPOL
264189251Ssam	struct eapol_config eapol_conf;
265189251Ssam	struct wpa_ssid *ssid = wpa_s->current_ssid;
266189251Ssam
267214734Srpaulo#ifdef CONFIG_IBSS_RSN
268214734Srpaulo	if (ssid->mode == WPAS_MODE_IBSS &&
269214734Srpaulo	    wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
270214734Srpaulo	    wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
271214734Srpaulo		/*
272214734Srpaulo		 * RSN IBSS authentication is per-STA and we can disable the
273214734Srpaulo		 * per-BSSID EAPOL authentication.
274214734Srpaulo		 */
275214734Srpaulo		eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
276214734Srpaulo		eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
277214734Srpaulo		eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
278214734Srpaulo		return;
279214734Srpaulo	}
280214734Srpaulo#endif /* CONFIG_IBSS_RSN */
281214734Srpaulo
282189251Ssam	eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
283189251Ssam	eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
284189251Ssam
285189251Ssam	if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
286189251Ssam	    wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
287189251Ssam		eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
288189251Ssam	else
289189251Ssam		eapol_sm_notify_portControl(wpa_s->eapol, Auto);
290189251Ssam
291189251Ssam	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
292189251Ssam	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
293189251Ssam		eapol_conf.accept_802_1x_keys = 1;
294189251Ssam		eapol_conf.required_keys = 0;
295189251Ssam		if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
296189251Ssam			eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
297189251Ssam		}
298189251Ssam		if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
299189251Ssam			eapol_conf.required_keys |=
300189251Ssam				EAPOL_REQUIRE_KEY_BROADCAST;
301189251Ssam		}
302189251Ssam
303214734Srpaulo		if (wpa_s->conf && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
304189251Ssam			eapol_conf.required_keys = 0;
305189251Ssam	}
306189251Ssam	if (wpa_s->conf)
307189251Ssam		eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
308189251Ssam	eapol_conf.workaround = ssid->eap_workaround;
309189251Ssam	eapol_conf.eap_disabled =
310189251Ssam		!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
311189251Ssam		wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
312189251Ssam		wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
313189251Ssam	eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
314189251Ssam#endif /* IEEE8021X_EAPOL */
315189251Ssam}
316189251Ssam
317189251Ssam
318189251Ssam/**
319189251Ssam * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
320189251Ssam * @wpa_s: Pointer to wpa_supplicant data
321189251Ssam * @ssid: Configuration data for the network
322189251Ssam *
323189251Ssam * This function is used to configure WPA state machine and related parameters
324189251Ssam * to a mode where WPA is not enabled. This is called as part of the
325189251Ssam * authentication configuration when the selected network does not use WPA.
326189251Ssam */
327189251Ssamvoid wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
328189251Ssam				       struct wpa_ssid *ssid)
329189251Ssam{
330189251Ssam	int i;
331189251Ssam
332189251Ssam	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
333189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
334189251Ssam	else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
335189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
336189251Ssam	else
337189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
338189251Ssam	wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
339189251Ssam	wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
340189251Ssam	wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
341189251Ssam	wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
342189251Ssam	wpa_s->group_cipher = WPA_CIPHER_NONE;
343189251Ssam	wpa_s->mgmt_group_cipher = 0;
344189251Ssam
345189251Ssam	for (i = 0; i < NUM_WEP_KEYS; i++) {
346189251Ssam		if (ssid->wep_key_len[i] > 5) {
347189251Ssam			wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
348189251Ssam			wpa_s->group_cipher = WPA_CIPHER_WEP104;
349189251Ssam			break;
350189251Ssam		} else if (ssid->wep_key_len[i] > 0) {
351189251Ssam			wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
352189251Ssam			wpa_s->group_cipher = WPA_CIPHER_WEP40;
353189251Ssam			break;
354189251Ssam		}
355189251Ssam	}
356189251Ssam
357189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
358189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
359189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
360189251Ssam			 wpa_s->pairwise_cipher);
361189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
362189251Ssam#ifdef CONFIG_IEEE80211W
363189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
364189251Ssam			 wpa_s->mgmt_group_cipher);
365189251Ssam#endif /* CONFIG_IEEE80211W */
366189251Ssam
367189251Ssam	pmksa_cache_clear_current(wpa_s->wpa);
368189251Ssam}
369189251Ssam
370189251Ssam
371252726Srpaulovoid free_hw_features(struct wpa_supplicant *wpa_s)
372252726Srpaulo{
373252726Srpaulo	int i;
374252726Srpaulo	if (wpa_s->hw.modes == NULL)
375252726Srpaulo		return;
376252726Srpaulo
377252726Srpaulo	for (i = 0; i < wpa_s->hw.num_modes; i++) {
378252726Srpaulo		os_free(wpa_s->hw.modes[i].channels);
379252726Srpaulo		os_free(wpa_s->hw.modes[i].rates);
380252726Srpaulo	}
381252726Srpaulo
382252726Srpaulo	os_free(wpa_s->hw.modes);
383252726Srpaulo	wpa_s->hw.modes = NULL;
384252726Srpaulo}
385252726Srpaulo
386252726Srpaulo
387189251Ssamstatic void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
388189251Ssam{
389214734Srpaulo	bgscan_deinit(wpa_s);
390252726Srpaulo	autoscan_deinit(wpa_s);
391189251Ssam	scard_deinit(wpa_s->scard);
392189251Ssam	wpa_s->scard = NULL;
393189251Ssam	wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
394189251Ssam	eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
395189251Ssam	l2_packet_deinit(wpa_s->l2);
396189251Ssam	wpa_s->l2 = NULL;
397189251Ssam	if (wpa_s->l2_br) {
398189251Ssam		l2_packet_deinit(wpa_s->l2_br);
399189251Ssam		wpa_s->l2_br = NULL;
400189251Ssam	}
401189251Ssam
402189251Ssam	if (wpa_s->conf != NULL) {
403214734Srpaulo		struct wpa_ssid *ssid;
404214734Srpaulo		for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
405214734Srpaulo			wpas_notify_network_removed(wpa_s, ssid);
406189251Ssam	}
407189251Ssam
408189251Ssam	os_free(wpa_s->confname);
409189251Ssam	wpa_s->confname = NULL;
410189251Ssam
411189251Ssam	wpa_sm_set_eapol(wpa_s->wpa, NULL);
412189251Ssam	eapol_sm_deinit(wpa_s->eapol);
413189251Ssam	wpa_s->eapol = NULL;
414189251Ssam
415189251Ssam	rsn_preauth_deinit(wpa_s->wpa);
416189251Ssam
417252726Srpaulo#ifdef CONFIG_TDLS
418252726Srpaulo	wpa_tdls_deinit(wpa_s->wpa);
419252726Srpaulo#endif /* CONFIG_TDLS */
420252726Srpaulo
421189251Ssam	pmksa_candidate_free(wpa_s->wpa);
422189251Ssam	wpa_sm_deinit(wpa_s->wpa);
423189251Ssam	wpa_s->wpa = NULL;
424189251Ssam	wpa_blacklist_clear(wpa_s);
425189251Ssam
426214734Srpaulo	wpa_bss_deinit(wpa_s);
427189251Ssam
428189251Ssam	wpa_supplicant_cancel_scan(wpa_s);
429189251Ssam	wpa_supplicant_cancel_auth_timeout(wpa_s);
430252726Srpaulo	eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
431252726Srpaulo#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
432252726Srpaulo	eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
433252726Srpaulo			     wpa_s, NULL);
434252726Srpaulo#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
435189251Ssam
436189251Ssam	wpas_wps_deinit(wpa_s);
437209158Srpaulo
438209158Srpaulo	wpabuf_free(wpa_s->pending_eapol_rx);
439209158Srpaulo	wpa_s->pending_eapol_rx = NULL;
440214734Srpaulo
441214734Srpaulo#ifdef CONFIG_IBSS_RSN
442214734Srpaulo	ibss_rsn_deinit(wpa_s->ibss_rsn);
443214734Srpaulo	wpa_s->ibss_rsn = NULL;
444214734Srpaulo#endif /* CONFIG_IBSS_RSN */
445214734Srpaulo
446252726Srpaulo	sme_deinit(wpa_s);
447214734Srpaulo
448214734Srpaulo#ifdef CONFIG_AP
449214734Srpaulo	wpa_supplicant_ap_deinit(wpa_s);
450214734Srpaulo#endif /* CONFIG_AP */
451252726Srpaulo
452252726Srpaulo#ifdef CONFIG_P2P
453252726Srpaulo	wpas_p2p_deinit(wpa_s);
454252726Srpaulo#endif /* CONFIG_P2P */
455252726Srpaulo
456252726Srpaulo#ifdef CONFIG_OFFCHANNEL
457252726Srpaulo	offchannel_deinit(wpa_s);
458252726Srpaulo#endif /* CONFIG_OFFCHANNEL */
459252726Srpaulo
460252726Srpaulo	wpa_supplicant_cancel_sched_scan(wpa_s);
461252726Srpaulo
462252726Srpaulo	os_free(wpa_s->next_scan_freqs);
463252726Srpaulo	wpa_s->next_scan_freqs = NULL;
464252726Srpaulo
465252726Srpaulo	gas_query_deinit(wpa_s->gas);
466252726Srpaulo	wpa_s->gas = NULL;
467252726Srpaulo
468252726Srpaulo	free_hw_features(wpa_s);
469252726Srpaulo
470252726Srpaulo	os_free(wpa_s->bssid_filter);
471252726Srpaulo	wpa_s->bssid_filter = NULL;
472252726Srpaulo
473252726Srpaulo	os_free(wpa_s->disallow_aps_bssid);
474252726Srpaulo	wpa_s->disallow_aps_bssid = NULL;
475252726Srpaulo	os_free(wpa_s->disallow_aps_ssid);
476252726Srpaulo	wpa_s->disallow_aps_ssid = NULL;
477252726Srpaulo
478252726Srpaulo	wnm_bss_keep_alive_deinit(wpa_s);
479252726Srpaulo
480252726Srpaulo	ext_password_deinit(wpa_s->ext_pw);
481252726Srpaulo	wpa_s->ext_pw = NULL;
482252726Srpaulo
483252726Srpaulo	wpabuf_free(wpa_s->last_gas_resp);
484252726Srpaulo
485252726Srpaulo	os_free(wpa_s->last_scan_res);
486252726Srpaulo	wpa_s->last_scan_res = NULL;
487189251Ssam}
488189251Ssam
489189251Ssam
490189251Ssam/**
491189251Ssam * wpa_clear_keys - Clear keys configured for the driver
492189251Ssam * @wpa_s: Pointer to wpa_supplicant data
493189251Ssam * @addr: Previously used BSSID or %NULL if not available
494189251Ssam *
495189251Ssam * This function clears the encryption keys that has been previously configured
496189251Ssam * for the driver.
497189251Ssam */
498189251Ssamvoid wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
499189251Ssam{
500189251Ssam	if (wpa_s->keys_cleared) {
501189251Ssam		/* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have
502189251Ssam		 * timing issues with keys being cleared just before new keys
503189251Ssam		 * are set or just after association or something similar. This
504189251Ssam		 * shows up in group key handshake failing often because of the
505189251Ssam		 * client not receiving the first encrypted packets correctly.
506189251Ssam		 * Skipping some of the extra key clearing steps seems to help
507189251Ssam		 * in completing group key handshake more reliably. */
508252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "No keys have been configured - "
509252726Srpaulo			"skip key clearing");
510189251Ssam		return;
511189251Ssam	}
512189251Ssam
513189251Ssam	/* MLME-DELETEKEYS.request */
514252726Srpaulo	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
515252726Srpaulo	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
516252726Srpaulo	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
517252726Srpaulo	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
518209158Srpaulo#ifdef CONFIG_IEEE80211W
519252726Srpaulo	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
520252726Srpaulo	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
521209158Srpaulo#endif /* CONFIG_IEEE80211W */
522189251Ssam	if (addr) {
523189251Ssam		wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
524189251Ssam				0);
525189251Ssam		/* MLME-SETPROTECTION.request(None) */
526189251Ssam		wpa_drv_mlme_setprotection(
527189251Ssam			wpa_s, addr,
528189251Ssam			MLME_SETPROTECTION_PROTECT_TYPE_NONE,
529189251Ssam			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
530189251Ssam	}
531189251Ssam	wpa_s->keys_cleared = 1;
532189251Ssam}
533189251Ssam
534189251Ssam
535189251Ssam/**
536189251Ssam * wpa_supplicant_state_txt - Get the connection state name as a text string
537189251Ssam * @state: State (wpa_state; WPA_*)
538189251Ssam * Returns: The state name as a printable text string
539189251Ssam */
540214734Srpauloconst char * wpa_supplicant_state_txt(enum wpa_states state)
541189251Ssam{
542189251Ssam	switch (state) {
543189251Ssam	case WPA_DISCONNECTED:
544189251Ssam		return "DISCONNECTED";
545189251Ssam	case WPA_INACTIVE:
546189251Ssam		return "INACTIVE";
547252726Srpaulo	case WPA_INTERFACE_DISABLED:
548252726Srpaulo		return "INTERFACE_DISABLED";
549189251Ssam	case WPA_SCANNING:
550189251Ssam		return "SCANNING";
551214734Srpaulo	case WPA_AUTHENTICATING:
552214734Srpaulo		return "AUTHENTICATING";
553189251Ssam	case WPA_ASSOCIATING:
554189251Ssam		return "ASSOCIATING";
555189251Ssam	case WPA_ASSOCIATED:
556189251Ssam		return "ASSOCIATED";
557189251Ssam	case WPA_4WAY_HANDSHAKE:
558189251Ssam		return "4WAY_HANDSHAKE";
559189251Ssam	case WPA_GROUP_HANDSHAKE:
560189251Ssam		return "GROUP_HANDSHAKE";
561189251Ssam	case WPA_COMPLETED:
562189251Ssam		return "COMPLETED";
563189251Ssam	default:
564189251Ssam		return "UNKNOWN";
565189251Ssam	}
566189251Ssam}
567189251Ssam
568189251Ssam
569252726Srpaulo#ifdef CONFIG_BGSCAN
570252726Srpaulo
571252726Srpaulostatic void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
572252726Srpaulo{
573252726Srpaulo	if (wpas_driver_bss_selection(wpa_s))
574252726Srpaulo		return;
575252726Srpaulo	if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
576252726Srpaulo		return;
577252726Srpaulo
578252726Srpaulo	bgscan_deinit(wpa_s);
579252726Srpaulo	if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan) {
580252726Srpaulo		if (bgscan_init(wpa_s, wpa_s->current_ssid)) {
581252726Srpaulo			wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
582252726Srpaulo				"bgscan");
583252726Srpaulo			/*
584252726Srpaulo			 * Live without bgscan; it is only used as a roaming
585252726Srpaulo			 * optimization, so the initial connection is not
586252726Srpaulo			 * affected.
587252726Srpaulo			 */
588252726Srpaulo		} else {
589252726Srpaulo			struct wpa_scan_results *scan_res;
590252726Srpaulo			wpa_s->bgscan_ssid = wpa_s->current_ssid;
591252726Srpaulo			scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
592252726Srpaulo								   0);
593252726Srpaulo			if (scan_res) {
594252726Srpaulo				bgscan_notify_scan(wpa_s, scan_res);
595252726Srpaulo				wpa_scan_results_free(scan_res);
596252726Srpaulo			}
597252726Srpaulo		}
598252726Srpaulo	} else
599252726Srpaulo		wpa_s->bgscan_ssid = NULL;
600252726Srpaulo}
601252726Srpaulo
602252726Srpaulo
603252726Srpaulostatic void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
604252726Srpaulo{
605252726Srpaulo	if (wpa_s->bgscan_ssid != NULL) {
606252726Srpaulo		bgscan_deinit(wpa_s);
607252726Srpaulo		wpa_s->bgscan_ssid = NULL;
608252726Srpaulo	}
609252726Srpaulo}
610252726Srpaulo
611252726Srpaulo#endif /* CONFIG_BGSCAN */
612252726Srpaulo
613252726Srpaulo
614252726Srpaulostatic void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
615252726Srpaulo{
616252726Srpaulo	if (autoscan_init(wpa_s, 0))
617252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
618252726Srpaulo}
619252726Srpaulo
620252726Srpaulo
621252726Srpaulostatic void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
622252726Srpaulo{
623252726Srpaulo	autoscan_deinit(wpa_s);
624252726Srpaulo}
625252726Srpaulo
626252726Srpaulo
627252726Srpaulovoid wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
628252726Srpaulo{
629252726Srpaulo	if (wpa_s->wpa_state == WPA_DISCONNECTED ||
630252726Srpaulo	    wpa_s->wpa_state == WPA_SCANNING) {
631252726Srpaulo		autoscan_deinit(wpa_s);
632252726Srpaulo		wpa_supplicant_start_autoscan(wpa_s);
633252726Srpaulo	}
634252726Srpaulo}
635252726Srpaulo
636252726Srpaulo
637189251Ssam/**
638189251Ssam * wpa_supplicant_set_state - Set current connection state
639189251Ssam * @wpa_s: Pointer to wpa_supplicant data
640189251Ssam * @state: The new connection state
641189251Ssam *
642189251Ssam * This function is called whenever the connection state changes, e.g.,
643189251Ssam * association is completed for WPA/WPA2 4-Way Handshake is started.
644189251Ssam */
645214734Srpaulovoid wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
646214734Srpaulo			      enum wpa_states state)
647189251Ssam{
648214734Srpaulo	enum wpa_states old_state = wpa_s->wpa_state;
649214734Srpaulo
650252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
651252726Srpaulo		wpa_supplicant_state_txt(wpa_s->wpa_state),
652252726Srpaulo		wpa_supplicant_state_txt(state));
653189251Ssam
654209158Srpaulo	if (state != WPA_SCANNING)
655209158Srpaulo		wpa_supplicant_notify_scanning(wpa_s, 0);
656209158Srpaulo
657189251Ssam	if (state == WPA_COMPLETED && wpa_s->new_connection) {
658189251Ssam#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
659189251Ssam		struct wpa_ssid *ssid = wpa_s->current_ssid;
660189251Ssam		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
661252726Srpaulo			MACSTR " completed [id=%d id_str=%s]",
662252726Srpaulo			MAC2STR(wpa_s->bssid),
663189251Ssam			ssid ? ssid->id : -1,
664189251Ssam			ssid && ssid->id_str ? ssid->id_str : "");
665189251Ssam#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
666252726Srpaulo		wpas_clear_temp_disabled(wpa_s, ssid, 1);
667252726Srpaulo		wpa_s->extra_blacklist_count = 0;
668189251Ssam		wpa_s->new_connection = 0;
669189251Ssam		wpa_drv_set_operstate(wpa_s, 1);
670252726Srpaulo#ifndef IEEE8021X_EAPOL
671252726Srpaulo		wpa_drv_set_supp_port(wpa_s, 1);
672252726Srpaulo#endif /* IEEE8021X_EAPOL */
673214734Srpaulo		wpa_s->after_wps = 0;
674252726Srpaulo#ifdef CONFIG_P2P
675252726Srpaulo		wpas_p2p_completed(wpa_s);
676252726Srpaulo#endif /* CONFIG_P2P */
677252726Srpaulo
678252726Srpaulo		sme_sched_obss_scan(wpa_s, 1);
679189251Ssam	} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
680189251Ssam		   state == WPA_ASSOCIATED) {
681189251Ssam		wpa_s->new_connection = 1;
682189251Ssam		wpa_drv_set_operstate(wpa_s, 0);
683252726Srpaulo#ifndef IEEE8021X_EAPOL
684252726Srpaulo		wpa_drv_set_supp_port(wpa_s, 0);
685252726Srpaulo#endif /* IEEE8021X_EAPOL */
686252726Srpaulo		sme_sched_obss_scan(wpa_s, 0);
687189251Ssam	}
688189251Ssam	wpa_s->wpa_state = state;
689214734Srpaulo
690252726Srpaulo#ifdef CONFIG_BGSCAN
691252726Srpaulo	if (state == WPA_COMPLETED)
692252726Srpaulo		wpa_supplicant_start_bgscan(wpa_s);
693252726Srpaulo	else
694252726Srpaulo		wpa_supplicant_stop_bgscan(wpa_s);
695252726Srpaulo#endif /* CONFIG_BGSCAN */
696252726Srpaulo
697252726Srpaulo	if (state == WPA_AUTHENTICATING)
698252726Srpaulo		wpa_supplicant_stop_autoscan(wpa_s);
699252726Srpaulo
700252726Srpaulo	if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
701252726Srpaulo		wpa_supplicant_start_autoscan(wpa_s);
702252726Srpaulo
703252726Srpaulo	if (wpa_s->wpa_state != old_state) {
704214734Srpaulo		wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
705252726Srpaulo
706252726Srpaulo		if (wpa_s->wpa_state == WPA_COMPLETED ||
707252726Srpaulo		    old_state == WPA_COMPLETED)
708252726Srpaulo			wpas_notify_auth_changed(wpa_s);
709252726Srpaulo	}
710189251Ssam}
711189251Ssam
712189251Ssam
713214734Srpaulovoid wpa_supplicant_terminate_proc(struct wpa_global *global)
714189251Ssam{
715214734Srpaulo	int pending = 0;
716214734Srpaulo#ifdef CONFIG_WPS
717214734Srpaulo	struct wpa_supplicant *wpa_s = global->ifaces;
718214734Srpaulo	while (wpa_s) {
719214734Srpaulo		if (wpas_wps_terminate_pending(wpa_s) == 1)
720214734Srpaulo			pending = 1;
721214734Srpaulo		wpa_s = wpa_s->next;
722214734Srpaulo	}
723214734Srpaulo#endif /* CONFIG_WPS */
724214734Srpaulo	if (pending)
725214734Srpaulo		return;
726214734Srpaulo	eloop_terminate();
727214734Srpaulo}
728214734Srpaulo
729214734Srpaulo
730214734Srpaulostatic void wpa_supplicant_terminate(int sig, void *signal_ctx)
731214734Srpaulo{
732214734Srpaulo	struct wpa_global *global = signal_ctx;
733214734Srpaulo	wpa_supplicant_terminate_proc(global);
734189251Ssam}
735189251Ssam
736189251Ssam
737252726Srpaulovoid wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
738189251Ssam{
739214734Srpaulo	enum wpa_states old_state = wpa_s->wpa_state;
740214734Srpaulo
741189251Ssam	wpa_s->pairwise_cipher = 0;
742189251Ssam	wpa_s->group_cipher = 0;
743189251Ssam	wpa_s->mgmt_group_cipher = 0;
744189251Ssam	wpa_s->key_mgmt = 0;
745252726Srpaulo	if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
746252726Srpaulo		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
747214734Srpaulo
748214734Srpaulo	if (wpa_s->wpa_state != old_state)
749214734Srpaulo		wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
750189251Ssam}
751189251Ssam
752189251Ssam
753189251Ssam/**
754189251Ssam * wpa_supplicant_reload_configuration - Reload configuration data
755189251Ssam * @wpa_s: Pointer to wpa_supplicant data
756189251Ssam * Returns: 0 on success or -1 if configuration parsing failed
757189251Ssam *
758189251Ssam * This function can be used to request that the configuration data is reloaded
759189251Ssam * (e.g., after configuration file change). This function is reloading
760189251Ssam * configuration only for one interface, so this may need to be called multiple
761189251Ssam * times if %wpa_supplicant is controlling multiple interfaces and all
762189251Ssam * interfaces need reconfiguration.
763189251Ssam */
764189251Ssamint wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
765189251Ssam{
766189251Ssam	struct wpa_config *conf;
767189251Ssam	int reconf_ctrl;
768214734Srpaulo	int old_ap_scan;
769214734Srpaulo
770189251Ssam	if (wpa_s->confname == NULL)
771189251Ssam		return -1;
772189251Ssam	conf = wpa_config_read(wpa_s->confname);
773189251Ssam	if (conf == NULL) {
774189251Ssam		wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
775189251Ssam			"file '%s' - exiting", wpa_s->confname);
776189251Ssam		return -1;
777189251Ssam	}
778252726Srpaulo	conf->changed_parameters = (unsigned int) -1;
779189251Ssam
780189251Ssam	reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
781189251Ssam		|| (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
782189251Ssam		    os_strcmp(conf->ctrl_interface,
783189251Ssam			      wpa_s->conf->ctrl_interface) != 0);
784189251Ssam
785189251Ssam	if (reconf_ctrl && wpa_s->ctrl_iface) {
786189251Ssam		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
787189251Ssam		wpa_s->ctrl_iface = NULL;
788189251Ssam	}
789189251Ssam
790189251Ssam	eapol_sm_invalidate_cached_session(wpa_s->eapol);
791252726Srpaulo	if (wpa_s->current_ssid) {
792252726Srpaulo		wpa_supplicant_deauthenticate(wpa_s,
793252726Srpaulo					      WLAN_REASON_DEAUTH_LEAVING);
794252726Srpaulo	}
795214734Srpaulo
796189251Ssam	/*
797189251Ssam	 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
798189251Ssam	 * pkcs11_engine_path, pkcs11_module_path.
799189251Ssam	 */
800189251Ssam	if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
801189251Ssam		/*
802189251Ssam		 * Clear forced success to clear EAP state for next
803189251Ssam		 * authentication.
804189251Ssam		 */
805189251Ssam		eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
806189251Ssam	}
807189251Ssam	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
808189251Ssam	wpa_sm_set_config(wpa_s->wpa, NULL);
809252726Srpaulo	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
810189251Ssam	wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
811189251Ssam	rsn_preauth_deinit(wpa_s->wpa);
812214734Srpaulo
813214734Srpaulo	old_ap_scan = wpa_s->conf->ap_scan;
814189251Ssam	wpa_config_free(wpa_s->conf);
815189251Ssam	wpa_s->conf = conf;
816214734Srpaulo	if (old_ap_scan != wpa_s->conf->ap_scan)
817214734Srpaulo		wpas_notify_ap_scan_changed(wpa_s);
818214734Srpaulo
819189251Ssam	if (reconf_ctrl)
820189251Ssam		wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
821189251Ssam
822252726Srpaulo	wpa_supplicant_update_config(wpa_s);
823252726Srpaulo
824189251Ssam	wpa_supplicant_clear_status(wpa_s);
825252726Srpaulo	if (wpa_supplicant_enabled_networks(wpa_s)) {
826252726Srpaulo		wpa_s->reassociate = 1;
827252726Srpaulo		wpa_supplicant_req_scan(wpa_s, 0, 0);
828252726Srpaulo	}
829252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
830189251Ssam	return 0;
831189251Ssam}
832189251Ssam
833189251Ssam
834214734Srpaulostatic void wpa_supplicant_reconfig(int sig, void *signal_ctx)
835189251Ssam{
836214734Srpaulo	struct wpa_global *global = signal_ctx;
837189251Ssam	struct wpa_supplicant *wpa_s;
838189251Ssam	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
839252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
840252726Srpaulo			sig);
841189251Ssam		if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
842214734Srpaulo			wpa_supplicant_terminate_proc(global);
843189251Ssam		}
844189251Ssam	}
845189251Ssam}
846189251Ssam
847189251Ssam
848214734Srpauloenum wpa_cipher cipher_suite2driver(int cipher)
849189251Ssam{
850189251Ssam	switch (cipher) {
851189251Ssam	case WPA_CIPHER_NONE:
852189251Ssam		return CIPHER_NONE;
853189251Ssam	case WPA_CIPHER_WEP40:
854189251Ssam		return CIPHER_WEP40;
855189251Ssam	case WPA_CIPHER_WEP104:
856189251Ssam		return CIPHER_WEP104;
857189251Ssam	case WPA_CIPHER_CCMP:
858189251Ssam		return CIPHER_CCMP;
859252726Srpaulo	case WPA_CIPHER_GCMP:
860252726Srpaulo		return CIPHER_GCMP;
861189251Ssam	case WPA_CIPHER_TKIP:
862189251Ssam	default:
863189251Ssam		return CIPHER_TKIP;
864189251Ssam	}
865189251Ssam}
866189251Ssam
867189251Ssam
868214734Srpauloenum wpa_key_mgmt key_mgmt2driver(int key_mgmt)
869189251Ssam{
870189251Ssam	switch (key_mgmt) {
871189251Ssam	case WPA_KEY_MGMT_NONE:
872189251Ssam		return KEY_MGMT_NONE;
873189251Ssam	case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
874189251Ssam		return KEY_MGMT_802_1X_NO_WPA;
875189251Ssam	case WPA_KEY_MGMT_IEEE8021X:
876189251Ssam		return KEY_MGMT_802_1X;
877189251Ssam	case WPA_KEY_MGMT_WPA_NONE:
878189251Ssam		return KEY_MGMT_WPA_NONE;
879189251Ssam	case WPA_KEY_MGMT_FT_IEEE8021X:
880189251Ssam		return KEY_MGMT_FT_802_1X;
881189251Ssam	case WPA_KEY_MGMT_FT_PSK:
882189251Ssam		return KEY_MGMT_FT_PSK;
883189251Ssam	case WPA_KEY_MGMT_IEEE8021X_SHA256:
884189251Ssam		return KEY_MGMT_802_1X_SHA256;
885189251Ssam	case WPA_KEY_MGMT_PSK_SHA256:
886189251Ssam		return KEY_MGMT_PSK_SHA256;
887189251Ssam	case WPA_KEY_MGMT_WPS:
888189251Ssam		return KEY_MGMT_WPS;
889189251Ssam	case WPA_KEY_MGMT_PSK:
890189251Ssam	default:
891189251Ssam		return KEY_MGMT_PSK;
892189251Ssam	}
893189251Ssam}
894189251Ssam
895189251Ssam
896189251Ssamstatic int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
897189251Ssam					 struct wpa_ssid *ssid,
898189251Ssam					 struct wpa_ie_data *ie)
899189251Ssam{
900189251Ssam	int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
901189251Ssam	if (ret) {
902189251Ssam		if (ret == -2) {
903189251Ssam			wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
904189251Ssam				"from association info");
905189251Ssam		}
906189251Ssam		return -1;
907189251Ssam	}
908189251Ssam
909252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
910252726Srpaulo		"cipher suites");
911189251Ssam	if (!(ie->group_cipher & ssid->group_cipher)) {
912189251Ssam		wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
913189251Ssam			"cipher 0x%x (mask 0x%x) - reject",
914189251Ssam			ie->group_cipher, ssid->group_cipher);
915189251Ssam		return -1;
916189251Ssam	}
917189251Ssam	if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
918189251Ssam		wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
919189251Ssam			"cipher 0x%x (mask 0x%x) - reject",
920189251Ssam			ie->pairwise_cipher, ssid->pairwise_cipher);
921189251Ssam		return -1;
922189251Ssam	}
923189251Ssam	if (!(ie->key_mgmt & ssid->key_mgmt)) {
924189251Ssam		wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
925189251Ssam			"management 0x%x (mask 0x%x) - reject",
926189251Ssam			ie->key_mgmt, ssid->key_mgmt);
927189251Ssam		return -1;
928189251Ssam	}
929189251Ssam
930189251Ssam#ifdef CONFIG_IEEE80211W
931189251Ssam	if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
932252726Srpaulo	    (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
933252726Srpaulo	     wpa_s->conf->pmf : ssid->ieee80211w) ==
934252726Srpaulo	    MGMT_FRAME_PROTECTION_REQUIRED) {
935189251Ssam		wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
936189251Ssam			"that does not support management frame protection - "
937189251Ssam			"reject");
938189251Ssam		return -1;
939189251Ssam	}
940189251Ssam#endif /* CONFIG_IEEE80211W */
941189251Ssam
942189251Ssam	return 0;
943189251Ssam}
944189251Ssam
945189251Ssam
946189251Ssam/**
947189251Ssam * wpa_supplicant_set_suites - Set authentication and encryption parameters
948189251Ssam * @wpa_s: Pointer to wpa_supplicant data
949189251Ssam * @bss: Scan results for the selected BSS, or %NULL if not available
950189251Ssam * @ssid: Configuration data for the selected network
951189251Ssam * @wpa_ie: Buffer for the WPA/RSN IE
952189251Ssam * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
953189251Ssam * used buffer length in case the functions returns success.
954189251Ssam * Returns: 0 on success or -1 on failure
955189251Ssam *
956189251Ssam * This function is used to configure authentication and encryption parameters
957189251Ssam * based on the network configuration and scan result for the selected BSS (if
958189251Ssam * available).
959189251Ssam */
960189251Ssamint wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
961214734Srpaulo			      struct wpa_bss *bss, struct wpa_ssid *ssid,
962189251Ssam			      u8 *wpa_ie, size_t *wpa_ie_len)
963189251Ssam{
964189251Ssam	struct wpa_ie_data ie;
965189251Ssam	int sel, proto;
966189251Ssam	const u8 *bss_wpa, *bss_rsn;
967189251Ssam
968189251Ssam	if (bss) {
969214734Srpaulo		bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
970214734Srpaulo		bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
971189251Ssam	} else
972189251Ssam		bss_wpa = bss_rsn = NULL;
973189251Ssam
974189251Ssam	if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
975189251Ssam	    wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
976189251Ssam	    (ie.group_cipher & ssid->group_cipher) &&
977189251Ssam	    (ie.pairwise_cipher & ssid->pairwise_cipher) &&
978189251Ssam	    (ie.key_mgmt & ssid->key_mgmt)) {
979252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
980189251Ssam		proto = WPA_PROTO_RSN;
981189251Ssam	} else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
982189251Ssam		   wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
983189251Ssam		   (ie.group_cipher & ssid->group_cipher) &&
984189251Ssam		   (ie.pairwise_cipher & ssid->pairwise_cipher) &&
985189251Ssam		   (ie.key_mgmt & ssid->key_mgmt)) {
986252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
987189251Ssam		proto = WPA_PROTO_WPA;
988189251Ssam	} else if (bss) {
989189251Ssam		wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
990189251Ssam		return -1;
991189251Ssam	} else {
992189251Ssam		if (ssid->proto & WPA_PROTO_RSN)
993189251Ssam			proto = WPA_PROTO_RSN;
994189251Ssam		else
995189251Ssam			proto = WPA_PROTO_WPA;
996189251Ssam		if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
997189251Ssam			os_memset(&ie, 0, sizeof(ie));
998189251Ssam			ie.group_cipher = ssid->group_cipher;
999189251Ssam			ie.pairwise_cipher = ssid->pairwise_cipher;
1000189251Ssam			ie.key_mgmt = ssid->key_mgmt;
1001189251Ssam#ifdef CONFIG_IEEE80211W
1002189251Ssam			ie.mgmt_group_cipher =
1003214734Srpaulo				ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
1004189251Ssam				WPA_CIPHER_AES_128_CMAC : 0;
1005189251Ssam#endif /* CONFIG_IEEE80211W */
1006252726Srpaulo			wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
1007252726Srpaulo				"based on configuration");
1008189251Ssam		} else
1009189251Ssam			proto = ie.proto;
1010189251Ssam	}
1011189251Ssam
1012252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1013252726Srpaulo		"pairwise %d key_mgmt %d proto %d",
1014252726Srpaulo		ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1015189251Ssam#ifdef CONFIG_IEEE80211W
1016189251Ssam	if (ssid->ieee80211w) {
1017252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1018252726Srpaulo			ie.mgmt_group_cipher);
1019189251Ssam	}
1020189251Ssam#endif /* CONFIG_IEEE80211W */
1021189251Ssam
1022252726Srpaulo	wpa_s->wpa_proto = proto;
1023189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1024189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
1025189251Ssam			 !!(ssid->proto & WPA_PROTO_RSN));
1026189251Ssam
1027189251Ssam	if (bss || !wpa_s->ap_ies_from_associnfo) {
1028189251Ssam		if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1029189251Ssam					 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1030189251Ssam		    wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1031189251Ssam					 bss_rsn ? 2 + bss_rsn[1] : 0))
1032189251Ssam			return -1;
1033189251Ssam	}
1034189251Ssam
1035189251Ssam	sel = ie.group_cipher & ssid->group_cipher;
1036189251Ssam	if (sel & WPA_CIPHER_CCMP) {
1037189251Ssam		wpa_s->group_cipher = WPA_CIPHER_CCMP;
1038252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK CCMP");
1039252726Srpaulo	} else if (sel & WPA_CIPHER_GCMP) {
1040252726Srpaulo		wpa_s->group_cipher = WPA_CIPHER_GCMP;
1041252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK GCMP");
1042189251Ssam	} else if (sel & WPA_CIPHER_TKIP) {
1043189251Ssam		wpa_s->group_cipher = WPA_CIPHER_TKIP;
1044252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK TKIP");
1045189251Ssam	} else if (sel & WPA_CIPHER_WEP104) {
1046189251Ssam		wpa_s->group_cipher = WPA_CIPHER_WEP104;
1047252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP104");
1048189251Ssam	} else if (sel & WPA_CIPHER_WEP40) {
1049189251Ssam		wpa_s->group_cipher = WPA_CIPHER_WEP40;
1050252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP40");
1051189251Ssam	} else {
1052252726Srpaulo		wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1053252726Srpaulo			"cipher");
1054189251Ssam		return -1;
1055189251Ssam	}
1056189251Ssam
1057189251Ssam	sel = ie.pairwise_cipher & ssid->pairwise_cipher;
1058189251Ssam	if (sel & WPA_CIPHER_CCMP) {
1059189251Ssam		wpa_s->pairwise_cipher = WPA_CIPHER_CCMP;
1060252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK CCMP");
1061252726Srpaulo	} else if (sel & WPA_CIPHER_GCMP) {
1062252726Srpaulo		wpa_s->pairwise_cipher = WPA_CIPHER_GCMP;
1063252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK GCMP");
1064189251Ssam	} else if (sel & WPA_CIPHER_TKIP) {
1065189251Ssam		wpa_s->pairwise_cipher = WPA_CIPHER_TKIP;
1066252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK TKIP");
1067189251Ssam	} else if (sel & WPA_CIPHER_NONE) {
1068189251Ssam		wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
1069252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK NONE");
1070189251Ssam	} else {
1071252726Srpaulo		wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1072252726Srpaulo			"cipher");
1073189251Ssam		return -1;
1074189251Ssam	}
1075189251Ssam
1076189251Ssam	sel = ie.key_mgmt & ssid->key_mgmt;
1077252726Srpaulo#ifdef CONFIG_SAE
1078252726Srpaulo	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1079252726Srpaulo		sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1080252726Srpaulo#endif /* CONFIG_SAE */
1081189251Ssam	if (0) {
1082189251Ssam#ifdef CONFIG_IEEE80211R
1083189251Ssam	} else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1084189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1085252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1086189251Ssam	} else if (sel & WPA_KEY_MGMT_FT_PSK) {
1087189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1088252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1089189251Ssam#endif /* CONFIG_IEEE80211R */
1090252726Srpaulo#ifdef CONFIG_SAE
1091252726Srpaulo	} else if (sel & WPA_KEY_MGMT_SAE) {
1092252726Srpaulo		wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1093252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1094252726Srpaulo	} else if (sel & WPA_KEY_MGMT_FT_SAE) {
1095252726Srpaulo		wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1096252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1097252726Srpaulo#endif /* CONFIG_SAE */
1098189251Ssam#ifdef CONFIG_IEEE80211W
1099189251Ssam	} else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1100189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1101252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG,
1102189251Ssam			"WPA: using KEY_MGMT 802.1X with SHA256");
1103189251Ssam	} else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1104189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1105252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG,
1106189251Ssam			"WPA: using KEY_MGMT PSK with SHA256");
1107189251Ssam#endif /* CONFIG_IEEE80211W */
1108189251Ssam	} else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1109189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1110252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1111189251Ssam	} else if (sel & WPA_KEY_MGMT_PSK) {
1112189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1113252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1114189251Ssam	} else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1115189251Ssam		wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1116252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
1117189251Ssam	} else {
1118252726Srpaulo		wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1119252726Srpaulo			"authenticated key management type");
1120189251Ssam		return -1;
1121189251Ssam	}
1122189251Ssam
1123189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1124189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1125189251Ssam			 wpa_s->pairwise_cipher);
1126189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1127189251Ssam
1128189251Ssam#ifdef CONFIG_IEEE80211W
1129189251Ssam	sel = ie.mgmt_group_cipher;
1130252726Srpaulo	if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1131252726Srpaulo	     wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
1132189251Ssam	    !(ie.capabilities & WPA_CAPABILITY_MFPC))
1133189251Ssam		sel = 0;
1134189251Ssam	if (sel & WPA_CIPHER_AES_128_CMAC) {
1135189251Ssam		wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1136252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1137189251Ssam			"AES-128-CMAC");
1138189251Ssam	} else {
1139189251Ssam		wpa_s->mgmt_group_cipher = 0;
1140252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1141189251Ssam	}
1142189251Ssam	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1143189251Ssam			 wpa_s->mgmt_group_cipher);
1144252726Srpaulo	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1145252726Srpaulo			 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1146252726Srpaulo			  wpa_s->conf->pmf : ssid->ieee80211w));
1147189251Ssam#endif /* CONFIG_IEEE80211W */
1148189251Ssam
1149189251Ssam	if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1150252726Srpaulo		wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1151189251Ssam		return -1;
1152189251Ssam	}
1153189251Ssam
1154252726Srpaulo	if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
1155189251Ssam		wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
1156252726Srpaulo#ifndef CONFIG_NO_PBKDF2
1157252726Srpaulo		if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1158252726Srpaulo		    ssid->passphrase) {
1159252726Srpaulo			u8 psk[PMK_LEN];
1160252726Srpaulo		        pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1161252726Srpaulo				    4096, psk, PMK_LEN);
1162252726Srpaulo		        wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1163252726Srpaulo					psk, PMK_LEN);
1164252726Srpaulo			wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1165252726Srpaulo		}
1166252726Srpaulo#endif /* CONFIG_NO_PBKDF2 */
1167252726Srpaulo#ifdef CONFIG_EXT_PASSWORD
1168252726Srpaulo		if (ssid->ext_psk) {
1169252726Srpaulo			struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1170252726Srpaulo							     ssid->ext_psk);
1171252726Srpaulo			char pw_str[64 + 1];
1172252726Srpaulo			u8 psk[PMK_LEN];
1173252726Srpaulo
1174252726Srpaulo			if (pw == NULL) {
1175252726Srpaulo				wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1176252726Srpaulo					"found from external storage");
1177252726Srpaulo				return -1;
1178252726Srpaulo			}
1179252726Srpaulo
1180252726Srpaulo			if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1181252726Srpaulo				wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1182252726Srpaulo					"PSK length %d in external storage",
1183252726Srpaulo					(int) wpabuf_len(pw));
1184252726Srpaulo				ext_password_free(pw);
1185252726Srpaulo				return -1;
1186252726Srpaulo			}
1187252726Srpaulo
1188252726Srpaulo			os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1189252726Srpaulo			pw_str[wpabuf_len(pw)] = '\0';
1190252726Srpaulo
1191252726Srpaulo#ifndef CONFIG_NO_PBKDF2
1192252726Srpaulo			if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1193252726Srpaulo			{
1194252726Srpaulo				pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1195252726Srpaulo					    4096, psk, PMK_LEN);
1196252726Srpaulo				os_memset(pw_str, 0, sizeof(pw_str));
1197252726Srpaulo				wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1198252726Srpaulo						"external passphrase)",
1199252726Srpaulo						psk, PMK_LEN);
1200252726Srpaulo				wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1201252726Srpaulo			} else
1202252726Srpaulo#endif /* CONFIG_NO_PBKDF2 */
1203252726Srpaulo			if (wpabuf_len(pw) == 2 * PMK_LEN) {
1204252726Srpaulo				if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1205252726Srpaulo					wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1206252726Srpaulo						"Invalid PSK hex string");
1207252726Srpaulo					os_memset(pw_str, 0, sizeof(pw_str));
1208252726Srpaulo					ext_password_free(pw);
1209252726Srpaulo					return -1;
1210252726Srpaulo				}
1211252726Srpaulo				wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1212252726Srpaulo			} else {
1213252726Srpaulo				wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1214252726Srpaulo					"PSK available");
1215252726Srpaulo				os_memset(pw_str, 0, sizeof(pw_str));
1216252726Srpaulo				ext_password_free(pw);
1217252726Srpaulo				return -1;
1218252726Srpaulo			}
1219252726Srpaulo
1220252726Srpaulo			os_memset(pw_str, 0, sizeof(pw_str));
1221252726Srpaulo			ext_password_free(pw);
1222252726Srpaulo		}
1223252726Srpaulo#endif /* CONFIG_EXT_PASSWORD */
1224252726Srpaulo	} else
1225189251Ssam		wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1226189251Ssam
1227189251Ssam	return 0;
1228189251Ssam}
1229189251Ssam
1230189251Ssam
1231252726Srpauloint wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
1232252726Srpaulo{
1233252726Srpaulo	u32 ext_capab = 0;
1234252726Srpaulo	u8 *pos = buf;
1235252726Srpaulo
1236252726Srpaulo#ifdef CONFIG_INTERWORKING
1237252726Srpaulo	if (wpa_s->conf->interworking)
1238252726Srpaulo		ext_capab |= BIT(31); /* Interworking */
1239252726Srpaulo#endif /* CONFIG_INTERWORKING */
1240252726Srpaulo
1241252726Srpaulo#ifdef CONFIG_WNM
1242252726Srpaulo	ext_capab |= BIT(17); /* WNM-Sleep Mode */
1243252726Srpaulo	ext_capab |= BIT(19); /* BSS Transition */
1244252726Srpaulo#endif /* CONFIG_WNM */
1245252726Srpaulo
1246252726Srpaulo	if (!ext_capab)
1247252726Srpaulo		return 0;
1248252726Srpaulo
1249252726Srpaulo	*pos++ = WLAN_EID_EXT_CAPAB;
1250252726Srpaulo	*pos++ = 4;
1251252726Srpaulo	WPA_PUT_LE32(pos, ext_capab);
1252252726Srpaulo	pos += 4;
1253252726Srpaulo
1254252726Srpaulo	return pos - buf;
1255252726Srpaulo}
1256252726Srpaulo
1257252726Srpaulo
1258189251Ssam/**
1259189251Ssam * wpa_supplicant_associate - Request association
1260189251Ssam * @wpa_s: Pointer to wpa_supplicant data
1261189251Ssam * @bss: Scan results for the selected BSS, or %NULL if not available
1262189251Ssam * @ssid: Configuration data for the selected network
1263189251Ssam *
1264189251Ssam * This function is used to request %wpa_supplicant to associate with a BSS.
1265189251Ssam */
1266189251Ssamvoid wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1267214734Srpaulo			      struct wpa_bss *bss, struct wpa_ssid *ssid)
1268189251Ssam{
1269252726Srpaulo	u8 wpa_ie[200];
1270189251Ssam	size_t wpa_ie_len;
1271214734Srpaulo	int use_crypt, ret, i, bssid_changed;
1272214734Srpaulo	int algs = WPA_AUTH_ALG_OPEN;
1273214734Srpaulo	enum wpa_cipher cipher_pairwise, cipher_group;
1274189251Ssam	struct wpa_driver_associate_params params;
1275189251Ssam	int wep_keys_set = 0;
1276189251Ssam	struct wpa_driver_capa capa;
1277189251Ssam	int assoc_failed = 0;
1278214734Srpaulo	struct wpa_ssid *old_ssid;
1279252726Srpaulo	u8 ext_capab[10];
1280252726Srpaulo	int ext_capab_len;
1281252726Srpaulo#ifdef CONFIG_HT_OVERRIDES
1282252726Srpaulo	struct ieee80211_ht_capabilities htcaps;
1283252726Srpaulo	struct ieee80211_ht_capabilities htcaps_mask;
1284252726Srpaulo#endif /* CONFIG_HT_OVERRIDES */
1285189251Ssam
1286252726Srpaulo#ifdef CONFIG_IBSS_RSN
1287252726Srpaulo	ibss_rsn_deinit(wpa_s->ibss_rsn);
1288252726Srpaulo	wpa_s->ibss_rsn = NULL;
1289252726Srpaulo#endif /* CONFIG_IBSS_RSN */
1290252726Srpaulo
1291252726Srpaulo	if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1292252726Srpaulo	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1293214734Srpaulo#ifdef CONFIG_AP
1294214734Srpaulo		if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1295252726Srpaulo			wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1296252726Srpaulo				"mode");
1297214734Srpaulo			return;
1298214734Srpaulo		}
1299252726Srpaulo		if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1300252726Srpaulo			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1301252726Srpaulo			return;
1302252726Srpaulo		}
1303214734Srpaulo		wpa_s->current_bss = bss;
1304214734Srpaulo#else /* CONFIG_AP */
1305252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1306252726Srpaulo			"the build");
1307214734Srpaulo#endif /* CONFIG_AP */
1308214734Srpaulo		return;
1309214734Srpaulo	}
1310214734Srpaulo
1311252726Srpaulo#ifdef CONFIG_TDLS
1312252726Srpaulo	if (bss)
1313252726Srpaulo		wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1314252726Srpaulo				bss->ie_len);
1315252726Srpaulo#endif /* CONFIG_TDLS */
1316252726Srpaulo
1317214734Srpaulo	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1318214734Srpaulo	    ssid->mode == IEEE80211_MODE_INFRA) {
1319214734Srpaulo		sme_authenticate(wpa_s, bss, ssid);
1320214734Srpaulo		return;
1321214734Srpaulo	}
1322214734Srpaulo
1323252726Srpaulo	os_memset(&params, 0, sizeof(params));
1324189251Ssam	wpa_s->reassociate = 0;
1325252726Srpaulo	if (bss && !wpas_driver_bss_selection(wpa_s)) {
1326189251Ssam#ifdef CONFIG_IEEE80211R
1327214734Srpaulo		const u8 *ie, *md = NULL;
1328189251Ssam#endif /* CONFIG_IEEE80211R */
1329189251Ssam		wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1330189251Ssam			" (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1331214734Srpaulo			wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1332214734Srpaulo		bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1333189251Ssam		os_memset(wpa_s->bssid, 0, ETH_ALEN);
1334189251Ssam		os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1335214734Srpaulo		if (bssid_changed)
1336214734Srpaulo			wpas_notify_bssid_changed(wpa_s);
1337189251Ssam#ifdef CONFIG_IEEE80211R
1338214734Srpaulo		ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1339189251Ssam		if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1340189251Ssam			md = ie + 2;
1341214734Srpaulo		wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1342189251Ssam		if (md) {
1343189251Ssam			/* Prepare for the next transition */
1344214734Srpaulo			wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1345189251Ssam		}
1346189251Ssam#endif /* CONFIG_IEEE80211R */
1347189251Ssam#ifdef CONFIG_WPS
1348189251Ssam	} else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1349189251Ssam		   wpa_s->conf->ap_scan == 2 &&
1350189251Ssam		   (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1351189251Ssam		/* Use ap_scan==1 style network selection to find the network
1352189251Ssam		 */
1353252726Srpaulo		wpa_s->scan_req = MANUAL_SCAN_REQ;
1354189251Ssam		wpa_s->reassociate = 1;
1355189251Ssam		wpa_supplicant_req_scan(wpa_s, 0, 0);
1356189251Ssam		return;
1357189251Ssam#endif /* CONFIG_WPS */
1358189251Ssam	} else {
1359189251Ssam		wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1360189251Ssam			wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1361189251Ssam		os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1362189251Ssam	}
1363252726Srpaulo	wpa_supplicant_cancel_sched_scan(wpa_s);
1364189251Ssam	wpa_supplicant_cancel_scan(wpa_s);
1365189251Ssam
1366189251Ssam	/* Starting new association, so clear the possibly used WPA IE from the
1367189251Ssam	 * previous association. */
1368189251Ssam	wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1369189251Ssam
1370189251Ssam#ifdef IEEE8021X_EAPOL
1371189251Ssam	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1372189251Ssam		if (ssid->leap) {
1373189251Ssam			if (ssid->non_leap == 0)
1374214734Srpaulo				algs = WPA_AUTH_ALG_LEAP;
1375189251Ssam			else
1376214734Srpaulo				algs |= WPA_AUTH_ALG_LEAP;
1377189251Ssam		}
1378189251Ssam	}
1379189251Ssam#endif /* IEEE8021X_EAPOL */
1380252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1381189251Ssam	if (ssid->auth_alg) {
1382214734Srpaulo		algs = ssid->auth_alg;
1383252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1384252726Srpaulo			"0x%x", algs);
1385189251Ssam	}
1386189251Ssam
1387214734Srpaulo	if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1388214734Srpaulo		    wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
1389252726Srpaulo	    wpa_key_mgmt_wpa(ssid->key_mgmt)) {
1390189251Ssam		int try_opportunistic;
1391252726Srpaulo		try_opportunistic = (ssid->proactive_key_caching < 0 ?
1392252726Srpaulo				     wpa_s->conf->okc :
1393252726Srpaulo				     ssid->proactive_key_caching) &&
1394189251Ssam			(ssid->proto & WPA_PROTO_RSN);
1395189251Ssam		if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
1396189251Ssam					    wpa_s->current_ssid,
1397189251Ssam					    try_opportunistic) == 0)
1398189251Ssam			eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1399189251Ssam		wpa_ie_len = sizeof(wpa_ie);
1400189251Ssam		if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1401189251Ssam					      wpa_ie, &wpa_ie_len)) {
1402252726Srpaulo			wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1403252726Srpaulo				"key management and encryption suites");
1404189251Ssam			return;
1405189251Ssam		}
1406252726Srpaulo	} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1407252726Srpaulo		   wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1408252726Srpaulo		/*
1409252726Srpaulo		 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1410252726Srpaulo		 * use non-WPA since the scan results did not indicate that the
1411252726Srpaulo		 * AP is using WPA or WPA2.
1412252726Srpaulo		 */
1413252726Srpaulo		wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1414252726Srpaulo		wpa_ie_len = 0;
1415252726Srpaulo		wpa_s->wpa_proto = 0;
1416252726Srpaulo	} else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
1417189251Ssam		wpa_ie_len = sizeof(wpa_ie);
1418189251Ssam		if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1419189251Ssam					      wpa_ie, &wpa_ie_len)) {
1420252726Srpaulo			wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1421252726Srpaulo				"key management and encryption suites (no "
1422252726Srpaulo				"scan results)");
1423189251Ssam			return;
1424189251Ssam		}
1425189251Ssam#ifdef CONFIG_WPS
1426189251Ssam	} else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1427189251Ssam		struct wpabuf *wps_ie;
1428189251Ssam		wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1429189251Ssam		if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1430189251Ssam			wpa_ie_len = wpabuf_len(wps_ie);
1431189251Ssam			os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1432189251Ssam		} else
1433189251Ssam			wpa_ie_len = 0;
1434189251Ssam		wpabuf_free(wps_ie);
1435189251Ssam		wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1436252726Srpaulo		if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1437252726Srpaulo			params.wps = WPS_MODE_PRIVACY;
1438252726Srpaulo		else
1439252726Srpaulo			params.wps = WPS_MODE_OPEN;
1440252726Srpaulo		wpa_s->wpa_proto = 0;
1441189251Ssam#endif /* CONFIG_WPS */
1442189251Ssam	} else {
1443189251Ssam		wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1444189251Ssam		wpa_ie_len = 0;
1445252726Srpaulo		wpa_s->wpa_proto = 0;
1446189251Ssam	}
1447189251Ssam
1448252726Srpaulo#ifdef CONFIG_P2P
1449252726Srpaulo	if (wpa_s->global->p2p) {
1450252726Srpaulo		u8 *pos;
1451252726Srpaulo		size_t len;
1452252726Srpaulo		int res;
1453252726Srpaulo		pos = wpa_ie + wpa_ie_len;
1454252726Srpaulo		len = sizeof(wpa_ie) - wpa_ie_len;
1455252726Srpaulo		res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1456252726Srpaulo					    ssid->p2p_group);
1457252726Srpaulo		if (res >= 0)
1458252726Srpaulo			wpa_ie_len += res;
1459252726Srpaulo	}
1460252726Srpaulo
1461252726Srpaulo	wpa_s->cross_connect_disallowed = 0;
1462252726Srpaulo	if (bss) {
1463252726Srpaulo		struct wpabuf *p2p;
1464252726Srpaulo		p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1465252726Srpaulo		if (p2p) {
1466252726Srpaulo			wpa_s->cross_connect_disallowed =
1467252726Srpaulo				p2p_get_cross_connect_disallowed(p2p);
1468252726Srpaulo			wpabuf_free(p2p);
1469252726Srpaulo			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1470252726Srpaulo				"connection",
1471252726Srpaulo				wpa_s->cross_connect_disallowed ?
1472252726Srpaulo				"disallows" : "allows");
1473252726Srpaulo		}
1474252726Srpaulo	}
1475252726Srpaulo#endif /* CONFIG_P2P */
1476252726Srpaulo
1477252726Srpaulo#ifdef CONFIG_HS20
1478252726Srpaulo	if (wpa_s->conf->hs20) {
1479252726Srpaulo		struct wpabuf *hs20;
1480252726Srpaulo		hs20 = wpabuf_alloc(20);
1481252726Srpaulo		if (hs20) {
1482252726Srpaulo			wpas_hs20_add_indication(hs20);
1483252726Srpaulo			os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1484252726Srpaulo				  wpabuf_len(hs20));
1485252726Srpaulo			wpa_ie_len += wpabuf_len(hs20);
1486252726Srpaulo			wpabuf_free(hs20);
1487252726Srpaulo		}
1488252726Srpaulo	}
1489252726Srpaulo#endif /* CONFIG_HS20 */
1490252726Srpaulo
1491252726Srpaulo	ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1492252726Srpaulo	if (ext_capab_len > 0) {
1493252726Srpaulo		u8 *pos = wpa_ie;
1494252726Srpaulo		if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1495252726Srpaulo			pos += 2 + pos[1];
1496252726Srpaulo		os_memmove(pos + ext_capab_len, pos,
1497252726Srpaulo			   wpa_ie_len - (pos - wpa_ie));
1498252726Srpaulo		wpa_ie_len += ext_capab_len;
1499252726Srpaulo		os_memcpy(pos, ext_capab, ext_capab_len);
1500252726Srpaulo	}
1501252726Srpaulo
1502189251Ssam	wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1503189251Ssam	use_crypt = 1;
1504189251Ssam	cipher_pairwise = cipher_suite2driver(wpa_s->pairwise_cipher);
1505189251Ssam	cipher_group = cipher_suite2driver(wpa_s->group_cipher);
1506189251Ssam	if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1507189251Ssam	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1508189251Ssam		if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1509189251Ssam			use_crypt = 0;
1510189251Ssam		if (wpa_set_wep_keys(wpa_s, ssid)) {
1511189251Ssam			use_crypt = 1;
1512189251Ssam			wep_keys_set = 1;
1513189251Ssam		}
1514189251Ssam	}
1515189251Ssam	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1516189251Ssam		use_crypt = 0;
1517189251Ssam
1518189251Ssam#ifdef IEEE8021X_EAPOL
1519189251Ssam	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1520189251Ssam		if ((ssid->eapol_flags &
1521189251Ssam		     (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1522189251Ssam		      EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1523189251Ssam		    !wep_keys_set) {
1524189251Ssam			use_crypt = 0;
1525189251Ssam		} else {
1526189251Ssam			/* Assume that dynamic WEP-104 keys will be used and
1527189251Ssam			 * set cipher suites in order for drivers to expect
1528189251Ssam			 * encryption. */
1529189251Ssam			cipher_pairwise = cipher_group = CIPHER_WEP104;
1530189251Ssam		}
1531189251Ssam	}
1532189251Ssam#endif /* IEEE8021X_EAPOL */
1533189251Ssam
1534189251Ssam	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1535189251Ssam		/* Set the key before (and later after) association */
1536189251Ssam		wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1537189251Ssam	}
1538189251Ssam
1539189251Ssam	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1540189251Ssam	if (bss) {
1541214734Srpaulo		params.ssid = bss->ssid;
1542214734Srpaulo		params.ssid_len = bss->ssid_len;
1543252726Srpaulo		if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1544252726Srpaulo			wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1545252726Srpaulo				   MACSTR " freq=%u MHz based on scan results "
1546252726Srpaulo				   "(bssid_set=%d)",
1547252726Srpaulo				   MAC2STR(bss->bssid), bss->freq,
1548252726Srpaulo				   ssid->bssid_set);
1549252726Srpaulo			params.bssid = bss->bssid;
1550252726Srpaulo			params.freq = bss->freq;
1551252726Srpaulo		}
1552189251Ssam	} else {
1553189251Ssam		params.ssid = ssid->ssid;
1554189251Ssam		params.ssid_len = ssid->ssid_len;
1555189251Ssam	}
1556252726Srpaulo
1557252726Srpaulo	if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1558252726Srpaulo	    wpa_s->conf->ap_scan == 2) {
1559252726Srpaulo		params.bssid = ssid->bssid;
1560252726Srpaulo		params.fixed_bssid = 1;
1561252726Srpaulo	}
1562252726Srpaulo
1563214734Srpaulo	if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1564214734Srpaulo	    params.freq == 0)
1565189251Ssam		params.freq = ssid->frequency; /* Initial channel for IBSS */
1566189251Ssam	params.wpa_ie = wpa_ie;
1567189251Ssam	params.wpa_ie_len = wpa_ie_len;
1568189251Ssam	params.pairwise_suite = cipher_pairwise;
1569189251Ssam	params.group_suite = cipher_group;
1570189251Ssam	params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
1571252726Srpaulo	params.wpa_proto = wpa_s->wpa_proto;
1572189251Ssam	params.auth_alg = algs;
1573189251Ssam	params.mode = ssid->mode;
1574252726Srpaulo	params.bg_scan_period = ssid->bg_scan_period;
1575189251Ssam	for (i = 0; i < NUM_WEP_KEYS; i++) {
1576189251Ssam		if (ssid->wep_key_len[i])
1577189251Ssam			params.wep_key[i] = ssid->wep_key[i];
1578189251Ssam		params.wep_key_len[i] = ssid->wep_key_len[i];
1579189251Ssam	}
1580189251Ssam	params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1581189251Ssam
1582214734Srpaulo	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
1583189251Ssam	    (params.key_mgmt_suite == KEY_MGMT_PSK ||
1584189251Ssam	     params.key_mgmt_suite == KEY_MGMT_FT_PSK)) {
1585189251Ssam		params.passphrase = ssid->passphrase;
1586189251Ssam		if (ssid->psk_set)
1587189251Ssam			params.psk = ssid->psk;
1588189251Ssam	}
1589189251Ssam
1590214734Srpaulo	params.drop_unencrypted = use_crypt;
1591214734Srpaulo
1592189251Ssam#ifdef CONFIG_IEEE80211W
1593252726Srpaulo	params.mgmt_frame_protection =
1594252726Srpaulo		ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1595252726Srpaulo		wpa_s->conf->pmf : ssid->ieee80211w;
1596252726Srpaulo	if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
1597214734Srpaulo		const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1598189251Ssam		struct wpa_ie_data ie;
1599189251Ssam		if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1600189251Ssam		    ie.capabilities &
1601189251Ssam		    (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1602252726Srpaulo			wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1603252726Srpaulo				"MFP: require MFP");
1604189251Ssam			params.mgmt_frame_protection =
1605189251Ssam				MGMT_FRAME_PROTECTION_REQUIRED;
1606189251Ssam		}
1607189251Ssam	}
1608189251Ssam#endif /* CONFIG_IEEE80211W */
1609189251Ssam
1610252726Srpaulo	params.p2p = ssid->p2p_group;
1611252726Srpaulo
1612252726Srpaulo	if (wpa_s->parent->set_sta_uapsd)
1613252726Srpaulo		params.uapsd = wpa_s->parent->sta_uapsd;
1614189251Ssam	else
1615252726Srpaulo		params.uapsd = -1;
1616252726Srpaulo
1617252726Srpaulo#ifdef CONFIG_HT_OVERRIDES
1618252726Srpaulo	os_memset(&htcaps, 0, sizeof(htcaps));
1619252726Srpaulo	os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1620252726Srpaulo	params.htcaps = (u8 *) &htcaps;
1621252726Srpaulo	params.htcaps_mask = (u8 *) &htcaps_mask;
1622252726Srpaulo	wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1623252726Srpaulo#endif /* CONFIG_HT_OVERRIDES */
1624252726Srpaulo
1625252726Srpaulo	ret = wpa_drv_associate(wpa_s, &params);
1626189251Ssam	if (ret < 0) {
1627189251Ssam		wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1628189251Ssam			"failed");
1629252726Srpaulo		if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1630252726Srpaulo			/*
1631252726Srpaulo			 * The driver is known to mean what is saying, so we
1632252726Srpaulo			 * can stop right here; the association will not
1633252726Srpaulo			 * succeed.
1634252726Srpaulo			 */
1635252726Srpaulo			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1636252726Srpaulo			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1637252726Srpaulo			os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1638252726Srpaulo			return;
1639252726Srpaulo		}
1640189251Ssam		/* try to continue anyway; new association will be tried again
1641189251Ssam		 * after timeout */
1642189251Ssam		assoc_failed = 1;
1643189251Ssam	}
1644189251Ssam
1645189251Ssam	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1646189251Ssam		/* Set the key after the association just in case association
1647189251Ssam		 * cleared the previously configured key. */
1648189251Ssam		wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1649189251Ssam		/* No need to timeout authentication since there is no key
1650189251Ssam		 * management. */
1651189251Ssam		wpa_supplicant_cancel_auth_timeout(wpa_s);
1652189251Ssam		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1653214734Srpaulo#ifdef CONFIG_IBSS_RSN
1654214734Srpaulo	} else if (ssid->mode == WPAS_MODE_IBSS &&
1655214734Srpaulo		   wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1656214734Srpaulo		   wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1657214734Srpaulo		/*
1658214734Srpaulo		 * RSN IBSS authentication is per-STA and we can disable the
1659214734Srpaulo		 * per-BSSID authentication.
1660214734Srpaulo		 */
1661214734Srpaulo		wpa_supplicant_cancel_auth_timeout(wpa_s);
1662214734Srpaulo#endif /* CONFIG_IBSS_RSN */
1663189251Ssam	} else {
1664189251Ssam		/* Timeout for IEEE 802.11 authentication and association */
1665189251Ssam		int timeout = 60;
1666189251Ssam
1667189251Ssam		if (assoc_failed) {
1668189251Ssam			/* give IBSS a bit more time */
1669214734Srpaulo			timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1670189251Ssam		} else if (wpa_s->conf->ap_scan == 1) {
1671189251Ssam			/* give IBSS a bit more time */
1672214734Srpaulo			timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1673189251Ssam		}
1674189251Ssam		wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1675189251Ssam	}
1676189251Ssam
1677189251Ssam	if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
1678189251Ssam	    capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC) {
1679189251Ssam		/* Set static WEP keys again */
1680189251Ssam		wpa_set_wep_keys(wpa_s, ssid);
1681189251Ssam	}
1682189251Ssam
1683189251Ssam	if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1684189251Ssam		/*
1685189251Ssam		 * Do not allow EAP session resumption between different
1686189251Ssam		 * network configurations.
1687189251Ssam		 */
1688189251Ssam		eapol_sm_invalidate_cached_session(wpa_s->eapol);
1689189251Ssam	}
1690214734Srpaulo	old_ssid = wpa_s->current_ssid;
1691189251Ssam	wpa_s->current_ssid = ssid;
1692214734Srpaulo	wpa_s->current_bss = bss;
1693189251Ssam	wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1694189251Ssam	wpa_supplicant_initiate_eapol(wpa_s);
1695214734Srpaulo	if (old_ssid != wpa_s->current_ssid)
1696214734Srpaulo		wpas_notify_network_changed(wpa_s);
1697189251Ssam}
1698189251Ssam
1699189251Ssam
1700252726Srpaulostatic void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1701252726Srpaulo					    const u8 *addr)
1702189251Ssam{
1703214734Srpaulo	struct wpa_ssid *old_ssid;
1704214734Srpaulo
1705189251Ssam	wpa_clear_keys(wpa_s, addr);
1706252726Srpaulo	old_ssid = wpa_s->current_ssid;
1707189251Ssam	wpa_supplicant_mark_disassoc(wpa_s);
1708189251Ssam	wpa_sm_set_config(wpa_s->wpa, NULL);
1709189251Ssam	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1710214734Srpaulo	if (old_ssid != wpa_s->current_ssid)
1711214734Srpaulo		wpas_notify_network_changed(wpa_s);
1712214734Srpaulo	eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1713189251Ssam}
1714189251Ssam
1715189251Ssam
1716189251Ssam/**
1717189251Ssam * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1718189251Ssam * @wpa_s: Pointer to wpa_supplicant data
1719189251Ssam * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1720189251Ssam *
1721189251Ssam * This function is used to request %wpa_supplicant to deauthenticate from the
1722189251Ssam * current AP.
1723189251Ssam */
1724189251Ssamvoid wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1725189251Ssam				   int reason_code)
1726189251Ssam{
1727189251Ssam	u8 *addr = NULL;
1728252726Srpaulo	union wpa_event_data event;
1729252726Srpaulo	int zero_addr = 0;
1730214734Srpaulo
1731252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1732252726Srpaulo		" pending_bssid=" MACSTR " reason=%d state=%s",
1733252726Srpaulo		MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1734252726Srpaulo		reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1735252726Srpaulo
1736252726Srpaulo	if (!is_zero_ether_addr(wpa_s->bssid))
1737189251Ssam		addr = wpa_s->bssid;
1738252726Srpaulo	else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1739252726Srpaulo		 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1740252726Srpaulo		  wpa_s->wpa_state == WPA_ASSOCIATING))
1741252726Srpaulo		addr = wpa_s->pending_bssid;
1742252726Srpaulo	else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1743252726Srpaulo		/*
1744252726Srpaulo		 * When using driver-based BSS selection, we may not know the
1745252726Srpaulo		 * BSSID with which we are currently trying to associate. We
1746252726Srpaulo		 * need to notify the driver of this disconnection even in such
1747252726Srpaulo		 * a case, so use the all zeros address here.
1748252726Srpaulo		 */
1749252726Srpaulo		addr = wpa_s->bssid;
1750252726Srpaulo		zero_addr = 1;
1751189251Ssam	}
1752252726Srpaulo
1753252726Srpaulo	if (addr) {
1754252726Srpaulo		wpa_drv_deauthenticate(wpa_s, addr, reason_code);
1755252726Srpaulo		os_memset(&event, 0, sizeof(event));
1756252726Srpaulo		event.deauth_info.reason_code = (u16) reason_code;
1757252726Srpaulo		event.deauth_info.locally_generated = 1;
1758252726Srpaulo		wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
1759252726Srpaulo		if (zero_addr)
1760252726Srpaulo			addr = NULL;
1761252726Srpaulo	}
1762252726Srpaulo
1763252726Srpaulo	wpa_supplicant_clear_connection(wpa_s, addr);
1764189251Ssam}
1765189251Ssam
1766189251Ssam
1767214734Srpaulo/**
1768214734Srpaulo * wpa_supplicant_enable_network - Mark a configured network as enabled
1769214734Srpaulo * @wpa_s: wpa_supplicant structure for a network interface
1770214734Srpaulo * @ssid: wpa_ssid structure for a configured network or %NULL
1771214734Srpaulo *
1772214734Srpaulo * Enables the specified network or all networks if no network specified.
1773214734Srpaulo */
1774214734Srpaulovoid wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1775214734Srpaulo				   struct wpa_ssid *ssid)
1776189251Ssam{
1777214734Srpaulo	struct wpa_ssid *other_ssid;
1778214734Srpaulo	int was_disabled;
1779189251Ssam
1780214734Srpaulo	if (ssid == NULL) {
1781252726Srpaulo		for (other_ssid = wpa_s->conf->ssid; other_ssid;
1782252726Srpaulo		     other_ssid = other_ssid->next) {
1783252726Srpaulo			if (other_ssid->disabled == 2)
1784252726Srpaulo				continue; /* do not change persistent P2P group
1785252726Srpaulo					   * data */
1786214734Srpaulo			if (other_ssid == wpa_s->current_ssid &&
1787214734Srpaulo			    other_ssid->disabled)
1788214734Srpaulo				wpa_s->reassociate = 1;
1789189251Ssam
1790214734Srpaulo			was_disabled = other_ssid->disabled;
1791189251Ssam
1792214734Srpaulo			other_ssid->disabled = 0;
1793252726Srpaulo			if (was_disabled)
1794252726Srpaulo				wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
1795189251Ssam
1796214734Srpaulo			if (was_disabled != other_ssid->disabled)
1797214734Srpaulo				wpas_notify_network_enabled_changed(
1798214734Srpaulo					wpa_s, other_ssid);
1799214734Srpaulo		}
1800214734Srpaulo		if (wpa_s->reassociate)
1801214734Srpaulo			wpa_supplicant_req_scan(wpa_s, 0, 0);
1802252726Srpaulo	} else if (ssid->disabled && ssid->disabled != 2) {
1803214734Srpaulo		if (wpa_s->current_ssid == NULL) {
1804214734Srpaulo			/*
1805214734Srpaulo			 * Try to reassociate since there is no current
1806214734Srpaulo			 * configuration and a new network was made available.
1807214734Srpaulo			 */
1808214734Srpaulo			wpa_s->reassociate = 1;
1809214734Srpaulo			wpa_supplicant_req_scan(wpa_s, 0, 0);
1810214734Srpaulo		}
1811189251Ssam
1812214734Srpaulo		was_disabled = ssid->disabled;
1813189251Ssam
1814214734Srpaulo		ssid->disabled = 0;
1815252726Srpaulo		wpas_clear_temp_disabled(wpa_s, ssid, 1);
1816189251Ssam
1817214734Srpaulo		if (was_disabled != ssid->disabled)
1818214734Srpaulo			wpas_notify_network_enabled_changed(wpa_s, ssid);
1819214734Srpaulo	}
1820214734Srpaulo}
1821189251Ssam
1822189251Ssam
1823214734Srpaulo/**
1824214734Srpaulo * wpa_supplicant_disable_network - Mark a configured network as disabled
1825214734Srpaulo * @wpa_s: wpa_supplicant structure for a network interface
1826214734Srpaulo * @ssid: wpa_ssid structure for a configured network or %NULL
1827214734Srpaulo *
1828214734Srpaulo * Disables the specified network or all networks if no network specified.
1829214734Srpaulo */
1830214734Srpaulovoid wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1831214734Srpaulo				    struct wpa_ssid *ssid)
1832214734Srpaulo{
1833214734Srpaulo	struct wpa_ssid *other_ssid;
1834214734Srpaulo	int was_disabled;
1835189251Ssam
1836214734Srpaulo	if (ssid == NULL) {
1837252726Srpaulo		for (other_ssid = wpa_s->conf->ssid; other_ssid;
1838252726Srpaulo		     other_ssid = other_ssid->next) {
1839214734Srpaulo			was_disabled = other_ssid->disabled;
1840252726Srpaulo			if (was_disabled == 2)
1841252726Srpaulo				continue; /* do not change persistent P2P group
1842252726Srpaulo					   * data */
1843189251Ssam
1844214734Srpaulo			other_ssid->disabled = 1;
1845189251Ssam
1846214734Srpaulo			if (was_disabled != other_ssid->disabled)
1847214734Srpaulo				wpas_notify_network_enabled_changed(
1848214734Srpaulo					wpa_s, other_ssid);
1849189251Ssam		}
1850214734Srpaulo		if (wpa_s->current_ssid)
1851252726Srpaulo			wpa_supplicant_deauthenticate(
1852214734Srpaulo				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1853252726Srpaulo	} else if (ssid->disabled != 2) {
1854214734Srpaulo		if (ssid == wpa_s->current_ssid)
1855252726Srpaulo			wpa_supplicant_deauthenticate(
1856214734Srpaulo				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1857189251Ssam
1858214734Srpaulo		was_disabled = ssid->disabled;
1859214734Srpaulo
1860214734Srpaulo		ssid->disabled = 1;
1861214734Srpaulo
1862214734Srpaulo		if (was_disabled != ssid->disabled)
1863214734Srpaulo			wpas_notify_network_enabled_changed(wpa_s, ssid);
1864189251Ssam	}
1865214734Srpaulo}
1866189251Ssam
1867189251Ssam
1868214734Srpaulo/**
1869214734Srpaulo * wpa_supplicant_select_network - Attempt association with a network
1870214734Srpaulo * @wpa_s: wpa_supplicant structure for a network interface
1871214734Srpaulo * @ssid: wpa_ssid structure for a configured network or %NULL for any network
1872214734Srpaulo */
1873214734Srpaulovoid wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
1874214734Srpaulo				   struct wpa_ssid *ssid)
1875214734Srpaulo{
1876214734Srpaulo
1877214734Srpaulo	struct wpa_ssid *other_ssid;
1878252726Srpaulo	int disconnected = 0;
1879214734Srpaulo
1880252726Srpaulo	if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
1881252726Srpaulo		wpa_supplicant_deauthenticate(
1882214734Srpaulo			wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1883252726Srpaulo		disconnected = 1;
1884252726Srpaulo	}
1885214734Srpaulo
1886252726Srpaulo	if (ssid)
1887252726Srpaulo		wpas_clear_temp_disabled(wpa_s, ssid, 1);
1888252726Srpaulo
1889214734Srpaulo	/*
1890214734Srpaulo	 * Mark all other networks disabled or mark all networks enabled if no
1891214734Srpaulo	 * network specified.
1892214734Srpaulo	 */
1893252726Srpaulo	for (other_ssid = wpa_s->conf->ssid; other_ssid;
1894252726Srpaulo	     other_ssid = other_ssid->next) {
1895214734Srpaulo		int was_disabled = other_ssid->disabled;
1896252726Srpaulo		if (was_disabled == 2)
1897252726Srpaulo			continue; /* do not change persistent P2P group data */
1898214734Srpaulo
1899214734Srpaulo		other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
1900252726Srpaulo		if (was_disabled && !other_ssid->disabled)
1901252726Srpaulo			wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
1902214734Srpaulo
1903214734Srpaulo		if (was_disabled != other_ssid->disabled)
1904214734Srpaulo			wpas_notify_network_enabled_changed(wpa_s, other_ssid);
1905252726Srpaulo	}
1906214734Srpaulo
1907252726Srpaulo	if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
1908252726Srpaulo		/* We are already associated with the selected network */
1909252726Srpaulo		wpa_printf(MSG_DEBUG, "Already associated with the "
1910252726Srpaulo			   "selected network - do nothing");
1911252726Srpaulo		return;
1912214734Srpaulo	}
1913252726Srpaulo
1914252726Srpaulo	if (ssid)
1915252726Srpaulo		wpa_s->current_ssid = ssid;
1916252726Srpaulo	wpa_s->connect_without_scan = NULL;
1917214734Srpaulo	wpa_s->disconnected = 0;
1918214734Srpaulo	wpa_s->reassociate = 1;
1919252726Srpaulo	wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
1920214734Srpaulo
1921214734Srpaulo	if (ssid)
1922214734Srpaulo		wpas_notify_network_selected(wpa_s, ssid);
1923189251Ssam}
1924189251Ssam
1925189251Ssam
1926189251Ssam/**
1927214734Srpaulo * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
1928214734Srpaulo * @wpa_s: wpa_supplicant structure for a network interface
1929214734Srpaulo * @ap_scan: AP scan mode
1930214734Srpaulo * Returns: 0 if succeed or -1 if ap_scan has an invalid value
1931189251Ssam *
1932189251Ssam */
1933214734Srpauloint wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
1934189251Ssam{
1935189251Ssam
1936214734Srpaulo	int old_ap_scan;
1937189251Ssam
1938214734Srpaulo	if (ap_scan < 0 || ap_scan > 2)
1939214734Srpaulo		return -1;
1940189251Ssam
1941252726Srpaulo#ifdef ANDROID
1942252726Srpaulo	if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
1943252726Srpaulo	    wpa_s->wpa_state >= WPA_ASSOCIATING &&
1944252726Srpaulo	    wpa_s->wpa_state < WPA_COMPLETED) {
1945252726Srpaulo		wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
1946252726Srpaulo			   "associating", wpa_s->conf->ap_scan, ap_scan);
1947252726Srpaulo		return 0;
1948252726Srpaulo	}
1949252726Srpaulo#endif /* ANDROID */
1950252726Srpaulo
1951214734Srpaulo	old_ap_scan = wpa_s->conf->ap_scan;
1952214734Srpaulo	wpa_s->conf->ap_scan = ap_scan;
1953214734Srpaulo
1954214734Srpaulo	if (old_ap_scan != wpa_s->conf->ap_scan)
1955214734Srpaulo		wpas_notify_ap_scan_changed(wpa_s);
1956214734Srpaulo
1957214734Srpaulo	return 0;
1958189251Ssam}
1959189251Ssam
1960189251Ssam
1961189251Ssam/**
1962252726Srpaulo * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
1963252726Srpaulo * @wpa_s: wpa_supplicant structure for a network interface
1964252726Srpaulo * @expire_age: Expiration age in seconds
1965252726Srpaulo * Returns: 0 if succeed or -1 if expire_age has an invalid value
1966252726Srpaulo *
1967252726Srpaulo */
1968252726Srpauloint wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
1969252726Srpaulo					  unsigned int bss_expire_age)
1970252726Srpaulo{
1971252726Srpaulo	if (bss_expire_age < 10) {
1972252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
1973252726Srpaulo			bss_expire_age);
1974252726Srpaulo		return -1;
1975252726Srpaulo	}
1976252726Srpaulo	wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
1977252726Srpaulo		bss_expire_age);
1978252726Srpaulo	wpa_s->conf->bss_expiration_age = bss_expire_age;
1979252726Srpaulo
1980252726Srpaulo	return 0;
1981252726Srpaulo}
1982252726Srpaulo
1983252726Srpaulo
1984252726Srpaulo/**
1985252726Srpaulo * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
1986252726Srpaulo * @wpa_s: wpa_supplicant structure for a network interface
1987252726Srpaulo * @expire_count: number of scans after which an unseen BSS is reclaimed
1988252726Srpaulo * Returns: 0 if succeed or -1 if expire_count has an invalid value
1989252726Srpaulo *
1990252726Srpaulo */
1991252726Srpauloint wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
1992252726Srpaulo					    unsigned int bss_expire_count)
1993252726Srpaulo{
1994252726Srpaulo	if (bss_expire_count < 1) {
1995252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
1996252726Srpaulo			bss_expire_count);
1997252726Srpaulo		return -1;
1998252726Srpaulo	}
1999252726Srpaulo	wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2000252726Srpaulo		bss_expire_count);
2001252726Srpaulo	wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2002252726Srpaulo
2003252726Srpaulo	return 0;
2004252726Srpaulo}
2005252726Srpaulo
2006252726Srpaulo
2007252726Srpaulo/**
2008252726Srpaulo * wpa_supplicant_set_scan_interval - Set scan interval
2009252726Srpaulo * @wpa_s: wpa_supplicant structure for a network interface
2010252726Srpaulo * @scan_interval: scan interval in seconds
2011252726Srpaulo * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2012252726Srpaulo *
2013252726Srpaulo */
2014252726Srpauloint wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2015252726Srpaulo				     int scan_interval)
2016252726Srpaulo{
2017252726Srpaulo	if (scan_interval < 0) {
2018252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2019252726Srpaulo			scan_interval);
2020252726Srpaulo		return -1;
2021252726Srpaulo	}
2022252726Srpaulo	wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2023252726Srpaulo		scan_interval);
2024252726Srpaulo	wpa_s->scan_interval = scan_interval;
2025252726Srpaulo
2026252726Srpaulo	return 0;
2027252726Srpaulo}
2028252726Srpaulo
2029252726Srpaulo
2030252726Srpaulo/**
2031214734Srpaulo * wpa_supplicant_set_debug_params - Set global debug params
2032214734Srpaulo * @global: wpa_global structure
2033214734Srpaulo * @debug_level: debug level
2034214734Srpaulo * @debug_timestamp: determines if show timestamp in debug data
2035214734Srpaulo * @debug_show_keys: determines if show keys in debug data
2036214734Srpaulo * Returns: 0 if succeed or -1 if debug_level has wrong value
2037214734Srpaulo */
2038214734Srpauloint wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2039214734Srpaulo				    int debug_timestamp, int debug_show_keys)
2040214734Srpaulo{
2041214734Srpaulo
2042214734Srpaulo	int old_level, old_timestamp, old_show_keys;
2043214734Srpaulo
2044214734Srpaulo	/* check for allowed debuglevels */
2045252726Srpaulo	if (debug_level != MSG_EXCESSIVE &&
2046252726Srpaulo	    debug_level != MSG_MSGDUMP &&
2047214734Srpaulo	    debug_level != MSG_DEBUG &&
2048214734Srpaulo	    debug_level != MSG_INFO &&
2049214734Srpaulo	    debug_level != MSG_WARNING &&
2050214734Srpaulo	    debug_level != MSG_ERROR)
2051214734Srpaulo		return -1;
2052214734Srpaulo
2053214734Srpaulo	old_level = wpa_debug_level;
2054214734Srpaulo	old_timestamp = wpa_debug_timestamp;
2055214734Srpaulo	old_show_keys = wpa_debug_show_keys;
2056214734Srpaulo
2057214734Srpaulo	wpa_debug_level = debug_level;
2058214734Srpaulo	wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2059214734Srpaulo	wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2060214734Srpaulo
2061214734Srpaulo	if (wpa_debug_level != old_level)
2062214734Srpaulo		wpas_notify_debug_level_changed(global);
2063214734Srpaulo	if (wpa_debug_timestamp != old_timestamp)
2064214734Srpaulo		wpas_notify_debug_timestamp_changed(global);
2065214734Srpaulo	if (wpa_debug_show_keys != old_show_keys)
2066214734Srpaulo		wpas_notify_debug_show_keys_changed(global);
2067214734Srpaulo
2068214734Srpaulo	return 0;
2069214734Srpaulo}
2070214734Srpaulo
2071214734Srpaulo
2072214734Srpaulo/**
2073189251Ssam * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2074189251Ssam * @wpa_s: Pointer to wpa_supplicant data
2075189251Ssam * Returns: A pointer to the current network structure or %NULL on failure
2076189251Ssam */
2077189251Ssamstruct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2078189251Ssam{
2079189251Ssam	struct wpa_ssid *entry;
2080189251Ssam	u8 ssid[MAX_SSID_LEN];
2081189251Ssam	int res;
2082189251Ssam	size_t ssid_len;
2083189251Ssam	u8 bssid[ETH_ALEN];
2084189251Ssam	int wired;
2085189251Ssam
2086252726Srpaulo	res = wpa_drv_get_ssid(wpa_s, ssid);
2087252726Srpaulo	if (res < 0) {
2088252726Srpaulo		wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2089252726Srpaulo			"driver");
2090252726Srpaulo		return NULL;
2091189251Ssam	}
2092252726Srpaulo	ssid_len = res;
2093189251Ssam
2094252726Srpaulo	if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
2095252726Srpaulo		wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2096252726Srpaulo			"driver");
2097189251Ssam		return NULL;
2098189251Ssam	}
2099189251Ssam
2100214734Srpaulo	wired = wpa_s->conf->ap_scan == 0 &&
2101214734Srpaulo		(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2102189251Ssam
2103189251Ssam	entry = wpa_s->conf->ssid;
2104189251Ssam	while (entry) {
2105252726Srpaulo		if (!wpas_network_disabled(wpa_s, entry) &&
2106189251Ssam		    ((ssid_len == entry->ssid_len &&
2107189251Ssam		      os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2108189251Ssam		    (!entry->bssid_set ||
2109189251Ssam		     os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2110189251Ssam			return entry;
2111189251Ssam#ifdef CONFIG_WPS
2112252726Srpaulo		if (!wpas_network_disabled(wpa_s, entry) &&
2113189251Ssam		    (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2114189251Ssam		    (entry->ssid == NULL || entry->ssid_len == 0) &&
2115189251Ssam		    (!entry->bssid_set ||
2116189251Ssam		     os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2117189251Ssam			return entry;
2118189251Ssam#endif /* CONFIG_WPS */
2119252726Srpaulo
2120252726Srpaulo		if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
2121252726Srpaulo		    entry->ssid_len == 0 &&
2122252726Srpaulo		    os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2123252726Srpaulo			return entry;
2124252726Srpaulo
2125189251Ssam		entry = entry->next;
2126189251Ssam	}
2127189251Ssam
2128189251Ssam	return NULL;
2129189251Ssam}
2130189251Ssam
2131189251Ssam
2132252726Srpaulostatic int select_driver(struct wpa_supplicant *wpa_s, int i)
2133252726Srpaulo{
2134252726Srpaulo	struct wpa_global *global = wpa_s->global;
2135252726Srpaulo
2136252726Srpaulo	if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2137252726Srpaulo		global->drv_priv[i] = wpa_drivers[i]->global_init();
2138252726Srpaulo		if (global->drv_priv[i] == NULL) {
2139252726Srpaulo			wpa_printf(MSG_ERROR, "Failed to initialize driver "
2140252726Srpaulo				   "'%s'", wpa_drivers[i]->name);
2141252726Srpaulo			return -1;
2142252726Srpaulo		}
2143252726Srpaulo	}
2144252726Srpaulo
2145252726Srpaulo	wpa_s->driver = wpa_drivers[i];
2146252726Srpaulo	wpa_s->global_drv_priv = global->drv_priv[i];
2147252726Srpaulo
2148252726Srpaulo	return 0;
2149252726Srpaulo}
2150252726Srpaulo
2151252726Srpaulo
2152189251Ssamstatic int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2153189251Ssam				     const char *name)
2154189251Ssam{
2155189251Ssam	int i;
2156214734Srpaulo	size_t len;
2157252726Srpaulo	const char *pos, *driver = name;
2158189251Ssam
2159189251Ssam	if (wpa_s == NULL)
2160189251Ssam		return -1;
2161189251Ssam
2162214734Srpaulo	if (wpa_drivers[0] == NULL) {
2163252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2164252726Srpaulo			"wpa_supplicant");
2165189251Ssam		return -1;
2166189251Ssam	}
2167189251Ssam
2168189251Ssam	if (name == NULL) {
2169189251Ssam		/* default to first driver in the list */
2170252726Srpaulo		return select_driver(wpa_s, 0);
2171189251Ssam	}
2172189251Ssam
2173252726Srpaulo	do {
2174252726Srpaulo		pos = os_strchr(driver, ',');
2175252726Srpaulo		if (pos)
2176252726Srpaulo			len = pos - driver;
2177252726Srpaulo		else
2178252726Srpaulo			len = os_strlen(driver);
2179252726Srpaulo
2180252726Srpaulo		for (i = 0; wpa_drivers[i]; i++) {
2181252726Srpaulo			if (os_strlen(wpa_drivers[i]->name) == len &&
2182252726Srpaulo			    os_strncmp(driver, wpa_drivers[i]->name, len) ==
2183252726Srpaulo			    0) {
2184252726Srpaulo				/* First driver that succeeds wins */
2185252726Srpaulo				if (select_driver(wpa_s, i) == 0)
2186252726Srpaulo					return 0;
2187252726Srpaulo			}
2188189251Ssam		}
2189189251Ssam
2190252726Srpaulo		driver = pos + 1;
2191252726Srpaulo	} while (pos);
2192252726Srpaulo
2193252726Srpaulo	wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2194189251Ssam	return -1;
2195189251Ssam}
2196189251Ssam
2197189251Ssam
2198214734Srpaulo/**
2199214734Srpaulo * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2200214734Srpaulo * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2201214734Srpaulo *	with struct wpa_driver_ops::init()
2202214734Srpaulo * @src_addr: Source address of the EAPOL frame
2203214734Srpaulo * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2204214734Srpaulo * @len: Length of the EAPOL data
2205214734Srpaulo *
2206214734Srpaulo * This function is called for each received EAPOL frame. Most driver
2207214734Srpaulo * interfaces rely on more generic OS mechanism for receiving frames through
2208214734Srpaulo * l2_packet, but if such a mechanism is not available, the driver wrapper may
2209214734Srpaulo * take care of received EAPOL frames and deliver them to the core supplicant
2210214734Srpaulo * code by calling this function.
2211214734Srpaulo */
2212189251Ssamvoid wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2213189251Ssam			     const u8 *buf, size_t len)
2214189251Ssam{
2215189251Ssam	struct wpa_supplicant *wpa_s = ctx;
2216189251Ssam
2217252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2218189251Ssam	wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2219189251Ssam
2220252726Srpaulo	if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2221252726Srpaulo	    (wpa_s->last_eapol_matches_bssid &&
2222252726Srpaulo#ifdef CONFIG_AP
2223252726Srpaulo	     !wpa_s->ap_iface &&
2224252726Srpaulo#endif /* CONFIG_AP */
2225252726Srpaulo	     os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
2226209158Srpaulo		/*
2227209158Srpaulo		 * There is possible race condition between receiving the
2228209158Srpaulo		 * association event and the EAPOL frame since they are coming
2229209158Srpaulo		 * through different paths from the driver. In order to avoid
2230209158Srpaulo		 * issues in trying to process the EAPOL frame before receiving
2231209158Srpaulo		 * association information, lets queue it for processing until
2232252726Srpaulo		 * the association event is received. This may also be needed in
2233252726Srpaulo		 * driver-based roaming case, so also use src_addr != BSSID as a
2234252726Srpaulo		 * trigger if we have previously confirmed that the
2235252726Srpaulo		 * Authenticator uses BSSID as the src_addr (which is not the
2236252726Srpaulo		 * case with wired IEEE 802.1X).
2237209158Srpaulo		 */
2238252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
2239252726Srpaulo			"of received EAPOL frame (state=%s bssid=" MACSTR ")",
2240252726Srpaulo			wpa_supplicant_state_txt(wpa_s->wpa_state),
2241252726Srpaulo			MAC2STR(wpa_s->bssid));
2242209158Srpaulo		wpabuf_free(wpa_s->pending_eapol_rx);
2243209158Srpaulo		wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2244209158Srpaulo		if (wpa_s->pending_eapol_rx) {
2245209158Srpaulo			os_get_time(&wpa_s->pending_eapol_rx_time);
2246209158Srpaulo			os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2247209158Srpaulo				  ETH_ALEN);
2248209158Srpaulo		}
2249209158Srpaulo		return;
2250209158Srpaulo	}
2251209158Srpaulo
2252252726Srpaulo	wpa_s->last_eapol_matches_bssid =
2253252726Srpaulo		os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2254252726Srpaulo
2255214734Srpaulo#ifdef CONFIG_AP
2256214734Srpaulo	if (wpa_s->ap_iface) {
2257214734Srpaulo		wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2258214734Srpaulo		return;
2259214734Srpaulo	}
2260214734Srpaulo#endif /* CONFIG_AP */
2261214734Srpaulo
2262189251Ssam	if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2263252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2264252726Srpaulo			"no key management is configured");
2265189251Ssam		return;
2266189251Ssam	}
2267189251Ssam
2268189251Ssam	if (wpa_s->eapol_received == 0 &&
2269214734Srpaulo	    (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2270189251Ssam	     !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2271214734Srpaulo	     wpa_s->wpa_state != WPA_COMPLETED) &&
2272214734Srpaulo	    (wpa_s->current_ssid == NULL ||
2273214734Srpaulo	     wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2274189251Ssam		/* Timeout for completing IEEE 802.1X and WPA authentication */
2275189251Ssam		wpa_supplicant_req_auth_timeout(
2276189251Ssam			wpa_s,
2277189251Ssam			(wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2278189251Ssam			 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2279189251Ssam			 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2280189251Ssam			70 : 10, 0);
2281189251Ssam	}
2282189251Ssam	wpa_s->eapol_received++;
2283189251Ssam
2284189251Ssam	if (wpa_s->countermeasures) {
2285252726Srpaulo		wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2286252726Srpaulo			"EAPOL packet");
2287189251Ssam		return;
2288189251Ssam	}
2289189251Ssam
2290214734Srpaulo#ifdef CONFIG_IBSS_RSN
2291214734Srpaulo	if (wpa_s->current_ssid &&
2292214734Srpaulo	    wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2293214734Srpaulo		ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2294214734Srpaulo		return;
2295214734Srpaulo	}
2296214734Srpaulo#endif /* CONFIG_IBSS_RSN */
2297214734Srpaulo
2298189251Ssam	/* Source address of the incoming EAPOL frame could be compared to the
2299189251Ssam	 * current BSSID. However, it is possible that a centralized
2300189251Ssam	 * Authenticator could be using another MAC address than the BSSID of
2301189251Ssam	 * an AP, so just allow any address to be used for now. The replies are
2302189251Ssam	 * still sent to the current BSSID (if available), though. */
2303189251Ssam
2304189251Ssam	os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2305189251Ssam	if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2306189251Ssam	    eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2307189251Ssam		return;
2308189251Ssam	wpa_drv_poll(wpa_s);
2309214734Srpaulo	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2310189251Ssam		wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2311189251Ssam	else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2312189251Ssam		/*
2313189251Ssam		 * Set portValid = TRUE here since we are going to skip 4-way
2314189251Ssam		 * handshake processing which would normally set portValid. We
2315189251Ssam		 * need this to allow the EAPOL state machines to be completed
2316189251Ssam		 * without going through EAPOL-Key handshake.
2317189251Ssam		 */
2318189251Ssam		eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2319189251Ssam	}
2320189251Ssam}
2321189251Ssam
2322189251Ssam
2323252726Srpauloint wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
2324189251Ssam{
2325189251Ssam	if (wpa_s->driver->send_eapol) {
2326189251Ssam		const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2327189251Ssam		if (addr)
2328189251Ssam			os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2329252726Srpaulo	} else if (!(wpa_s->drv_flags &
2330252726Srpaulo		     WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
2331252726Srpaulo		l2_packet_deinit(wpa_s->l2);
2332189251Ssam		wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2333189251Ssam					   wpa_drv_get_mac_addr(wpa_s),
2334189251Ssam					   ETH_P_EAPOL,
2335189251Ssam					   wpa_supplicant_rx_eapol, wpa_s, 0);
2336189251Ssam		if (wpa_s->l2 == NULL)
2337189251Ssam			return -1;
2338252726Srpaulo	} else {
2339252726Srpaulo		const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2340252726Srpaulo		if (addr)
2341252726Srpaulo			os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2342189251Ssam	}
2343189251Ssam
2344189251Ssam	if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2345252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2346189251Ssam		return -1;
2347189251Ssam	}
2348189251Ssam
2349252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2350252726Srpaulo		MAC2STR(wpa_s->own_addr));
2351252726Srpaulo	wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2352189251Ssam
2353252726Srpaulo	return 0;
2354252726Srpaulo}
2355252726Srpaulo
2356252726Srpaulo
2357252726Srpaulostatic void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2358252726Srpaulo					   const u8 *buf, size_t len)
2359252726Srpaulo{
2360252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
2361252726Srpaulo	const struct l2_ethhdr *eth;
2362252726Srpaulo
2363252726Srpaulo	if (len < sizeof(*eth))
2364252726Srpaulo		return;
2365252726Srpaulo	eth = (const struct l2_ethhdr *) buf;
2366252726Srpaulo
2367252726Srpaulo	if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2368252726Srpaulo	    !(eth->h_dest[0] & 0x01)) {
2369252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2370252726Srpaulo			" (bridge - not for this interface - ignore)",
2371252726Srpaulo			MAC2STR(src_addr), MAC2STR(eth->h_dest));
2372252726Srpaulo		return;
2373252726Srpaulo	}
2374252726Srpaulo
2375252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2376252726Srpaulo		" (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2377252726Srpaulo	wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2378252726Srpaulo				len - sizeof(*eth));
2379252726Srpaulo}
2380252726Srpaulo
2381252726Srpaulo
2382252726Srpaulo/**
2383252726Srpaulo * wpa_supplicant_driver_init - Initialize driver interface parameters
2384252726Srpaulo * @wpa_s: Pointer to wpa_supplicant data
2385252726Srpaulo * Returns: 0 on success, -1 on failure
2386252726Srpaulo *
2387252726Srpaulo * This function is called to initialize driver interface parameters.
2388252726Srpaulo * wpa_drv_init() must have been called before this function to initialize the
2389252726Srpaulo * driver interface.
2390252726Srpaulo */
2391252726Srpauloint wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2392252726Srpaulo{
2393252726Srpaulo	static int interface_count = 0;
2394252726Srpaulo
2395252726Srpaulo	if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2396252726Srpaulo		return -1;
2397252726Srpaulo
2398189251Ssam	if (wpa_s->bridge_ifname[0]) {
2399252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2400252726Srpaulo			"interface '%s'", wpa_s->bridge_ifname);
2401189251Ssam		wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2402189251Ssam					      wpa_s->own_addr,
2403189251Ssam					      ETH_P_EAPOL,
2404252726Srpaulo					      wpa_supplicant_rx_eapol_bridge,
2405252726Srpaulo					      wpa_s, 1);
2406189251Ssam		if (wpa_s->l2_br == NULL) {
2407252726Srpaulo			wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2408252726Srpaulo				"connection for the bridge interface '%s'",
2409252726Srpaulo				wpa_s->bridge_ifname);
2410189251Ssam			return -1;
2411189251Ssam		}
2412189251Ssam	}
2413189251Ssam
2414189251Ssam	wpa_clear_keys(wpa_s, NULL);
2415189251Ssam
2416189251Ssam	/* Make sure that TKIP countermeasures are not left enabled (could
2417189251Ssam	 * happen if wpa_supplicant is killed during countermeasures. */
2418189251Ssam	wpa_drv_set_countermeasures(wpa_s, 0);
2419189251Ssam
2420252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2421189251Ssam	wpa_drv_flush_pmkid(wpa_s);
2422189251Ssam
2423214734Srpaulo	wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
2424252726Srpaulo	wpa_s->prev_scan_wildcard = 0;
2425252726Srpaulo
2426252726Srpaulo	if (wpa_supplicant_enabled_networks(wpa_s)) {
2427252726Srpaulo		if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2428252726Srpaulo						      100000))
2429252726Srpaulo			wpa_supplicant_req_scan(wpa_s, interface_count,
2430252726Srpaulo						100000);
2431214734Srpaulo		interface_count++;
2432214734Srpaulo	} else
2433214734Srpaulo		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2434189251Ssam
2435189251Ssam	return 0;
2436189251Ssam}
2437189251Ssam
2438189251Ssam
2439189251Ssamstatic int wpa_supplicant_daemon(const char *pid_file)
2440189251Ssam{
2441189251Ssam	wpa_printf(MSG_DEBUG, "Daemonize..");
2442189251Ssam	return os_daemonize(pid_file);
2443189251Ssam}
2444189251Ssam
2445189251Ssam
2446189251Ssamstatic struct wpa_supplicant * wpa_supplicant_alloc(void)
2447189251Ssam{
2448189251Ssam	struct wpa_supplicant *wpa_s;
2449189251Ssam
2450189251Ssam	wpa_s = os_zalloc(sizeof(*wpa_s));
2451189251Ssam	if (wpa_s == NULL)
2452189251Ssam		return NULL;
2453252726Srpaulo	wpa_s->scan_req = INITIAL_SCAN_REQ;
2454252726Srpaulo	wpa_s->scan_interval = 5;
2455214734Srpaulo	wpa_s->new_connection = 1;
2456252726Srpaulo	wpa_s->parent = wpa_s;
2457252726Srpaulo	wpa_s->sched_scanning = 0;
2458189251Ssam
2459189251Ssam	return wpa_s;
2460189251Ssam}
2461189251Ssam
2462189251Ssam
2463252726Srpaulo#ifdef CONFIG_HT_OVERRIDES
2464252726Srpaulo
2465252726Srpaulostatic int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2466252726Srpaulo			     struct ieee80211_ht_capabilities *htcaps,
2467252726Srpaulo			     struct ieee80211_ht_capabilities *htcaps_mask,
2468252726Srpaulo			     const char *ht_mcs)
2469252726Srpaulo{
2470252726Srpaulo	/* parse ht_mcs into hex array */
2471252726Srpaulo	int i;
2472252726Srpaulo	const char *tmp = ht_mcs;
2473252726Srpaulo	char *end = NULL;
2474252726Srpaulo
2475252726Srpaulo	/* If ht_mcs is null, do not set anything */
2476252726Srpaulo	if (!ht_mcs)
2477252726Srpaulo		return 0;
2478252726Srpaulo
2479252726Srpaulo	/* This is what we are setting in the kernel */
2480252726Srpaulo	os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2481252726Srpaulo
2482252726Srpaulo	wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2483252726Srpaulo
2484252726Srpaulo	for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2485252726Srpaulo		errno = 0;
2486252726Srpaulo		long v = strtol(tmp, &end, 16);
2487252726Srpaulo		if (errno == 0) {
2488252726Srpaulo			wpa_msg(wpa_s, MSG_DEBUG,
2489252726Srpaulo				"htcap value[%i]: %ld end: %p  tmp: %p",
2490252726Srpaulo				i, v, end, tmp);
2491252726Srpaulo			if (end == tmp)
2492252726Srpaulo				break;
2493252726Srpaulo
2494252726Srpaulo			htcaps->supported_mcs_set[i] = v;
2495252726Srpaulo			tmp = end;
2496252726Srpaulo		} else {
2497252726Srpaulo			wpa_msg(wpa_s, MSG_ERROR,
2498252726Srpaulo				"Failed to parse ht-mcs: %s, error: %s\n",
2499252726Srpaulo				ht_mcs, strerror(errno));
2500252726Srpaulo			return -1;
2501252726Srpaulo		}
2502252726Srpaulo	}
2503252726Srpaulo
2504252726Srpaulo	/*
2505252726Srpaulo	 * If we were able to parse any values, then set mask for the MCS set.
2506252726Srpaulo	 */
2507252726Srpaulo	if (i) {
2508252726Srpaulo		os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2509252726Srpaulo			  IEEE80211_HT_MCS_MASK_LEN - 1);
2510252726Srpaulo		/* skip the 3 reserved bits */
2511252726Srpaulo		htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2512252726Srpaulo			0x1f;
2513252726Srpaulo	}
2514252726Srpaulo
2515252726Srpaulo	return 0;
2516252726Srpaulo}
2517252726Srpaulo
2518252726Srpaulo
2519252726Srpaulostatic int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2520252726Srpaulo				 struct ieee80211_ht_capabilities *htcaps,
2521252726Srpaulo				 struct ieee80211_ht_capabilities *htcaps_mask,
2522252726Srpaulo				 int disabled)
2523252726Srpaulo{
2524252726Srpaulo	u16 msk;
2525252726Srpaulo
2526252726Srpaulo	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2527252726Srpaulo
2528252726Srpaulo	if (disabled == -1)
2529252726Srpaulo		return 0;
2530252726Srpaulo
2531252726Srpaulo	msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2532252726Srpaulo	htcaps_mask->ht_capabilities_info |= msk;
2533252726Srpaulo	if (disabled)
2534252726Srpaulo		htcaps->ht_capabilities_info &= msk;
2535252726Srpaulo	else
2536252726Srpaulo		htcaps->ht_capabilities_info |= msk;
2537252726Srpaulo
2538252726Srpaulo	return 0;
2539252726Srpaulo}
2540252726Srpaulo
2541252726Srpaulo
2542252726Srpaulostatic int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2543252726Srpaulo				struct ieee80211_ht_capabilities *htcaps,
2544252726Srpaulo				struct ieee80211_ht_capabilities *htcaps_mask,
2545252726Srpaulo				int factor)
2546252726Srpaulo{
2547252726Srpaulo	wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2548252726Srpaulo
2549252726Srpaulo	if (factor == -1)
2550252726Srpaulo		return 0;
2551252726Srpaulo
2552252726Srpaulo	if (factor < 0 || factor > 3) {
2553252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2554252726Srpaulo			"Must be 0-3 or -1", factor);
2555252726Srpaulo		return -EINVAL;
2556252726Srpaulo	}
2557252726Srpaulo
2558252726Srpaulo	htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2559252726Srpaulo	htcaps->a_mpdu_params &= ~0x3;
2560252726Srpaulo	htcaps->a_mpdu_params |= factor & 0x3;
2561252726Srpaulo
2562252726Srpaulo	return 0;
2563252726Srpaulo}
2564252726Srpaulo
2565252726Srpaulo
2566252726Srpaulostatic int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2567252726Srpaulo				 struct ieee80211_ht_capabilities *htcaps,
2568252726Srpaulo				 struct ieee80211_ht_capabilities *htcaps_mask,
2569252726Srpaulo				 int density)
2570252726Srpaulo{
2571252726Srpaulo	wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2572252726Srpaulo
2573252726Srpaulo	if (density == -1)
2574252726Srpaulo		return 0;
2575252726Srpaulo
2576252726Srpaulo	if (density < 0 || density > 7) {
2577252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR,
2578252726Srpaulo			"ampdu_density: %d out of range. Must be 0-7 or -1.",
2579252726Srpaulo			density);
2580252726Srpaulo		return -EINVAL;
2581252726Srpaulo	}
2582252726Srpaulo
2583252726Srpaulo	htcaps_mask->a_mpdu_params |= 0x1C;
2584252726Srpaulo	htcaps->a_mpdu_params &= ~(0x1C);
2585252726Srpaulo	htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2586252726Srpaulo
2587252726Srpaulo	return 0;
2588252726Srpaulo}
2589252726Srpaulo
2590252726Srpaulo
2591252726Srpaulostatic int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2592252726Srpaulo				struct ieee80211_ht_capabilities *htcaps,
2593252726Srpaulo				struct ieee80211_ht_capabilities *htcaps_mask,
2594252726Srpaulo				int disabled)
2595252726Srpaulo{
2596252726Srpaulo	/* Masking these out disables HT40 */
2597252726Srpaulo	u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2598252726Srpaulo			       HT_CAP_INFO_SHORT_GI40MHZ);
2599252726Srpaulo
2600252726Srpaulo	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2601252726Srpaulo
2602252726Srpaulo	if (disabled)
2603252726Srpaulo		htcaps->ht_capabilities_info &= ~msk;
2604252726Srpaulo	else
2605252726Srpaulo		htcaps->ht_capabilities_info |= msk;
2606252726Srpaulo
2607252726Srpaulo	htcaps_mask->ht_capabilities_info |= msk;
2608252726Srpaulo
2609252726Srpaulo	return 0;
2610252726Srpaulo}
2611252726Srpaulo
2612252726Srpaulo
2613252726Srpaulostatic int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2614252726Srpaulo			       struct ieee80211_ht_capabilities *htcaps,
2615252726Srpaulo			       struct ieee80211_ht_capabilities *htcaps_mask,
2616252726Srpaulo			       int disabled)
2617252726Srpaulo{
2618252726Srpaulo	/* Masking these out disables SGI */
2619252726Srpaulo	u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2620252726Srpaulo			       HT_CAP_INFO_SHORT_GI40MHZ);
2621252726Srpaulo
2622252726Srpaulo	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2623252726Srpaulo
2624252726Srpaulo	if (disabled)
2625252726Srpaulo		htcaps->ht_capabilities_info &= ~msk;
2626252726Srpaulo	else
2627252726Srpaulo		htcaps->ht_capabilities_info |= msk;
2628252726Srpaulo
2629252726Srpaulo	htcaps_mask->ht_capabilities_info |= msk;
2630252726Srpaulo
2631252726Srpaulo	return 0;
2632252726Srpaulo}
2633252726Srpaulo
2634252726Srpaulo
2635252726Srpaulovoid wpa_supplicant_apply_ht_overrides(
2636252726Srpaulo	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2637252726Srpaulo	struct wpa_driver_associate_params *params)
2638252726Srpaulo{
2639252726Srpaulo	struct ieee80211_ht_capabilities *htcaps;
2640252726Srpaulo	struct ieee80211_ht_capabilities *htcaps_mask;
2641252726Srpaulo
2642252726Srpaulo	if (!ssid)
2643252726Srpaulo		return;
2644252726Srpaulo
2645252726Srpaulo	params->disable_ht = ssid->disable_ht;
2646252726Srpaulo	if (!params->htcaps || !params->htcaps_mask)
2647252726Srpaulo		return;
2648252726Srpaulo
2649252726Srpaulo	htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2650252726Srpaulo	htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2651252726Srpaulo	wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2652252726Srpaulo	wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2653252726Srpaulo			      ssid->disable_max_amsdu);
2654252726Srpaulo	wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2655252726Srpaulo	wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2656252726Srpaulo	wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
2657252726Srpaulo	wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
2658252726Srpaulo}
2659252726Srpaulo
2660252726Srpaulo#endif /* CONFIG_HT_OVERRIDES */
2661252726Srpaulo
2662252726Srpaulo
2663252726Srpaulostatic int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2664252726Srpaulo{
2665252726Srpaulo#ifdef PCSC_FUNCS
2666252726Srpaulo	size_t len;
2667252726Srpaulo
2668252726Srpaulo	if (!wpa_s->conf->pcsc_reader)
2669252726Srpaulo		return 0;
2670252726Srpaulo
2671252726Srpaulo	wpa_s->scard = scard_init(SCARD_TRY_BOTH, wpa_s->conf->pcsc_reader);
2672252726Srpaulo	if (!wpa_s->scard)
2673252726Srpaulo		return 1;
2674252726Srpaulo
2675252726Srpaulo	if (wpa_s->conf->pcsc_pin &&
2676252726Srpaulo	    scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2677252726Srpaulo		scard_deinit(wpa_s->scard);
2678252726Srpaulo		wpa_s->scard = NULL;
2679252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2680252726Srpaulo		return -1;
2681252726Srpaulo	}
2682252726Srpaulo
2683252726Srpaulo	len = sizeof(wpa_s->imsi) - 1;
2684252726Srpaulo	if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2685252726Srpaulo		scard_deinit(wpa_s->scard);
2686252726Srpaulo		wpa_s->scard = NULL;
2687252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2688252726Srpaulo		return -1;
2689252726Srpaulo	}
2690252726Srpaulo	wpa_s->imsi[len] = '\0';
2691252726Srpaulo
2692252726Srpaulo	wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2693252726Srpaulo
2694252726Srpaulo	wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2695252726Srpaulo		   wpa_s->imsi, wpa_s->mnc_len);
2696252726Srpaulo
2697252726Srpaulo	wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2698252726Srpaulo	eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2699252726Srpaulo#endif /* PCSC_FUNCS */
2700252726Srpaulo
2701252726Srpaulo	return 0;
2702252726Srpaulo}
2703252726Srpaulo
2704252726Srpaulo
2705252726Srpauloint wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2706252726Srpaulo{
2707252726Srpaulo	char *val, *pos;
2708252726Srpaulo
2709252726Srpaulo	ext_password_deinit(wpa_s->ext_pw);
2710252726Srpaulo	wpa_s->ext_pw = NULL;
2711252726Srpaulo	eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2712252726Srpaulo
2713252726Srpaulo	if (!wpa_s->conf->ext_password_backend)
2714252726Srpaulo		return 0;
2715252726Srpaulo
2716252726Srpaulo	val = os_strdup(wpa_s->conf->ext_password_backend);
2717252726Srpaulo	if (val == NULL)
2718252726Srpaulo		return -1;
2719252726Srpaulo	pos = os_strchr(val, ':');
2720252726Srpaulo	if (pos)
2721252726Srpaulo		*pos++ = '\0';
2722252726Srpaulo
2723252726Srpaulo	wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2724252726Srpaulo
2725252726Srpaulo	wpa_s->ext_pw = ext_password_init(val, pos);
2726252726Srpaulo	os_free(val);
2727252726Srpaulo	if (wpa_s->ext_pw == NULL) {
2728252726Srpaulo		wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2729252726Srpaulo		return -1;
2730252726Srpaulo	}
2731252726Srpaulo	eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2732252726Srpaulo
2733252726Srpaulo	return 0;
2734252726Srpaulo}
2735252726Srpaulo
2736252726Srpaulo
2737189251Ssamstatic int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
2738189251Ssam				     struct wpa_interface *iface)
2739189251Ssam{
2740214734Srpaulo	const char *ifname, *driver;
2741214734Srpaulo	struct wpa_driver_capa capa;
2742214734Srpaulo
2743189251Ssam	wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
2744189251Ssam		   "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
2745189251Ssam		   iface->confname ? iface->confname : "N/A",
2746189251Ssam		   iface->driver ? iface->driver : "default",
2747189251Ssam		   iface->ctrl_interface ? iface->ctrl_interface : "N/A",
2748189251Ssam		   iface->bridge_ifname ? iface->bridge_ifname : "N/A");
2749189251Ssam
2750189251Ssam	if (iface->confname) {
2751189251Ssam#ifdef CONFIG_BACKEND_FILE
2752189251Ssam		wpa_s->confname = os_rel2abs_path(iface->confname);
2753189251Ssam		if (wpa_s->confname == NULL) {
2754189251Ssam			wpa_printf(MSG_ERROR, "Failed to get absolute path "
2755189251Ssam				   "for configuration file '%s'.",
2756189251Ssam				   iface->confname);
2757189251Ssam			return -1;
2758189251Ssam		}
2759189251Ssam		wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
2760189251Ssam			   iface->confname, wpa_s->confname);
2761189251Ssam#else /* CONFIG_BACKEND_FILE */
2762189251Ssam		wpa_s->confname = os_strdup(iface->confname);
2763189251Ssam#endif /* CONFIG_BACKEND_FILE */
2764189251Ssam		wpa_s->conf = wpa_config_read(wpa_s->confname);
2765189251Ssam		if (wpa_s->conf == NULL) {
2766189251Ssam			wpa_printf(MSG_ERROR, "Failed to read or parse "
2767189251Ssam				   "configuration '%s'.", wpa_s->confname);
2768189251Ssam			return -1;
2769189251Ssam		}
2770189251Ssam
2771189251Ssam		/*
2772189251Ssam		 * Override ctrl_interface and driver_param if set on command
2773189251Ssam		 * line.
2774189251Ssam		 */
2775189251Ssam		if (iface->ctrl_interface) {
2776189251Ssam			os_free(wpa_s->conf->ctrl_interface);
2777189251Ssam			wpa_s->conf->ctrl_interface =
2778189251Ssam				os_strdup(iface->ctrl_interface);
2779189251Ssam		}
2780189251Ssam
2781189251Ssam		if (iface->driver_param) {
2782189251Ssam			os_free(wpa_s->conf->driver_param);
2783189251Ssam			wpa_s->conf->driver_param =
2784189251Ssam				os_strdup(iface->driver_param);
2785189251Ssam		}
2786189251Ssam	} else
2787189251Ssam		wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
2788189251Ssam						     iface->driver_param);
2789189251Ssam
2790189251Ssam	if (wpa_s->conf == NULL) {
2791189251Ssam		wpa_printf(MSG_ERROR, "\nNo configuration found.");
2792189251Ssam		return -1;
2793189251Ssam	}
2794189251Ssam
2795189251Ssam	if (iface->ifname == NULL) {
2796189251Ssam		wpa_printf(MSG_ERROR, "\nInterface name is required.");
2797189251Ssam		return -1;
2798189251Ssam	}
2799189251Ssam	if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
2800189251Ssam		wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
2801189251Ssam			   iface->ifname);
2802189251Ssam		return -1;
2803189251Ssam	}
2804189251Ssam	os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
2805189251Ssam
2806189251Ssam	if (iface->bridge_ifname) {
2807189251Ssam		if (os_strlen(iface->bridge_ifname) >=
2808189251Ssam		    sizeof(wpa_s->bridge_ifname)) {
2809189251Ssam			wpa_printf(MSG_ERROR, "\nToo long bridge interface "
2810189251Ssam				   "name '%s'.", iface->bridge_ifname);
2811189251Ssam			return -1;
2812189251Ssam		}
2813189251Ssam		os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
2814189251Ssam			   sizeof(wpa_s->bridge_ifname));
2815189251Ssam	}
2816189251Ssam
2817189251Ssam	/* RSNA Supplicant Key Management - INITIALIZE */
2818189251Ssam	eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
2819189251Ssam	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
2820189251Ssam
2821189251Ssam	/* Initialize driver interface and register driver event handler before
2822189251Ssam	 * L2 receive handler so that association events are processed before
2823189251Ssam	 * EAPOL-Key packets if both become available for the same select()
2824189251Ssam	 * call. */
2825214734Srpaulo	driver = iface->driver;
2826214734Srpaulonext_driver:
2827214734Srpaulo	if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
2828214734Srpaulo		return -1;
2829214734Srpaulo
2830189251Ssam	wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
2831189251Ssam	if (wpa_s->drv_priv == NULL) {
2832214734Srpaulo		const char *pos;
2833214734Srpaulo		pos = driver ? os_strchr(driver, ',') : NULL;
2834214734Srpaulo		if (pos) {
2835252726Srpaulo			wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
2836252726Srpaulo				"driver interface - try next driver wrapper");
2837214734Srpaulo			driver = pos + 1;
2838214734Srpaulo			goto next_driver;
2839214734Srpaulo		}
2840252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
2841252726Srpaulo			"interface");
2842189251Ssam		return -1;
2843189251Ssam	}
2844189251Ssam	if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
2845252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
2846252726Srpaulo			"driver_param '%s'", wpa_s->conf->driver_param);
2847189251Ssam		return -1;
2848189251Ssam	}
2849189251Ssam
2850189251Ssam	ifname = wpa_drv_get_ifname(wpa_s);
2851189251Ssam	if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
2852252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
2853252726Srpaulo			"interface name with '%s'", ifname);
2854189251Ssam		os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
2855189251Ssam	}
2856189251Ssam
2857189251Ssam	if (wpa_supplicant_init_wpa(wpa_s) < 0)
2858189251Ssam		return -1;
2859189251Ssam
2860189251Ssam	wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
2861189251Ssam			  wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
2862189251Ssam			  NULL);
2863189251Ssam	wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
2864189251Ssam
2865189251Ssam	if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
2866189251Ssam	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
2867189251Ssam			     wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
2868252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2869252726Srpaulo			"dot11RSNAConfigPMKLifetime");
2870189251Ssam		return -1;
2871189251Ssam	}
2872189251Ssam
2873189251Ssam	if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
2874189251Ssam	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
2875189251Ssam			     wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
2876252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2877189251Ssam			"dot11RSNAConfigPMKReauthThreshold");
2878189251Ssam		return -1;
2879189251Ssam	}
2880189251Ssam
2881189251Ssam	if (wpa_s->conf->dot11RSNAConfigSATimeout &&
2882189251Ssam	    wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
2883189251Ssam			     wpa_s->conf->dot11RSNAConfigSATimeout)) {
2884252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2885252726Srpaulo			"dot11RSNAConfigSATimeout");
2886189251Ssam		return -1;
2887189251Ssam	}
2888189251Ssam
2889252726Srpaulo	wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
2890252726Srpaulo						      &wpa_s->hw.num_modes,
2891252726Srpaulo						      &wpa_s->hw.flags);
2892252726Srpaulo
2893214734Srpaulo	if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
2894252726Srpaulo		wpa_s->drv_capa_known = 1;
2895214734Srpaulo		wpa_s->drv_flags = capa.flags;
2896252726Srpaulo		wpa_s->drv_enc = capa.enc;
2897252726Srpaulo		wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
2898214734Srpaulo		wpa_s->max_scan_ssids = capa.max_scan_ssids;
2899252726Srpaulo		wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
2900252726Srpaulo		wpa_s->sched_scan_supported = capa.sched_scan_supported;
2901252726Srpaulo		wpa_s->max_match_sets = capa.max_match_sets;
2902214734Srpaulo		wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
2903252726Srpaulo		wpa_s->max_stations = capa.max_stations;
2904214734Srpaulo	}
2905214734Srpaulo	if (wpa_s->max_remain_on_chan == 0)
2906214734Srpaulo		wpa_s->max_remain_on_chan = 1000;
2907214734Srpaulo
2908189251Ssam	if (wpa_supplicant_driver_init(wpa_s) < 0)
2909189251Ssam		return -1;
2910189251Ssam
2911252726Srpaulo#ifdef CONFIG_TDLS
2912252726Srpaulo	if (wpa_tdls_init(wpa_s->wpa))
2913252726Srpaulo		return -1;
2914252726Srpaulo#endif /* CONFIG_TDLS */
2915252726Srpaulo
2916189251Ssam	if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
2917189251Ssam	    wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
2918252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
2919189251Ssam		return -1;
2920189251Ssam	}
2921189251Ssam
2922189251Ssam	if (wpas_wps_init(wpa_s))
2923189251Ssam		return -1;
2924189251Ssam
2925189251Ssam	if (wpa_supplicant_init_eapol(wpa_s) < 0)
2926189251Ssam		return -1;
2927189251Ssam	wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2928189251Ssam
2929189251Ssam	wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
2930189251Ssam	if (wpa_s->ctrl_iface == NULL) {
2931189251Ssam		wpa_printf(MSG_ERROR,
2932189251Ssam			   "Failed to initialize control interface '%s'.\n"
2933189251Ssam			   "You may have another wpa_supplicant process "
2934189251Ssam			   "already running or the file was\n"
2935189251Ssam			   "left by an unclean termination of wpa_supplicant "
2936189251Ssam			   "in which case you will need\n"
2937189251Ssam			   "to manually remove this file before starting "
2938189251Ssam			   "wpa_supplicant again.\n",
2939189251Ssam			   wpa_s->conf->ctrl_interface);
2940189251Ssam		return -1;
2941189251Ssam	}
2942189251Ssam
2943252726Srpaulo	wpa_s->gas = gas_query_init(wpa_s);
2944252726Srpaulo	if (wpa_s->gas == NULL) {
2945252726Srpaulo		wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
2946214734Srpaulo		return -1;
2947189251Ssam	}
2948189251Ssam
2949252726Srpaulo#ifdef CONFIG_P2P
2950252726Srpaulo	if (wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
2951252726Srpaulo		wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
2952252726Srpaulo		return -1;
2953252726Srpaulo	}
2954252726Srpaulo#endif /* CONFIG_P2P */
2955252726Srpaulo
2956214734Srpaulo	if (wpa_bss_init(wpa_s) < 0)
2957214734Srpaulo		return -1;
2958214734Srpaulo
2959252726Srpaulo	if (pcsc_reader_init(wpa_s) < 0)
2960252726Srpaulo		return -1;
2961252726Srpaulo
2962252726Srpaulo	if (wpas_init_ext_pw(wpa_s) < 0)
2963252726Srpaulo		return -1;
2964252726Srpaulo
2965189251Ssam	return 0;
2966189251Ssam}
2967189251Ssam
2968189251Ssam
2969214734Srpaulostatic void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
2970252726Srpaulo					int notify, int terminate)
2971189251Ssam{
2972189251Ssam	if (wpa_s->drv_priv) {
2973189251Ssam		wpa_supplicant_deauthenticate(wpa_s,
2974189251Ssam					      WLAN_REASON_DEAUTH_LEAVING);
2975189251Ssam
2976189251Ssam		wpa_drv_set_countermeasures(wpa_s, 0);
2977189251Ssam		wpa_clear_keys(wpa_s, NULL);
2978189251Ssam	}
2979189251Ssam
2980189251Ssam	wpa_supplicant_cleanup(wpa_s);
2981189251Ssam
2982252726Srpaulo#ifdef CONFIG_P2P
2983252726Srpaulo	if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
2984252726Srpaulo		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
2985252726Srpaulo			"the management interface is being removed");
2986252726Srpaulo		wpas_p2p_deinit_global(wpa_s->global);
2987252726Srpaulo	}
2988252726Srpaulo#endif /* CONFIG_P2P */
2989252726Srpaulo
2990252726Srpaulo	if (wpa_s->drv_priv)
2991252726Srpaulo		wpa_drv_deinit(wpa_s);
2992252726Srpaulo
2993214734Srpaulo	if (notify)
2994214734Srpaulo		wpas_notify_iface_removed(wpa_s);
2995214734Srpaulo
2996252726Srpaulo	if (terminate)
2997252726Srpaulo		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
2998252726Srpaulo
2999252726Srpaulo	if (wpa_s->ctrl_iface) {
3000252726Srpaulo		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3001252726Srpaulo		wpa_s->ctrl_iface = NULL;
3002252726Srpaulo	}
3003252726Srpaulo
3004252726Srpaulo	if (wpa_s->conf != NULL) {
3005252726Srpaulo		wpa_config_free(wpa_s->conf);
3006252726Srpaulo		wpa_s->conf = NULL;
3007252726Srpaulo	}
3008189251Ssam}
3009189251Ssam
3010189251Ssam
3011189251Ssam/**
3012189251Ssam * wpa_supplicant_add_iface - Add a new network interface
3013189251Ssam * @global: Pointer to global data from wpa_supplicant_init()
3014189251Ssam * @iface: Interface configuration options
3015189251Ssam * Returns: Pointer to the created interface or %NULL on failure
3016189251Ssam *
3017189251Ssam * This function is used to add new network interfaces for %wpa_supplicant.
3018189251Ssam * This can be called before wpa_supplicant_run() to add interfaces before the
3019189251Ssam * main event loop has been started. In addition, new interfaces can be added
3020189251Ssam * dynamically while %wpa_supplicant is already running. This could happen,
3021189251Ssam * e.g., when a hotplug network adapter is inserted.
3022189251Ssam */
3023189251Ssamstruct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3024189251Ssam						 struct wpa_interface *iface)
3025189251Ssam{
3026189251Ssam	struct wpa_supplicant *wpa_s;
3027214734Srpaulo	struct wpa_interface t_iface;
3028214734Srpaulo	struct wpa_ssid *ssid;
3029189251Ssam
3030189251Ssam	if (global == NULL || iface == NULL)
3031189251Ssam		return NULL;
3032189251Ssam
3033189251Ssam	wpa_s = wpa_supplicant_alloc();
3034189251Ssam	if (wpa_s == NULL)
3035189251Ssam		return NULL;
3036189251Ssam
3037209158Srpaulo	wpa_s->global = global;
3038209158Srpaulo
3039214734Srpaulo	t_iface = *iface;
3040214734Srpaulo	if (global->params.override_driver) {
3041214734Srpaulo		wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3042214734Srpaulo			   "('%s' -> '%s')",
3043214734Srpaulo			   iface->driver, global->params.override_driver);
3044214734Srpaulo		t_iface.driver = global->params.override_driver;
3045214734Srpaulo	}
3046214734Srpaulo	if (global->params.override_ctrl_interface) {
3047214734Srpaulo		wpa_printf(MSG_DEBUG, "Override interface parameter: "
3048214734Srpaulo			   "ctrl_interface ('%s' -> '%s')",
3049214734Srpaulo			   iface->ctrl_interface,
3050214734Srpaulo			   global->params.override_ctrl_interface);
3051214734Srpaulo		t_iface.ctrl_interface =
3052214734Srpaulo			global->params.override_ctrl_interface;
3053214734Srpaulo	}
3054214734Srpaulo	if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3055189251Ssam		wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3056189251Ssam			   iface->ifname);
3057252726Srpaulo		wpa_supplicant_deinit_iface(wpa_s, 0, 0);
3058189251Ssam		os_free(wpa_s);
3059189251Ssam		return NULL;
3060189251Ssam	}
3061189251Ssam
3062214734Srpaulo	/* Notify the control interfaces about new iface */
3063214734Srpaulo	if (wpas_notify_iface_added(wpa_s)) {
3064252726Srpaulo		wpa_supplicant_deinit_iface(wpa_s, 1, 0);
3065189251Ssam		os_free(wpa_s);
3066189251Ssam		return NULL;
3067189251Ssam	}
3068209158Srpaulo
3069214734Srpaulo	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3070214734Srpaulo		wpas_notify_network_added(wpa_s, ssid);
3071214734Srpaulo
3072189251Ssam	wpa_s->next = global->ifaces;
3073189251Ssam	global->ifaces = wpa_s;
3074189251Ssam
3075252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
3076252726Srpaulo	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3077189251Ssam
3078189251Ssam	return wpa_s;
3079189251Ssam}
3080189251Ssam
3081189251Ssam
3082189251Ssam/**
3083189251Ssam * wpa_supplicant_remove_iface - Remove a network interface
3084189251Ssam * @global: Pointer to global data from wpa_supplicant_init()
3085189251Ssam * @wpa_s: Pointer to the network interface to be removed
3086189251Ssam * Returns: 0 if interface was removed, -1 if interface was not found
3087189251Ssam *
3088189251Ssam * This function can be used to dynamically remove network interfaces from
3089189251Ssam * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3090189251Ssam * addition, this function is used to remove all remaining interfaces when
3091189251Ssam * %wpa_supplicant is terminated.
3092189251Ssam */
3093189251Ssamint wpa_supplicant_remove_iface(struct wpa_global *global,
3094252726Srpaulo				struct wpa_supplicant *wpa_s,
3095252726Srpaulo				int terminate)
3096189251Ssam{
3097189251Ssam	struct wpa_supplicant *prev;
3098189251Ssam
3099189251Ssam	/* Remove interface from the global list of interfaces */
3100189251Ssam	prev = global->ifaces;
3101189251Ssam	if (prev == wpa_s) {
3102189251Ssam		global->ifaces = wpa_s->next;
3103189251Ssam	} else {
3104189251Ssam		while (prev && prev->next != wpa_s)
3105189251Ssam			prev = prev->next;
3106189251Ssam		if (prev == NULL)
3107189251Ssam			return -1;
3108189251Ssam		prev->next = wpa_s->next;
3109189251Ssam	}
3110189251Ssam
3111252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3112189251Ssam
3113252726Srpaulo	if (global->p2p_group_formation == wpa_s)
3114252726Srpaulo		global->p2p_group_formation = NULL;
3115252726Srpaulo	wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
3116189251Ssam	os_free(wpa_s);
3117189251Ssam
3118189251Ssam	return 0;
3119189251Ssam}
3120189251Ssam
3121189251Ssam
3122189251Ssam/**
3123252726Srpaulo * wpa_supplicant_get_eap_mode - Get the current EAP mode
3124252726Srpaulo * @wpa_s: Pointer to the network interface
3125252726Srpaulo * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3126252726Srpaulo */
3127252726Srpauloconst char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3128252726Srpaulo{
3129252726Srpaulo	const char *eapol_method;
3130252726Srpaulo
3131252726Srpaulo        if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3132252726Srpaulo            wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3133252726Srpaulo		return "NO-EAP";
3134252726Srpaulo	}
3135252726Srpaulo
3136252726Srpaulo	eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3137252726Srpaulo	if (eapol_method == NULL)
3138252726Srpaulo		return "UNKNOWN-EAP";
3139252726Srpaulo
3140252726Srpaulo	return eapol_method;
3141252726Srpaulo}
3142252726Srpaulo
3143252726Srpaulo
3144252726Srpaulo/**
3145189251Ssam * wpa_supplicant_get_iface - Get a new network interface
3146189251Ssam * @global: Pointer to global data from wpa_supplicant_init()
3147189251Ssam * @ifname: Interface name
3148189251Ssam * Returns: Pointer to the interface or %NULL if not found
3149189251Ssam */
3150189251Ssamstruct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3151189251Ssam						 const char *ifname)
3152189251Ssam{
3153189251Ssam	struct wpa_supplicant *wpa_s;
3154189251Ssam
3155189251Ssam	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3156189251Ssam		if (os_strcmp(wpa_s->ifname, ifname) == 0)
3157189251Ssam			return wpa_s;
3158189251Ssam	}
3159189251Ssam	return NULL;
3160189251Ssam}
3161189251Ssam
3162189251Ssam
3163252726Srpaulo#ifndef CONFIG_NO_WPA_MSG
3164252726Srpaulostatic const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3165252726Srpaulo{
3166252726Srpaulo	struct wpa_supplicant *wpa_s = ctx;
3167252726Srpaulo	if (wpa_s == NULL)
3168252726Srpaulo		return NULL;
3169252726Srpaulo	return wpa_s->ifname;
3170252726Srpaulo}
3171252726Srpaulo#endif /* CONFIG_NO_WPA_MSG */
3172252726Srpaulo
3173252726Srpaulo
3174189251Ssam/**
3175189251Ssam * wpa_supplicant_init - Initialize %wpa_supplicant
3176189251Ssam * @params: Parameters for %wpa_supplicant
3177189251Ssam * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3178189251Ssam *
3179189251Ssam * This function is used to initialize %wpa_supplicant. After successful
3180189251Ssam * initialization, the returned data pointer can be used to add and remove
3181189251Ssam * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3182189251Ssam */
3183189251Ssamstruct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3184189251Ssam{
3185189251Ssam	struct wpa_global *global;
3186189251Ssam	int ret, i;
3187189251Ssam
3188189251Ssam	if (params == NULL)
3189189251Ssam		return NULL;
3190189251Ssam
3191252726Srpaulo#ifdef CONFIG_DRIVER_NDIS
3192252726Srpaulo	{
3193252726Srpaulo		void driver_ndis_init_ops(void);
3194252726Srpaulo		driver_ndis_init_ops();
3195252726Srpaulo	}
3196252726Srpaulo#endif /* CONFIG_DRIVER_NDIS */
3197252726Srpaulo
3198252726Srpaulo#ifndef CONFIG_NO_WPA_MSG
3199252726Srpaulo	wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3200252726Srpaulo#endif /* CONFIG_NO_WPA_MSG */
3201252726Srpaulo
3202189251Ssam	wpa_debug_open_file(params->wpa_debug_file_path);
3203189262Ssam	if (params->wpa_debug_syslog)
3204189262Ssam		wpa_debug_open_syslog();
3205252726Srpaulo	if (params->wpa_debug_tracing) {
3206252726Srpaulo		ret = wpa_debug_open_linux_tracing();
3207252726Srpaulo		if (ret) {
3208252726Srpaulo			wpa_printf(MSG_ERROR,
3209252726Srpaulo				   "Failed to enable trace logging");
3210252726Srpaulo			return NULL;
3211252726Srpaulo		}
3212252726Srpaulo	}
3213189251Ssam
3214214734Srpaulo	ret = eap_register_methods();
3215189251Ssam	if (ret) {
3216189251Ssam		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3217189251Ssam		if (ret == -2)
3218189251Ssam			wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3219189251Ssam				   "the same EAP type.");
3220189251Ssam		return NULL;
3221189251Ssam	}
3222189251Ssam
3223189251Ssam	global = os_zalloc(sizeof(*global));
3224189251Ssam	if (global == NULL)
3225189251Ssam		return NULL;
3226252726Srpaulo	dl_list_init(&global->p2p_srv_bonjour);
3227252726Srpaulo	dl_list_init(&global->p2p_srv_upnp);
3228189251Ssam	global->params.daemonize = params->daemonize;
3229189251Ssam	global->params.wait_for_monitor = params->wait_for_monitor;
3230189251Ssam	global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3231189251Ssam	if (params->pid_file)
3232189251Ssam		global->params.pid_file = os_strdup(params->pid_file);
3233189251Ssam	if (params->ctrl_interface)
3234189251Ssam		global->params.ctrl_interface =
3235189251Ssam			os_strdup(params->ctrl_interface);
3236214734Srpaulo	if (params->override_driver)
3237214734Srpaulo		global->params.override_driver =
3238214734Srpaulo			os_strdup(params->override_driver);
3239214734Srpaulo	if (params->override_ctrl_interface)
3240214734Srpaulo		global->params.override_ctrl_interface =
3241214734Srpaulo			os_strdup(params->override_ctrl_interface);
3242189251Ssam	wpa_debug_level = global->params.wpa_debug_level =
3243189251Ssam		params->wpa_debug_level;
3244189251Ssam	wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3245189251Ssam		params->wpa_debug_show_keys;
3246189251Ssam	wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3247189251Ssam		params->wpa_debug_timestamp;
3248189251Ssam
3249252726Srpaulo	wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3250252726Srpaulo
3251214734Srpaulo	if (eloop_init()) {
3252189251Ssam		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3253189251Ssam		wpa_supplicant_deinit(global);
3254189251Ssam		return NULL;
3255189251Ssam	}
3256189251Ssam
3257252726Srpaulo	random_init(params->entropy_file);
3258252726Srpaulo
3259189251Ssam	global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3260189251Ssam	if (global->ctrl_iface == NULL) {
3261189251Ssam		wpa_supplicant_deinit(global);
3262189251Ssam		return NULL;
3263189251Ssam	}
3264189251Ssam
3265214734Srpaulo	if (wpas_notify_supplicant_initialized(global)) {
3266214734Srpaulo		wpa_supplicant_deinit(global);
3267214734Srpaulo		return NULL;
3268189251Ssam	}
3269189251Ssam
3270214734Srpaulo	for (i = 0; wpa_drivers[i]; i++)
3271189251Ssam		global->drv_count++;
3272189251Ssam	if (global->drv_count == 0) {
3273189251Ssam		wpa_printf(MSG_ERROR, "No drivers enabled");
3274189251Ssam		wpa_supplicant_deinit(global);
3275189251Ssam		return NULL;
3276189251Ssam	}
3277189251Ssam	global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3278189251Ssam	if (global->drv_priv == NULL) {
3279189251Ssam		wpa_supplicant_deinit(global);
3280189251Ssam		return NULL;
3281189251Ssam	}
3282252726Srpaulo
3283252726Srpaulo#ifdef CONFIG_WIFI_DISPLAY
3284252726Srpaulo	if (wifi_display_init(global) < 0) {
3285252726Srpaulo		wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3286252726Srpaulo		wpa_supplicant_deinit(global);
3287252726Srpaulo		return NULL;
3288189251Ssam	}
3289252726Srpaulo#endif /* CONFIG_WIFI_DISPLAY */
3290189251Ssam
3291189251Ssam	return global;
3292189251Ssam}
3293189251Ssam
3294189251Ssam
3295189251Ssam/**
3296189251Ssam * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3297189251Ssam * @global: Pointer to global data from wpa_supplicant_init()
3298189251Ssam * Returns: 0 after successful event loop run, -1 on failure
3299189251Ssam *
3300189251Ssam * This function starts the main event loop and continues running as long as
3301189251Ssam * there are any remaining events. In most cases, this function is running as
3302189251Ssam * long as the %wpa_supplicant process in still in use.
3303189251Ssam */
3304189251Ssamint wpa_supplicant_run(struct wpa_global *global)
3305189251Ssam{
3306189251Ssam	struct wpa_supplicant *wpa_s;
3307189251Ssam
3308189251Ssam	if (global->params.daemonize &&
3309189251Ssam	    wpa_supplicant_daemon(global->params.pid_file))
3310189251Ssam		return -1;
3311189251Ssam
3312189251Ssam	if (global->params.wait_for_monitor) {
3313189251Ssam		for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3314189251Ssam			if (wpa_s->ctrl_iface)
3315189251Ssam				wpa_supplicant_ctrl_iface_wait(
3316189251Ssam					wpa_s->ctrl_iface);
3317189251Ssam	}
3318189251Ssam
3319214734Srpaulo	eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3320214734Srpaulo	eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3321189251Ssam
3322189251Ssam	eloop_run();
3323189251Ssam
3324189251Ssam	return 0;
3325189251Ssam}
3326189251Ssam
3327189251Ssam
3328189251Ssam/**
3329189251Ssam * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3330189251Ssam * @global: Pointer to global data from wpa_supplicant_init()
3331189251Ssam *
3332189251Ssam * This function is called to deinitialize %wpa_supplicant and to free all
3333189251Ssam * allocated resources. Remaining network interfaces will also be removed.
3334189251Ssam */
3335189251Ssamvoid wpa_supplicant_deinit(struct wpa_global *global)
3336189251Ssam{
3337189251Ssam	int i;
3338189251Ssam
3339189251Ssam	if (global == NULL)
3340189251Ssam		return;
3341189251Ssam
3342252726Srpaulo#ifdef CONFIG_WIFI_DISPLAY
3343252726Srpaulo	wifi_display_deinit(global);
3344252726Srpaulo#endif /* CONFIG_WIFI_DISPLAY */
3345252726Srpaulo#ifdef CONFIG_P2P
3346252726Srpaulo	wpas_p2p_deinit_global(global);
3347252726Srpaulo#endif /* CONFIG_P2P */
3348252726Srpaulo
3349189251Ssam	while (global->ifaces)
3350252726Srpaulo		wpa_supplicant_remove_iface(global, global->ifaces, 1);
3351189251Ssam
3352189251Ssam	if (global->ctrl_iface)
3353189251Ssam		wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3354189251Ssam
3355214734Srpaulo	wpas_notify_supplicant_deinitialized(global);
3356214734Srpaulo
3357189251Ssam	eap_peer_unregister_methods();
3358214734Srpaulo#ifdef CONFIG_AP
3359214734Srpaulo	eap_server_unregister_methods();
3360214734Srpaulo#endif /* CONFIG_AP */
3361189251Ssam
3362214734Srpaulo	for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3363189251Ssam		if (!global->drv_priv[i])
3364189251Ssam			continue;
3365214734Srpaulo		wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3366189251Ssam	}
3367189251Ssam	os_free(global->drv_priv);
3368189251Ssam
3369252726Srpaulo	random_deinit();
3370252726Srpaulo
3371189251Ssam	eloop_destroy();
3372189251Ssam
3373189251Ssam	if (global->params.pid_file) {
3374189251Ssam		os_daemonize_terminate(global->params.pid_file);
3375189251Ssam		os_free(global->params.pid_file);
3376189251Ssam	}
3377189251Ssam	os_free(global->params.ctrl_interface);
3378214734Srpaulo	os_free(global->params.override_driver);
3379214734Srpaulo	os_free(global->params.override_ctrl_interface);
3380189251Ssam
3381252726Srpaulo	os_free(global->p2p_disallow_freq);
3382252726Srpaulo
3383189251Ssam	os_free(global);
3384189262Ssam	wpa_debug_close_syslog();
3385189251Ssam	wpa_debug_close_file();
3386252726Srpaulo	wpa_debug_close_linux_tracing();
3387189251Ssam}
3388252726Srpaulo
3389252726Srpaulo
3390252726Srpaulovoid wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3391252726Srpaulo{
3392252726Srpaulo	if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3393252726Srpaulo	    wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3394252726Srpaulo		char country[3];
3395252726Srpaulo		country[0] = wpa_s->conf->country[0];
3396252726Srpaulo		country[1] = wpa_s->conf->country[1];
3397252726Srpaulo		country[2] = '\0';
3398252726Srpaulo		if (wpa_drv_set_country(wpa_s, country) < 0) {
3399252726Srpaulo			wpa_printf(MSG_ERROR, "Failed to set country code "
3400252726Srpaulo				   "'%s'", country);
3401252726Srpaulo		}
3402252726Srpaulo	}
3403252726Srpaulo
3404252726Srpaulo	if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3405252726Srpaulo		wpas_init_ext_pw(wpa_s);
3406252726Srpaulo
3407252726Srpaulo#ifdef CONFIG_WPS
3408252726Srpaulo	wpas_wps_update_config(wpa_s);
3409252726Srpaulo#endif /* CONFIG_WPS */
3410252726Srpaulo
3411252726Srpaulo#ifdef CONFIG_P2P
3412252726Srpaulo	wpas_p2p_update_config(wpa_s);
3413252726Srpaulo#endif /* CONFIG_P2P */
3414252726Srpaulo
3415252726Srpaulo	wpa_s->conf->changed_parameters = 0;
3416252726Srpaulo}
3417252726Srpaulo
3418252726Srpaulo
3419252726Srpaulostatic void add_freq(int *freqs, int *num_freqs, int freq)
3420252726Srpaulo{
3421252726Srpaulo	int i;
3422252726Srpaulo
3423252726Srpaulo	for (i = 0; i < *num_freqs; i++) {
3424252726Srpaulo		if (freqs[i] == freq)
3425252726Srpaulo			return;
3426252726Srpaulo	}
3427252726Srpaulo
3428252726Srpaulo	freqs[*num_freqs] = freq;
3429252726Srpaulo	(*num_freqs)++;
3430252726Srpaulo}
3431252726Srpaulo
3432252726Srpaulo
3433252726Srpaulostatic int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3434252726Srpaulo{
3435252726Srpaulo	struct wpa_bss *bss, *cbss;
3436252726Srpaulo	const int max_freqs = 10;
3437252726Srpaulo	int *freqs;
3438252726Srpaulo	int num_freqs = 0;
3439252726Srpaulo
3440252726Srpaulo	freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3441252726Srpaulo	if (freqs == NULL)
3442252726Srpaulo		return NULL;
3443252726Srpaulo
3444252726Srpaulo	cbss = wpa_s->current_bss;
3445252726Srpaulo
3446252726Srpaulo	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3447252726Srpaulo		if (bss == cbss)
3448252726Srpaulo			continue;
3449252726Srpaulo		if (bss->ssid_len == cbss->ssid_len &&
3450252726Srpaulo		    os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
3451252726Srpaulo		    wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
3452252726Srpaulo			add_freq(freqs, &num_freqs, bss->freq);
3453252726Srpaulo			if (num_freqs == max_freqs)
3454252726Srpaulo				break;
3455252726Srpaulo		}
3456252726Srpaulo	}
3457252726Srpaulo
3458252726Srpaulo	if (num_freqs == 0) {
3459252726Srpaulo		os_free(freqs);
3460252726Srpaulo		freqs = NULL;
3461252726Srpaulo	}
3462252726Srpaulo
3463252726Srpaulo	return freqs;
3464252726Srpaulo}
3465252726Srpaulo
3466252726Srpaulo
3467252726Srpaulovoid wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
3468252726Srpaulo{
3469252726Srpaulo	int timeout;
3470252726Srpaulo	int count;
3471252726Srpaulo	int *freqs = NULL;
3472252726Srpaulo
3473252726Srpaulo	/*
3474252726Srpaulo	 * Remove possible authentication timeout since the connection failed.
3475252726Srpaulo	 */
3476252726Srpaulo	eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3477252726Srpaulo
3478252726Srpaulo	/*
3479252726Srpaulo	 * Add the failed BSSID into the blacklist and speed up next scan
3480252726Srpaulo	 * attempt if there could be other APs that could accept association.
3481252726Srpaulo	 * The current blacklist count indicates how many times we have tried
3482252726Srpaulo	 * connecting to this AP and multiple attempts mean that other APs are
3483252726Srpaulo	 * either not available or has already been tried, so that we can start
3484252726Srpaulo	 * increasing the delay here to avoid constant scanning.
3485252726Srpaulo	 */
3486252726Srpaulo	count = wpa_blacklist_add(wpa_s, bssid);
3487252726Srpaulo	if (count == 1 && wpa_s->current_bss) {
3488252726Srpaulo		/*
3489252726Srpaulo		 * This BSS was not in the blacklist before. If there is
3490252726Srpaulo		 * another BSS available for the same ESS, we should try that
3491252726Srpaulo		 * next. Otherwise, we may as well try this one once more
3492252726Srpaulo		 * before allowing other, likely worse, ESSes to be considered.
3493252726Srpaulo		 */
3494252726Srpaulo		freqs = get_bss_freqs_in_ess(wpa_s);
3495252726Srpaulo		if (freqs) {
3496252726Srpaulo			wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
3497252726Srpaulo				"has been seen; try it next");
3498252726Srpaulo			wpa_blacklist_add(wpa_s, bssid);
3499252726Srpaulo			/*
3500252726Srpaulo			 * On the next scan, go through only the known channels
3501252726Srpaulo			 * used in this ESS based on previous scans to speed up
3502252726Srpaulo			 * common load balancing use case.
3503252726Srpaulo			 */
3504252726Srpaulo			os_free(wpa_s->next_scan_freqs);
3505252726Srpaulo			wpa_s->next_scan_freqs = freqs;
3506252726Srpaulo		}
3507252726Srpaulo	}
3508252726Srpaulo
3509252726Srpaulo	/*
3510252726Srpaulo	 * Add previous failure count in case the temporary blacklist was
3511252726Srpaulo	 * cleared due to no other BSSes being available.
3512252726Srpaulo	 */
3513252726Srpaulo	count += wpa_s->extra_blacklist_count;
3514252726Srpaulo
3515252726Srpaulo	switch (count) {
3516252726Srpaulo	case 1:
3517252726Srpaulo		timeout = 100;
3518252726Srpaulo		break;
3519252726Srpaulo	case 2:
3520252726Srpaulo		timeout = 500;
3521252726Srpaulo		break;
3522252726Srpaulo	case 3:
3523252726Srpaulo		timeout = 1000;
3524252726Srpaulo		break;
3525252726Srpaulo	case 4:
3526252726Srpaulo		timeout = 5000;
3527252726Srpaulo		break;
3528252726Srpaulo	default:
3529252726Srpaulo		timeout = 10000;
3530252726Srpaulo		break;
3531252726Srpaulo	}
3532252726Srpaulo
3533252726Srpaulo	wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
3534252726Srpaulo		"ms", count, timeout);
3535252726Srpaulo
3536252726Srpaulo	/*
3537252726Srpaulo	 * TODO: if more than one possible AP is available in scan results,
3538252726Srpaulo	 * could try the other ones before requesting a new scan.
3539252726Srpaulo	 */
3540252726Srpaulo	wpa_supplicant_req_scan(wpa_s, timeout / 1000,
3541252726Srpaulo				1000 * (timeout % 1000));
3542252726Srpaulo
3543252726Srpaulo#ifdef CONFIG_P2P
3544252726Srpaulo	if (wpa_s->global->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled &&
3545252726Srpaulo	    wpa_s->global->p2p != NULL) {
3546252726Srpaulo		wpa_s->global->p2p_cb_on_scan_complete = 0;
3547252726Srpaulo		if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
3548252726Srpaulo			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
3549252726Srpaulo				"continued after failed association");
3550252726Srpaulo		}
3551252726Srpaulo	}
3552252726Srpaulo#endif /* CONFIG_P2P */
3553252726Srpaulo}
3554252726Srpaulo
3555252726Srpaulo
3556252726Srpauloint wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
3557252726Srpaulo{
3558252726Srpaulo	return wpa_s->conf->ap_scan == 2 ||
3559252726Srpaulo		(wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
3560252726Srpaulo}
3561252726Srpaulo
3562252726Srpaulo
3563252726Srpaulo#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
3564252726Srpauloint wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
3565252726Srpaulo					      struct wpa_ssid *ssid,
3566252726Srpaulo					      const char *field,
3567252726Srpaulo					      const char *value)
3568252726Srpaulo{
3569252726Srpaulo#ifdef IEEE8021X_EAPOL
3570252726Srpaulo	struct eap_peer_config *eap = &ssid->eap;
3571252726Srpaulo
3572252726Srpaulo	wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
3573252726Srpaulo	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
3574252726Srpaulo			      (const u8 *) value, os_strlen(value));
3575252726Srpaulo
3576252726Srpaulo	switch (wpa_supplicant_ctrl_req_from_string(field)) {
3577252726Srpaulo	case WPA_CTRL_REQ_EAP_IDENTITY:
3578252726Srpaulo		os_free(eap->identity);
3579252726Srpaulo		eap->identity = (u8 *) os_strdup(value);
3580252726Srpaulo		eap->identity_len = os_strlen(value);
3581252726Srpaulo		eap->pending_req_identity = 0;
3582252726Srpaulo		if (ssid == wpa_s->current_ssid)
3583252726Srpaulo			wpa_s->reassociate = 1;
3584252726Srpaulo		break;
3585252726Srpaulo	case WPA_CTRL_REQ_EAP_PASSWORD:
3586252726Srpaulo		os_free(eap->password);
3587252726Srpaulo		eap->password = (u8 *) os_strdup(value);
3588252726Srpaulo		eap->password_len = os_strlen(value);
3589252726Srpaulo		eap->pending_req_password = 0;
3590252726Srpaulo		if (ssid == wpa_s->current_ssid)
3591252726Srpaulo			wpa_s->reassociate = 1;
3592252726Srpaulo		break;
3593252726Srpaulo	case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
3594252726Srpaulo		os_free(eap->new_password);
3595252726Srpaulo		eap->new_password = (u8 *) os_strdup(value);
3596252726Srpaulo		eap->new_password_len = os_strlen(value);
3597252726Srpaulo		eap->pending_req_new_password = 0;
3598252726Srpaulo		if (ssid == wpa_s->current_ssid)
3599252726Srpaulo			wpa_s->reassociate = 1;
3600252726Srpaulo		break;
3601252726Srpaulo	case WPA_CTRL_REQ_EAP_PIN:
3602252726Srpaulo		os_free(eap->pin);
3603252726Srpaulo		eap->pin = os_strdup(value);
3604252726Srpaulo		eap->pending_req_pin = 0;
3605252726Srpaulo		if (ssid == wpa_s->current_ssid)
3606252726Srpaulo			wpa_s->reassociate = 1;
3607252726Srpaulo		break;
3608252726Srpaulo	case WPA_CTRL_REQ_EAP_OTP:
3609252726Srpaulo		os_free(eap->otp);
3610252726Srpaulo		eap->otp = (u8 *) os_strdup(value);
3611252726Srpaulo		eap->otp_len = os_strlen(value);
3612252726Srpaulo		os_free(eap->pending_req_otp);
3613252726Srpaulo		eap->pending_req_otp = NULL;
3614252726Srpaulo		eap->pending_req_otp_len = 0;
3615252726Srpaulo		break;
3616252726Srpaulo	case WPA_CTRL_REQ_EAP_PASSPHRASE:
3617252726Srpaulo		os_free(eap->private_key_passwd);
3618252726Srpaulo		eap->private_key_passwd = (u8 *) os_strdup(value);
3619252726Srpaulo		eap->pending_req_passphrase = 0;
3620252726Srpaulo		if (ssid == wpa_s->current_ssid)
3621252726Srpaulo			wpa_s->reassociate = 1;
3622252726Srpaulo		break;
3623252726Srpaulo	default:
3624252726Srpaulo		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
3625252726Srpaulo		return -1;
3626252726Srpaulo	}
3627252726Srpaulo
3628252726Srpaulo	return 0;
3629252726Srpaulo#else /* IEEE8021X_EAPOL */
3630252726Srpaulo	wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
3631252726Srpaulo	return -1;
3632252726Srpaulo#endif /* IEEE8021X_EAPOL */
3633252726Srpaulo}
3634252726Srpaulo#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
3635252726Srpaulo
3636252726Srpaulo
3637252726Srpauloint wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
3638252726Srpaulo{
3639252726Srpaulo	int i;
3640252726Srpaulo	unsigned int drv_enc;
3641252726Srpaulo
3642252726Srpaulo	if (ssid == NULL)
3643252726Srpaulo		return 1;
3644252726Srpaulo
3645252726Srpaulo	if (ssid->disabled)
3646252726Srpaulo		return 1;
3647252726Srpaulo
3648252726Srpaulo	if (wpa_s && wpa_s->drv_capa_known)
3649252726Srpaulo		drv_enc = wpa_s->drv_enc;
3650252726Srpaulo	else
3651252726Srpaulo		drv_enc = (unsigned int) -1;
3652252726Srpaulo
3653252726Srpaulo	for (i = 0; i < NUM_WEP_KEYS; i++) {
3654252726Srpaulo		size_t len = ssid->wep_key_len[i];
3655252726Srpaulo		if (len == 0)
3656252726Srpaulo			continue;
3657252726Srpaulo		if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
3658252726Srpaulo			continue;
3659252726Srpaulo		if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
3660252726Srpaulo			continue;
3661252726Srpaulo		if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
3662252726Srpaulo			continue;
3663252726Srpaulo		return 1; /* invalid WEP key */
3664252726Srpaulo	}
3665252726Srpaulo
3666252726Srpaulo	if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
3667252726Srpaulo	    !ssid->ext_psk)
3668252726Srpaulo		return 1;
3669252726Srpaulo
3670252726Srpaulo	return 0;
3671252726Srpaulo}
3672252726Srpaulo
3673252726Srpaulo
3674252726Srpauloint wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
3675252726Srpaulo{
3676252726Srpaulo	if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
3677252726Srpaulo		return 1;
3678252726Srpaulo	if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
3679252726Srpaulo		return 0;
3680252726Srpaulo	return -1;
3681252726Srpaulo}
3682252726Srpaulo
3683252726Srpaulo
3684252726Srpaulovoid wpas_auth_failed(struct wpa_supplicant *wpa_s)
3685252726Srpaulo{
3686252726Srpaulo	struct wpa_ssid *ssid = wpa_s->current_ssid;
3687252726Srpaulo	int dur;
3688252726Srpaulo	struct os_time now;
3689252726Srpaulo
3690252726Srpaulo	if (ssid == NULL) {
3691252726Srpaulo		wpa_printf(MSG_DEBUG, "Authentication failure but no known "
3692252726Srpaulo			   "SSID block");
3693252726Srpaulo		return;
3694252726Srpaulo	}
3695252726Srpaulo
3696252726Srpaulo	if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
3697252726Srpaulo		return;
3698252726Srpaulo
3699252726Srpaulo	ssid->auth_failures++;
3700252726Srpaulo	if (ssid->auth_failures > 50)
3701252726Srpaulo		dur = 300;
3702252726Srpaulo	else if (ssid->auth_failures > 20)
3703252726Srpaulo		dur = 120;
3704252726Srpaulo	else if (ssid->auth_failures > 10)
3705252726Srpaulo		dur = 60;
3706252726Srpaulo	else if (ssid->auth_failures > 5)
3707252726Srpaulo		dur = 30;
3708252726Srpaulo	else if (ssid->auth_failures > 1)
3709252726Srpaulo		dur = 20;
3710252726Srpaulo	else
3711252726Srpaulo		dur = 10;
3712252726Srpaulo
3713252726Srpaulo	os_get_time(&now);
3714252726Srpaulo	if (now.sec + dur <= ssid->disabled_until.sec)
3715252726Srpaulo		return;
3716252726Srpaulo
3717252726Srpaulo	ssid->disabled_until.sec = now.sec + dur;
3718252726Srpaulo
3719252726Srpaulo	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
3720252726Srpaulo		"id=%d ssid=\"%s\" auth_failures=%u duration=%d",
3721252726Srpaulo		ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
3722252726Srpaulo		ssid->auth_failures, dur);
3723252726Srpaulo}
3724252726Srpaulo
3725252726Srpaulo
3726252726Srpaulovoid wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
3727252726Srpaulo			      struct wpa_ssid *ssid, int clear_failures)
3728252726Srpaulo{
3729252726Srpaulo	if (ssid == NULL)
3730252726Srpaulo		return;
3731252726Srpaulo
3732252726Srpaulo	if (ssid->disabled_until.sec) {
3733252726Srpaulo		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
3734252726Srpaulo			"id=%d ssid=\"%s\"",
3735252726Srpaulo			ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
3736252726Srpaulo	}
3737252726Srpaulo	ssid->disabled_until.sec = 0;
3738252726Srpaulo	ssid->disabled_until.usec = 0;
3739252726Srpaulo	if (clear_failures)
3740252726Srpaulo		ssid->auth_failures = 0;
3741252726Srpaulo}
3742252726Srpaulo
3743252726Srpaulo
3744252726Srpauloint disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
3745252726Srpaulo{
3746252726Srpaulo	size_t i;
3747252726Srpaulo
3748252726Srpaulo	if (wpa_s->disallow_aps_bssid == NULL)
3749252726Srpaulo		return 0;
3750252726Srpaulo
3751252726Srpaulo	for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
3752252726Srpaulo		if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
3753252726Srpaulo			      bssid, ETH_ALEN) == 0)
3754252726Srpaulo			return 1;
3755252726Srpaulo	}
3756252726Srpaulo
3757252726Srpaulo	return 0;
3758252726Srpaulo}
3759252726Srpaulo
3760252726Srpaulo
3761252726Srpauloint disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
3762252726Srpaulo		    size_t ssid_len)
3763252726Srpaulo{
3764252726Srpaulo	size_t i;
3765252726Srpaulo
3766252726Srpaulo	if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
3767252726Srpaulo		return 0;
3768252726Srpaulo
3769252726Srpaulo	for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
3770252726Srpaulo		struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
3771252726Srpaulo		if (ssid_len == s->ssid_len &&
3772252726Srpaulo		    os_memcmp(ssid, s->ssid, ssid_len) == 0)
3773252726Srpaulo			return 1;
3774252726Srpaulo	}
3775252726Srpaulo
3776252726Srpaulo	return 0;
3777252726Srpaulo}
3778252726Srpaulo
3779252726Srpaulo
3780252726Srpaulo/**
3781252726Srpaulo * wpas_request_connection - Request a new connection
3782252726Srpaulo * @wpa_s: Pointer to the network interface
3783252726Srpaulo *
3784252726Srpaulo * This function is used to request a new connection to be found. It will mark
3785252726Srpaulo * the interface to allow reassociation and request a new scan to find a
3786252726Srpaulo * suitable network to connect to.
3787252726Srpaulo */
3788252726Srpaulovoid wpas_request_connection(struct wpa_supplicant *wpa_s)
3789252726Srpaulo{
3790252726Srpaulo	wpa_s->normal_scans = 0;
3791252726Srpaulo	wpa_supplicant_reinit_autoscan(wpa_s);
3792252726Srpaulo	wpa_s->extra_blacklist_count = 0;
3793252726Srpaulo	wpa_s->disconnected = 0;
3794252726Srpaulo	wpa_s->reassociate = 1;
3795252726Srpaulo	wpa_supplicant_req_scan(wpa_s, 0, 0);
3796252726Srpaulo}
3797